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. एक header और section table को parse करना।
  2. हर section के लिए एक heap buffer allocate करना।
  3. एक SectionArray बनाना, जो हर section का base pointer स्टोर करता है।
  4. relocation tables लागू करना ताकि section data के अंदर embedded pointers सही target section + offset पर patched हो जाएँ।

जब relocation handler attacker-controlled metadata पर अंधविश्वास करता है, तो हर relocation संभावित arbitrary read/write primitive बन जाता है। Anno 1404: Venice में, granny2.dll निम्न helper को शिप करता है:

`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 को कभी range-checked नहीं किया जाता और SectionOffset को वर्तमान section size के खिलाफ कभी validate नहीं किया जाता है। negative offsets या oversized indices वाले relocation entries बनाकर आप उस section के बाहर जा सकते हैं जिसे आप control करते हैं और allocator metadata जैसे section pointer array को stomp कर सकते हैं।

Stage 1 – loader metadata में पीछे की ओर लिखना

लक्ष्य यह है कि section 0 की relocation table SectionContentArray के entries को overwrite कर दे (जो SectionArray का mirror है और पहले section buffer के ठीक पहले स्टोर होता है)। चूँकि Granny’s custom allocator पहले 0x1F bytes जोड़ता है और NT heap अपना 0x10-byte header और alignment जोड़ता है, एक attacker पहले section (destination) की शुरुआत और section-pointer array के बीच की दूरी को precalculate कर सकता है।

टेस्ट किए गए build में, loader को मजबूर करके एक ऐसी GrannyFile संरचना allocate कराना जो बिल्कुल 0x4000 bytes की हो, section-pointer arrays को पहले section buffer के ठीक पहले लाकर खड़ा कर देता है। समाधान

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

देंता है n = 2720 सेक्शन्स। एक relocation entry जिसकी SectionOffset = -0x3FF0 ( 0x4000 - 0x20 - 0x20 + 0x30 ) अब SectionContentArray[1] पर resolve होती है भले ही destination सेक्शन यह सोचे कि यह internal pointers को patch कर रहा है।

Stage 2 – Windows 10 पर Deterministic heap लेआउट

Windows 10 NT Heap allocations ≤ RtlpLargestLfhBlock (0x4000) को randomized LFH में रूट करता है और उससे बड़े allocation deterministic backend allocator को भेजता है। GrannyFile metadata को उस threshold से थोड़ा ऊपर रखकर (2720 sections ट्रिक का उपयोग करके) और कई malicious .gr2 assets को preload करके, आप यह कर सकते हैं:

  • Allocation #1 (metadata + section pointer arrays) >0x4000 backend chunk में आता है।
  • Allocation #2 (section 0 contents) तुरंत Allocation #1 के बाद आता है।
  • Allocation #3 (section 1 contents) Allocation #2 के ठीक बाद आ जाता है, जिससे subsequent relocations के लिए एक predictable target मिल जाता है।

Process Monitor ने पुष्टि की कि assets demand पर streamed होते हैं, इसलिए crafted units/buildings को बार-बार request करना executable image को छुए बिना heap layout को “prime” करने के लिए पर्याप्त है।

Stage 3 – Primitive को RCE में बदलना

  1. Corrupt SectionContentArray[1]. Section 0 की relocation table इसे -0x3FF0 offset का उपयोग करके overwrite कर देती है। इसे किसी भी writable region पर point करें जिसे आप control करते हैं (उदा., बाद का section data)।
  2. Recycle the corrupted pointer. Section 1 की relocation table अब SectionNumber = 1 को उसी pointer के रूप में मानती है जिसे आपने inject किया था। handler SectionArray[1] + Offset को destination + SectionOffset पर लिखता है, जो हर relocation entry के लिए आपको एक arbitrary 4-byte write देता है।
  3. Hit reliable dispatchers. Anno 1404 में target के रूप में चुने गए थे granny2.dll allocator callbacks (no ASLR, DEP disabled)। उस function pointer को overwrite करना जिसे granny2.dll अगली Malloc/Free call के लिए उपयोग करता है तुरंत execution को attacker-controlled code की ओर मोड़ देता है जो trojanized asset से लोड किया गया होता है।

चूंकि both granny2.dll और injected .gr2 buffers ASLR/DEP disabled होने पर stable addresses पर रहते हैं, attack छोटे ROP chain या raw shellcode बनाने और callback को उसी पर point करने तक सिमट जाता है।

Practical checklist

  • ऐसे asset loaders खोजें जो SectionArray / relocation tables को maintain करते हों।
  • relocation handlers में indices/offsets पर missing bounds के लिए diff करें।
  • game के allocator wrapper और underlying OS heap द्वारा जो allocator headers जोड़े जाते हैं उन्हें मापें ताकि backwards offsets को सटीक रूप से गणना किया जा सके।
  • deterministic placement जबरदستی करें:
  • metadata inflate करें (कई empty sections) जब तक allocation size > RtlpLargestLfhBlock न हो;
  • backend holes भरने के लिए malicious asset को repeatedly load करें।
  • एक two-stage relocation table का उपयोग करें (पहला SectionArray को retarget करने के लिए, दूसरा writes को spray करने के लिए) और उन function pointers को overwrite करें जो normal rendering के दौरान फायर होंगे (allocator callbacks, virtual tables, animation dispatchers, आदि)।

एक बार जब आपको arbitrary file write मिल जाए (उदा., multiplayer save transfer में path traversal के माध्यम से), तो crafted .gr2 के साथ RDA archives को repack करना आपको एक साफ delivery vector देता है जिसे remote clients अपने आप decompress कर लेते हैं।

References

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 का समर्थन करें