[태그:] 스레드 하이재킹

  • 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 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