
Einfache POC-Bibliothek zur Ausführung beliebiger Aufrufe, die über NdrServerCall2 oder ähnliche Funktionen weitergeleitet werden.
Um eine allgemeine Möglichkeit zur Ausführung von lokalem und remote Code zu schaffen, haben wir eine relativ obskure Methode der Codeausführung entwickelt, die wir intern als RpcCraft (Self) und RpcExec (Remote Process) bezeichnen. Diese Technik nutzt eine unter Exploit-Entwicklern bekannte Methodik aus, indem RPC-Serveraufrufe (Remote Procedure Call) wie NdrServerCall2 oder NdrServerCallAll missbraucht werden, um beliebigen Code auszuführen.
Innerhalb von RPCRT4.dll sind Funktionen wie NdrServerCall2, NdrServerCallAll und NdrServerCallNdr64 (ein Alias von NdrServerCallAll) als Wrapper implementiert, die Funktionen der Serverfunktionalitäten dynamisch aufrufen. Diese Funktionen akzeptieren ein einziges Argument: einen Zeiger auf eine RPC_MESSAGE-Struktur.
RPC_MESSAGE-Struktur:
typedef struct _RPC_MESSAGE {
RPC_BINDING_HANDLE Handle;
unsigned long DataRepresentation;
void *Buffer;
unsigned int BufferLength;
unsigned int ProcNum;
PRPC_SYNTAX_IDENTIFIER TransferSyntax;
void *RpcInterfaceInformation;
void *ReservedForRuntime;
RPC_MGR_EPV *ManagerEpv;
void *ImportContext;
unsigned long RpcFlags;
} RPC_MESSAGE, *PRPC_MESSAGE;
Um die Laufzeitumgebung ohne Bindung an einen Dienst zu initialisieren, wird die Funktion PerformRpcInitialization verwendet. Diese Funktion initialisiert intern die erforderlichen Strukturen, ohne dass eine manuelle Bindung erforderlich ist.
Diese öffentliche Version der Technik wurde als POC entwickelt, um die Machbarkeit zu demonstrieren. Sie erzeugt derzeit eine Ausnahme bei NdrGetBuffer aufgrund eines fehlenden Binding-Handles. Dies kann auf verschiedene Weise behoben werden, aber die aktuelle Implementierung geht wie folgt vor:
int FetchReturnValue(const PEXCEPTION_POINTERS ExceptionInfo) {
ExceptionInfo->ContextRecord->EFlags |= (1 << 16);
g_ReturnValue = (PVOID)ExceptionInfo->ContextRecord->Rax;
return EXCEPTION_CONTINUE_EXECUTION;
}
RPC-Aufrufe sind durch CFG (Control Flow Guard) geschützt, was bedeutet, dass es für eine vollständige, uneingeschränkte Codeausführung erforderlich ist, entweder das Ziel mit SetProcessValidCallTargets als gültig zu markieren oder RpcInvokeCheckICall zu patchen.
Das RpcProxyInvoke-Projekt demonstriert eine alternative Technik, die missbraucht werden kann, um eine Bibliothek im RailGun-Stil zu implementieren. Obwohl die öffentliche Implementierung nicht perfekt ist, kann sie als Grundlage für die weitere Entwicklung dienen.
Dieses Projekt ist unter der MIT-Lizenz lizenziert – siehe die Datei LICENSE für Details.