Hey i have a very time consuming problem, and i thought i might find someone here with better experience than mine that could help me out.I am reverse-engineering an application which at some point uses the NdrClientCall2 api to use a remote procedure of some other service (which i dont know which one that is)Now before i hear comments about not trying anything my selfThere are some really good applications to accomplish what i want like NtTrace, Strace and roughly oSpy can achieve the same result aswell eventually. But my application has some really hard anti-debugging techniques which force me to do everything manually.What eventually i want to achieve is know what procedure is being called and on what service \ process.Here is the NdrClientCall2 Decleration by MSDNCLIENT_CALL_RETURN RPC_VAR_ENTRY NdrClientCall2(  __in          PMIDL_STUB_DESC pStubDescriptor,  __in          PFORMAT_STRING pFormat,  __in_out       ...);so it uses the PMIDL_STUB_DESC struct which its definition is as the following: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;And here is how it looks like in windbg, when i put a breakpoint in the NdrClientCall2 function0:006> .echo Arguments:; dds esp+4 L5Arguments:06d9ece4  74cc2158 SspiCli!sspirpc_StubDesc06d9ece8  74cc2322 SspiCli!sspirpc__MIDL_ProcFormatString+0x17a06d9ecec  06d9ed0006d9ecf0  9164000006d9ecf4  916400000:006> .echo PMIDL_STUB_DESC:; dds poi(esp+4) L20PMIDL_STUB_DESC:74cc2158  74cc2690 SspiCli!sspirpc_ServerInfo+0x2474cc215c  74cca1cd SspiCli!MIDL_user_allocate74cc2160  74cca1e6 SspiCli!MIDL_user_free74cc2164  74ce0590 SspiCli!SecpCheckSignatureRoutineRefCount+0x474cc2168  0000000074cc216c  0000000074cc2170  0000000074cc2174  0000000074cc2178  74cc1c52 SspiCli!sspirpc__MIDL_TypeFormatString+0x274cc217c  0000000174cc2180  0006000174cc2184  0000000074cc2188  0700022b74cc218c  0000000074cc2190  0000000074cc2194  0000000074cc2198  0000000174cc219c  0000000074cc21a0  0000000074cc21a4  0000000074cc21a8  4800000074cc21ac  0000000074cc21b0  001c000074cc21b4  0000003274cc21b8  0078000874cc21bc  4108064674cc21c0  0000000074cc21c4  000b000074cc21c8  0002000474cc21cc  0008004874cc21d0  2150000874cc21d4  0008000c0: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!<....!So how exactly do i figure out what is the remote process it is going to communicate with, or what pipe it is using to communicate?As far as i understand from the MSDN, it is supposed to call a remote procedure. if i understand that right, it means it should call a remote function as if its an exported dll function. How can i set a breakpoint there?P.S:The main reason im posing this function is because the NdrClientCall2 seems to be pretty huge.
at the rpcrt4!NdrClientCall2 function - how does it know which pipe to use in order to transfer data to another process?
windbg;anti debugging
So how exactly do i figure out what is the remote process it is going  to communicate with, or what pipe it is using to communicate?The first step is to find the RPC client interface. This can be found via the first argument to NdrClientCall2(), named pStubDescriptor. In your question, pStubDescriptor points to SspiCli!sspirpc_StubDesc:And here is how it looks like in windbg, when i put a breakpoint in  the NdrClientCall2 function0:006> .echo Arguments:; dds esp+4 L5Arguments:06d9ece4  74cc2158 SspiCli!sspirpc_StubDescSspiCli!sspirpc_StubDesc is a MIDL_STUB_DESC, and on my computer, here are its associated values (via 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>As documented on MSDN, the first field in the structure above points to an RPC client interface structure. Thus, we can parse the data at that address as an RPC_CLIENT_INTERFACE struct: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             ; FlagsFrom the RPC_CLIENT_INTERFACE struct above, we can extract the InterfaceId GUID: 4F32ADC8-6052-4A04-8701-293CCF2096F0We can now look up that interface GUID with RpcView to find the associated DLL, running process, and endpoints:To find out which specific endpoint is being used by the SSPI RPC server in the LSASS process, we can reverse engineer sspisrv.dll. In the exported function SspiSrvInitialize(), we see the following call:RpcServerUseProtseqEpW(Lncalrpc, 0xAu, Llsasspirpc, 0);To figure out which specific function is being called in sspisrv.dll, we need to look at the pFormat data passed to NdrClientCall2. In your example code above, the pFormat data is:00 48 00 00 00 00 06 00-4c 00 30 40 00 00 00 00 ...If we parse the pFormat data as an NDR_PROC_HEADER_RPC structure, we get:handle_type = 0x00Oi_flags    = 0x48rpc_flags   = 0x00000000proc_num    = 0x0006stack_size  = 0x004CFrom proc_num, we can see that this RPC call is calling the 6th RPC function in sspisrv.dll. We can use RpcView again to get the address for the 6th RPC function:And with IDA Pro, we can see the function in sspisrv.dll at address 0x7573159D:.text:7573159D __stdcall SspirProcessSecurityContext(x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x) proc nearRpcView also shows us a decompilation of that function's prototype:(Note that on your computer, the 6th function might not be at virtual address 0x7573159D, and furthermore, the 6th function might not be SspirProcessSecurityContext(), but this is the approach you would use nonetheless.)As such, we can now say the following:The RPC server code for your NdrClientCall2() call is in sspisrv.dllThe RPC server for your NdrClientCall2() call is running in LSASS's processThe endpoint for your NdrClientCall2() call is named lsasspirpcThe RPC server function called by your NdrClientCall2() call in sspisrv.dll is SspirProcessSecurityContext()