Inline Patch 기반 User-Mode API Hooking Stub 구조 분석
본 기록은 악성코드에서 빈번히 관찰되는 User‑Mode API 후킹 패턴 중,
가장 기본적인 형태인 Inline Patch(프롤로그 패치) 기반 Hook Stub의 구조를 리버싱 관점에서 정리한 것이다.
PE 구조, 함수 호출 규약, 스택 프레임, 제어 흐름 분석, 그리고 동적 API 획득·암호화 루틴 복원 절차와 연결지어 기술.
리버싱 기록
1. 개념적 Hooking 구조(C 관점, 비실행 예시)
이 예시는 실제로 실행되지 않도록 설계되었으며,
일반적인 악성 샘플에서 발견되는 구조적 패턴만 반영.
// 개념적 예시 — 구조 관찰 전용
unsigned char originalBytes[16];
void hook_target_function(void* target, void* hookStub) {
// 1) 타깃 함수의 첫 5바이트 백업
memcpy(originalBytes, target, 5);
// 2) JMP hookStub 패치
DWORD rel = (DWORD)hookStub - (DWORD)target - 5;
BYTE patch[5] = {0xE9}; // JMP rel32
memcpy(patch + 1, &rel, 4);
// 3) 메모리 보호 변경 후 패치 적용
write_patch_conceptually(target, patch, 5);
}
핵심 요약:
- 타깃 함수의 프롤로그를 덮고 JMP stub으로 제어 흐름을 이동시킴.
- 패치 전 원본 5바이트는 트램펄린(복구용 stub)에서 사용됨.
- 멀웨어는 보통 API명 문자열을 암호화하여 보호함.
2. Hook Stub 구조(비실행 Assembly)
실제 샘플에서 가장 흔히 보이는 형태의 개념적 디스어셈블리임.
구체적 주소·시스템콜·파라미터는 제외함.
; Hook Stub — 비실행 개념 코드
; 목적:
; 1) 호출자 레지스터/스택 보존
; 2) 악성 로직 수행
; 3) 원본 함수의 나머지 부분(트램펄린)으로 복귀
HOOK_STUB:
pushad ; GP 레지스터 전체 보존
pushfd ; EFLAGS 보존
; --- 악성 로직 (축약 예시) ---
; 예: API 호출 이름 로깅, 파라미터 변조, 조건부 차단 등
; --- 원본 코드 트램펄린 호출 ---
popfd
popad
jmp ORIGINAL_TRAMPOLINE ; 원본 코드로 흐름 복귀
※ pushad/popad는 분석용 개념 표현이며 실제 샘플은 다른 레지스터 보존 정책을 사용하기도함.
3. Inline Patch 적용 위치 분석
PE Export Table을 통해 얻은 함수 주소는 실제 실행 모듈 내부의 실제 엔트리이며,
보통 다음과 같은 프롤로그 패턴을 가짐.
; Typical Win32 API Prologue
MOV EDI, EDI ; Alignment
PUSH EBP
MOV EBP, ESP
SUB ESP, XX
악성코드는 이 상단 5바이트를 덮어 쓰며:
E9 XX XX XX XX ; JMP hookStub
**제어 흐름 전환(Control Flow Detour)**이 즉시 발생.
4. 트램펄린 구조 상세
트램펄린은 다음과 같은 구조로 형성됨.
; 비실행 예시 — 트램펄린
ORIGINAL_TRAMPOLINE:
; 1) 백업된 원본 바이트
DB 55 8B EC ... ; 실제 원본 프롤로그 일부
; 2) 원래 함수의 다음 주소로 점프
JMP [originalFunction + 5]
트램펄린은 분석에서 중요한 의미가 있음:
- API 후킹 여부 식별 가능
- 원래 함수의 실제 시작 지점을 확정 가능
- 후킹 탐지 코드에서 주로 탐지되는 지점
5. 동적 API 조회(PEB 및 Export 파싱 기반)
악성코드의 후킹 로직은 종종 API명을 직접 포함하지 않고,
Export Directory를 직접 파싱함.
// 개념적 예시 — Export 파싱
void* resolve_api_concept(const char* dll, const char* nameHash) {
// 1) PEB → LDR → Module 찾기
// 2) Export Directory 조회
// 3) 함수명 해시 비교
// 4) IAT/주소 반환
return 0;
}
분석 포인트:
- 문자열은 XOR, ROL 등 간단 암호화가 흔함
- 함수명 비교는 32비트/64비트 해시로 수행
- 정적 분석에서는 해시 루틴 복원 필요
6. Anti‑Debugging과 후킹의 결합 패턴
일부 악성코드는 후킹 코드 근처에서 다음과 같은 anti-debug 체크를 수행함.
mov eax, fs:[0x30] ; PEB
mov al, [eax+0x02] ; BeingDebugged
test al, al
jnz DEBUG_HANDLER ; 디버거 존재 시 분기
int 2D ; Soft breakpoint 유발 패턴
흔한 패턴:
- 후킹된 API 호출 시 디버거 탐지 수행
- 디버거 분위기에서만 다른 트램펄린을 호출
- 레지스터 변조로 스택 붕괴 유발
7. Control Flow 관찰 포인트
| 항목 | 체크 내용 |
|---|---|
| 스택 프레임 | 프롤로그 패턴 파괴 여부, ESP 변화 |
| Export Table | 실제 API 엔트리와 패치 여부 비교 |
| IAT | 후킹된 API가 Import Table 대신 Inline Patch 사용하는지 |
| 메모리 보호 | .text 구간이 RWX로 변경되었는지 |
| 의사 코드 | 트램펄린 내 jmp original+5 유무 |
| 레지스터 흐름 | hook stub 전후 레지스터 보존 여부 |
이 지표들은 API 후킹을 식별하고 후킹 로직이 어떤 방식으로 동작하는지 판단하는 데 유용함.
✨ 마무리 한 줄
Inline Patch 기반 User‑Mode Hooking은 작은 5바이트 프롤로그를 바꾸는 것만으로 시스템 흐름을 완전히 가로채며,
그 세밀한 패턴을 읽어내는 것이 리버스 엔지니어링의 핵심 감각을 단련하는 중요한 과정이다.
📍 Written by Code & Compass