https://pixabay.com/en/hong-kong-city-urban-skyscrapers-1990268/
Agenda • Component Object Model (COM) Internals • Attacking COM • Enumerating attack surface for EoP • Reverse engineering COM components • Bugs and “Features” We’ll be using my OleViewDotNet tool throughout. https://github.com/tyranid/oleviewdotnet 2
3 https://pixabay.com/en/ford-mustang-engine-hood-bonnet-1242192/
“Any sufficiently complex middleware is indistinguishable from magic.” Arthur C. Clarke’s Third Law of Software Development 4
In the Beginning was OLE 5
Interoperability Heaven Visual Basic Visual Basic C C COM C++ C++ .NET .NET Component Consumer Component Provider 6
Common ABI Object Pointer VTable Pointer Method1 Pointer Method2 Pointer Implementation Specific Data ... MethodN Pointer struct ObjectVTable { void (* SetInt )( struct Object * This, int i ); int (* GetInt )( struct Object * This); }; Object pointer is first. Arguments passed left to right struct Object { VTable Pointer at start struct ObjectVTable * Vtbl ; // Implementation specific data follows. }; struct Object * obj ; obj -> Vtbl -> SetInt ( obj , 1234 ); 7
The Casting Problem struct Interface1 { virtual void A () = 0 ; Define a }; pure virtual “Interface” struct Interface2 { virtual void B () = 0 ; }; Derive from Interface and class Object : public Interface1 , implement public Interface2 { void A () {} void B () {} }; // Okay (mostly). Interface1 * intf1 = new Object ; No no no!!! // Incredibly bad idea. Interface2 * intf2 = ( Interface2 *) intf1 ; 8
IUnknown, the Root of all COM Evil DEFINE_GUID ( IID_IUnknown , 00000000-0000-0000-C000-000000000046" ); struct IUnknown { HRESULT QueryInterface ( GUID & iid , void ** ppv ); LONG AddRef (); Used to Interfaces defined using a LONG Release (); reference count 128 bit Globally Unique ID. }; the object. struct Interface1 : public IUnknown {}; struct Interface2 : public IUnknown {}; Interface2 * intf2 ; if ( intf1 -> QueryInterface ( IID_Interface2 , ( void **)& intf2 ) >= 0 ) { Cast is a GIANT code // Success, we can call methods. smell! intf2 -> Release (); ¯\_( ツ )_/¯ } 9
Class Registration 10
Class Factories DEFINE_GUID ( IID_ClassFactory , "00000001-0000-0000-C000-000000000046" ); struct IClassFactory : public IUnknown { HRESULT CreateInstance ( IUnknown * pUnkOuter , REFIID riid , void ** ppvObject ); HRESULT LockServer ( BOOL fLock ); }; 11
Creating Class Factories and Instances HRESULT CoGetClassObject ( Specifies what type of server to lookup: REFCLSID rclsid , ● CLSCTX_INPROC_SERVER DWORD dwClsContext , ● CLSCTX_INPROC_HANDLER ● CLSCTX_LOCAL_SERVER COSERVERINFO * pServerInfo , ● CLSCTX_REMOTE_SERVER REFIID riid , LPVOID * ppv HRESULT CoCreateInstanceEx ( ); REFCLSID rclsid , IUnknown * punkOuter , DWORD dwClsCtx , Specify remote server COSERVERINFO * pServerInfo , information is required (more on this later). DWORD dwCount , MULTI_QI * pResults ); 12
In-Process Server Process ● DLL server filename specified in InProcServer32 key. Class Instance ● DLL loaded into process and class factory created by calling exported method: Client Class Factory HRESULT DllGetClassObject ( REFCLSID rclsid , REFIID riid , LPVOID * ppv ); server.dll 13
COM Apartments Process Thread X Thread Y STA X STA Y Instance Instance Instance Instance Instance Instance Thread A Thread B MTA or NTA Instance Instance Instance HRESULT CoInitializeEx ( COINIT_APARTMENTTHREADED LPVOID pvReserved , or DWORD dwCoInit COINIT_MULTITHREADED ); 14
Multi-Threaded Apartments (MTA) Process Thread X Thread Y MTA Client Y Instance Client X 15
Single Threaded Apartments (STA) Process Thread X Thread Y STA X STA Y Instance Client 16
Single Threaded Apartments (STA) Process Thread X Thread Y STA X STA Y Instance Client Proxy 17
Single Threaded Apartments (STA) Process Thread X Thread Y STA X STA Y Instance Client Proxy Marshaling Send STA HWND Message 18
Single Threaded Apartments (STA) Process Thread X Thread Y STA X STA Y Instance Client Unmarshaling Stub Proxy Send STA HWND Message 19
The Mystery Window HWND hwnd = FindWindowEx ( HWND_MESSAGE , NULL, NULL, NULL); while ( hwnd ) { WCHAR name [ 256 ] = {}; if ( GetWindowText ( hwnd , name , _countof ( name )) && _wcsnicmp ( name , L"ole" , 3 ) == 0 ) { DWORD pid = 0 ; DWORD tid = GetWindowThreadProcessId ( hwnd , & pid ); printf ( "%p %5d %5d %ls\n" , hwnd , pid , tid , name ); } hwnd = GetNextWindow ( hwnd , GW_HWNDNEXT ); } “Main” STA window. Per-Thread STA window. 20
Local Server Activation DCOM Activator (part of RPCSS) Server Process Client Process Instance Client Stub Proxy RPC Server RPC Client ALPC Channel 21
Local Server Activation RPCSS System Activator Send Request to System Activator Client Process Client 22
Local Server Activation RPCSS System Activator Create New Process Register Process Activator (if necessary) Server Process Client Process System Client Activator 23
Local Server Activation RPCSS System Activator Pass Activation Properties to Get Marshaled Result In-Process Activator Server Process Client Process System Client Activator Instance 24
Local Server Activation RPCSS System Activator Pass back result to client Server Process Client Process System Client Activator Connect to Instance Instance 25
System Activator DEFINE_GUID ( IID_ISystemActivator , "000001a0-0000-0000-c000-000000000046" ) struct ISystemActivator : public IUnknown { HRESULT GetClassObject ( IActivationPropertiesIn * pActProperties , IActivationPropertiesOut ** ppActProperties ); HRESULT CreateInstance ( IUnknown * pUnkOuter , IActivationPropertiesIn * pActProperties , IActivationPropertiesOut ** ppActProperties ); }; 26
Activation Properties In struct CustomHeader { DWORD totalSize ; DWORD headerSize ; DWORD dwReserved ; DWORD destCtx ; CustomHeader DWORD cIfs; CLSID classInfoClsid ; Property 1 CLSID *pclsid; DWORD *pSizes; Property 2 CustomOpaqueData *opaqueData; }; Property 3 Property 4 List of GUIDs and Sizes of following Property Blobs struct InstantiationInfoData { CLSID to CLSID classId ; create. enum ACTIVATION_FLAGS { DWORD classCtx ; ACTVFLAGS_DISABLE_AAA , DWORD actvflags ; ACTVFLAGS_ACTIVATE_32_BIT_SERVER , long fIsSurrogate ; ACTVFLAGS_ACTIVATE_64_BIT_SERVER , DWORD cIID ; ACTVFLAGS_NO_FAILURE_LOG , DWORD instFlag ; ACTVFLAGS_WINRT_LOCAL_SERVER , ACTVFLAGS_WINRT_PER_USER_OK , IID * pIID ; ACTVFLAGS_APPCONTAINER , DWORD thisSize ; List of IIDs to }; COMVERSION clientCOMVersion ; query for. }; 27
Activation Properties Out struct PropsOutInfo { DWORD cIfs ; struct MInterfacePointer { IID * piid ; unsigned long ulCntData ; HRESULT * phresults ; byte abData []; MInterfacePointer ** ppIntfData ; }; }; 28
It’s like Marshaling Cats 1 = Standard OBJREF 4 = Custom OBJREF ‘MEOW’ OBJREF Type IID (lower 64 bits) IID (upper 64 bits) Flags References CLSID (lower 64 bits) Object Exporter ID (OXID) CLSID (upper 64 bits) Object ID (OID) Reserved Data Size Interface Pointer ID (IPID) IPID (upper 64 bits) Custom Data Binding information for remote access Standard OBJREF Custom OBJREF 29
Standard Unmarshaling RPCSS System Object Resolver Activator Resolve OXID Binding Server Process Client Process Object Exporter ID (OXID) Object ID (OID) Instance Interface Pointer ID (IPID) Client IPIDTable ALPC OLEXXXX 30
Standard Unmarshaling RPCSS System Object Resolver Activator Server Process Client Process Object Exporter ID (OXID) Object ID (OID) Instance Interface Pointer ID (IPID) Client Server is at ncalrpc:[OLEXXXXX] IPIDTable ALPC OLEXXXX 31
Standard Unmarshaling RPCSS System Object Resolver Activator Server Process Client Process Object Exporter ID (OXID) Object ID (OID) Instance Interface Pointer ID (IPID) Client RPC Client IPIDTable ALPC OLEXXXX IPID@ncalrpc:[OLEXXXX] 32
Standard Unmarshaling RPCSS System Object Resolver Activator Server Process Client Process UUID ipid ; RpcBindingInqObject ( Binding , & ipid Instance ); IPIDTable :: Lookup ( ipid )-> Invoke (); Client RPC Client IPIDTable ALPC OLEXXXX 33
Standard Unmarshaling RPCSS System Object Resolver Activator Server Process Client Process Instance Client RPC Client IPIDTable ALPC OLEXXXX 34
Interface Proxies and Stubs 35
Interface Proxy-Stub Factory DEFINE_GUID ( IID_IPSFactoryBuffer , "D5F569D0-593B-101A-B569-08002B2DBF7A" ) struct IPSFactoryBuffer : public IUnknown { HRESULT CreateProxy ( IUnknown * pUnkOuter , REFIID riid , IRpcProxyBuffer ** ppProxy , void ** ppv ); HRESULT CreateStub ( REFIID riid , IUnknown * pUnkServer , IRpcStubBuffer ** ppStub ); }; 36
Recommend
More recommend