Skip to content

Instantly share code, notes, and snippets.

@flatz
Forked from SeanCline/windbg-comcall.md
Created December 14, 2019 20:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flatz/59431d0cb2304bdfba9b1d665372a340 to your computer and use it in GitHub Desktop.
Save flatz/59431d0cb2304bdfba9b1d665372a340 to your computer and use it in GitHub Desktop.
WinDbg: Getting COM Call target from SendReceive2 stack frame.

Looking at a callstack that is making a COM call to another apartment, look for the SendReceive2 stack frame.

  0:053> kb
  # ChildEBP RetAddr  Args to Child              
  00 1532ed98 752e0ca9 00000002 1532ef44 00000001 ntdll!NtWaitForMultipleObjects+0xc
  01 1532ef1c 756dc2a0 1532eef4 1532ef44 00000000 KERNELBASE!WaitForMultipleObjectsEx+0xdc
  02 1532ef74 75bec1db 00000000 1532efcc 000003e8 user32!MsgWaitForMultipleObjectsEx+0x159
  03 1532efac 75beb438 1532efcc 00000001 1532efd0 combase!CCliModalLoop::BlockFn+0x101
  04 (Inline) -------- -------- -------- -------- combase!ModalLoop+0x50
  05 1532efd4 75cb4e2f ffffffff 00000000 1532f280 combase!ClassicSTAThreadDispatchCrossApartmentCall+0x133
  06 (Inline) -------- -------- -------- -------- combase!CRpcChannelBuffer::SwitchAptAndDispatchCall+0x3839
  07 1532f124 75bec6ac 12d8c33c 1532f280 1532f268 combase!CRpcChannelBuffer::SendReceive2+0x631
  08 (Inline) -------- -------- -------- -------- combase!ClientCallRetryContext::SendReceiveWithRetry+0x1d
  09 (Inline) -------- -------- -------- -------- combase!CAptRpcChnl::SendReceiveInRetryContext+0x27
  0a 1532f1e4 75bb3b8f 12d8c33c 1532f280 1532f268 combase!ClassicSTAThreadSendReceive+0x209
  0b (Inline) -------- -------- -------- -------- combase!CAptRpcChnl::SendReceive+0x8b
  0c 1532f244 75cb14a5 12d8c33c 1532f280 1532f268 combase!CCtxComChnl::SendReceive+0xf9
  0d 1532f25c 7596470c 134215b4 1532f2ac 759def05 combase!NdrExtpProxySendReceive+0x42
  0e 1532f268 759def05 359a4ea5 00000000 1532f6dc rpcrt4!NdrpProxySendReceive+0xe
  0f 1532f6a8 75cb1a1e 12ee7418 12ee7568 1532f6dc rpcrt4!NdrClientCall2+0x2d6
  10 1532f6c4 75bb3a83 00000008 00000007 1532f74c combase!ObjectStublessClient+0x6b
  11 1532f6d4 12859a06 134215b4 7ad8e84f 00000000 combase!ObjectStubless+0xf
  12 1532f74c 74f4f2e9 0c1e4e20 34fd899b 00000000 CONTOSO!DoSomething+0x216
  13 1532f784 74f4f2cd 00000000 1532f79c 75d0919f msvcr110!_beginthreadex+0xb4

What we need is the first argument to combase!CRpcChannelBuffer::SendReceive2 which, in this case, is: 12d8c33c.

Here's where things get tricky. Since we don't have the private symbols for that struct, and the !SIEExtsPub.ComCalls extension command is now defunct and hasn't been updated to the new layout of the struct, we'll have to wing it and figure it out ourselves.

  0:053> dc 0x12d8c33c
  12d8c33c  75ba5c10 75bc0928 75bb1ab4 adb1682c  .\.u(..u...u,h..
  12d8c34c  429b3908 2b59b182 e6a936e1 00000003  .9.B..Y+.6......
  12d8c35c  00000022 04cbbf68 00000000 00f7bf40  "...h.......@...

As I mentioned, the layout of this struct changes. What I've found works best on most versions of Windows is to pick the 4th DWORD after value 00000003, which is 00f7bf40. This does tend to move in various versions of combase.dll.

It points to another struct containing the target process and thread...

  0:053> dc 0x00f7bf40
  00f7bf40  00f7c238 0471a7b0 000005a0 00001cb0  8.....q.........

Got it! The target process id is 05a0 and the thread id is 1cb0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment