ObjectStubless只需调用ObjectStublessClient,将方法索引(来自ecx)作为参数传递。最后,ObjectStublessClient从vtable中挑出格式字符串,然后跳转到NdrClientCall2。与NdrStubCall2一样,此RPCRT4.DLL例程执行解释性封送处理和取消封送处理,就像正在使用已编译的代理和存根一样。
ObjectStublessClient实际上用简单的话做什么?通过其索引调用方法?如果是这样,那么就我而言,它将是IShellWindows接口的OnActivate吗?看来参数不匹配(第一个看起来像
this
吗?)#1 楼
确定[edi+1Ch]
指向的功能的传统方法如下:查找给定接口的接口定义语言(IDL)文件。在您的情况下,接口为
IShellWindows
。根据IShellWindows
的文档,其接口在IDL文件Exdisp.idl
中定义。该IDL文件包含在Windows SDK中(可免费下载),并将安装到C:\Program Files\Microsoft SDKs\Windows\v7.1A\Include\Exdisp.idl
之类的位置。您可以使用文本编辑器打开Exdisp.idl
文件,以查看IShellWindows
的接口定义:[
uuid(85CB6900-4D95-11CF-960C-0080C7F4EE85), // IID_IShellWindows
helpstring("Definition of interface IShellWindows"),
oleautomation,
dual,
odl,
]
interface IShellWindows : IDispatch
{
//Properties
[propget, helpstring("Get count of open Shell windows")]
HRESULT Count([out, retval] long *Count);
//Methods
[id(0), helpstring("Return the shell window for the given index")]
HRESULT Item([in,optional] VARIANT index, [out, retval]IDispatch **Folder);
[id(-4), helpstring("Enumerates the figures")]
HRESULT _NewEnum([out, retval] IUnknown **ppunk);
// Some private hidden members to allow shell windows to add and
// remove themself from the list. We mark them hidden to keep
// random VB apps from trying to Register...
[helpstring("Register a window with the list"), hidden]
HRESULT Register([in] IDispatch *pid,
[in] long hwnd,
[in] int swClass,
[out]long *plCookie);
[helpstring("Register a pending open with the list"), hidden]
HRESULT RegisterPending([in] long lThreadId,
[in] VARIANT* pvarloc, // will hold pidl that is being opened.
[in] VARIANT* pvarlocRoot, // Optional root pidl
[in] int swClass,
[out]long *plCookie);
[helpstring("Remove a window from the list"), hidden]
HRESULT Revoke([in]long lCookie);
// As an optimization, each window notifies the new location
// only when
// (1) it's being deactivated
// (2) getFullName is called (we overload it to force update)
[helpstring("Notifies the new location"), hidden]
HRESULT OnNavigate([in]long lCookie, [in] VARIANT* pvarLoc);
[helpstring("Notifies the activation"), hidden]
HRESULT OnActivated([in]long lCookie, [in] VARIANT_BOOL fActive);
[helpstring("Find the window based on the location"), hidden]
HRESULT FindWindowSW([in] VARIANT* pvarLoc,
[in] VARIANT* pvarLocRoot, /* unused */
[in] int swClass,
[out] long * phwnd,
[in] int swfwOptions,
[out,retval] IDispatch** ppdispOut);
[helpstring("Notifies on creation and frame name set"), hidden]
HRESULT OnCreated([in]long lCookie,[in] IUnknown *punk);
[helpstring("Used by IExplore to register different processes"), hidden]
HRESULT ProcessAttachDetach([in] VARIANT_BOOL fAttach);
}
我们可以看到
IShellWindows
接口具有以下vtable条目:- Count()
- Item()
- _NewEnum()
- Register()
- RegisterPending()
- Revoke()
- OnNavigate()
- OnActivated()
- FindWindowSW()
- OnCreated()
- ProcessAttachDetach()
但是,您也可以在IDL中看到
IShellWindows
接口是从IDispatch
继承的。 IDispatch
具有以下vtable项(来自OAIdl.idl
):IDispatch
中的OAIdl.idl
的IDL还指定IDispatch
继承自IUnknown
。 IUnknown
具有以下vtable条目(来自Unknwn.idl
):- GetTypeInfoCount()
- GetTypeInfo()
- GetIDsOfNames()
- Invoke()
所以现在我们知道
IShellWindows
继承自IDispatch
,后者继承自IUnknown
。因此,用于IShellWindows
的vtable的完整布局如下:- QueryInterface()
- AddRef()
- Release()
回头看一下您的代码,我们看到了对
*ppv+1Ch
的调用,从我们的代码中可以看到上面构造的vtable是对函数IShellWindows::Count()
的调用,而&var_C
是指向IShellWindows::Count()
的[out, retval] long *Count
参数的指针。确定
[edi+1Ch]
指向的函数的动态方式如下: 在调试器中运行上面的代码,在
call dword ptr [edi+1Ch]
上设置断点,然后查看指令调用的函数。通过[edi+1Ch]
进行以下操作:使用COMView(到COMView的回溯机器链接)检查
IShellWindows
接口:您可以在上面的屏幕截图中看到vtable offset 28(1Ch)处的函数是Count()
。
评论
我忘了提一下,您也许还可以告诉IDA将ppv解释为IShellWindows *变量,在这种情况下,IDA将向您显示[ppv + 1C]是对IShellWindows :: Count()的调用。
–詹森·格夫纳(Jason Geffner)
2013年9月22日16:58
好答案!正如Jason在他的评论中所述,一旦您知道某个变量的类型名称,IDA就会经常知道它是否是标准Windows COM类型。在这种情况下,您将转到数据部分中的ppv变量(突出显示该令牌并按Enter),然后按“ y”输入类型IShellWindows *。从那里,IDA的参数跟踪算法将提取许多参考,并自动为您填充。 (这些算法并不是完美的-不可能是由于所涉及的数学上的不可能-因此您可能仍需要手动填写一些算法)。
–滚轴
2013年9月25日在21:26
ComView似乎没有运行。有人可以确认是否可行吗?
– Nuzzolilo
7月7日7:44