๐Ÿ“˜ 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

MalClown์—์„œ ๋” ์•Œ์•„๋ณด๊ธฐ

์ง€๊ธˆ ๊ตฌ๋…ํ•˜์—ฌ ๊ณ„์† ์ฝ๊ณ  ์ „์ฒด ์•„์นด์ด๋ธŒ์— ์•ก์„ธ์Šคํ•˜์„ธ์š”.

๊ณ„์† ์ฝ๊ธฐ