
Простая библиотека PoC для выполнения произвольных вызовов, проксируя их через NdrServerCall2 или аналогичные
Для создания общего способа выполнения локального и удаленного кода мы разработали относительно необычный метод выполнения кода, который внутри мы называем RpcCraft (Self) и RpcExec (Remote Process). Этот метод использует хорошо известную среди разработчиков эксплойтов методологию, злоупотребляя вызовами сервера RPC (удаленный вызов процедур), такими как NdrServerCall2 или NdrServerCallAll, для выполнения произвольного кода.
Внутри RPCRT4.dll функции, такие как NdrServerCall2, NdrServerCallAll и NdrServerCallNdr64 (псевдоним NdrServerCallAll), реализованы как обертки для динамического вызова функций, связанных с серверными функциональными возможностями. Эти функции принимают единственный аргумент — указатель на структуру RPC_MESSAGE.
Структура RPC_MESSAGE:
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;
Для инициализации среды выполнения без привязки к службе используется функция PerformRpcInitialization. Эта функция внутренне инициализирует необходимые структуры, не требуя ручной привязки.
Эта публичная версия метода была разработана как POC для демонстрации осуществимости, и в настоящее время она вызывает исключение в NdrGetBuffer из-за отсутствующего дескриптора привязки (Binding Handle). С этим можно справиться несколькими способами, но текущая реализация делает следующее:
int FetchReturnValue(const PEXCEPTION_POINTERS ExceptionInfo) {
ExceptionInfo->ContextRecord->EFlags |= (1 << 16);
g_ReturnValue = (PVOID)ExceptionInfo->ContextRecord->Rax;
return EXCEPTION_CONTINUE_EXECUTION;
}
Вызов RPC защищен CFG (Control Flow Guard), что означает, что для достижения полного, неограниченного выполнения кода необходимо либо пометить цель как допустимую с помощью SetProcessValidCallTargets, либо пропатчить RpcInvokeCheckICall.
Проект RpcProxyInvoke демонстрирует альтернативный метод, который можно использовать для реализации библиотеки в стиле RailGun. Хотя публичная реализация не идеальна, она может служить основой для дальнейшего развития.
Этот проект лицензирован по лицензии MIT - подробности в файле LICENSE.