相关资源:
Reversing Microsoft Visual C++ Part II: Classes, Methods and RTTI
Reversing C++
C++的RTTI一旦遇上了多重和虚继承,简直就是噩梦 -.-
这里介绍一下VC中用来表示RTTI的内部数据结构(具体可以参考《Reversing C++》里的描述)。利用下面的程序可以察看多态类的RTTI信息,我们可以借此熟悉一下RTTI到底长什么样子 :-)
#include <windows.h>
#include <iostream>
using namespace std;
#include <typeinfo>
using std::type_info;
typedef type_info TypeDescriptor;
struct PMD
{
ptrdiff_t mdisp; //vftable offset
ptrdiff_t pdisp; //vbtable offset
ptrdiff_t vdisp; //vftable offset (for virtual base class)
void Output();
};
struct _s_RTTICompleteObjectLocator;
struct _s_RTTIClassHierarchyDescriptor;
struct _s_RTTIBaseClassDescriptor;
struct _s_RTTICompleteObjectLocator
{
DWORD signature;
DWORD offset; //vftable offset to this
DWORD cdOffset;
TypeDescriptor *pTypeDescriptor;
_s_RTTIClassHierarchyDescriptor *pClassHierarchyDescriptor;
void Output(size_t tabs);
};
struct _s_RTTIClassHierarchyDescriptor
{
DWORD signature;
DWORD attributes; //bit 0 multiple inheritance, bit 1 virtual inheritance
size_t numBaseClasses; //at least 1 (all base classes, including itself)
_s_RTTIBaseClassDescriptor **pBaseClassArray;
void Output(size_t tabs);
};
struct _s_RTTIBaseClassDescriptor
{
TypeDescriptor *pTypeDescriptor;
size_t numBaseClasses; //direct base classes
PMD pmd; //Len=0xC
DWORD attributes;
_s_RTTIClassHierarchyDescriptor *pClassHierarchyDescriptor; //of this base class
void Output(size_t tabs);
};
void PMD::Output()
{
cout<<'('<<mdisp<<','<<pdisp<<','<<vdisp<<')';
}
void OutputTab(size_t tabs) {for(size_t i=0;i<tabs;++i) cout<<'/t';}
void _s_RTTICompleteObjectLocator::Output(size_t tabs)
{
OutputTab(tabs);
cout<<"CompleteObjectLocator:"<<endl;
OutputTab(tabs);
cout<<"signature:"<<signature<<endl;
OutputTab(tabs);
cout<<"offset:"<<offset<<endl;
OutputTab(tabs);
cout<<"cdOffset:"<<cdOffset<<endl;
OutputTab(tabs);
cout<<"pTypeDescriptor:"<<pTypeDescriptor->name()<<endl;
OutputTab(tabs);
cout<<"pClassHierarchyDescriptor:"<<endl;
pClassHierarchyDescriptor->Output(tabs+1);
cout<<endl;
cout<<endl;
}
void _s_RTTIClassHierarchyDescriptor::Output(size_t tabs)
{
OutputTab(tabs);
cout<<"signature:"<<signature<<endl;
OutputTab(tabs);
cout<<"attributes:"<<attributes<<endl;
for (size_t i=0;i<numBaseClasses;++i) {
OutputTab(tabs);
cout<<"base class "<<i+1<<":"<<endl;
pBaseClassArray[i]->Output(tabs+1);
}
}
void _s_RTTIBaseClassDescriptor::Output(size_t tabs)
{
OutputTab(tabs);
cout<<"pTypeDescriptor:"<<pTypeDescriptor->name()<<endl;
OutputTab(tabs);
cout<<"numBaseClasses:"<<numBaseClasses<<endl;
OutputTab(tabs);
cout<<"pmd:";
pmd.Output();
cout<<endl;
OutputTab(tabs);
cout<<"attributes:"<<attributes<<endl;
}
template<typename R> //only ptrdiff_t and size_t allowed
R ReadData(size_t ptr)
{
return *((const R *)ptr);
}
template<typename R,typename T>
R ReadData(const T *ptr)
{
return ReadData<R>((size_t)ptr);
}
//We assume the vftable is at offset 0
//If it is not the case, we assume the vbtable should be at offset 0, and with its first entry equal to 0 (point to itself).
//Then its second entry should contain the offset of vftable
template<typename T>
_s_RTTICompleteObjectLocator *GetCompleteObjectLocator(const T *ptr) //not have vbtable
{
ptrdiff_t offset=0;
if (ReadData<ptrdiff_t>(ReadData<size_t>(ptr))==0) offset=ReadData<ptrdiff_t>(ReadData<size_t>(ptr)+4);
return (_s_RTTICompleteObjectLocator *)(ReadData<size_t>(ReadData<size_t>((size_t)ptr+offset)-4));
}
#pragma warning(disable:4584)
class A1
{
public:
virtual ~A1() {}
private:
int data;
};
class A2
{
public:
virtual ~A2() {}
private:
int data;
};
class B1:virtual public A1,virtual public A2
{
public:
virtual ~B1() {}
virtual void FunB1() {}
private:
int data;
};
class B2:public A1,public A2
{
public:
virtual ~B2() {}
virtual void FunB2() {}
private:
int data;
};
class C:public B1,virtual public B2
{
public:
virtual ~C() {}
virtual void FunC() {}
private:
int data;
};
class D:public A1,virtual public A2
{
public:
virtual ~D() {}
virtual void FunD() {}
private:
int data;
};
class E:public C,public D
{
public:
virtual ~E() {}
virtual void FunE() {}
private:
int data;
};
#include <cstddef>
template<size_t N>
class Evil1:public Evil1<N-1>,public Evil1<N-2>
{
public:
virtual ~Evil1() {}
};
template<size_t N>
class Evil2:virtual public Evil2<N-1>,public Evil2<N-2>
{
public:
virtual ~Evil2() {}
};
template<size_t N>
class Evil3:public Evil3<N-1>,virtual public Evil3<N-2>
{
public:
virtual ~Evil3() {}
};
template<size_t N>
class Evil4:virtual public Evil4<N-1>,virtual public Evil4<N-2>
{
public:
virtual ~Evil4() {}
};
template<> class Evil1<0> {public: virtual ~Evil1() {}};
template<> class Evil1<1> {public: virtual ~Evil1() {}};
template<> class Evil2<0> {public: virtual ~Evil2() {}};
template<> class Evil2<1> {public: virtual ~Evil2() {}};
template<> class Evil3<0> {public: virtual ~Evil3() {}};
template<> class Evil3<1> {public: virtual ~Evil3() {}};
template<> class Evil4<0> {public: virtual ~Evil4() {}};
template<> class Evil4<1> {public: virtual ~Evil4() {}};
int main()
{
_s_RTTICompleteObjectLocator *pCompleteObjectLocator;
A1 a1;
A2 a2;
B1 b1;
B2 b2;
C c;
D d;
E e;
pCompleteObjectLocator=GetCompleteObjectLocator(&a1);
if (pCompleteObjectLocator) pCompleteObjectLocator->Output(0);
pCompleteObjectLocator=GetCompleteObjectLocator(&b1);
if (pCompleteObjectLocator) pCompleteObjectLocator->Output(0);
pCompleteObjectLocator=GetCompleteObjectLocator(&b2);
if (pCompleteObjectLocator) pCompleteObjectLocator->Output(0);
pCompleteObjectLocator=GetCompleteObjectLocator(&c);
if (pCompleteObjectLocator) pCompleteObjectLocator->Output(0);
pCompleteObjectLocator=GetCompleteObjectLocator(&d);
if (pCompleteObjectLocator) pCompleteObjectLocator->Output(0);
pCompleteObjectLocator=GetCompleteObjectLocator(&e);
if (pCompleteObjectLocator) pCompleteObjectLocator->Output(0);
Evil1<5> e1;
Evil2<5> e2;
Evil3<5> e3;
Evil4<5> e4;
pCompleteObjectLocator=GetCompleteObjectLocator(&e1);
if (pCompleteObjectLocator) pCompleteObjectLocator->Output(0);
pCompleteObjectLocator=GetCompleteObjectLocator(&e2);
if (pCompleteObjectLocator) pCompleteObjectLocator->Output(0);
pCompleteObjectLocator=GetCompleteObjectLocator(&e3);
if (pCompleteObjectLocator) pCompleteObjectLocator->Output(0);
pCompleteObjectLocator=GetCompleteObjectLocator(&e4);
if (pCompleteObjectLocator) pCompleteObjectLocator->Output(0);
}
转自:http://blog.csdn.net/vbvan/article/details/1907741