• Heap Spraying 기반 메모리 레이아웃 감염 기법 분석 — 브라우저 익스플로잇 및 셸코드

    브라우저·스크립팅 환경(특히 JIT 기반 엔진)에서 악성코드가 활용하는
    Heap Spraying 기법의 구조적 특성, 메모리 배치 패턴,
    셸코드 적재 방식, 그리고 포렌식 관점에서의 IOC를 정리함.

    리버싱 기록


    1. 개요 — Heap Spraying의 목적과 동작 원리

    Heap Spraying은 다음과 같은 목적을 위해 사용된다:

    1. 예측 가능한 메모리 주소 범위 확보
      JIT/GC 환경에서 무작위 주소가 부여되더라도
      공격자가 원하는 페이로드(주로 셸코드)를
      특정 패턴의 대규모 객체로 메모리에 반복 배치한다.
    2. 취약점 트리거 이후 제어 흐름 장악
      Type Confusion, Use-After-Free, Out-of-Bounds Read/Write 등
      브라우저 취약점이 발생할 때,
      공격자는 미리 뿌려둔 페이로드 영역으로 RIP/EIP를 전이시킨다.
    3. 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)
    

    레지스터 변화

    시점EIPEAXESP의미
    취약점 발생 직후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 관점에서 진행해야 할 주요 절차는 다음과 같다:

    1. 브라우저 힙 메모리 섹션 덤프 확보
    2. 연속 패턴 시그니처 탐지 (NOP-sled / XOR decoder)
    3. Crash Dump 기반 EIP 전이 지점 재구성
    4. GC 영역 및 JIT 페이지 분석
    5. 스크립트 로그/History 기반 공격 흐름 역추적

    8. 결론

    Heap Spraying은 브라우저 공격 체인의
    “메모리 레이아웃 장악” 단계에서 핵심적인 역할을 담당한다.

    JIT 기반 환경에서는 주소 무작위화(ASLR)를 온전히 우회하지 않더라도
    대규모 메모리 오염만으로 제어 흐름 획득 확률을 높일 수 있으며,
    포렌식 분석에서는 반복 문자열 패턴, Heap 오염 상태,
    EIP 전이 흔적 등을 통해 해당 공격을 충분히 식별할 수 있다.


    📍 Written by Code & Compass

  • TLS Callback 기반 은밀한 초기 실행 분석

    악성코드가 Thread Local Storage(TLS) Callback을 이용해
    PE 진입점(EntryPoint) 이전 단계에서 실행 흐름을 선점하는 기법을
    분석 관점에서 정리한 기록이다.

    TLS Callback은 PE 로더가 모듈을 로딩할 때 자동으로 호출되는 함수로,
    공격자는 이를 악용하여 Anti-Debugging, 환경 점검,
    언패킹 루틴의 사전 실행, 동적 API 해석 등을
    EntryPoint 이전 초기화 구역에 은밀히 삽입한다.

    리버싱 기록


    1. 개요 — 왜 TLS Callback을 사용하는가

    TLS Callback 기반 초기 실행 흐름 전이는 다음과 같은 목적에서 빈번히 활용된다:

    • EntryPoint 은닉: 정적 분석에서 확인되는 EntryPoint는 무해한 코드로 덮어두고, 실제 로직은 TLS에서 실행
    • Anti-Debugging 사전 수행: 디버거 부착 이전 단계에서 환경 검사
    • 언패킹 루틴 선실행: 압축·암호화된 페이로드를 EntryPoint보다 먼저 복구
    • Dynamic API Resolution 초기화
    • PE Loader 내부 동작을 악용한 선제 실행

    Windows PE 로더는 TLS Directory를 확인하고 Callback 목록을 순서대로 호출하므로,
    이는 PE 구조 관점에서 자연스러운 “합법적 진입점”으로 인식된다.


    2. TLS Directory 구조 관찰

    TLS 관련 PE Directory는 다음과 같이 구성된다:

    typedef struct _IMAGE_TLS_DIRECTORY32 {
        DWORD StartAddressOfRawData;
        DWORD EndAddressOfRawData;
        DWORD AddressOfIndex;
        DWORD AddressOfCallbacks;   // TLS Callback 배열
        DWORD SizeOfZeroFill;
        DWORD Characteristics;
    } IMAGE_TLS_DIRECTORY32;
    

    분석에서 주목해야 할 지점:

    • AddressOfCallbacks가 가리키는 함수 배열
    • 함수 주소들이 .text 범위를 벗어나는지
    • RWX 메모리 또는 Private Memory 영역을 가리키는지 여부
    • 정적 분석에서 EntryPoint보다 먼저 실행되는 경우

    3. TLS Callback 등록 패턴 (C 예제)

    // 패턴 — TLS Callback 선언
    void __stdcall DemoTLSCallback(PVOID DllHandle, DWORD Reason, PVOID Reserved) {
        // (예시) Anti-Debugging, Dynamic API Resolution, Unpacking 등
        // 실제 악성 행위 없음
    }
    
    // TLS Callback 배열 정의
    #pragma const_seg(".CRT$XLB")
    PIMAGE_TLS_CALLBACK pCallback = DemoTLSCallback;
    #pragma const_seg()
    

    특징

    • .CRT$XL* 섹션을 이용해 TLS 배열을 구성
    • 링커가 이를 TLS Directory에 자동으로 삽입
    • 실행 시 EntryPoint 이전 단계에서 호출됨

    4. 실행 흐름 디스어셈블리 분석

    다음은 PE 로더가 TLS Callback을 호출하는 단순화된 패턴이다.

    ; --- LdrpCallTlsInitializers 내부 흐름 단순화 버전 ---
    mov     esi, [TlsDirectory.AddressOfCallbacks]
    test    esi, esi
    jz      no_tls
    
    tls_loop:
        mov     eax, [esi]
        test    eax, eax
        jz      end_tls
    
        push    0                ; Reserved
        push    1                ; DLL_PROCESS_ATTACH
        push    dword ptr [ModuleHandle]
        call    eax              ; → TLS Callback 호출
    
        add     esi, 4
        jmp     tls_loop
    

    레지스터 변화 분석

    레지스터의미
    ESITLS Callback 배열 순회 포인터
    EAX현재 Callback 함수 주소
    ESP호출 규약에 따라 인자 3개 푸시 후 Call

    분석 포인트

    • Callback 주소가 PE 이미지 내 정적 함수인지 확인
    • Private Memory / 언패킹된 메모리로 흐름이 전이되는지
    • Return 시 스택 프레임 왜곡 여부 추적

    5. TLS 내부에서 수행되는 Anti-Debugging 패턴

    초기화 구간에서 자주 발견되는 패턴:

    1. PEB.BeingDebugged 플래그 확인
    mov     eax, fs:[30h]
    cmp     byte ptr [eax+2], 0     ; BeingDebugged
    jne     debug_found
    
    1. NtQueryInformationProcess(ProcessDebugFlags)
    // 패턴
    NTSTATUS status;
    DWORD flags = 0;
    NtQueryInformationProcess(GetCurrentProcess(),
                              ProcessDebugFlags,
                              &flags, sizeof(flags), NULL);
    // flags == 0 → 디버깅 중
    
    1. Timing Check (RDTSC / QueryPerformanceCounter)
      언패킹 루틴 전 디버깅 지연 여부 검사.

    6. TLS 기반 언패킹 초기화 패턴

    패커/로더는 TLS Callback에서 다음 작업을 수행한다:

    • 압축 블록 해제
    • XOR/RC4 기반 암호화 루틴 복호화
    • Shellcode를 RWX 메모리에 풀어 배치
    • IAT 재구성 또는 동적 API 로더 초기화
    • Process Injection 준비 (WriteProcessMemory 버퍼 생성 등)

    단순화된 언패킹 패턴 예시

    void __stdcall DemoTLSCallback(...) {
        for (int i = 0; i < payloadSize; i++)
            unpackBuf[i] ^= 0x5A;
    
        // EntryPoint 이전에 Memory Patch 완료
    }
    

    7. 메모리 포렌식에서의 IOC

    TLS 기반 공격은 다음 지표로 식별 가능:

    (1) TLS Directory 존재 + Callbacks 배열이 비정상적 주소 사용

    (2) Callback 함수가 Private Memory / RWX 메모리에 위치

    (3) EntryPoint 실행 이전 단계에서 언패킹 흔적

    (4) PEB 검사, Timing Check 등 Anti-Debugging 로직이 TLS 내부에 존재

    (5) Call Stack Reconstruction 시 EntryPoint보다 앞선 실행 기록 확인


    8. 결론

    TLS Callback 기반 실행 흐름 전이는
    EntryPoint 이전의 은닉 실행 엔진을 구성하기 위한
    대표적인 고급 로딩 기법이다.

    PE 구조·메모리 보호 속성·레지스터 전이·디버깅 플래그 관찰을 종합하면
    초기 흐름 왜곡을 충분히 추적할 수 있으며,
    포렌식 단계에서도 명확한 IOC가 남는다.


    📍 Written by Code & Compass

  • IAT Stomping 기반 흐름 분석

    본 문서는 공격자가 Import Address Table(IAT) Stomping을 활용해
    정적 분석을 회피하고, 동적 호출 전용 API 재해석 루틴을 삽입하는 과정에서 발생하는
    메모리 변조 패턴, 레지스터 조작, 스택 프레임 변화,
    그리고 PE 구조 관점의 무결성이 깨지는 지점을 작성함.

    리버싱 기록


    1. 개요 — IAT Stomping의 역할과 특징

    IAT Stomping은 PE 파일에 존재하는 정적 Import Address Table의
    개별 함수 주소 필드를 공격자가 임의 함수(대개 커스텀 로더 또는 난독화된 wrapper)로
    직접 덮어써 호출 흐름을 변조하는 기법이다.

    진단 관점에서 나타나는 특징:

    • IAT 엔트리가 원본 DLL 범위를 벗어난 Private Memory 주소로 변경
    • 정적 분석에서 확인한 함수 호출과 런타임 제어 흐름이 불일치
    • API 호출 규약(Calling Convention)이 원본 함수와 맞지 않아 스택 비정상 패턴 발생
    • 언패킹/로더 루틴 진입부가 정상 API 호출 직후 등장

    이 기법은 Packing, Shellcode Loader, Process Injection 초기화 코드에서 빈번히 등장한다.


    2. IAT 엔트리 변조 흐름

    아래는 단순화된 Stomping 패턴이다.

    // 샘플 코드
    BOOL Demo_IATStomp(BYTE* moduleBase, LPVOID fakeFuncPtr)
    {
        IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)moduleBase;
        IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)(moduleBase + dos->e_lfanew);
    
        // IAT RVA
        DWORD iatRVA = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
        if (!iatRVA) return FALSE;
    
        IMAGE_THUNK_DATA* iat = (IMAGE_THUNK_DATA*)(moduleBase + iatRVA);
    
        // 첫 번째 엔트리에 fakeFuncPtr 삽입 (예시)
        SIZE_T bytesWritten = 0;
        DWORD oldProtect = 0;
        VirtualProtect(iat, sizeof(LPVOID), PAGE_READWRITE, &oldProtect);
    
        iat[0].u1.Function = (ULONGLONG)fakeFuncPtr;
    
        VirtualProtect(iat, sizeof(LPVOID), oldProtect, &oldProtect);
        return TRUE;
    }
    

    분석 시 주목 포인트

    • IMAGE_DIRECTORY_ENTRY_IAT 기반 엔트리 접근
    • VirtualProtect를 통한 메모리 보호 속성 변경
    • 원본 DLL 모듈 주소 범위와 비교하여
      IAT 필드가 Private Memory를 가리키는지 여부
    • PE 구조의 Import Table 재해석을 통해 실제 호출 흐름 파악 가능

    3. Assembly 관점 — Stomping 이후 호출 흐름 패턴

    다음은 실제 호출이 IAT를 경유하여
    공격자 커스텀 함수로 전이되는 형태를 단순화한 패턴이다.

    ; --- 정상 API 호출 흐름 ---
    call    dword ptr [IAT_GetProcAddress]     ; 원래는 kernel32!GetProcAddress
    
    ; --- IAT Stomping 후 흐름 ---
    call    dword ptr [IAT_GetProcAddress]     ; IAT 엔트리가 이미 공격자 fakeFuncPtr로 변조됨
                                                ; → Private Memory 주소로 제어 흐름 전이
    
    ; 공격자 커스텀 루틴 시작점 (가상 코드)
    fakeFuncPtr:
        push    ebp
        mov     ebp, esp
        sub     esp, 20h
        ; 스택 프레임 생성, 이후 실제 API 호출 대신 자체 로직 수행
        ; (예: 해시 기반 API 재해석, 언패킹 루틴, Anti-Debugging)
        leave
        ret
    

    레지스터 동작 분석

    레지스터의미
    EIPIAT 엔트리의 변경된 주소(Private Memory)로 이동
    ESP/EBP호출 규약이 원본 함수와 달라 Return Address 불일치 가능
    EAX/ECX/EDXFake 함수 내부에서 임의 목적에 맞게 재활용

    4. PE 구조 기반 무결성 관찰

    일부 PE 분석 기준에 따르면
    IAT Stomping은 아래 요소에서 명확한 이상 패턴을 발생시킨다.

    (1) Import Address Table 엔트리 무결성 붕괴

    • IAT 엔트리가 ImageBase ~ ImageSize 범위에서 벗어남
    • 일반적으로는 kernel32.dll, user32.dll 등 모듈 내 주소여야 정상

    (2) Import Descriptor의 OriginalFirstThunk 대비 불일치

    • 정적 Import Table에 정의된 함수 주소와 런타임 주소 비교 시
      변조 여부가 즉시 노출된다

    (3) 메모리 보호 속성 변동

    • .idata는 원래 READONLY 상태이나
      Stomping 전후로 PAGE_READWRITEPAGE_READONLY 변경 흔적 확인 가능

    5. 동적 API 해석(Dynamic API Resolution)과의 결합 패턴

    Stomping은 단독으로 사용되기보다는 다음 패턴들과 연계된다:

    • 해시 기반 GetProcAddress Stub
    • PEB.LoaderData 를 통한 모듈 열거
    • ROR/ROR 기반 해시 연산 난독화
    • API 호출 전후의 RetSpoofing 형태 통제
    • Anti-Debugging: NtQueryInformationProcess(ProcessDebugFlags) 호출

    이는 IAT Stomping으로 진입한 fake 함수 내부에서
    초기화 루틴을 수행하는 구조로 관찰된다.


    6. 스택 프레임 및 호출 규약 무결성 검증

    IAT Stomping 후에는 다음과 같은 스택·프레임 이상 징후가 나타난다.

    비정상 패턴

    • 원래 stdcall 함수였으나 fake 함수는 cdecl 형태로 처리
    • 호출자 정리(Call-site cleanup) 불일치
    • Return Address가 모듈 내부가 아닌 Private Memory를 가리킴
    • Prologue/epilogue 패턴이 정상 라이브러리 함수와 다름
      (push ebp / mov ebp, esp 부재 또는 변형)

    포렌식에서는 Call Stack Reconstruction 시
    이러한 지점에서 Stack Trace Disruption이 흔하게 발생한다.


    7. 메모리 포렌식에서 확인되는 IOC

    (1) IAT 엔트리 주소가 정상 DLL 범위를 벗어남

    (2) .idata 섹션의 보호 속성 변경 흔적

    (3) Private Memory 영역에서 PE Header 단편(MZ/PE)이 발견

    (4) 호출 흐름 분석 시 IAT → Private Memory → API Resolver Stub 패턴

    (5) API 호출 빈도 이상 (정상 대비 높은 LoadLibrary / GetProcAddress 사용량)


    8. 결론

    IAT Stomping은 정적 분석을 막고,
    동적 API 해석 루틴과 결합되어 흐름을 은폐하는 데 사용되는
    전형적인 악성 로더 기법이다.

    PE 구조 기반 검증, 메모리 보호 속성 관찰,
    레지스터·스택 프레임 분석을 병행하면
    공격자가 구현한 은폐형 호출 경로는 충분히 추적 가능하다.


    📍 Written by Code & Compass

  • Process Hollowing 분석 — Unbacked Memory Image Overwrite 및 Thread Rebase 패턴

    악성코드가 빈번히 사용하는 Process Hollowing (a.k.a. RunPE) 기법의
    초기 구간(Stub → Target Image Unmapping → Memory Overwrite → Context 재설정)에서
    보여지는 프로세스 메모리 오염 패턴, 레지스터 전이, 스택 프레임 변형, 제어 흐름 재배치(Thread Rebase) 과정을 작성함.

    리버싱 기록


    1. 개요 — Process Hollowing의 핵심 구조

    Process Hollowing은 정상 프로세스를 생성한 뒤, 해당 프로세스의
    Image Section을 Unmap/Overwrite하여 공격자 임의 코드(일반적으로 언패킹된 PE)를
    삽입하고, 이어서 Thread Context(EIP/RIP) 를 새 EntryPoint로 재설정하여
    실행 흐름을 완전히 대체하는 기법이다.

    분석 관점에서 특징적인 포인트는 다음과 같다:

    • Suspended 상태의 프로세스 생성 (CreateProcess + CREATE_SUSPENDED)
    • NtUnmapViewOfSection 호출 후 ImageBase 제거
    • Private Memory에 공격자 이미지 재구성
    • PEB.ImageBaseAddress / RTL_USER_PROCESS_PARAMETERS 불일치
    • SetThreadContext 기반 Thread PC register 재배치
    • Import Table 재배치 또는 동적 API 해석 루틴 삽입
    • 스택 프레임/호출 규약이 정상 프로세스와 불일치

    이러한 패턴들은 메모리 포렌식에서 명확한 지표(IOC) 를 생성한다.


    2. 초기 Stub 코드 패턴 (무해화된 예시)

    프로세스 생성 및 Unmap 루틴의 대표적인 패턴은 다음과 같다:

    // 패턴
    BOOL Demo_ProcessHollowingStub(LPCSTR hostPath, LPVOID payloadBase, DWORD payloadSize) {
        STARTUPINFOA si = {0};
        PROCESS_INFORMATION pi = {0};
        si.cb = sizeof(si);
    
        // 1) Suspended 상태로 정상 프로세스 생성
        if (!CreateProcessA(hostPath, NULL, NULL, NULL, FALSE,
            CREATE_SUSPENDED, NULL, NULL, &si, &pi))
            return FALSE;
    
        // 2) Target 프로세스 ImageBase 조회 (PEB 읽기)
        CONTEXT ctx;
        ZeroMemory(&ctx, sizeof(ctx));
        ctx.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
    
        if (!GetThreadContext(pi.hThread, &ctx))
            return FALSE;
    
        // 3) PEB 구조에서 ImageBaseAddress 획득 (패턴 단순화)
        DWORD pebAddr = (DWORD)ctx.Ebx;       // 32bit PEB 포인터
        DWORD imageBase = 0;
        ReadProcessMemory(pi.hProcess, (LPCVOID)(pebAddr + 0x08), &imageBase, sizeof(DWORD), NULL);
    
        // 4) 원본 이미지 제거
        NtUnmapViewOfSection(pi.hProcess, (PVOID)imageBase);
    
        // 5) 공격자 Payload를 대상 프로세스 메모리에 매핑
        LPVOID remoteBase = VirtualAllocEx(pi.hProcess, (LPVOID)imageBase,
                                           payloadSize, MEM_COMMIT | MEM_RESERVE,
                                           PAGE_EXECUTE_READWRITE);
    
        // (이하: 무해화 처리된 흐름 — 실제 PE Rebuild/ImportFix 없음)
        WriteProcessMemory(pi.hProcess, remoteBase, payloadBase, payloadSize, NULL);
    
        return TRUE;
    }
    

    관찰 포인트

    • EBX 레지스터 사용 → x86에서 PEB 포인터
    • Remote 프로세스의 ImageBase를 제거함으로써
      정상 PE 구조가 사라지고 “Unbacked Private Memory”만 존재
    • RWX 메모리 영역 증가

    3. Thread Context 재설정 (RIP/EIP Rebase)

    Image Overwrite 이후에는 새 이미지의 EntryPoint로 제어 흐름을 재설정한다.
    공격자 코드는 이를 위해 EIP/RIP 수정을 수행한다.

    예제 코드

    // 패턴
    BOOL Demo_RebaseThreadContext(HANDLE hThread, DWORD newEntry) {
        CONTEXT ctx;
        ZeroMemory(&ctx, sizeof(ctx));
        ctx.ContextFlags = CONTEXT_CONTROL;
    
        if (!GetThreadContext(hThread, &ctx))
            return FALSE;
    
        ctx.Eip = newEntry;    // x86 기준
        return SetThreadContext(hThread, &ctx);
    }
    

    4. Assembly 관점 — Hollowing Stub의 전형적인 흐름

    다음은 프로세스 언매핑 및 EntryPoint 재배치를 수행하는
    “교육용 패턴화”된 디스어셈블리다:

    ; --- PEB에서 ImageBase 추출 ---
    mov     eax, [ebx+08h]            ; PEB.ImageBaseAddress
    push    eax
    push    [edi]                     ; hProcess
    call    dword ptr [NtUnmapViewOfSection]
    
    ; --- 새 Payload 매핑 ---
    push    PAGE_EXECUTE_READWRITE
    push    MEM_COMMIT
    push    payload_size
    push    eax                       ; desired base (기존 ImageBase)
    push    hProcess
    call    dword ptr [VirtualAllocEx]
    
    ; --- EntryPoint 재설정 ---
    mov     ecx, new_entry
    mov     [ctx+0B8h], ecx           ; CONTEXT.Eip 수정
    push    ctx
    push    hThread
    call    dword ptr [SetThreadContext]
    

    5. 레지스터·메모리·스택 변화 상세 분석

    시점레지스터 / 메모리 상태의미
    스레드 생성 직후EIP = 정상 EntryPoint, EBX = PEB정상 프로세스 초기 상태
    NtUnmapViewOfSection 후ImageBase 메모리 UnmappedPE Header/Sections 제거됨
    VirtualAllocEx 이후RemoteBase = Private Memory공격자 이미지가 위치할 공간 확보
    WriteProcessMemory 후Private Memory에 새 이미지 반영PE 전체가 디스크 없이 메모리 상 재구성
    SetThreadContext 후EIP = 새 EntryPoint정상 실행 흐름 완전 대체

    6. PE 구조 관점의 무결성 파괴

    리버싱 핵심원리 기준으로 보면 Process Hollowing은 PE 구조의
    다음 요소들이 비정상적으로 변형된다:

    (1) PEB.ImageBaseAddress 값과 실제 매핑 주소 불일치

    • 진짜 매핑된 이미지가 Private Memory로 바뀌었으나
      PEB는 갱신되지 않거나 부분적으로만 반영됨

    (2) Section Alignment 및 Header 구조 붕괴

    • 디스크 기반 백업 없음
    • .text, .rdata 경계와 실제 메모리 경계 불일치

    (3) Import Table 재배치 및 AddressOfFunctions 파편화

    • IAT 재해석 루틴 또는 동적 API 로더가 등장하는 경우 많음

    7. 동적 API 호출 및 Anti-Analysis 결합 패턴

    Process Hollowing과 결합되는 고전적 로더 패턴들:

    • API 해시 기반 Resolver
    • Kernel32 LoadLibrary/GetProcAddress Stub 삽입
    • TEB/PEB 직접 참조로 Anti-Hook 우회
    • Inline Anti-Debugging(NtQueryInformationProcess)
    • RDTSC / QueryPerformanceCounter 기반 Timing Check
    • IsDebuggerPresent 플래그 조작

    이들은 모두 Hollowing 단계 직후 등장하기 쉬운
    Payload 초기화 루틴의 공통 특징이다.


    8. 메모리 포렌식에서의 IOC

    Process Hollowing은 다음 IOC를 거의 항상 남긴다:

    (1) Private Memory에 PE Header 특유의 “MZ / PE” 시그니처 존재

    (2) 메모리맵에서 동일 주소대역이 “Unbacked” 상태로 표시

    (3) Module 리스트(PEB Loader Entries)와 실행중 EntryPoint의 불일치

    (4) RWX 메모리 증가 + Image 타입 섹션 사라짐

    (5) Call Stack Reconstruction 실패 (Return Address가 모듈 내부가 아님)


    9. 결론

    Process Hollowing은 사용자 공간 프로세스 구조(PEB, VAD, Section Mapping)를 직접 변형해
    정상 실행 흐름을 완전히 대체하는 공격 기법이다.

    그러나 PE 구조/메모리 보호 속성/Thread Context/스택 프레임 관찰을 기반으로
    꾸준히 정형화된 TTP를 보여주기 때문에
    디지털 포렌식·Incident Response 환경에서 충분히 탐지 가능하다.


    📍 Written by Code & Compass

  • SetThreadContext 기반 Thread Execution Hijacking 분석 — 프로세스 메모리 변조 및 비정상 흐름 전이 관점 정리

    본 내용은 SetThreadContext() API 호출을 이용한 Thread Execution Hijacking(스레드 실행 흐름 탈취) 기법을
    실제 악성코드가 활용하는 형태와 유사한 분석 관찰 패턴 중심으로 정리한 기록이다.

    Thread Context 조작 기반 기법은 다음과 같은 목적에서 공격자가 활용하는 것으로 알려져 있다:

    • 정상 스레드의 Instruction Pointer(EIP/RIP)를 임의 주소로 강제 이동
    • 언패킹 루틴 또는 메모리 상에 로드된 Payload로 흐름 전환
    • 정적 분석 우회(IAT 우회 + Entry Point 비가시화)
    • 샌드박스 탐지 회피
    • Suspended Injection / Process Hollowing 초기 단계 구성

    리버싱 기록


    1. 기술 개요: Thread Context Hijacking의 주요 특징

    Thread Execution Hijacking은 공격자가 GetThreadContext()로 대상 스레드의 레지스터 상태를 가져온 뒤,
    SetThreadContext()로 EIP/RIP를 프로세스 이미지 영역 밖(Private Memory) 또는 언패킹된 메모리 블록으로 변경하는 방식이다.

    다음과 같은 Indicator가 주요 특징으로 관찰된다:

    • 스레드가 Resume 직후 정상 모듈 경계를 벗어난 주소로 분기
    • 프로세스 메모리 레이아웃에서 RWX 메모리 구간 실행
    • 호출 규약(Calling Convention)과 불일치하는 스택 프레임
    • Hollowing/Injection 전형적 패턴과 결합

    2. Thread Context 구조 요소 (분석용 단순화 버전)

    아래 구조는 실제 Windows CONTEXT 구조에서 분석 상 필요한 요소만 발췌한 단순화 버전이다.

    typedef struct _DUMMY_CONTEXT {
        DWORD Eip;
        DWORD Esp;
        DWORD Ebp;
        DWORD Eax;
        DWORD Ebx;
        DWORD Ecx;
        DWORD Edx;
        // ...
    } DUMMY_CONTEXT;
    

    실제 환경에서는 CONTEXT_CONTROL, CONTEXT_INTEGER, CONTEXT_FULL
    ContextFlags 설정에 따라 캡처되는 필드가 달라진다.


    3. Thread Context 변조 패턴 (샘플 예제)

    아래 C 코드는 Thread Context 조작 패턴을 재현한 샘플 예시다.

    // 분석용 패턴 (악성 행위 제거)
    BOOL Demo_ModifyThreadContext(HANDLE hThread, LPVOID newEntryPoint) {
        CONTEXT ctx;
        ZeroMemory(&ctx, sizeof(ctx));
        ctx.ContextFlags = CONTEXT_CONTROL; // 제어 레지스터만 취급
    
        if (!GetThreadContext(hThread, &ctx))
            return FALSE;
    
        // --- 비정상 흐름 전이 패턴 ---
        // 실제 공격에서는 RWX 메모리 또는 언패킹된 payload 주소로 설정됨
        ctx.Eip = (DWORD)newEntryPoint;
    
        if (!SetThreadContext(hThread, &ctx))
            return FALSE;
    
        return TRUE;
    }
    

    실전 포렌식 분석 관찰 포인트

    • EIP/RIP가 PE 헤더에서 정의된 .text 섹션 경계를 벗어나는지
    • 해당 주소의 메모리 보호 속성(PAGE_EXECUTE_READWRITE)
    • 스택 포인터(ESP)와 이전 호출 스택 관계가 정상적인 호출 규약과 일치하는지
    • Suspended 상태로 생성된 스레드인지 여부

    4. Assembly 관점의 Context Hijacking 패턴

    샘플 코드는 다음과 같은 패턴을 가진다:

    mov     eax, [esp+4]        ; eax = CONTEXT*
    mov     ecx, [esp+8]        ; ecx = newEntryPoint
    
    ; CONTEXT.Eip 필드 오프셋에 임의 주소 저장
    mov     [eax+0B8h], ecx     ; (비정상 EIP 삽입)
    
    push    eax
    push    [ebp+08h]           ; hThread
    call    dword ptr [SetThreadContext]
    

    레지스터 동작 분석

    레지스터내용
    eaxCONTEXT 구조체 베이스
    ecx공격자가 삽입한 분기 대상 주소
    [eax+0xB8]EIP 저장 위치 (32bit 기준)
    ResumeThread 이후EIP = newEntryPoint

    5. PE 구조 관점에서 비정상 흐름 탐지

    PE 구조 기반 분석을 적용하면,
    Thread Hijacking은 다음과 같은 탐지 포인트가 형성된다.

    (1) EIP/RIP address validation

    • Target address가 PE ImageBase ~ ImageSize 범위인지 확인
    • .text 또는 .rdata 등 실행 가능한 섹션인지 판별

    (2) Memory Protection 확인

    • VirtualQuery 기반 탐지
    • 공격자 주소가 MEM_COMMIT + PAGE_EXECUTE_READWRITE 조합이면 위험도 상승

    (3) Hollowing/Injection 시그니처

    • 프로세스 Import Table 초기화 전에 EIP 이동
    • 신생 스레드의 StartAddress와 EIP가 서로 불일치

    6. 스택 프레임 무결성 검증

    Thread Context Hijacking은 스택 상태를 고려하지 않고 EIP만 변조하기 때문에,
    다음과 같은 ABI(Call Convention) 무결성 위반이 자주 관찰된다.

    비정상 스택 패턴(분석 예시)

    push 0x11223344     ; Return Address (정상 호출 흐름)
    ; ...
    ; EIP 변경 후 스택이 기존 호출 체인을 반영하지 않음
    

    포렌식에서 다음 검증이 중요하다:

    • EBP → saved EBP 체인이 끊겨 있는지
    • Return Address가 이미지 내부 진입점이 아닌지
    • 스택 상에서 함수 prologue 패턴(push ebp / mov ebp, esp)이 없거나 변형되어 있는지

    7. 동적 API 호출(Dynamic API Resolution)과의 결합 사례

    Thread Hijacking은 종종 다음과 같은 구성 요소와 함께 발견된다:

    • 해시 기반 동적 API 호출 기법
    • RWX 메모리 생성 (VirtualAlloc, NtAllocateVirtualMemory)
    • WriteProcessMemory 기반 Mapping
    • Shellcode Loader 스텁
    • PE-less Injection (Reflective Loader 패턴)

    분석관점 TTP 매핑 (MITRE ATT&CK)

    • T1055 Process Injection
    • T1055.003 Thread Execution Hijacking
    • T1027 Obfuscated/Encrypted Payloads
    • T1106 Native API 호출

    8. 메모리 포렌식에서 확인 가능한 아티팩트

    (1) Thread StartAddress vs EIP 불일치

    • CreateRemoteThreadEx / NtCreateThreadEx 흔적
    • ResumeThread 직후 EIP가 Private Memory에 존재

    (2) RWX Memory Region

    • 정상 프로세스에 거의 나타나지 않는 보호 속성
    • PE Image 섹션과 무관한 주소대역

    (3) 비정상 호출체인

    • Call Stack reconstruction 실패
    • Return Address가 모듈·DLL 구역 외부

    9. 결론

    SetThreadContext 기반 Thread Execution Hijacking은
    공격자가 제어 흐름을 프로세스 이미지 외부로 강제 전환하는 대표적 프로세스 변조 기법이다.
    그러나 PE 구조, 메모리 보호 속성, 스택 프레임 무결성, API 호출 시퀀스 등
    기본적인 분석 절차를 적용하면 의미 있는 탐지가 가능하다.

    이 문서는 샘플 패턴만 포함된 분석용 기록으로,
    실제 악성코드 분석·포렌식 교육 목적에서 참고할 수 있다.


    📍 Written by Code & Compass

  • Windows Shellcode의 해시 기반 동적 API 호출 기법

    이번 글은 실제 악성코드에서 가장 빈번하게 사용되는
    해시 기반 동적 API 호출 기법(Hash-Based Dynamic API Invocation Technique)을 정리함.

    이 기법은 다음 목적을 위해 활용된다:

    • IAT 없이 API 호출 — 정적 분석 회피
    • API 이름 문자열 제거 — 시그니처 탐지 우회
    • 쉘코드·패커·언패킹 루틴 등에서 환경 독립적 호출 구조 확보
    • 샌드박스·에뮬레이터 우회

    리버싱 기록


    1. 개요 — 왜 “해시 기반 동적 API 호출 기법”인가?

    일반 PE는 Import Table(IAT)을 통해 필요한 API를 정적으로 가져오지만,
    악성코드 및 Shellcode는 다음 이유로 IAT를 회피하여 해시 기반 호출을 사용한다.

    • 악성코드 분석 시 IAT만 보면 기능이 그대로 드러남
    • Shellcode는 PE 구조가 아니라서 IAT 자체가 존재하지 않음
    • 패킹된 샘플은 언패킹 전까지 API 주소를 알 수 없음
    • API 이름 문자열을 제거해 탐지 난이도를 높임

    → 따라서 API 이름을 해시값만으로 저장하고,
    실행 시 PEB → 모듈 → Export Table 순회로 API 주소를 직접 계산해 호출한다.

    이를 전체적으로 “해시 기반 동적 API 호출 기법”이라 부른다.


    2. PEB 기반 모듈 검색: 호출 기법의 첫 단계

    이 기법의 구조적 시작점은 항상 PEB(Process Environment Block) 이다.
    Shellcode는 보통 다음 순서로 모듈 위치를 찾는다.

    1. FS:[0x30] → PEB
    2. PEB->Ldr
    3. LDR_DATA_TABLE_ENTRY 리스트 순회
    4. kernel32.dll, ntdll.dll 등 모듈 이름 해시 비교
    5. 일치 시 Export Table 탐색 시작

    C 의사코드

    PPEB get_peb() {
        return (PPEB)__readfsdword(0x30);
    }
    

    어셈블리

    mov eax, fs:[0x30]   ; eax = PEB
    

    3. 해시 기반 동적 API 호출 기법의 핵심 구조

    해시 기반 호출은 다음 세 가지 루틴으로 구성된다.

    1. 문자열 해시 계산 루틴
    2. Export Table 순회 & 해시 비교 루틴
    3. 함수 주소 계산 & 호출

    다음은 1~3 항목에 대한 내용이다.


    4. 문자열 해시 계산 루틴

    가장 흔한 구현은 djb2 변형, ROR/ROL 기반, XOR 기반 해시다.

    C 의사코드

    DWORD hash_string_ansi(const char* s) {
        DWORD h = 0;
        while (*s) {
            char c = *s++;
            if (c >= 'a' && c <= 'z')
                c -= 0x20;  // uppercase
            h = ((h << 5) + h) + c;  // djb2 변형
        }
        return h;
    }
    

    어셈블리

    push ebp
    mov  ebp, esp
    push ebx
    
    xor  eax, eax
    mov  edx, [ebp+8]   ; s
    
    hash_loop:
    mov  bl, [edx]
    cmp  bl, 0
    je   hash_done
    
    ; lowercase → uppercase
    cmp  bl, 'a'
    jl   skip
    cmp  bl, 'z'
    jg   skip
    sub  bl, 0x20
    skip:
    
    inc  edx
    mov  ecx, eax
    shl  eax, 5
    add  eax, ecx
    add  eax, ebx
    
    jmp  hash_loop
    
    hash_done:
    pop  ebx
    pop  ebp
    ret  4
    

    5. Export Table 순회 및 해시 기반 함수 검색

    해시 기반 호출 기법의 핵심은
    API 이름 문자열 없이 해당 API 주소를 Export Table에서 직접 찾는 것이다.

    C 의사코드

    FARPROC resolve_function_by_hash(HMODULE mod, DWORD target_hash) {
        IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)mod;
        IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)((BYTE*)mod + dos->e_lfanew);
    
        DWORD expRVA = nt->OptionalHeader
            .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
        IMAGE_EXPORT_DIRECTORY* exp =
            (IMAGE_EXPORT_DIRECTORY*)((BYTE*)mod + expRVA);
    
        DWORD* names  = (DWORD*)((BYTE*)mod + exp->AddressOfNames);
        WORD*  ords   = (WORD*)((BYTE*)mod + exp->AddressOfNameOrdinals);
        DWORD* funcs  = (DWORD*)((BYTE*)mod + exp->AddressOfFunctions);
    
        for (DWORD i = 0; i < exp->NumberOfNames; i++) {
            const char* nm = (const char*)mod + names[i];
            if (hash_string_ansi(nm) == target_hash) {
                WORD o = ords[i];
                DWORD r = funcs[o];
                return (FARPROC)((BYTE*)mod + r);
            }
        }
        return NULL;
    }
    

    어셈블리 패턴

    mov  eax, [esi+3Ch]   ; e_lfanew
    add  eax, esi         ; NT Headers
    mov  ecx, [eax+78h]   ; Export Directory RVA
    add  ecx, esi         ; pExport
    
    mov  edx, [ecx+20h]   ; AddressOfNames RVA
    add  edx, esi         ; pNames
    

    이 구조는 거의 모든 악성 Shellcode/패커/드로퍼에서 동일한 패턴을 보인다.


    6. 해시 기반 동적 API 호출의 실제 호출 방식

    함수 주소를 획득한 뒤, Shellcode는 다음 방식으로 바로 호출한다.

    C 의사코드

    typedef LPVOID (WINAPI *pVirtualAlloc)(LPVOID, SIZE_T, DWORD, DWORD);
    
    pVirtualAlloc va = (pVirtualAlloc)resolve_function_by_hash(k32, HASH_VIRTUALALLOC);
    LPVOID mem = va(NULL, 0x2000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    

    어셈블리 패턴

    push 40h          ; PAGE_EXECUTE_READWRITE
    push 1000h        ; MEM_COMMIT
    push 2000h        ; size
    push 0            ; lpAddress
    call eax          ; eax = VirtualAlloc resolved address
    

    7. 악성코드에서 해시 기반 호출을 사용하는 이유

    목적설명
    정적 분석 회피Import Table을 비워두어 분석 난도 증가
    문자열 제거함수 이름을 문자열 대신 해시값으로 보관
    패커/언패커 최적화새 환경에서도 API 주소 자동 획득
    샌드박스 우회일부 자동화 엔진은 해시 기반 호출을 트래킹하지 못함
    쉘코드 호환성PE가 아니어도 API 호출 가능

    결과적으로 탐지 난이도가 높고, 분석자가 직접 흐름을 추적해야 한다.


    8. 해시 기반 호출 기법에서 흔히 보이는 부가 기능

    8.1 안티디버깅

    mov eax, fs:[0x30]
    mov al, [eax+2]
    test al, al
    jnz  debugger_present
    

    8.2 언패킹 전용 메모리 조작

    xor_loop:
    xor [edi], al
    inc edi
    dec ecx
    jnz xor_loop
    

    8.3 API 해시 테이블 존재

    데이터 섹션에 다음처럼 나열된 DWORD가 보이면 의심:

    EC0E4E8E
    7C0DFCAA
    5D1A902B
    1A2B3C4D
    

    9. 리버싱 관점의 분석 전략

    1. 해시 루틴 먼저 찾기
      • 문자열을 한 글자씩 읽는 루프가 핵심 시그니처
    2. Export Table 접근 코드 식별
      • e_lfanew, 78h, AddressOfNames 등 고정 오프셋 활용
    3. 해시값 목록 수집 → 실제 API 매핑
    4. 해시 기반 호출이 있는 경우 → Shellcode/Packer 1단계 의심
    5. PEB 접근 패턴이 보이면 → 동적 로딩 루틴 확률 ↑

    10. 결론

    해시 기반 동적 API 호출 기법은 악성코드에서 가장 널리 사용되는 스텔스 호출 방식이다.
    IAT를 제거하고 Export Table에서 직접 API를 계산하여 호출하기 때문에
    정적 분석·샌드박스·시그니처 기반 탐지를 어렵게 만든다.

    이 글에서 다룬 분석 절차(PEB 구조, Export Table, 디스어셈블리 패턴 추적)를
    기본 틀로 익혀두면, 대부분의 Shellcode/패커 초기 스텁을 빠르게 해석할 수 있다.


    📍 Written by Code & Compass

  • 🧩 Windows Thread Hiding 기반 스텔스형 인젝션

    이번 내용은 스텔스 인젝션 기법 중 비교적 고급 형태인
    “Thread Hiding + APC 기반 코드 실행 흐름 감추기” 패턴을 분석한 내용임.

    리버싱 기록


    1. 개요 — Thread Hiding 기법 개념

    일부 샘플은 기본적인 CreateRemoteThread 사용을 피하고,
    이미 존재하는 타깃 프로세스의 스레드에
    **APC(Asynchronous Procedure Call)**를 큐잉하거나
    Thread State를 Suspended → Running으로 미세 조작하여
    코드 실행 흐름을 감춘다.

    핵심 목표:

    • 스레드 시작 주소(Start Address)로 드러나는 인젝션 흔적 최소화
    • 디버거·EDR의 스레드 생성 이벤트 탐지 회피
    • APC 스케줄 타이밍을 이용해 호출 스택을 은폐

    2. 개념적 인젝션 흐름도

    [1] 타깃 프로세스 열기
        ↓
    [2] 메모리 공간 확보(VirtualAllocEx)
        ↓
    [3] Payload 쓰기
        ↓
    [4] 타깃의 기존 스레드 핸들 획득(Thread32First/Next)
        ↓
    [5] APC 큐잉(QueueUserAPC)
        ↓
    [6] 스레드가 Alertable 상태로 진입할 때 실행
    

    3. PE 구조 및 API 동적 해석(Export Directory 스캔 기반)

    악성코드는 보통 API 문자열을 직접 포함하지 않는다.
    다음은 C로 작성된 예시로, Export Table을 순회하여
    함수 해시를 비교해 주소를 찾는 루틴의 형태를 보여준다.

    // 예시 — Export 스캔 기반 동적 API 검색
    void* ResolveAPI(void* moduleBase, unsigned int targetHash) {
        IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)moduleBase;
        IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)((BYTE*)moduleBase + dos->e_lfanew);
    
        IMAGE_EXPORT_DIRECTORY* exp = 
            (IMAGE_EXPORT_DIRECTORY*)((BYTE*)moduleBase +
            nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    
        DWORD* nameRVA = (DWORD*)((BYTE*)moduleBase + exp->AddressOfNames);
        WORD* ordinal = (WORD*)((BYTE*)moduleBase + exp->AddressOfNameOrdinals);
        DWORD* funcRVA = (DWORD*)((BYTE*)moduleBase + exp->AddressOfFunctions);
    
        for (DWORD i = 0; i < exp->NumberOfNames; i++) {
            char* name = (char*)moduleBase + nameRVA[i];
            unsigned int h = HashFunctionConcept(name);   // 해시
            if (h == targetHash) {
                void* fn = (BYTE*)moduleBase + funcRVA[ordinal[i]];
                return fn;
            }
        }
        return NULL;
    }
    

    4. APC 기반 코드 실행 디스어셈블리 패턴 분석

    다음은 APC를 통해 실행되는 함수의
    x86 디스어셈블리 분석.

    ; 예시 — APC로 호출된 함수의 프롤로그 패턴
    APC_PAYLOAD:
        push ebp
        mov  ebp, esp
        sub  esp, 0x20              ; 로컬 버퍼 확보
    
        mov  eax, [ebp+0x08]        ; APC 전달 파라미터
        xor  ecx, ecx               ; 레지스터 초기화
        mov  [ebp-0x04], eax        ; Stack frame 내부에 저장
    
        ; --- 메모리 조작 또는 스텔스 로직 (개념) ---
        ; 예: 특정 메모리 페이지의 플래그 확인
        mov  edx, [eax]             ; (메모리 참조)
        test edx, edx
        jz   SHORT .exit_path
    
        ; 추가 연산 또는 분기
        add  edx, 0x10
        mov  [ebp-0x08], edx
    
    .exit_path:
        mov  esp, ebp
        pop  ebp
        ret  4
    

    ▶ 스택 프레임 구성 해석

    위치설명
    [ebp+8]APC 함수의 첫 번째 파라미터
    [ebp-4]임시 저장용 로컬 변수
    [ebp-8]분기 계산용 로컬 버퍼

    ▶ 제어 흐름 분석 포인트

    • jz SHORT .exit_path조건부로 스텔스 로직을 건너뛰어 분석을 방해할 수 있음
    • 분석 시 조건을 역방향으로 추적해 실제 실행 경로를 확인해야 함
    • EAX/EDX의 실제 사용 패턴이 payload 성격을 결정

    5. Anti-Debugging 연계 패턴

    APC 기반 인젝션은 종종 디버거 탐지와 함께 사용된다.

    x86 코드:

    mov eax, fs:[0x30]           ; PEB
    mov al,  [eax+0x02]          ; BeingDebugged
    test al, al
    jnz  SHORT DEBUG_EXIT        ; 디버거 있으면 다른 경로
    
    ; 타이밍 체크 기반 안티 디버깅
    rdtsc
    mov ebx, eax
    rdtsc
    sub eax, ebx
    cmp eax, 0x00001000          ; 임계값 기준
    jg SHORT DEBUG_EXIT
    
    ; 정상이면 계속
    jmp CONTINUE_EXECUTION
    

    특징

    • PEB 플래그 확인
    • RDTSC 사이클 차이로 single-step, breakpoints, VM 속도 저하 감지
    • APC 페이로드가 디버거 우회 경로로만 실행되도록 조건 분기 구성 가능

    6. Thread Hiding 구현 개념

    아래는 C 언어 예시이다.

    // 개념 예시 — Thread Hide
    void HideThreadContext(HANDLE hThread) {
    
        // 1) 스레드 컨텍스트 가져오기
        CONTEXT ctx = {0};
        ctx.ContextFlags = CONTEXT_FULL;
        GetThreadContext(hThread, &ctx);
    
        // 2) 스택 포인터 및 명령 포인터 조정(개념적)
        ctx.Esp -= 0x200;      // 새로운 스택 영역
        ctx.Eip = (DWORD)APC_PAYLOAD;  // 페이로드 엔트리
    
        // 3) 조작된 컨텍스트 반영
        SetThreadContext(hThread, &ctx);
    }
    

    이 과정이 실제로는 다음과 같은 점에서 탐지 회피에 기여한다:

    • 스레드 시작 주소(Start Address)와 실행 위치가 불일치
    • 스택 프레임이 정상 API 호출 스택 형태를 갖추지 않음
    • 스레드가 Alertable 상태 전환 시에만 비정상 코드가 실행됨

    7. Call Stack 흐름 분석 기법

    APC 기반 페이로드는 Call Stack이 다음처럼 구성된다:

    [ ReturnAddress to ntdll!KiUserApcDispatcher ]
    [ APC_PAYLOAD arguments ]
    [ ... local stack frame ... ]
    

    분석 포인트:

    1. ReturnAddress가 항상 KiUserApcDispatcher 근처
    2. 정상 스레드의 Call Stack 패턴과 불일치
    3. 페이로드 진입 전에 호출 규약이 명확하지 않아
      stdcall/cdecl 구분이 모호한 형태로 나타남
    4. 스택 복구(mov esp, ebp; pop ebp)가 제대로 맞지 않으면
      다른 APC와 충돌 위험

    8. 암호화된 페이로드 복원(개념)

    대부분의 APC 페이로드는 압축·암호화되어 있으며,
    복원 루틴은 다음과 같은 패턴을 갖는다.

    // 예시
    void DecryptConcept(BYTE* buf, size_t len, BYTE key) {
        for (size_t i = 0; i < len; i++) {
            buf[i] ^= key;         // 단순 XOR 개념
            buf[i] = rol(buf[i], 3); // ROL 기반 변형
        }
    }
    

    디스어셈블리 특징:

    movzx eax, byte ptr [ecx]
    xor   al, dl
    rol   al, 3
    mov   [ecx], al
    inc   ecx
    cmp   ecx, edi
    jb    SHORT LOOP
    

    ✨ 마무리 한 줄

    APC 기반 스레드 하이딩은 “스레드 생성 이벤트 없이 코드 실행 흐름을 전환하는” 특성 덕분에
    정적·동적 분석 모두에서 탐지 난도가 높다.
    분석가는 스레드 컨텍스트, 콜스택 패턴, Export 기반 API 해석 루틴을
    정밀하게 추적해야 전체 흐름을 복원할 수 있다.


    📍 Written by Code & Compass

  • 📘 Process Hollowing 기반 프로세스 인젝션

    Windows Process Hollowing의 내부 제어 흐름 및 스택/레지스터 변화 분석

    악성코드에서 광범위하게 사용되는 Process Hollowing의 내부 동작을 리버싱 관점에서 단계별로 분석함.

    리버싱 기록


    1. Process Hollowing 개요

    Process Hollowing은 다음과 같은 고전적 인젝션 절차를 따름:

    1. 정상 프로세스를 Suspended 상태로 생성
    2. 생성된 프로세스의 메모리 영역(Unmap Section) 비우기
    3. 악성 페이로드의 PE 헤더 및 섹션을 새 주소 공간에 수동 매핑
    4. 프로세스 스레드 컨텍스트(EIP/RIP) 를 새로운 Entry Point로 변경
    5. 스레드 재개

    이 방식의 장점:

    • 외부에서 보면 정상 프로세스 이름을 유지
    • IAT 후킹·DLL Injection보다 탐지 지점이 적음
    • 이미지 경로/명령줄/서명 모두 정상으로 보임

    2. Suspended 프로세스 생성 (C)

    // 비실행 개념 코드 — Suspended Process 생성
    STARTUPINFOA si = {0};
    PROCESS_INFORMATION pi = {0};
    
    CreateProcessA(
        "C:\\Windows\\System32\\notepad.exe",
        NULL,
        NULL,
        NULL,
        FALSE,
        CREATE_SUSPENDED,
        NULL,
        NULL,
        &si,
        &pi
    );
    

    분석 포인트:

    • CREATE_SUSPENDED 플래그로 새 스레드가 실행되기 전에 컨텍스트를 추출 가능
    • pi.hThread → CONTEXT 구조 확인
    • 악성코드는 이후 GetThreadContext로 레지스터 값을 읽어 진입점 조작에 사용

    3. 원본 이미지 제거(Unmap) Assembly 예시

    실제 샘플은 NtUnmapViewOfSection을 동적 API 획득으로 호출하는 경우가 많음.

    ; 호출 전: EAX → 함수 주소, ECX/EDX → 파라미터
    ; 예시
    push    processHandle
    push    baseAddress
    call    eax                     ; eax = NtUnmapViewOfSection
    
    ; 반환값 확인
    test    eax, eax
    jnz     UNMAP_FAILED
    

    레지스터 흐름 관찰 포인트:

    • call eax 패턴은 동적 API 해석 루틴이 성공적으로 주소를 찾은 뒤 사용
    • baseAddress는 PEB의 ImageBaseAddress 또는 컨텍스트 Ebx/ Rdx 등에서 획득

    4. 악성 이미지 매핑 — 수동 PE 로딩(C)

    아래 코드는 구조 설명을 위해 단순화한 예시.

    // 개념적 매핑 구조
    LPVOID remoteBase = VirtualAllocEx(
        pi.hProcess,
        (LPVOID)payloadImageBase,
        payloadSize,
        MEM_COMMIT | MEM_RESERVE,
        PAGE_EXECUTE_READWRITE
    );
    
    // PE Header 복사
    WriteProcessMemory(
        pi.hProcess,
        remoteBase,
        payloadBuffer,
        payloadHeadersSize,
        NULL
    );
    
    // Section 루프 복사
    for (int i=0; i<sectionCount; i++) {
        WriteProcessMemory(
            pi.hProcess,
            (LPVOID)((SIZE_T)remoteBase + section[i].VirtualAddress),
            payloadBuffer + section[i].PointerToRawData,
            section[i].SizeOfRawData,
            NULL
        );
    }
    

    분석 관점:

    • 인젝션 페이로드가 “file-backed image”가 아닌 “memory-backed image”이므로
      모듈 리스트에 표시되지 않아 탐지가 어려움
    • PE 구조 파싱(이미지베이스, 섹션 RVA, 정렬 값)이 정확히 일치해야 정상 작동

    5. 진입점(EIP/RIP) 재설정 — CONTEXT 변조

    // 비실행 예시 — Entry Point 변경
    CONTEXT ctx;
    ctx.ContextFlags = CONTEXT_FULL;
    
    GetThreadContext(pi.hThread, &ctx);
    
    // x86
    ctx.Eip = (DWORD)((SIZE_T)remoteBase + payloadEntryRVA);
    
    // x64
    // ctx.Rip = ...
    
    SetThreadContext(pi.hThread, &ctx);
    

    레지스터 변화 관찰:

    • GetThreadContext 후 EIP/RIP 값은 원래 notepad.exe의 Entry Point
    • 악성코드가 이 값을 새로운 PE Entry Address로 변경
    • 이후 ResumeThread로 실행되는 스레드는 완전히 다른 코드 흐름 수행

    6. Shellcode Pre-Staging 패턴(Assembly)

    일부 악성코드는 신뢰도 향상을 위해 Entry Point에 Shellcode Stub을 두고
    그 Stub 안에서 추가 환경 체크 및 Anti-Debug 수행 후 메인 페이로드로 점프함.

    ; 비실행 예시 — Shellcode Stub
    SHELL_STUB:
        pushad
        pushfd
    
        mov     eax, fs:[0x30]          ; PEB
        mov     al, [eax+0x02]          ; BeingDebugged
        test    al, al
        jnz     DEBUG_PATH
    
        ; 간단한 XOR 복호화 루틴
        mov     esi, [encryptedPayload]
        mov     ecx, payloadSize
    XOR_LOOP:
        xor     byte ptr [esi], 0x5A
        inc     esi
        loop    XOR_LOOP
    
        popfd
        popad
        jmp     DECRYPTED_ENTRY
    

    요점:

    • Shellcode는 매우 작은 공간에서 환경 체크 + 복호화 + 점프까지 처리
    • PEB BeingDebugged 플래그 확인 → 악성코드의 고전적 anti-debug 루틴
    • XOR decrypt 루프는 스택/레지스터 조작 없이 간단하게 구현되는 패턴

    7. “Hollowing Signature” 탐지 체크리스트

    실제 Process Hollowing을 판별하는 주요 지표는 다음과 같음.

    구분탐지 지표
    프로세스 구조Suspended 상태에서 시작됨
    메모리 매핑ImageBaseAddress가 원본과 불일치
    섹션 검사PE 섹션이 파일과 메모리에서 다르게 나타남
    쓰기 패턴큰 연속 WriteProcessMemory 호출 흔적
    스레드 컨텍스트Entry Point 레지스터(EIP/RIP)가 정상 이미지 범위 외부
    모듈 리스트로드된 이미지가 정상 EXE지만 내부 코드는 다른 바이너리

    8. 제어 흐름 요약 (전체 플로우)

    1. CreateProcessA(..., CREATE_SUSPENDED)
    2. GetThreadContext → EIP/RIP 추출
    3. NtUnmapViewOfSection로 원본 이미지 제거
    4. VirtualAllocEx로 새로운 ImageBase 확보
    5. 헤더 및 섹션 수동 매핑 (PE 구조 기반)
    6. EntryPoint를 새 주소로 SetThreadContext
    7. ResumeThread로 실행 흐름 전환
    8. Shellcode Stub → Anti-debug → 복호화 → 메인 실행

    모든 단계를 통해 정상 프로세스가 완전히 다른 바이너리로 “속이 비워지고 교체”됨.


    ✨ 마무리 한 줄

    Process Hollowing은 “프로세스를 실행하지 않고 먼저 빌려온 뒤 내부를 완전히 교체하는 방식”이며,
    이 미세한 교체 과정 속 레지스터/메모리의 작은 변화를 읽어내는 능력이 핵심 역량으로 이어진다.


    📍 Written by Code & Compass

  • 📘 User-Mode Hooking Stub

    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

  • 📘 Windows Thread Hijacking 기반 프로세스 인젝션 분석 개요

    스레드 하이재킹(Thread Hijacking) 동작 원리 분석

    Windows 악성코드 분석 시 자주 관찰되는 기법 중 하나가 Thread Hijacking 기반 프로세스 인젝션임.
    이는 기존의 정지된 스레드를 일시적으로 중단한 뒤, 그 스레드 컨텍스트를 수정해 특정 페이로드를 실행시키는 구조로 동작.
    이번 분석은 《리버싱 핵심원리》의 흐름에 따라 스택 프레임, 제어 흐름, 레지스터 컨텍스트 변조,
    PE 구조 기반 페이로드 위치 산정, 동적 API 조회 등을 중심으로 기록식으로 정리함.

    리버싱 기록


    1. 개념적 C 스타일 구조(비실행·고위험 요소 제거)

    아래 코드는 일반적인 Thread Hijacking의 “구조”를 관찰 용도로만 반영한 예시.

    // 구조 예시
    typedef void* HTHREAD;
    typedef struct _CTX { unsigned long regs[8]; } CTX;
    
    void conceptual_thread_hijack(HTHREAD t, unsigned char* payloadBase) {
        CTX ctx = {0};
    
        // 1) 스레드 정지
        suspend_thread(t);
    
        // 2) 컨텍스트 조회
        get_thread_context(t, &ctx);
    
        // 3) 명령 포인터(EIP/RIP) 변경
        //    실제 주소 계산은 생략된 개념적 표현
        ctx.regs[0] = (unsigned long)(payloadBase);
    
        // 4) 수정된 컨텍스트 주입
        set_thread_context(t, &ctx);
    
        // 5) 스레드 재개
        resume_thread(t);
    }
    

    이 함수는 실제 실행이 불가능하도록 설계되었지만,
    실제 분석 시 “관찰 포인트”가 되는 흐름을 그대로 나타냄.


    2. Assembly 기반의 개념적 컨텍스트 변조 흐름(비실행)

    아래 코드는 일부 세부사항은 제거된 구조 예시.

    PSEUDO_HIJACK:
        push ebp
        mov  ebp, esp
    
        ; --- 스레드 일시 정지 ---
        ; (구체적 API 호출 생략)
    
        ; --- 컨텍스트 조회 ---
        ; 컨텍스트 구조체가 EAX에 저장된다고 가정
        mov  eax, [ebp-0x20]
    
        ; --- 명령 포인터 변경 ---
        ; 원래 EIP를 읽어온 뒤 페이로드 기점으로 가정한 값으로 치환
        mov  edx, [eax + CTX_EIP]      ; 원래 EIP
        mov  [eax + CTX_EIP], 0xDEADBEEF  ; 더미 주소
    
        ; --- 수정된 컨텍스트 쓰기 ---
        ; (구체적 API 호출 생략)
    
        leave
        ret
    

    이 흐름에서 중요한 건 다음입니다:

    • **컨텍스트(스레드 레지스터 집합)**는 구조체이며
      내부 필드에 EIP/RIP, ESP/RSP, EFLAGS, general-purpose register가 포함됨
    • 페이로드 실행을 위해 **명령 포인터(RIP/EIP)**가 수정됨
    • 해당 스레드가 재개되면 원래 코드가 아닌 새로운 주소로 흐름이 이동함
    • 이는 제어 흐름 교란(Control Flow Subversion)의 대표 패턴

    3. 제어 흐름 관찰 포인트

    Thread Hijacking 분석 시 포렌식·리버싱 관점에서 주로 확인하는 지점은 다음과 같음:

    1. SuspendThread / GetThreadContext / SetThreadContext / ResumeThread 호출 흔적
      • API 이름이 난독화되어 있을 수 있음
      • PE의 Import Table이 비어 있고, Export Directory 파싱으로 직접 API 주소를 가져오는 경우 빈번
    2. 레지스터 컨텍스트 구조 변형 여부
      • EIP/RIP가 갑작스럽게 비정상 주소로 이동
      • 스택 프레임이 전환되며 ESP/RSP가 자연스럽지 않게 변경
    3. PE 페이로드 구조¶
      • 패킹된 PE의 .text 외부에 존재하는 임의 메모리 공간
      • RWX 보호 속성의 세션 기반 메모리 영역(mmap된 구간 등)
    4. 실행 재개 후 흐름
      • 재개 직후 디스어셈블리 패턴이 정상 함수 프롤로그가 아닌
        NOP, JMP, 단순 MOV 시퀀스 등으로 시작하는지 관찰

    4. 동적 API 해결(PEB 기반) 개념 흐름

    실제 악성코드는 보통 Import Table을 제거하고 PEB 기반으로 API를 직접 파싱.
    아래는 책임 회피를 위해 개념적 형태만 제시한 예시.

    // 비실행 예시
    void* resolve_api_conceptually(const char* dllName, const char* funcName) {
        // 1) PEB → LDR 접근
        // 2) InMemoryOrderModuleList 순회
        // 3) dllName 비교
        // 4) Export Directory 파싱
        // 5) funcName 해시 또는 복호화 후 비교
        // 6) 주소 반환
        return 0;
    }
    

    포인트:

    • 해시 기반 문자열 비교
    • Export Directory의 AddressOfNames / AddressOfFunctions 사용
    • 악성코드 포렌식에서는 이 부분에서 암호화 루틴이 가장 자주 관찰됨

    5. 분석자가 확인해야 할 Windows Internals 포인트

    ✔ TEB / PEB 구조

    • PEB에서 LDR 위치
    • BeingDebugged flag
    • ImageBaseAddress 관찰

    ✔ 스레드 컨텍스트 구조

    • CONTEXT.Eip / Rip
    • SegGs 기반 접근(TLS 등)
    • 스택 기반 주소 전환 여부 확인

    ✔ 메모리 맵

    • RWX 섹션 추적
    • Unbacked 메모리(파일 매핑되지 않은 공간)

    ✔ 패커 흔적

    • OEP 복원 전 stub
    • API name 암호화
    • 호출 규약 교란(calling convention confusion)

    6. 조사 요약

    항목분석 포인트
    제어 흐름 분석EIP/RIP 변조, OEP 전환, JMP 패턴
    스택 프레임Thread Context 변경 전·후 비교
    PE 구조Import Table 비어 있음, Export 재파싱
    디스어셈블리 패턴비정상 프롤로그, 인위적 MOV/JMP
    암호화 루틴해시·XOR 기반 스트링 복호화 흔적
    API 후킹Thread Hijack 뒤 CreateRemoteThread와 구별 필요

    ✨ 마무리 한 줄

    Thread Hijacking은 프로세스 인젝션 기법 중에서도 제어 흐름 교란의 핵심 패턴을 가장 잘 드러내며,
    스레드 컨텍스트와 PEB 기반 동적 API 해석 흐름의 상호작용은 리버스 엔지니어링에서 반드시 짚어야 할 분석 축입니다.


    📍 Written by Code & Compass