Unsichere Relocation-Fixups in Asset-Loadern

Tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks

Warum Asset-Relocations wichtig sind

Viele ältere Game-Engines (Granny 3D, Gamebryo usw.) laden komplexe Assets folgendermaßen:

  1. Einen Header und eine Abschnittstabelle parsen.
  2. Für jeden Abschnitt einen Heap-Puffer reservieren.
  3. Ein SectionArray aufbauen, das den Basiszeiger jedes Abschnitts speichert.
  4. Relocation-Tabellen anwenden, sodass Pointer innerhalb der Abschnittsdaten auf den richtigen Zielabschnitt + Offset gepatcht werden.

Wenn der Relocation-Handler blind den vom Angreifer kontrollierten Metadaten vertraut, wird jede Relocation zu einer potenziellen arbitrary read/write primitive. In Anno 1404: Venice stellt granny2.dll den folgenden Helfer bereit:

`GrannyGRNFixUp_0` (gekürzt) ```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 wird nie auf Gültigkeit geprüft und SectionOffset wird nicht gegen die Größe der aktuellen Section validiert. Das Erstellen von relocation entries mit negativen Offsets oder übergroßen Indizes erlaubt es, außerhalb der von Ihnen kontrollierten Section zu gehen und Allocator-Metadaten wie das section pointer array selbst zu überschreiben.

Stage 1 – Rückwärts in Loader-Metadaten schreiben

Das Ziel ist, die relocation table von section 0 so zu manipulieren, dass sie Einträge von SectionContentArray überschreibt (welches SectionArray spiegelt und direkt vor dem ersten section buffer gespeichert ist). Da Granny’s custom allocator 0x1F bytes voranstellt und der NT heap zusätzlich einen 0x10-Byte-Header plus Alignment hinzufügt, kann ein Angreifer den Abstand zwischen dem Beginn der ersten Section (destination) und dem section-pointer array vorab berechnen.

In dem getesteten Build führt das Erzwingen, dass der Loader eine GrannyFile-Struktur alloziert, die genau 0x4000 bytes groß ist, dazu, dass die section-pointer arrays direkt vor dem ersten section buffer landen. Damit…

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.

Stufe 2 – Deterministisches Heap-Layout unter Windows 10

Der Windows 10 NT-Heap leitet Allokationen ≤ RtlpLargestLfhBlock (0x4000) an den randomisierten LFH und größere an den deterministischen Backend-Allocator weiter. Indem man die GrannyFile-Metadaten knapp über dieser Schwelle hält (mithilfe des 2720-Sektionen-Tricks) und mehrere bösartige .gr2 assets vorlädt, kann man:

  • Allokation #1 (Metadaten + Section-Pointer-Arrays) in einen Backend-Chunk >0x4000 platzieren.
  • Allokation #2 (Inhalte von Section 0) unmittelbar nach Allokation #1 platzieren.
  • Allokation #3 (Inhalte von Section 1) direkt nach Allokation #2 platzieren und so ein vorhersehbares Ziel für folgende Relocations schaffen.

Process Monitor bestätigte, dass Assets on-demand gestreamt werden, sodass wiederholtes Anfordern von manipulierten Units/Gebäuden ausreicht, um das Heap-Layout zu “primen”, ohne das ausführbare Image anzufassen.

Stufe 3 – Die Primitive in RCE umwandeln

  1. Korruptiere SectionContentArray[1]. Die Relocation-Tabelle von Section 0 überschreibt es durch Verwendung des Offsets -0x3FF0. Richte es auf einen beliebigen beschreibbaren Bereich, den du kontrollierst (z. B. spätere Sektion-Daten).
  2. Recycle den korrupten Pointer. Die Relocation-Tabelle von Section 1 behandelt jetzt SectionNumber = 1 als den von dir eingesetzten Pointer. Der Handler schreibt SectionArray[1] + Offset an destination + SectionOffset, wodurch du für jeden Relocation-Eintrag einen beliebigen 4-Byte-Write erzielst.
  3. Treffe verlässliche Dispatcher. In Anno 1404 war das Ziel der Wahl die granny2.dll allocator callbacks (keine ASLR, DEP deaktiviert). Das Überschreiben des Funktionszeigers, den granny2.dll für den nächsten Malloc/Free-Aufruf verwendet, leitet die Ausführung sofort auf vom Angreifer kontrollierten Code um, der aus dem trojanisierten Asset geladen wurde.

Da sowohl granny2.dll als auch die injizierten .gr2-Puffer bei deaktiviertem ASLR/DEP an stabilen Adressen liegen, reduziert sich der Angriff darauf, eine kleine ROP chain oder rohen shellcode zu bauen und den Callback darauf zu zeigen.

Praktische Checkliste

  • Suche nach Asset-Loadern, die SectionArray / relocation tables verwalten.
  • Vergleiche Relocation-Handler auf fehlende Grenzprüfungen für Indizes/Offsets.
  • Vermesse die Allocator-Header, die sowohl vom Allocator-Wrapper des Spiels als auch vom zugrundeliegenden OS-Heap hinzugefügt werden, um Rückwärts-Offsets präzise zu berechnen.
  • Erzwinge deterministische Platzierung durch:
    • Aufblähen der Metadaten (viele leere Sektionen), bis die Allokationsgröße > RtlpLargestLfhBlock;
    • wiederholtes Laden des bösartigen Assets, um Backend-Lücken zu füllen.
  • Verwende eine zweistufige Relocation-Tabelle (zuerst zum Umleiten von SectionArray, dann zum Sprayen von Writes) und überschreibe Funktionszeiger, die während der normalen Render-Phase ausgelöst werden (allocator callbacks, virtual tables, animation dispatchers, etc.).

Sobald du einen beliebigen Dateischreibzugriff erlangst (z. B. via path traversal beim Multiplayer-Save-Transfer), liefert das Umverpacken von RDA-Archiven mit der manipulierten .gr2 einen sauberen Angriffsvektor, der von entfernten Clients automatisch entpackt wird.

Referenzen

Tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks