
Biblioteca POC simples para executar chamadas arbitrárias proxando-as via NdrServerCall2 ou similar
Para criar uma forma geral de executar código local e remoto, projetamos um método relativamente obscuro de execução de código, que internamente chamamos de RpcCraft (Self) e RpcExec (Remote Process). Esta técnica aproveita uma metodologia bem conhecida entre desenvolvedores de exploits, abusando de chamadas de servidor RPC (Remote Procedure Call), como NdrServerCall2 ou NdrServerCallAll, para executar código arbitrário.
Dentro de RPCRT4.dll, funções como NdrServerCall2, NdrServerCallAll e NdrServerCallNdr64 (um alias de NdrServerCallAll) são implementadas como wrappers para invocar dinamicamente funções relacionadas a funcionalidades do servidor. Essas funções recebem um único argumento, um ponteiro para uma estrutura RPC_MESSAGE.
Estrutura 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;
Para inicializar o runtime sem se vincular a um serviço, a função PerformRpcInitialization é utilizada. Esta função inicializa internamente as estruturas necessárias sem exigir vinculação manual.
Esta versão pública da técnica foi desenvolvida como POC para demonstrar a viabilidade e atualmente gera uma exceção no NdrGetBuffer devido a um Binding Handle ausente. Isso pode ser tratado de várias formas, mas a implementação atual faz:
int FetchReturnValue(const PEXCEPTION_POINTERS ExceptionInfo) {
ExceptionInfo->ContextRecord->EFlags |= (1 << 16);
g_ReturnValue = (PVOID)ExceptionInfo->ContextRecord->Rax;
return EXCEPTION_CONTINUE_EXECUTION;
}
A invocação RPC é protegida por CFG, o que significa que, para alcançar execução de código completa e irrestrita, é necessário marcar o alvo como válido com SetProcessValidCallTargets ou aplicar patch no RpcInvokeCheckICall.
O projeto RpcProxyInvoke demonstra uma técnica alternativa que pode ser abusada para implementar uma biblioteca no estilo RailGun. Embora a implementação pública não seja perfeita, pode servir como base para desenvolvimentos futuros.
Este projeto está licenciado sob a Licença MIT - consulte o arquivo LICENSE para obter detalhes.