0815 GetProcAddress Hacks

Wenn ich mich nicht irre, habe ich etwas Ähnliches schon bei der Einführung von Windows Phone 8 gelesen:

Eigentlich gesperrte API Funktionen sind per GetProcAddress() erreichbar.

Es geht dabei um APIs die Microsoft in den SDKs für bestimmte Plattformen deaktiviert bzw ausgeschlossen hat. Früher war das beim Windows Phone so, heute sind das allgemein “Store Apps” oder andere UWP Konstellationen.


In Desktop Apps kann man per LoadLibrary () und GetProcAddress() quasi alles laden und danach ausführen. In Verbindung mit CreateRemoteThread() konnte also jeder Virus sich selbst in bereits laufende Prozesse hineinladen und dort Daten ausspähen oder Blödsinn anstellen.

Kein Wunder also, dass Microsoft dieses aus Kompatibilitätsgründen erhaltene Einbruchwerkzeug wo immer es möglich war deaktivieren wollte. Und die neuen Plattformen ab Windows 8 waren dabei ein guter Kandidat.

Windows Store Apps verfügen daher zwar noch über GetProcAddress(), doch die anderen APIs zur Lieferung des HMODULE Pointers, der für GetProcAddress() notwendig ist, sind diesen Prozessen nicht zugänglich.
Man findet sie nicht in den Headern und sie fehlen auch in den Lib-Bibliotheken. Damit kann ein Prozess eigentlich nichts mehr dynamisch nachladen. (Für Plugins und Ähnliches gibt es das abgespeckte LoadPackagedLibrary um DLLs innerhalb einer signierten App laden zu dürfen).

Der Punkt ist also: Hat man ein HMODULE der implizit geladenen DLLs, könnte man auch andere Funktionen der Bibliotheken nutzen, die uns das SDK vorenthalten möchte.

Und dafür gibt es tatsächlich einen bekannten Hack, der so lange funktionieren wird, bis Microsoft die gesamte Windows API aufräumt. Und nachdem das bis Windows 10 nicht passiert wird, wird die Lösung vermutlich noch lange funktionieren:

VirtualQuery() auf einen Funktionspointer liefert in AllocationBase die Addresse zurück, auf die auch HMODULE normalerweise zeigt.

Das heißt also, nachdem LoadLibrary() zumeist im gleichen Modul sitzt wie auch GetProcAddress() (nämlich kernel32.dll), hilft uns folgender Hack:

 1typedef HMODULE (WINAPI *loader_ptr)(LPCWSTR lpLibFileName);
 2MEMORY_BASIC_INFORMATION info;
 3
 4VirtualQuery(&GetProcAddress, &info, sizeof(info));
 5HMODULE hkernel = (HMODULE)mbi.AllocationBase;
 6
 7loader_ptr my_loader = GetProcAddress(hkernel, "LoadLibraryW");
 8
 9HMODULE injected = my_loader(L"unsupported.dll");
10FARPROC backdoor = GetProcAddress(injected, "backdoor");

Natürlich kann Windows dann immer noch das Laden innerhalb der Funktionen blockieren bzw. nur nach bestimmten Regeln zulassen. Man kann also nie sicher sein, wann und wo der Hack wirklich funktioniert.

Es gibt aber eine ähnliche Anwendung, die mir recht nützlich erscheint:
Man kann so auch “Nachbarfunktionen” dynamisch Laden, die gar nicht gesperrt sind und diese Technik versetzt dann ältere Compiler oder ältere SDKs in die Lage Funktionen einzubinden, die sie offiziell gar nicht unterstützen.

Ein Beispiel: Mit dem Wissen, dass einige WinRT Funktionen in combase.dll implementiert sind und dort nun auch alte OLE Routinen liegen, kann man daher “klassisch” linken und dann z.B. per HMODULE von CoCreateInstance() zu RoGetActivationFactory wechseln.
Dann hätte man nämlich Code, der Windows 7 kompatibel ist und trotzdem unter Windows 8 / Windows 10 innerhalb eines App-Pakets auf die Windows RunTime zugreifen könnte. Der Linker entscheidet dann, was verfügbar ist und der Code kann ohne Änderungen beide Szenarien abbilden. Das wäre also in statischen Bibliotheken ein gangbarer Weg, die keine unnötigen bzw. exklusive Abhängigkeiten eingehen wollen.

Ob das dann sinnvoll ist, ist natürlich eine ganz andere Frage ;)
Aber hey … wir wollen hier schließlich keine “bösen” Pfade beschreiten.


Wenn sich eine triviale Erkenntnis mit Dummheit in der Interpretation paart, dann gibt es in der Regel Kollateralschäden in der Anwendung.
frei zitiert nach A. Van der Bellen
... also dann paaren wir mal eine komplexe Erkenntnis mit Klugheit in der Interpretation!