ole32dll 中的 ObjectStublessClientXX 是什么?

逆向工程 艾达 视窗 dll 动态分析
2021-06-24 08:27:42

当我进行动态反转时,我看到了ObjectStublessClientXXin 的用法ole32.dll

那是什么功能?它有什么作用?

有什么方法可以在两个进程之间传输消息?我看到在从1.exeso调用这些函数之后2.exe收到一条消息

1个回答

COM 是面向对象编程 (OOP) 中非常抽象的概念。要很好地理解这一点,您需要深入了解OOP 中继承虚拟方法表单独进程中的 COM以及使用 COM 进行数据编组

这些子例程是 COM 代理/存根 DLL 的一部分。当 COM 接口在单独的 DLL 文件中定义/实现时,将使用代理 DLL。将这些视为一个简单的函数调用,但使用 COM 虚拟表。在动态链接的情况下,DLL 有导出函数,EXE 文件调用它们。在代理/存根 COM 的情况下,底层函数在单独的 DLL 文件中定义。当可执行文件调用任何方法时,参数通过代理 DLL 被编组(即打包/组装)到所有真实事情发生的主 DLL。代理 DLL 仅包含这些方法的列表,也就是。虚拟方法表(vtable 或 vtbl)中的虚拟函数。因此,“ObjectStublessClient”只是虚函数。在简单的 C 语言中,这可以作为结构中的函数指针进行比较(过度简化)。

在 IDA 中,转到 View --> Open subviews --> Names 或按Shift+F4打开“Names Window”。搜索“ProxyVtbl”,您可以找到定义的虚拟表。下面是Ole32.DLL 文件IOleCacheControl 接口的示例。

  • 在 IDA 程序集视图中:
.rdata:00000001800CE9D0 ; $2F7D790A470334608EE0E1481017719B IOleCacheControlProxyVtbl
.rdata:00000001800CE9D0 _IOleCacheControlProxyVtbl dq offset IOleCacheControl_ProxyInfo; header.piid
.rdata:00000001800CE9D0                                         ; DATA XREF: .rdata:00000001800C9BF8↑o
.rdata:00000001800CE9D0                 db 0D0h, 0AEh, 0Fh, 80h, 1, 3 dup(0); gap8
.rdata:00000001800CE9D0                 dq offset IUnknown_QueryInterface_Proxy, offset IUnknown_AddRef_Proxy; Vtbl
.rdata:00000001800CE9D0                 dq offset IUnknown_Release_Proxy, offset ObjectStublessClient3_0; Vtbl
.rdata:00000001800CE9D0                 dq offset ObjectStublessClient4_0; Vtbl
.rdata:00000001800CEA08                 align 10h
  • 在 oleidl.h 文件中(C++ 接口):
MIDL_INTERFACE("00000129-0000-0000-C000-000000000046")
IOleCacheControl : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE OnRun( 
        LPDATAOBJECT pDataObject) = 0;
    
    virtual HRESULT STDMETHODCALLTYPE OnStop( void) = 0;
    
};
  • 在简单的 C 语言中:
GUID IID_IOleCacheControl = { 0x00000129, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };

typedef struct _IOleCacheControl IOleCacheControl, *PIOleCacheControl;

struct _IOleCacheControl {
    
    //0th IUnknown_QueryInterface_Proxy
    HRESULT (__fastcall *QueryInterface )( 
        PIOleCacheControl* This,
        GUID* riid, 
        PVOID* ppvObject
        );
    
    //1st IUnknown_AddRef_Proxy
    ULONG (__fastcall *AddRef )( 
        PIOleCacheControl* This
        );
    
    //2nd IUnknown_Release_Proxy
    ULONG (__fastcall *Release )( 
        PIOleCacheControl* This
        );
    
    //3rd ObjectStublessClient3_0
    HRESULT (__fastcall *OnRun )( 
        PIOleCacheControl* This,
        IDataObject* pDataObject
        );
    
    //4th ObjectStublessClient4_0
    HRESULT (__fastcall *OnStop )( 
        PIOleCacheControl* This
        );
    
};

前三个函数(QueryInterface、AddRef、Release)继承自(即复制自)IUnknown 接口然后其他剩余的虚函数用它们的偏移量命名。因此ObjectStublessClient3_0OnRun()ObjectStublessClient4_0OnStop()函数指针。我将调用约定更改为__fastcall因为 Windows 二进制文件通常使用该调用约定。

可以在我的存储库GitHub 中看到此方法的真实示例:WslReverse,其中显示了LxssManager.DLL的隐藏 COM 接口。

进一步阅读: