如何让 IDA Pro 理解虚函数表?

逆向工程 艾达 C 六线谱 虚表 虚函数
2021-06-27 23:48:48

我正在反转使用 DirectX 7 的旧 DirectDraw 游戏。

我有一个LPDIRECTDRAWSURFACE7 g_lpDDSBackandg_lpDDSBack->BltFast正在被调用,但这就是它在 HexRays 中的反编译方式:

(*(int (__stdcall **)(struct IDirectDrawSurface7Vtbl *, int, int, LPDIRECTDRAWSURFACE7, RECT *, MACRO_DDBLTFAST))((int (__stdcall **)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD))g_lpDDSBack->QueryInterface + 7))(
                                      g_lpDDSBack,
                                      x,
                                      y,
                                      pgf2->lpDDSrcSurface,
                                      &pgf2->rect,
                                      DDBLTFAST_SRCCOLORKEY);

作为参考,这里是接口:

DECLARE_INTERFACE_( IDirectDrawSurface7, IUnknown )
{
    /*** IUnknown methods ***/
    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; // 0
    STDMETHOD_(ULONG,AddRef) (THIS)  PURE; // 1
    STDMETHOD_(ULONG,Release) (THIS) PURE; // 2
    /*** IDirectDrawSurface methods ***/
    STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE7) PURE; // 3
    STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE; // 4
    STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE7, LPRECT,DWORD, LPDDBLTFX) PURE; // 5
    STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE; // 6
    STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE7, LPRECT,DWORD) PURE; // 7
    // etc ...

因此,从 HexRays 代码中g_lpDDSBack->QueryInterface + 7,我们可以看到它正在调用g_lpDDSBack->BltFast. 但是HexRays为什么不直接调用BltFast呢?

2个回答

HexRays 不调用它,因为它不知道g_lpDDSBack->QueryInterface在常见情况下的值是什么

一般来说,您可以将结构定义为QueryInterface类型,其中该结构的成员根据相关的函数名称进行命名,然后您将看到调用为g_lpDDSBack->QueryInterface->BltFast.

原来是 IDA pro 中的一个错误。我似乎无法编辑我的原始问题,所以首先,我想指出我在原始问题中犯的一个错误。


g_lpDDSBack定义为 时struct IDirectDrawSurface7Vtbl *g_lpDDSBack;,这就是 HexRays 显示的输出:

(*(int (__stdcall **)(struct IDirectDrawSurface7Vtbl *, int, int, LPDIRECTDRAWSURFACE7, RECT *, MACRO_DDBLTFAST))((int (__stdcall **)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD))g_lpDDSBack->QueryInterface + 7))(
                                      g_lpDDSBack,
                                      x,
                                      y,
                                      pgf2->lpDDSrcSurface,
                                      &pgf2->rect,
                                      DDBLTFAST_SRCCOLORKEY);

g_lpDDSBack定义为 时LPDIRECTDRAWSURFACE7 g_lpDDSBack;,这就是 HexRays 显示的输出:

(*((int (__stdcall **)(int, int, int, _DWORD, int, signed int))g_lpDDSBack->lpVtbl + 7))(
                       g_lpDDSBack,
                       x,
                       y,
                       pgf2->lpDDSrcSurface,
                       &pgf2->rect,
                       DDBLTFAST_SRCCOLORKEY);

好的,现在这里是修复错误的说明(g_lpDDSBack定义为LPDIRECTDRAWSURFACE7 g_lpDDSBack;):

  1. 选择lpVtblin g_lpDDSBack->lpVtbl,按 y,然后将文本框的内容复制到记事本。在这种情况下,内容是struct IDirectDrawSurface7::IDirectDrawSurface7Vtbl *lpVtbl.
  2. 将类型更改为int lpVtbl并按确定
  3. 再次按 ylpVtbl并将类型更改回记事本中存储的原始类型。在这种情况下,它是struct IDirectDrawSurface7::IDirectDrawSurface7Vtbl *lpVtbl

执行此操作后,这就是 HexRays 中的样子(您可能必须先按 F5):

g_lpDDSBack->lpVtbl->BltFast(g_lpDDSBack,
                                      x,
                                      y,
                                      pgf2->lpDDSrcSurface,
                                      &pgf2->rect,
                                      DDBLTFAST_SRCCOLORKEY);