C++ 在不调试正在运行的程序的情况下计算对象的内存布局?

C++ 在不调试正在运行的程序的情况下计算对象的内存布局?,c++,reverse-engineering,ida,C++,Reverse Engineering,Ida,我正在做一个逆向工程项目。我正在使用IDA Pro和Hex-Rays反编译器。我遇到了代码块,我知道有一个对象,有一个对该对象的方法调用,但它以一种我无法理解的方式显示出来。例如: if ( (*(*interfacePtr + 24))(interfacePtr, &v23) >= 0 ) 这里我知道interfacePtr指向一个ICLRRuntimeHost对象。(C++,.NET CLR运行时)但是。。。。我不知道*(*interfacePtr+24)是什么。我可以说这

我正在做一个逆向工程项目。我正在使用IDA Pro和Hex-Rays反编译器。我遇到了代码块,我知道有一个对象,有一个对该对象的方法调用,但它以一种我无法理解的方式显示出来。例如:

 if ( (*(*interfacePtr + 24))(interfacePtr, &v23) >= 0 )

这里我知道interfacePtr指向一个ICLRRuntimeHost对象。(C++,.NET CLR运行时)但是。。。。我不知道*(*interfacePtr+24)是什么。我可以说这是一个方法,但如何计算+24的位置?

类的vtable只是指向函数的指针列表。它为每个虚函数包含一个指针,顺序是:非常非常顶级的基类,下一个基类,它的子类。大多数派生类

例如:

struct A {
    virtual ~A() {}
    virtual void foo() = 0;
}
struct B : public A {
    virtual void foo() { // do something }
    virtual void bar() { // do something else }
}
B的vtable将按以下顺序包含:

  • ~A
  • 酒吧
(A的指针必须放在第一位,这样代码中具有指向该对象的类型为A的指针的部分就可以使用相同的vtable;该代码不知道底层对象实际上是B。)

如果您查看的是32位源代码,指针是4个字节,因此24=4*6,您查看的是第7个虚拟函数(索引从0开始)。如果你是64位的,指针是8字节,所以24=8*3,你要找第四个。实际上,我没有使用IDA的“转换为C++”功能,所以24可能实际上是表中的第24个条目


确认的简单方法:编写自己的程序。声明ICLRRuntimeHost类型的变量。调用您怀疑的函数(基于查看头文件并计数到7或4,取决于比特数,如果我误解了您的示例,则为24)。查看生成的汇编代码,并确认索引是否正确。(在这类事情上,我总是以一个为准,所以这将提供一个检查。)

看看
mscoree.h
ICLRRuntimeHostVtbl
ICLRRuntimeHostVtbl
的定义

大致翻译成hexrays可以理解的东西,它们看起来是这样的:

struct ICLRRuntimeHost {
    ICLRRuntimeHostVtbl *vtbl;
};
struct ICLRRuntimeHostVtbl {
    _DWORD (*QueryInterface)(ICLRRuntimeHost*, _DWORD*, void**);
    _DWORD (*AddRef)(ICLRRuntimeHost*);
    _DWORD (*Release)(ICLRRuntimeHost*);
    _DWORD (*Start)(ICLRRuntimeHost*);
    _DWORD (*Stop)(ICLRRuntimeHost*);
    _DWORD (*SetHostControl)(ICLRRuntimeHost*, void*);
    _DWORD (*GetCLRControl)(ICLRRuntimeHost*, void**);
};
interfacePtr->GetCLRControl(&v23);
您的变量interfacePtr的类型应为:ICLRRuntimeHost,然后您的代码应按如下方式反编译:

struct ICLRRuntimeHost {
    ICLRRuntimeHostVtbl *vtbl;
};
struct ICLRRuntimeHostVtbl {
    _DWORD (*QueryInterface)(ICLRRuntimeHost*, _DWORD*, void**);
    _DWORD (*AddRef)(ICLRRuntimeHost*);
    _DWORD (*Release)(ICLRRuntimeHost*);
    _DWORD (*Start)(ICLRRuntimeHost*);
    _DWORD (*Stop)(ICLRRuntimeHost*);
    _DWORD (*SetHostControl)(ICLRRuntimeHost*, void*);
    _DWORD (*GetCLRControl)(ICLRRuntimeHost*, void**);
};
interfacePtr->GetCLRControl(&v23);

你不觉得在一个逆向工程论坛上回答这个问题更好吗?或者可能是IDA/hex-rays论坛,在为这个软件支付了高昂的价格后,您应该可以访问这个论坛?IDA可以解析C头文件进行结构声明
ICLRRuntimeHost
是在Windows SDK
mscoree.h
文件中定义的,通过一些工作,您应该能够将此文件提供给IDA,或者至少将类和vtable声明提取到另一个文件并解析它。在IDA定义了这个类之后,您可以简单地告诉Hex Rays,
interfacePtr
ICLRRuntimeHost
(按Y键或右键单击变量名)类型,它将更新显示以包含函数名。@snemark我认为这个问题是完全正确的,考虑到编程也是如此,最后。。。。这就是我的问题的真正含义。如果我对产品有问题,我会使用产品讨论板。然而,这只是因为我对本机Windows可执行文件的底层机制了解不够。。。不是我对IDA或Hex-Rays反编译器有问题。@DCoder我只是将vtable与调用中指定的方法偏移量关联起来。。。但我一定会尝试一下你的方法。自动关联会好得多。:)我是否正确地假设您打算声明B扩展A?除了我上面的评论之外,在阅读此psuedocode时查看mscoree.h与整个vtable排序方案非常匹配。看来这是我丢失的重要一环染料,B应延伸A。固定。