Unsafe Relocation Fixups in Asset Loaders

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

์™œ asset relocations๊ฐ€ ์ค‘์š”ํ•œ๊ฐ€

๋งŽ์€ ๋ ˆ๊ฑฐ์‹œ ๊ฒŒ์ž„ ์—”์ง„(Granny 3D, Gamebryo ๋“ฑ)์€ ๋ณต์žกํ•œ assets๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋กœ๋“œํ•œ๋‹ค:

  1. ํ—ค๋”์™€ ์„น์…˜ ํ…Œ์ด๋ธ”์„ ํŒŒ์‹ฑํ•œ๋‹ค.
  2. ์„น์…˜๋งˆ๋‹ค ํž™ ๋ฒ„ํผ๋ฅผ ํ•˜๋‚˜ ํ• ๋‹นํ•œ๋‹ค.
  3. ๋ชจ๋“  ์„น์…˜์˜ base pointer๋ฅผ ์ €์žฅํ•˜๋Š” SectionArray๋ฅผ ๊ตฌ์ถ•ํ•œ๋‹ค.
  4. ์„น์…˜ ๋ฐ์ดํ„ฐ ๋‚ด๋ถ€์— ํฌํ•จ๋œ ํฌ์ธํ„ฐ๋“ค์ด ์˜ฌ๋ฐ”๋ฅธ ๋Œ€์ƒ ์„น์…˜ + ์˜คํ”„์…‹์œผ๋กœ ํŒจ์น˜๋˜๋„๋ก relocation tables๋ฅผ ์ ์šฉํ•œ๋‹ค.

relocation ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๊ณต๊ฒฉ์ž๊ฐ€ ์ œ์–ดํ•˜๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋งน์‹ ํ•˜๋ฉด, ๋ชจ๋“  relocation์€ ์ž ์žฌ์ ์ธ ์ž„์˜ ์ฝ๊ธฐ/์“ฐ๊ธฐ ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๊ฐ€ ๋œ๋‹ค. Anno 1404: Venice์—์„œ, granny2.dll์€ ๋‹ค์Œ ํ—ฌํผ๋ฅผ ์ œ๊ณตํ•œ๋‹ค:

`GrannyGRNFixUp_0` (์ƒ๋žต๋จ) ```c int *__cdecl GrannyGRNFixUp_0(DWORD RelocationCount, Relocation *PointerFixupArray, int *SectionArray, char *destination) { while (RelocationCount--) { int target_base = SectionArray[PointerFixupArray->SectionNumber]; // unchecked index int *patch_site = (int *)(destination + PointerFixupArray->SectionOffset); // unchecked offset *patch_site = target_base ; if (target_base) *patch_site = target_base + PointerFixupArray->Offset; ++PointerFixupArray; } return SectionArray; } ```

SectionNumber์€ ๋ฒ”์œ„ ๊ฒ€์‚ฌ๋˜์ง€ ์•Š์œผ๋ฉฐ SectionOffset์€ ํ˜„์žฌ ์„น์…˜ ํฌ๊ธฐ์— ๋Œ€ํ•ด ๊ฒ€์ฆ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์Œ์ˆ˜ ์˜คํ”„์…‹์ด๋‚˜ ๊ณผ๋„ํ•œ ์ธ๋ฑ์Šค๋ฅผ ๊ฐ€์ง„ relocation entries๋ฅผ ์กฐ์ž‘ํ•˜๋ฉด ์ œ์–ดํ•˜๋Š” ์„น์…˜ ๋ฐ–์œผ๋กœ ๋ฒ—์–ด๋‚˜ ์„น์…˜ ํฌ์ธํ„ฐ ๋ฐฐ์—ด ์ž์ฒด์™€ ๊ฐ™์€ allocator metadata๋ฅผ ์ง“๋ฐŸ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Stage 1 โ€“ ๋กœ๋” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋กœ ์—ญ๋ฐฉํ–ฅ ์“ฐ๊ธฐ

