브라우저·스크립팅 환경(특히 JIT 기반 엔진)에서 악성코드가 활용하는
Heap Spraying 기법의 구조적 특성, 메모리 배치 패턴,
셸코드 적재 방식, 그리고 포렌식 관점에서의 IOC를 정리함.
리버싱 기록
1. 개요 — Heap Spraying의 목적과 동작 원리
Heap Spraying은 다음과 같은 목적을 위해 사용된다:
- 예측 가능한 메모리 주소 범위 확보
JIT/GC 환경에서 무작위 주소가 부여되더라도
공격자가 원하는 페이로드(주로 셸코드)를
특정 패턴의 대규모 객체로 메모리에 반복 배치한다. - 취약점 트리거 이후 제어 흐름 장악
Type Confusion, Use-After-Free, Out-of-Bounds Read/Write 등
브라우저 취약점이 발생할 때,
공격자는 미리 뿌려둔 페이로드 영역으로 RIP/EIP를 전이시킨다. - ASLR 우회에 대한 부분적 보조 역할
ASLR 자체를 해제하진 않지만,
대량의 동일 패턴 객체를 배치해
공격 성공 확률을 크게 높인다.
2. 기본 Heap Spray 패턴 — 단순화된 JS 예시
다음은 단순화된 Spray 패턴이다.
// 비실행 예제 — 분석용 형태
var spray = [];
var block = "\u9090\u9090"; // NOP sled (Unicode 기반 단순 패턴)
while (block.length < 0x2000) {
block += block; // 크기 확장
}
// 셸코드 더미(비실행)
var payload = "\u4141\u4242\u4343\u4444";
for (var i = 0; i < 5000; i++) {
spray[i] = block + payload;
}
특징
- Unicode 문자열을 이용한 NOP-sled 확장
- 수천 개 단위로 동일한 블록을 할당해 Heap 전역을 “오염”
- 메모리 단편화가 심각하게 증가
- 브라우저 엔진의 힙 세그먼트에 반복 배치 → 예측성 확보
3. JIT 기반 Exploit 연계 — 메모리 배치 구조 관찰
Heap Spray 이후 브라우저 엔진은 아래와 같은 구조로 메모리를 배치한다:
[LargeStringBlock-A][LargeStringBlock-A][LargeStringBlock-A]...
[LargeStringBlock-A][LargeStringBlock-A][LargeStringBlock-A]...
[... repeated thousands of times ...]
공격자는 다음 조건을 노린다:
- 특정 취약점 발생 시 RIP/EIP가 “대략적인 범위”만 일치해도
NOP-sled 구간을 통해 페이로드로 유입 - Spray된 객체가 같은 힙 세그먼트에 밀집 → 주소 충돌 난이도 감소
4. Shellcode Dummy Payload — 구조적 형식 제시
아래는 셸코드 구조 예시이다.
; --- 더미 Shellcode 구조 ---
start:
xor eax, eax
mov edx, esp ; 스택 기반 환경 점검 (dummy)
nop
nop
nop ; NOP sled extension
decode_loop:
mov bl, [esi] ; 암호화된 페이로드 디코딩 (dummy)
xor bl, 0x5A
mov [edi], bl
inc esi
inc edi
loop decode_loop
jmp edi ; 디코딩 완료 후 Jump
분석 포인트
- NOP-sled 이후 “decode → jump” 패턴은 셸코드 전형
- ASLR 우회 보조 역할: 정확한 주소 대신 범위만 노려도 성공
- 디코더 루프가 짧게 구성되어 있어 스캔 탐지에 취약
5. 메모리 레이아웃 단계별 레지스터·스택 변화
취약점 트리거 후 예시 흐름은 다음과 같다:
(1) 잘못된 함수 포인터/가상 테이블 접근
mov eax, [ecx] ; ECX는 공격 가능한 객체
call dword ptr [eax+4] ; 공격자가 덮어쓴 vtable 엔트리 호출
(2) EIP 전이 (취약 지점 → Spray 영역)
eax+4가 Spray 영역 내 특정 오프셋을 가리키도록 변조- 제어 흐름이 NOP-sled로 진입
(3) NOP-sled 진입 후 페이로드 실행
0x0C0C1000: 90 90 90 90 90 90 ...
0x0C0C1F00: EB 10 5A ... (decode stub)
레지스터 변화
| 시점 | EIP | EAX | ESP | 의미 |
|---|---|---|---|---|
| 취약점 발생 직후 | Spray 범위 | vtable pointer | 정상 | EIP 강제 전이 |
| NOP-sled 구간 | sled 내부 | 불변 | 정상 | EIP 증가(NOP 수행) |
| decode stub 진입 | stub entry | 함수 param 없음 | 정상 | 페이로드 복호화 시작 |
6. 포렌식 관점에서의 Heap Spray IOC
Heap Spraying은 다음과 같은 지표를 남긴다:
(1) 브라우저 힙 세그먼트 내 비정상적 대형 문자열 반복
- Unicode 기반 NOP-sled 패턴 (
\u9090\u9090)이 다량 반복
(2) 연속적이고 규칙적인 Heap allocation
- 동일한 크기의 대규모 객체 수천 개 존재
(3) 메모리 덤프에서 Shellcode-like 바이트 패턴
- 디코더 루프 / NOP-sled / XOR 패턴
- 엔트리 포인트 이전 코드 삽입 흔적과 유사
(4) Crash Dump 분석 시 EIP가 Non-Image 영역(Heap)을 가리킴
- 정상 모듈이 아닌 “Heap 주소”로 RIP/EIP 전이
(5) JIT Spray 흔적
- RWX 페이지 내 반복 패턴
- 스크립트 엔진 내부 메모리 조작 흔적
7. 대응 및 디지털 포렌식 절차
포렌식·Incident Response 관점에서 진행해야 할 주요 절차는 다음과 같다:
- 브라우저 힙 메모리 섹션 덤프 확보
- 연속 패턴 시그니처 탐지 (NOP-sled / XOR decoder)
- Crash Dump 기반 EIP 전이 지점 재구성
- GC 영역 및 JIT 페이지 분석
- 스크립트 로그/History 기반 공격 흐름 역추적
8. 결론
Heap Spraying은 브라우저 공격 체인의
“메모리 레이아웃 장악” 단계에서 핵심적인 역할을 담당한다.
JIT 기반 환경에서는 주소 무작위화(ASLR)를 온전히 우회하지 않더라도
대규모 메모리 오염만으로 제어 흐름 획득 확률을 높일 수 있으며,
포렌식 분석에서는 반복 문자열 패턴, Heap 오염 상태,
EIP 전이 흔적 등을 통해 해당 공격을 충분히 식별할 수 있다.
📍 Written by Code & Compass






