How to repeat vtable COM class?

How can I iterate / access a vtable of a COM class that will implement the methods of its open interfaces?

I need to access the vtable part, where all the addresses of the public methods of its interfaces are stored.

eg. Math is a COM object, its open interface "Operations" and "Sum" is a method of this interface, how can I get the address "Sum"?

+4
source share
2 answers

I won’t ask why you are doing this, but maybe this can help ... Every COM object should implement at least the IUnknown interface. Therefore, the first four bytes of an instance of a COM object are a pointer to an IUnknown object. The first four bytes of the IUnknown object (and any other object with virtual functions) is a pointer to vtbl.

(There is no error checking in this example, so please do not split the hair on this topic.)

I used an instance of IReferenceClock for demonstration.

int main() { CoInitialize( NULL ); IReferenceClock* pRefClock; HRESULT hr = CoCreateInstance( CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, IID_IReferenceClock, (void**)&pRefClock ); DWORD* pIUnknownAddress = (DWORD*)pRefClock; DWORD* pVTBLaddress = (DWORD*)*pIUnknownAddress; // for example, the next interface could be accessed like this DWORD* pNextInterfaceAddress = ( (DWORD*)pRefClock ) + 1; DWORD* pNextVTBLaddress = (DWORD*)*pNextInterfaceAddress; // and you would access virtual functions in the same way as QueryInterface, AddRef and Release below in this example HRESULT (__stdcall *pQueryInterfaceFunction)(void*, REFIID, void**); ULONG (__stdcall *pAddRef)( void* ); ULONG (__stdcall *pRelease)( void* ); // IUnknown looks like this: // // virtual HRESULT QueryInterface( REFIID riid, void** ppvObject); // virtual ULONG AddRef( void ); // virtual ULONG Release( void ); // // So, the first function in vtbl is QueryInterface, the second is AddRef... pQueryInterfaceFunction = (HRESULT (__stdcall*)(void*, REFIID, void**))*pVTBLaddress; pAddRef = (ULONG (__stdcall *)( void* ))*( pVTBLaddress + 1 ); pRelease = (ULONG (__stdcall *)( void* ))*( pVTBLaddress + 2 ); // Note: extra void* is actually this pointer.. see below that we pass pRefClock to every call IUnknown* pUnknown; UINT nRefCount; hr = pQueryInterfaceFunction( pRefClock, IID_IUnknown, (void**)&pUnknown ); if( SUCCEEDED( hr ) ) { nRefCount = pUnknown->Release(); ATLTRACE( TEXT( "nRefCount = %d\n" ), nRefCount ); } nRefCount = pAddRef( pRefClock ); ATLTRACE( TEXT( "nRefCount after AddRef() call = %d\n" ), nRefCount ); nRefCount = pRelease( pRefClock ); ATLTRACE( TEXT( "nRefCount after Release() call = %d\n" ), nRefCount ); nRefCount = pRefClock->Release(); CoUninitialize(); return 0; } 
+6
source

Sorry to answer the question, but I have to ask "where?"

If you mean how you can iterate through a vtable from a COM client, I don't think you can. On the client side, all you have is a proxy server that knows how to communicate (possibly a cross process or cross process) with a COM server. Perhaps you can explore the vtable of this proxy, but it will never be able to tell you the addresses of the functions inside the COM server.

Of course, if the server is actually running in another process, the address of the functions may be of little use to you. Even if the server is in the same process, but in a different apartment, getting function addresses can be dangerous: you can directly access functions, bypass COM interception and break server class assumptions around the calling thread, etc.

I assume the vtable iteration is a means to an end ...? Maybe post what you are actually trying to do, and I think COM probably has a way to do this.

0
source

Source: https://habr.com/ru/post/1303712/


All Articles