๋ชฉํ‘œ๋Š” section 0์˜ relocation table์ด SectionContentArray์˜ ์—”ํŠธ๋ฆฌ๋“ค์„ ๋ฎ์–ด์“ฐ๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(SectionContentArray๋Š” SectionArray๋ฅผ ๋ฏธ๋Ÿฌ๋งํ•˜๋ฉฐ ์ฒซ ๋ฒˆ์งธ ์„น์…˜ ๋ฒ„ํผ ๋ฐ”๋กœ ์•ž์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค). Grannyโ€™s custom allocator๊ฐ€ ์•ž์— 0x1F ๋ฐ”์ดํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  NT heap์ด ์ž์ฒด 0x10-๋ฐ”์ดํŠธ ํ—ค๋”์™€ ์ •๋ ฌ์„ ๋”ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ณต๊ฒฉ์ž๋Š” ์ฒซ ๋ฒˆ์งธ ์„น์…˜์˜ ์‹œ์ž‘(destination)๊ณผ ์„น์…˜-ํฌ์ธํ„ฐ ๋ฐฐ์—ด ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ๋ฅผ ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๋œ ๋นŒ๋“œ์—์„œ๋Š” ๋กœ๋”๊ฐ€ ์ •ํ™•ํžˆ 0x4000 bytes์ธ GrannyFile ๊ตฌ์กฐ๋ฅผ ํ• ๋‹นํ•˜๋„๋ก ๊ฐ•์ œํ•˜๋ฉด ์„น์…˜-ํฌ์ธํ„ฐ ๋ฐฐ์—ด์ด ์ฒซ ๋ฒˆ์งธ ์„น์…˜ ๋ฒ„ํผ ๋ฐ”๋กœ ์•ž์— ์œ„์น˜ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. Solving

0x20 (header) + 0x20 (section descriptors)
+ n * 1 (section types) + n * 1 (flags)
+ n * 4 (pointer table) = 0x4000

gives n = 2720 sections. A relocation entry with SectionOffset = -0x3FF0 ( 0x4000 - 0x20 - 0x20 + 0x30 ) now resolves to SectionContentArray[1] even though the destination section thinks it is patching internal pointers.

Stage 2 โ€“ Windows 10์—์„œ ๊ฒฐ์ •๋ก ์  ํž™ ๋ ˆ์ด์•„์›ƒ

Windows 10 NT Heap๋Š” โ‰ค RtlpLargestLfhBlock (0x4000) ์ธ ํ• ๋‹น์„ ๋žœ๋คํ™”๋œ LFH๋กœ, ๊ทธ๋ณด๋‹ค ํฐ ํ• ๋‹น์„ ๊ฒฐ์ •๋ก ์  ๋ฐฑ์—”๋“œ ํ• ๋‹น์ž๋กœ ๋ณด๋‚ธ๋‹ค. GrannyFile ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ ์ž„๊ณ„๊ฐ’๋ณด๋‹ค ์•ฝ๊ฐ„ ํฌ๊ฒŒ ์œ ์ง€(2720 ์„น์…˜ ํŠธ๋ฆญ ์‚ฌ์šฉ)ํ•˜๊ณ  ์•…์„ฑ .gr2 ์—์…‹์„ ์—ฌ๋Ÿฌ ๊ฐœ ๋ฏธ๋ฆฌ ๋กœ๋“œํ•˜๋ฉด ๋‹ค์Œ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค:

  • Allocation #1 (metadata + section pointer arrays)๊ฐ€ >0x4000 ๋ฐฑ์—”๋“œ ์ฒญํฌ์— ๋ฐฐ์น˜๋œ๋‹ค.
  • Allocation #2 (section 0 contents)๊ฐ€ Allocation #1 ๋ฐ”๋กœ ๋‹ค์Œ์— ๋ฐฐ์น˜๋œ๋‹ค.
  • Allocation #3 (section 1 contents)๊ฐ€ Allocation #2 ๋ฐ”๋กœ ๋’ค์— ๋ฐฐ์น˜๋˜์–ด ์ดํ›„ ์žฌ๋ฐฐ์น˜(relocations)์— ๋Œ€ํ•ด ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ํƒ€๊นƒ์„ ์ œ๊ณตํ•œ๋‹ค.

