Niebezpieczne poprawki relokacji w ładowarkach zasobów
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Dlaczego relokacje zasobów są ważne
Wiele przestarzałych silników gier (Granny 3D, Gamebryo, itd.) wczytuje złożone zasoby przez:
- Parsowanie nagłówka i tabeli sekcji.
- Alokowanie jednego bufora na stercie na każdą sekcję.
- Tworzenie
SectionArray, który przechowuje wskaźnik bazowy każdej sekcji. - Stosowanie tabel relokacji, aby wskaźniki osadzone w danych sekcji zostały poprawione na właściwą sekcję docelową + przesunięcie.
Kiedy obsługa relokacji bezkrytycznie ufa metadanym kontrolowanym przez atakującego, każda relokacja staje się potencjalnym prymitywem dowolnego odczytu/zapisu. W Anno 1404: Venice, granny2.dll dostarcza następującą funkcję pomocniczą:
`GrannyGRNFixUp_0` (skrócone)
```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 nie jest sprawdzany zakresowo, a SectionOffset nie jest weryfikowany względem rozmiaru bieżącej sekcji. Sporządzanie wpisów relokacji z ujemnymi przesunięciami lub nadmiernie dużymi indeksami pozwala wyjść poza kontrolowaną sekcję i nadpisać metadane alokatora, takie jak sama tablica wskaźników sekcji.
Stage 1 – Zapis wstecz w metadanych loadera
Celem jest sprawienie, by tabela relokacji section 0 nadpisała wpisy SectionContentArray (która odzwierciedla SectionArray i jest przechowywana tuż przed pierwszym buforem sekcji). Ponieważ niestandardowy alokator Granny dokłada z przodu 0x1F bajtów, a NT heap dodaje własny nagłówek o rozmiarze 0x10 bajtów oraz wyrównanie, atakujący może wstępnie obliczyć odległość między początkiem pierwszej sekcji (destination) a tablicą wskaźników sekcji.
W testowanej kompilacji zmuszenie loadera do zaalokowania struktury GrannyFile o dokładnie 0x4000 bajtów powoduje, że tablice wskaźników sekcji lądują tuż przed pierwszym buforem sekcji. Rozwiązanie
0x20 (header) + 0x20 (section descriptors)
+ n * 1 (section types) + n * 1 (flags)
+ n * 4 (pointer table) = 0x4000
daje n = 2720 sekcji. Wpis relocacji z SectionOffset = -0x3FF0 ( 0x4000 - 0x20 - 0x20 + 0x30 ) teraz rozwiązuje się do SectionContentArray[1], mimo że docelowa sekcja myśli, że poprawia wewnętrzne wskaźniki.
Etap 2 – Deterministyczny heap layout na Windows 10
Windows 10 NT Heap kieruje alokacje ≤ RtlpLargestLfhBlock (0x4000) do zrandomizowanego LFH, a większe do deterministycznego backend allocator. Zachowując metadane GrannyFile nieco powyżej tego progu (używając sztuczki z 2720 sekcjami) i wstępnie ładując kilka złośliwych assetów .gr2, możesz spowodować:
- Alokacja #1 (metadata + tablice wskaźników sekcji) trafi do backend chunku >0x4000.
- Alokacja #2 (zawartość sekcji 0) trafi bezpośrednio po alokacji #1.
- Alokacja #3 (zawartość sekcji 1) trafi tuż po alokacji #2, dając przewidywalny cel dla kolejnych relocacji.
Process Monitor potwierdził, że assety są streamowane na żądanie, więc wielokrotne żądanie spreparowanych jednostek/budynków wystarczy, by „przygotować” heap layout bez dotykania pliku wykonywalnego.
Etap 3 – Konwersja prymitywu na RCE
- Uszkodź
SectionContentArray[1]. Tabela relocacji sekcji 0 nadpisuje ją używając offsetu-0x3FF0. Wskaż ją na dowolny zapisywalny region, który kontrolujesz (np. dane późniejszej sekcji). - Ponownie użyj skażonego wskaźnika. Tabela relocacji sekcji 1 teraz traktuje
SectionNumber = 1jako wskaźnik, który wstrzyknąłeś. Handler zapisujeSectionArray[1] + Offsetdodestination + SectionOffset, dając Ci arbitralny zapis 4 bajtów dla każdego wpisu relocacji. - Traf w niezawodne dispatchery. W Anno 1404 celem z wyboru były allocator callbacks w
granny2.dll(brak ASLR, DEP wyłączone). Nadpisanie wskaźnika funkcji, któregogranny2.dllużywa dla następnego wywołaniaMalloc/Free, natychmiast przekierowuje wykonanie do kodu kontrolowanego przez atakującego załadowanego z trojanizowanego assetu.
Ponieważ zarówno granny2.dll, jak i wstrzyknięte bufory .gr2 znajdują się pod stabilnymi adresami, gdy ASLR/DEP są wyłączone, atak sprowadza się do zbudowania małego łańcucha ROP lub surowego shellcode’u i skierowania callbacka na niego.
Praktyczna lista kontrolna
- Szukaj loaderów assetów, które utrzymują
SectionArray/ tabele relocacji. - Porównaj (diff) handlery obsługi relocacji pod kątem brakujących sprawdzeń granic dla indeksów/offsetów.
- Zmierz nagłówki alokatorów dodawane zarówno przez wrapper alokatora gry, jak i przez systemowy heap, aby precyzyjnie obliczyć odwrotne offsety.
- Wymuś deterministyczne rozmieszczenie przez:
- zwiększanie metadata (wiele pustych sekcji) aż rozmiar alokacji >
RtlpLargestLfhBlock; - wielokrotne ładowanie złośliwego assetu, aby wypełnić luki w backendzie.
- zwiększanie metadata (wiele pustych sekcji) aż rozmiar alokacji >
- Użyj dwustopniowej tabeli relocacji (najpierw do przelokowania
SectionArray, potem do rozpylenia zapisów) i nadpisz wskaźniki funkcji, które zostaną wywołane podczas normalnego renderowania (allocator callbacks, virtual tables, animation dispatchers, itd.).
Gdy uzyskasz arbitralny zapis pliku (np. przez path traversal w transferze zapisu multiplayer), przepakowanie archiwów RDA ze spreparowanym .gr2 daje czysty wektor dostarczenia, który jest automatycznie dekompresowany przez zdalnych klientów.
References
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.


