简单的POC库,通过NdrServerCall2或类似方法代理执行任意调用
为了创建一种通用的执行本地和远程代码的方法,我们设计了一种相对隐蔽的代码执行方式,内部称为RpcCraft(自身)和RpcExec(远程进程)。该技术利用了漏洞利用开发者熟知的方法,滥用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上会产生异常。这可以通过多种方式处理,但当前实现如下:
int FetchReturnValue(const PEXCEPTION_POINTERS ExceptionInfo) {
ExceptionInfo->ContextRecord->EFlags |= (1 << 16);
g_ReturnValue = (PVOID)ExceptionInfo->ContextRecord->Rax;
return EXCEPTION_CONTINUE_EXECUTION;
}
RPC调用受到CFG保护,这意味着要实现完全不受限制的代码执行,需要使用SetProcessValidCallTargets将目标标记为有效,或者修补RpcInvokeCheckICall。
RpcProxyInvoke项目展示了一种可被滥用的替代技术,用于实现RailGun风格的库。尽管公开的实现并不完美,但它可以作为进一步开发的基础。
本项目采用MIT许可证 - 详情请参见LICENSE文件。