Process Monitor๋Š” ์—์…‹์ด ์˜จ๋””๋งจ๋“œ๋กœ ์ŠคํŠธ๋ฆฌ๋ฐ๋œ๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์กฐ์ž‘๋œ ์œ ๋‹›/๊ฑด๋ฌผ์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ์š”์ฒญํ•˜๋ฉด ์‹คํ–‰ ํŒŒ์ผ ์ด๋ฏธ์ง€๋ฅผ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๊ณ ๋„ ํž™ ๋ ˆ์ด์•„์›ƒ์„ โ€œํ”„๋ผ์ž„โ€œํ•˜๋Š” ๋ฐ ์ถฉ๋ถ„ํ•˜๋‹ค.

Stage 3 โ€“ ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๋ฅผ RCE๋กœ ์ „ํ™˜

  1. Corrupt SectionContentArray[1]. Section 0์˜ ์žฌ๋ฐฐ์น˜ ํ…Œ์ด๋ธ”์ด -0x3FF0 ์˜คํ”„์…‹์„ ์‚ฌ์šฉํ•ด ์ด๋ฅผ ๋ฎ์–ด์“ด๋‹ค. ์ด๋ฅผ ์ œ์–ด ๊ฐ€๋Šฅํ•œ ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•œ ์˜์—ญ(์˜ˆ: ์ดํ›„ ์„น์…˜ ๋ฐ์ดํ„ฐ)์„ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ํ•˜๋ผ.
  2. Recycle the corrupted pointer. ์ด์ œ Section 1์˜ ์žฌ๋ฐฐ์น˜ ํ…Œ์ด๋ธ”์€ SectionNumber = 1์„ ๋‹น์‹ ์ด ์ฃผ์ž…ํ•œ ์ž„์˜์˜ ํฌ์ธํ„ฐ๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค. ํ•ธ๋“ค๋Ÿฌ๋Š” SectionArray[1] + Offset์„ destination + SectionOffset์— ์“ฐ๋ฏ€๋กœ ๊ฐ ์žฌ๋ฐฐ์น˜ ์—”ํŠธ๋ฆฌ๋งˆ๋‹ค ์ž„์˜์˜ 4๋ฐ”์ดํŠธ ์“ฐ๊ธฐ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.
  3. Hit reliable dispatchers. Anno 1404์—์„œ๋Š” ๋Œ€์ƒ ์„ ํƒ์œผ๋กœ granny2.dll์˜ allocator ์ฝœ๋ฐฑ์ด ์‚ฌ์šฉ๋˜์—ˆ๋‹ค(ASLR ์—†์Œ, DEP ๋น„ํ™œ์„ฑ). ๋‹ค์Œ Malloc/Free ํ˜ธ์ถœ์— granny2.dll์ด ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ๋ฎ์–ด์“ฐ๋ฉด ํŠธ๋กœ์ดํ™”๋œ ์—์…‹์—์„œ ๋กœ๋“œ๋œ ๊ณต๊ฒฉ์ž ์ œ์–ด ์ฝ”๋“œ๋กœ ์ฆ‰์‹œ ์‹คํ–‰์ด ์ „ํ™˜๋œ๋‹ค.

ASLR/DEP๊ฐ€ ๋น„ํ™œ์„ฑํ™”๋œ ์ƒํƒœ์—์„œ๋Š” granny2.dll๊ณผ ์ฃผ์ž…๋œ .gr2 ๋ฒ„ํผ๊ฐ€ ์•ˆ์ •์ ์ธ ์ฃผ์†Œ์— ์กด์žฌํ•˜๋ฏ€๋กœ, ๊ณต๊ฒฉ์€ ์ž‘์€ ROP ์ฒด์ธ์ด๋‚˜ ์›์‹œ ์‰˜์ฝ”๋“œ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ์ฝœ๋ฐฑ์„ ๊ทธ์ชฝ์œผ๋กœ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ท€๊ฒฐ๋œ๋‹ค.

