virtual void eat() {
cout << "Fish eat" << endl;
}
};
class Cat : public Animal {
public:
virtual void breathe() {
cout << "Cat breathe" << endl;
}
virtual void eat() {
cout << "Cat eat" eat();
cout << "————–" << endl;
cout << "sizeof(fish) = " << sizeof(fish) << endl;
cout << "sizeof(cat) = " << sizeof(cat) << endl;
cout << "————–" eat();
delete fish;
delete cat;
return 0;
}
输出:

文章插图
通过上面的输出 , 可以看到 , fish和cat对象都只占据4个字节 。 因为这两个类都没有成员变量 , 唯一需要存储的就是一个虚函数表指针 。
以cat对象为例 , 看一下它的地址 , 是0x005cfc30:

文章插图
看一下这个地址起始的4个字节 , 是什么:

文章插图
虚表指针是0x000d9b90(这里需要注意字节顺序) 。
通过这个地址 , 找到虚函数表 , 里面有两个函数地址:

文章插图
查看这两个地址 , 都是指向了一个jmp指令 , 分别跳到了Cat类的两个虚函数 。

文章插图

文章插图
通过上面的实例 , 总结一下对象、虚函数表和虚函数代码之间的关系如下图所示:

文章插图
每个包含虚函数的类对象 , 在内存中都有一个指针 , 位于对象头部 , 指向的是一个虚函数表 , 表中的每一项都是虚函数地址 。
类继承后 , 如果重写了父类的虚函数 , 子类对象指向的表格中对应函数的地址将会更新为子类的函数 。
这样 , 使用父类指针指向子类对象 , 通过指针调用虚函数时 , 就能调用到子类重写的虚函数 , 从而实现多态性 。
既然是记录函数地址的表格 , 那就有存在被篡改的可能 , 这就是C++ virtable HOOK 。
通过篡改对应虚函数的地址 , 实现对相应函数调用的拦截 。
实施这种HOOK , 需要逆向分析目标C++对象的结构 , 掌握虚函数表中各个函数的位置 , 才能精准打击 。
上面几种HOOK , 修改的都是应用层的函数指针 , 而操作系统内核中还有一些非常重要的表格 , 它们的表项中记录了一些更加关键的函数 , HOOK这些表格中的函数是非常高危的操作 , 操作不当将导致操作系统崩溃 。 当然 , 高风险高回报 , HOOK这些函数 , 能实现一些非常强大的功能 , 是病毒、木马、安全软件非常爱干的事情 。
SSDT HOOK
系统调用是操作系统提供给应用程序的编程接口API , 应用程序通过这些API得以操作计算机的资源(如进程、网络、文件等) 。
特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
