C++对象模型小探索

class base {
public:
    base():a(10),b(11){}
    virtual void fa(){ std::cout << "base a function...\n";}
    virtual void fb(){ std::cout << "base b function...\n";}
    
public:
    int a;
    int b;
    std::string c{"angel"};
};

class derived: public base {
public:
    void fa() override { std::cout << "derived a function ...\n";}
    void fb() override { std::cout << "derived b function...\n"; }
    void fc() { std::cout << "derived c function...\n";}
public:
    int c;
};



int main(int argc, char** argv)
{
    std::cout << "class base size : " << sizeof(base) << std::endl;
    std::cout << "class derived size: " << sizeof(derived) << std::endl;
    
    derived* pd = new derived();
    base* pb = new derived();
 
    using func= void(*)();
    
    long int vptr1 = reinterpret_cast<long int>(pb);
    long int vptr2 = reinterpret_cast<long int>(pd);
    
    long int* p = (long int*)vptr1;
    long int* p1 = (long int*)vptr2;
    std::cout << "p  " <<  p << std::endl;
    std::cout << "p1 " <<  p1 << std::endl;
    
    long int* vtaddr = (long int*)(*p);
    long int* vtaddr2 = (long int*)(*p1);
    std::cout << "vtaddr  " << vtaddr << std::endl;
    std::cout << "vtaddr2 " << vtaddr2 << std::endl;
    
    
    func* ptr = (func*)(vtaddr);
    (*ptr)();
    func* ptrb = (func*)(vtaddr+1);
    (*ptrb)();
    
    
    func* bptr = (func*)(vtaddr2);
    (*bptr)();
    func* bptrb = (func*)(vtaddr2+1);
    (*bptrb)();
    
    std::cout << *(int*)(long int*)(vptr1+8) << std::endl;
    std::cout << *(int*)(long int*)(vptr1+12) << std::endl;
    std::cout << std::string((char*)(long int*)(vptr1+16))<< std::endl;
    
    
    pd->fa();
    pb->fa();
    
    

    return 0;
}


以上代码强制调用vtable指向的函数,从安全性角度讲:可以替换虚表的任何函数。

结果是:

 class base size : 40
 class derived size: 48
 p  0x102a84240
 p1 0x102a84210
 vtaddr  0x10000b090
 vtaddr2 0x10000b090
 derived a function ...value is ...34
 derived b function...
 derived a function ...value is ...-1746446496
 derived b function...
 10
 11
 
 angel
 derived a function ...value is ...10
 derived a function ...value is ...10

强行使用裸指针调用,得到的成员值明显不对。推测是没有代入隐含的this指针。

下次谈谈如何基于本案列做C++的逆向工程。

发表评论

电子邮件地址不会被公开。 必填项已用*标注