์‹ค์ „ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

  • SectionArray / ์žฌ๋ฐฐ์น˜ ํ…Œ์ด๋ธ”์„ ์œ ์ง€ํ•˜๋Š” ์—์…‹ ๋กœ๋”๋ฅผ ์ฐพ์•„๋ผ.
  • ์ธ๋ฑ์Šค/์˜คํ”„์…‹์— ๋Œ€ํ•œ ๊ฒฝ๊ณ„ ๊ฒ€์‚ฌ๊ฐ€ ๋ˆ„๋ฝ๋œ ์žฌ๋ฐฐ์น˜ ํ•ธ๋“ค๋Ÿฌ๋ฅผ diffํ•˜์—ฌ ์ฐพ์•„๋ผ.
  • ๊ฒŒ์ž„์˜ allocator ๋ž˜ํผ์™€ ๊ธฐ์ € OS ํž™์ด ์ถ”๊ฐ€ํ•˜๋Š” allocator ํ—ค๋”๋ฅผ ์ธก์ •ํ•ด ์—ญ๋ฐฉํ–ฅ ์˜คํ”„์…‹์„ ์ •ํ™•ํžˆ ๊ณ„์‚ฐํ•˜๋ผ.
  • ๊ฒฐ์ •๋ก ์  ๋ฐฐ์น˜๋ฅผ ๊ฐ•์ œํ•˜๋ ค๋ฉด:
    • ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋Š˜๋ ค(์—ฌ๋Ÿฌ ๋นˆ ์„น์…˜) ํ• ๋‹น ํฌ๊ธฐ๊ฐ€ RtlpLargestLfhBlock๋ณด๋‹ค ์ปค์ง€๊ฒŒ ํ•œ๋‹ค;
    • ์•…์„ฑ ์—์…‹์„ ๋ฐ˜๋ณต ๋กœ๋“œํ•ด ๋ฐฑ์—”๋“œ์˜ ๋นˆํ‹ˆ์„ ์ฑ„์šด๋‹ค.
  • 2๋‹จ๊ณ„ ์žฌ๋ฐฐ์น˜ ํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•˜๋ผ(๋จผ์ € SectionArray๋ฅผ ์žฌํƒ€๊นƒํŒ…ํ•˜๊ณ , ๋‘๋ฒˆ์งธ๋Š” ์“ฐ๊ธฐ ์Šคํ”„๋ ˆ์ด) ๊ทธ๋ฆฌ๊ณ  ์ •์ƒ ๋ Œ๋”๋ง ์ค‘์— ์‹คํ–‰๋  ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋“ค(allocator ์ฝœ๋ฐฑ, ๊ฐ€์ƒ ํ…Œ์ด๋ธ”, ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋””์ŠคํŒจ์ฒ˜ ๋“ฑ)์„ ๋ฎ์–ด์จ๋ผ.

์ž„์˜์˜ ํŒŒ์ผ ์“ฐ๊ธฐ ๊ถŒํ•œ์„ ์–ป์œผ๋ฉด(์˜ˆ: ๋ฉ€ํ‹ฐํ”Œ๋ ˆ์ด์–ด ์„ธ์ด๋ธŒ ์ „์†ก์˜ ๊ฒฝ๋กœ ํƒ์ƒ‰์„ ํ†ตํ•ด) ์กฐ์ž‘๋œ .gr2๋กœ RDA ์•„์นด์ด๋ธŒ๋ฅผ ์žฌํŒจํ‚ค์ง•ํ•˜๋Š” ๊ฒƒ์€ ์›๊ฒฉ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ์••์ถ• ํ•ด์ œํ•˜๋Š” ๊น”๋”ํ•œ ์ „๋‹ฌ ๋ฒกํ„ฐ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

์ฐธ๊ณ ์ž๋ฃŒ

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