【RPC】GodPotato原理分析之RPCSS

概述:在 GodPotato原理分析 文中,描述了 GodPotato 的大致逻辑,但是对核心的处理操作部分没有处理,也就是——RPCSS 的接口 Hook 部分,本文就这一部分进行记录。

调试环境

Windows Server 2016

前文:GodPotato原理分析

调试

代码部分我们已经了解了,那么调试部分就比较简单了,双机调试挂载目标进程,在 combase!_UseProtseq 处下断点即可。当然,整体的流程可以结合 IDA 反汇编的代码查看。

UseProtseq 函数原型

⚠️ 注意 UseProtseq 在不同版本下的参数可能不同

1
2
3
4
5
6
__int64 __fastcall UseProtseq(
void *hRpc,
unsigned __int16 wTowerId,
unsigned int *pdwTCPPort,
tagDUALSTRINGARRAY **ppsaNewBindings,
tagDUALSTRINGARRAY **ppsaSecurity)

触发断点

在 GodPotato 源码中,调用 unmarshalTrigger.Trigger() 就触发断点了,可以先查看下相关入参:

1
2
3
dt /v
# 或者
dx -r1 Debugger.State.Scripts.CodeFlow.Contents.host.currentThread.Stack.Frames[0]

主要关注参数 ppsaNewBindings 就行

代码中对 ppsaNewBindings 的使用就只有 CopyStringArray

call combase!CopyStringArray 处添加断点,然后看执行完成后的内容就行。单步跳过,查看写入的内容

可以看到其写入的内容由三部分,WNameEntrieswSecurityOffsetaStringArray

  • WNameEntries: aStringArray 的长度
  • wSecurityOffsetUseProtseq 的最后一个参数的长度

其中 aStringArray 的内容为 ncalrpc:[OLE9EC507FE2C47565F9B30D6BC6C29]。而 GodPotato 则修改了这一部分逻辑,写入的 ncacn_np:localhost/pipe/GodPotato[\pipe\epmapper]

获取参数个数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
typedef struct
{
unsigned char FullPtrUsed : 1;
unsigned char RpcSsAllocUsed : 1;
unsigned char ObjectProc : 1;
unsigned char HasRpcFlags : 1;
unsigned char IgnoreObjectException : 1;
unsigned char HasCommOrFault : 1;
unsigned char UseNewInitRoutines : 1;
unsigned char Unused : 1;
} INTERPRETER_FLAGS, * PINTERPRETER_FLAGS;

typedef struct
{
unsigned char ServerMustSize : 1;
unsigned char ClientMustSize : 1;
unsigned char HasReturn : 1;
unsigned char HasPipes : 1;
unsigned char Unused : 1;
unsigned char HasAsyncUuid : 1;
unsigned char HasExtensions : 1;
unsigned char HasAsyncHandle : 1;
} INTERPRETER_OPT_FLAGS, * PINTERPRETER_OPT_FLAGS;

typedef struct _NDR_DCOM_OI2_PROC_HEADER
{
unsigned char HandleType; // The Oi header
INTERPRETER_FLAGS OldOiFlags; //
unsigned short RpcFlagsLow; //
unsigned short RpcFlagsHi; //
unsigned short ProcNum; //
unsigned short StackSize; //
// expl handle descr is never generated //
unsigned short ClientBufferSize; // The Oi2 header
unsigned short ServerBufferSize; //
INTERPRETER_OPT_FLAGS Oi2Flags; //
unsigned char NumberParams; //
} NDR_DCOM_OI2_PROC_HEADER, * PNDR_DCOM_OI2_PROC_HEADER;

RPC结构体解析

这里我参考 GodPotato 的 C# 版本实现了 C++ 版本的解析。同时尽可能的完善了部分细节以便于学习了解相关结构体。

链接:holdyounger/DecodeRPCStruct: Decode RPC_SERVER_INTERFACE Struct,take combase.dll as an example

对于 ProcString 字段的解析参考了 rpcrt4!MulNdrpInitializeContextFromProc 函数。

对应代码的 PE 文件可以使用 https://github.com/holdyounger/DecodeRPCStruct/actions/runs/12923652850


【RPC】GodPotato原理分析之RPCSS
https://hodlyounger.github.io/2025/01/13/A_OS/Windows/RPC/【RPC】GodPotato原理分析之RPCSS/
作者
mingming
发布于
2025年1月13日
许可协议