嘿,我遇到了一个非常耗时的问题,我想我可能会在这里找到比我更好的经验的人,可以帮到我。其他服务的远程过程(我不知道是哪一个)
现在,在我听到关于不尝试任何事情的评论之前,
有一些非常好的应用程序可以完成我想要的功能,例如NtTrace,Strace而且大致oSpy最终也可以达到相同的结果。
但是我的应用程序具有一些非常困难的反调试技术,迫使我手动执行所有操作。
这是MSDN的NdrClientCall2拒绝条件
CLIENT_CALL_RETURN RPC_VAR_ENTRY NdrClientCall2(
  __in          PMIDL_STUB_DESC pStubDescriptor,
  __in          PFORMAT_STRING pFormat,
  __in_out       ...
);

,因此它使用PMIDL_STUB_DESC结构,其定义如下:
typedef struct _MIDL_STUB_DESC {
  void                                 *RpcInterfaceInformation;
  void*                                (__RPC_API *pfnAllocate)(size_t);
  void                                 (__RPC_API *pfnFree)(void*);
  union {
    handle_t              *pAutoHandle;
    handle_t              *pPrimitiveHandle;
    PGENERIC_BINDING_INFO pGenericBindingInfo;
  } IMPLICIT_HANDLE_INFO;
  const NDR_RUNDOWN                    *apfnNdrRundownRoutines;
  const GENERIC_BINDING_ROUTINE_PAIR   *aGenericBindingRoutinePairs;
  const EXPR_EVAL                      *apfnExprEval;
  const XMIT_ROUTINE_QUINTUPLE         *aXmitQuintuple;
  const unsigned char                  *pFormatTypes;
  int                                  fCheckBounds;
  unsigned long                        Version;
  MALLOC_FREE_STRUCT                   *pMallocFreeStruct;
  long                                 MIDLVersion;
  const COMM_FAULT_OFFSETS             *CommFaultOffsets;
  const USER_MARSHAL_ROUTINE_QUADRUPLE *aUserMarshalQuadruple;
  const NDR_NOTIFY_ROUTINE             *NotifyRoutineTable;
  ULONG_PTR                            mFlags;
  const NDR_CS_ROUTINES                *CsRoutineTables;
  void                                 *Reserved4;
  ULONG_PTR                            Reserved5;
} MIDL_STUB_DESC, *PMIDL_STUB_DESC;

这就是当我放一张breakpoi时在windbg中的样子NdrClientCall2函数中的nt
0:006> .echo "Arguments:"; dds esp+4 L5
Arguments:
06d9ece4  74cc2158 SspiCli!sspirpc_StubDesc
06d9ece8  74cc2322 SspiCli!sspirpc__MIDL_ProcFormatString+0x17a
06d9ecec  06d9ed00
06d9ecf0  91640000
06d9ecf4  91640000
0:006> .echo "PMIDL_STUB_DESC:"; dds poi(esp+4) L20
PMIDL_STUB_DESC:
74cc2158  74cc2690 SspiCli!sspirpc_ServerInfo+0x24
74cc215c  74cca1cd SspiCli!MIDL_user_allocate
74cc2160  74cca1e6 SspiCli!MIDL_user_free
74cc2164  74ce0590 SspiCli!SecpCheckSignatureRoutineRefCount+0x4
74cc2168  00000000
74cc216c  00000000
74cc2170  00000000
74cc2174  00000000
74cc2178  74cc1c52 SspiCli!sspirpc__MIDL_TypeFormatString+0x2
74cc217c  00000001
74cc2180  00060001
74cc2184  00000000
74cc2188  0700022b
74cc218c  00000000
74cc2190  00000000
74cc2194  00000000
74cc2198  00000001
74cc219c  00000000
74cc21a0  00000000
74cc21a4  00000000
74cc21a8  48000000
74cc21ac  00000000
74cc21b0  001c0000
74cc21b4  00000032
74cc21b8  00780008
74cc21bc  41080646
74cc21c0  00000000
74cc21c4  000b0000
74cc21c8  00020004
74cc21cc  00080048
74cc21d0  21500008
74cc21d4  0008000c
0:006> .echo "PFORMAT_STRING:"; db poi(esp+8)
PFORMAT_STRING:
74cc2322  00 48 00 00 00 00 06 00-4c 00 30 40 00 00 00 00  .H......L.0@....
74cc2332  ec 00 bc 00 47 13 08 47-01 00 01 00 00 00 08 00  ....G..G........
74cc2342  00 00 14 01 0a 01 04 00-6e 00 58 01 08 00 08 00  ........n.X.....
74cc2352  0b 00 0c 00 20 01 0a 01-10 00 f6 00 0a 01 14 00  .... ...........
74cc2362  f6 00 48 00 18 00 08 00-48 00 1c 00 08 00 0b 00  ..H.....H.......
74cc2372  20 00 2c 01 0b 01 24 00-a2 01 0b 00 28 00 b8 01   .,...$.....(...
74cc2382  13 41 2c 00 a2 01 13 20-30 00 f8 01 13 41 34 00  .A,.... 0....A4.
74cc2392  60 01 12 41 38 00 f6 00-50 21 3c 00 08 00 12 21  `..A8...P!<....!

那么我如何确切地知道它要与之通信的远程进程是什么,或者它正在使用什么管道进行通信?
就我而言从MSDN了解到,应该调用一个远程过程。如果我理解该权利,则意味着它应该调用远程函数,就像它是导出的dll函数一样。
PS:
设置此函数的主要原因是因为NdrClientCall2似乎很大。

#1 楼


那么,我如何准确地知道它要与之通信的远程进程是什么,或者它正在使用什么管道进行通信?


第一个步骤是找到RPC客户端接口。这可以通过NdrClientCall2()的第一个参数pStubDescriptor找到。在您的问题中,pStubDescriptor指向SspiCli!sspirpc_StubDesc


这是在windbg中的样子,当我在NdrClientCall2函数中放置断点时
/>
0:006> .echo "Arguments:"; dds esp+4 L5
Arguments:
06d9ece4  74cc2158 SspiCli!sspirpc_StubDesc



SspiCli!sspirpc_StubDescMIDL_STUB_DESC,在我的计算机上,这是其关联的值(通过IDA Pro):

struct _MIDL_STUB_DESC const sspirpc_StubDesc MIDL_STUB_DESC
<
    offset dword_22229B8,
    offset SecClientAllocate(x),
    offset MIDL_user_free(x),
    <offset unk_22383F4>,
    0,
    0,
    0,
    0,
    offset word_22224B2,
    1,
    60001h,
    0,
    700022Bh,
    0,
    0,
    0,
    1,
    0,
    0,
    0
>


如MSDN上所述,上面结构中的第一个字段“指向RPC客户端接口结构”。因此,我们可以将该地址处的数据解析为一个RPC_CLIENT_INTERFACE结构:
我们现在可以使用RpcView查找该接口GUID,以找到相关的DLL,运行进程和端点:



以找出具体的在LSASS进程中,SSPI RPC服务器正在使用端点,我们可以反向工程RPC_CLIENT_INTERFACE。在导出的函数InterfaceId中,我们看到以下调用:

stru_22229B8    dd 44h                  ; Length
                dd 4F32ADC8h            ; InterfaceId.SyntaxGUID.Data1
                dw 6052h                ; InterfaceId.SyntaxGUID.Data2
                dw 4A04h                ; InterfaceId.SyntaxGUID.Data3
                db 87h, 1, 29h, 3Ch, 0CFh, 20h, 96h, 0F0h; InterfaceId.SyntaxGUID.Data4
                dw 1                    ; InterfaceId.SyntaxVersion.MajorVersion
                dw 0                    ; InterfaceId.SyntaxVersion.MinorVersion
                dd 8A885D04h            ; TransferSyntax.SyntaxGUID.Data1
                dw 1CEBh                ; TransferSyntax.SyntaxGUID.Data2
                dw 11C9h                ; TransferSyntax.SyntaxGUID.Data3
                db 9Fh, 0E8h, 8, 0, 2Bh, 10h, 48h, 60h; TransferSyntax.SyntaxGUID.Data4
                dw 2                    ; TransferSyntax.SyntaxVersion.MajorVersion
                dw 0                    ; TransferSyntax.SyntaxVersion.MinorVersion
                dd offset RPC_DISPATCH_TABLE const sspirpc_DispatchTable; DispatchTable
                dd 0                    ; RpcProtseqEndpointCount
                dd 0                    ; RpcProtseqEndpoint
                dd 0                    ; Reserved
                dd offset _MIDL_SERVER_INFO_ const sspirpc_ServerInfo; InterpreterInfo
                dd 4000000h             ; Flags


要弄清楚4F32ADC8-6052-4A04-8701-293CCF2096F0中正在调用哪个特定函数,我们需要查看传递的sspisrv.dll数据至SspiSrvInitialize()。在上面的示例代码中,sspisrv.dll数据为:

RpcServerUseProtseqEpW(L"ncalrpc", 0xAu, L"lsasspirpc", 0);


如果将pFormat数据解析为NDR_PROC_HEADER_RPC结构,则得到:

00 48 00 00 00 00 06 00-4c 00 30 40 00 00 00 00 ...


NdrClientCall2可以看到,此RPC调用正在调用pFormat中的第6个RPC函数。我们可以再次使用RpcView获取第6个RPC函数的地址:



使用IDA Pro,我们可以在pFormat的地址proc_num处看到该函数:

handle_type = 0x00
Oi_flags    = 0x48
rpc_flags   = 0x00000000
proc_num    = 0x0006
stack_size  = 0x004C


RpcView还向我们展示了该函数原型的反编译:



(请注意,在您的计算机上,第6个函数可能不在虚拟地址sspisrv.dll上,第六个功能可能不是sspisrv.dll,但这仍然是您要使用的方法。)

这样,我们现在可以说以下内容:


RPC 0x7573159D调用的服务器代码在0x7573159D

SspirProcessSecurityContext()调用的RPC服务器在LSASS的进程中运行
NdrClientCall2()调用的端点名为sspisrv.dll

您在NdrClientCall2()中的NdrClientCall2()调用所调用的RPC服务器功能是lsasspirpc



评论


好吧,这让我很想!感谢那。但是对于我的问题的第二部分,是否有办法知道什么是-final-过程?您最终发现的是导出的初始化函数,该函数调用RpcServerUseProtseqEpW(),这不是真正的函数。还是我错过了什么?

– 0xAK
2015年1月30日23:00

还是更好,我应该在哪里放置BreakPoint?

– 0xAK
15年1月30日在23:44

我已经更新了上面的答案以回答该问题。

–詹森·格夫纳(Jason Geffner)
2015年1月31日0:50

是的,这正是我想要的。仅供以后参考。.您如何确定Struct参数类型的?您怎么知道MIDL_STUB_DESC.RpcInterfaceInformation的类型是msdn只是说它指向** RPC客户端接口结构**,而我在msdn的任何地方都看不到“ RPC_CLIENT_INTERFACE”。你是在哪里找到那个东西的。顺便说一句,谢谢你的回答

– 0xAK
2015年2月1日下午6:35

我想没有什么比真实的经验。万分感谢

– 0xAK
2015年2月1日15:31