How to determine the referenced COM object from System.__ComObject

Perhaps you are debugging your .NET Application and would like to know to which COM component an instance of System.__ComObject refers. Currently, I've only tested these steps in an .NET 2.0 x86 environment. Also, I'm using the incredible debugger extension developed by Rodney Viana which you can also
use by downloading NetExt from https://netext.codeplex.com/. Make sure to leave Rodney feedback and encourage him to continue to develop this powerful debugging tool. I'm also using the built in debugger extension (located in your .NET Framework folder for the version of the application you are using) SOS.dll.

Method 1: x86 With Public Symbols mscorwks

1. List stack objects and find the System.__ComObject
 
!wstack
05cb517c 04a28de4   0  2         16 System.__ComObject //This is our reference to the COM component
 
2. Now let's get the SyncBlock Address -4 and 1 level deep (to keep our output clean and simple)
 
0:037> dw 04a28de4-4 l1
04a28de0  0002
 
3. Now we can get the SyncBlock Address directly:

0:037> !sos.syncblk 0002
Index SyncBlock MonitorHeld Recursion Owning Thread Info  SyncBlock Owner
2 0597007c            0         0 00000000     none    05b7eb90 System.__ComObject

4. I haven't these steps on x64 so I would expect this to fail.
 
0:037> ?0597007c+1c
Evaluate expression: 93782168 = 05970098

0:037> dc 05970098 l1
05970098  0053afa0  //InteropSyncInfo

0:037> ?0053afa0+c
Evaluate expression: 5484460 = 0053afac

0:037> dc 0053afac l1
0053afac  004cdfd0  //RCW
 
0:037> ?0x004cdfd0+0x64
Evaluate expression: 5038132 = 004ce034
 
0:037> dc 004ce034 l1
004ce034  004d9b44  //IUnknown
 
0:037> dc 004d9b44 l1
004d9b44  68f289a0  //Vtable

5. You will need symbols for the COM component to know if this is a valid Vtable:

0:037> dds 68f289a0
68f289a0 68e559f0 example!Com::Component::QueryInterface
68f289a4 68e4ba80 example!Com::Component::AddRef
68f289a8 68e55a20 example!Com::Component::Release

Some follow up notes. If you don't have symbols but you see a component listed in the output, you could unassemble one of the functions to determine if it actually looks like the beginning of a function. Also, you could look the component up in the registry and see if it's a registered COM component. Also, depending upon the symbols you have, you may be able to find this information, regardless of the offset values I've used in the example, by noting the types I've highlighted in yellow in the above example.