
Simple bibliothèque POC pour exécuter des appels arbitraires en les proxyant via NdrServerCall2 ou similaire
Pour créer un moyen général d'exécuter du code local et distant, nous avons conçu une méthode d'exécution de code relativement obscure, que nous appelons en interne RpcCraft (Self) et RpcExec (Remote Process). Cette technique exploite une méthodologie bien connue des développeurs d'exploits, en abusant des appels serveur RPC (Remote Procedure Call) tels que NdrServerCall2 ou NdrServerCallAll pour exécuter du code arbitraire.
Dans RPCRT4.dll, des fonctions comme NdrServerCall2, NdrServerCallAll et NdrServerCallNdr64 (un alias de NdrServerCallAll) sont implémentées comme des wrappers pour invoquer dynamiquement des fonctions liées aux fonctionnalités du serveur. Ces fonctions prennent un seul argument, un pointeur vers une structure RPC_MESSAGE.
Structure 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;
Pour initialiser le runtime sans se lier à un service, la fonction PerformRpcInitialization est utilisée. Cette fonction initialise en interne les structures nécessaires sans nécessiter de liaison manuelle.
Cette version publique de la technique a été développée comme POC pour démontrer la faisabilité, et elle génère actuellement une exception sur NdrGetBuffer en raison d'un Binding Handle manquant. Cela peut être traité de plusieurs manières, mais l'implémentation actuelle fait :
int FetchReturnValue(const PEXCEPTION_POINTERS ExceptionInfo) {
ExceptionInfo->ContextRecord->EFlags |= (1 << 16);
g_ReturnValue = (PVOID)ExceptionInfo->ContextRecord->Rax;
return EXCEPTION_CONTINUE_EXECUTION;
}
L'invocation RPC est protégée par CFG, ce qui signifie que pour obtenir une exécution de code complète et sans restriction, il est nécessaire soit de marquer la cible comme valide avec SetProcessValidCallTargets, soit de patcher RpcInvokeCheckICall.
Le projet RpcProxyInvoke démontre une technique alternative pouvant être abusée pour implémenter une bibliothèque de style RailGun. Bien que l'implémentation publique ne soit pas parfaite, elle peut servir de base pour un développement ultérieur.
Ce projet est sous licence MIT - voir le fichier LICENSE pour plus de détails.