C++浅析——虚表和虚表Hook
来源:互联网 发布:阿里云报价单 编辑:程序博客网 时间:2024/06/15 07:01
为了探究虚表的今生前世,先来一段测试代码
虚函数类:
classCTest{public:intm_nData;virtualvoidPrintData(){printf("Data = 0x%x\n", m_nData);}};classCBase1{public:intm_nData;virtualvoid PrintData1() = 0;};classCBase2{public:intm_nData;virtualvoid PrintData2() = 0;};classCBaseTest : public CBase1, public CBase2{public:voidPrintData1(){printf("Data = 0x%x\n", CBase1::m_nData);}voidPrintData2(){printf("Data = 0x%x\n", CBase2::m_nData);}};测试代码:
voidTest(){CTestoCTest;CTest*pCTest = new CTest();pCTest->m_nData = 0x8888;pCTest->PrintData();oCTest.m_nData = 888;oCTest.PrintData();deletepCTest;}voidBaseTest(){CBaseTestoCBaseTest;oCBaseTest.PrintData1();}
1、虚表位于何处?
WinDbg显示虚表的地址的属性:Usage RegionUsageImage(代表此地址区域被映射到二进制文件的镜像),为只读属性。
2、同一个类对象的虚表位置相同吗?
同一个类对象的虚表位置相同。
加载模块的内存位置:0x00380000
虚表的VA = 0x003FDF2C - 0x00380000 = 0x0007DF2C3、虚表需要在加载后进行初始化吗?
否,虚表的位置在PE文件的 .rdata 节中,.rdata 是存放程序常量的地方,属性为只读
其VA = 0x003A9EFB- 0x00380000 = 0x00029EFB
由于该PE文件的基址 = 0x00040000(默认情况下)
故其未重定位前的虚拟地址 = 0x00040000 + 0x00029EFB = 0x00429EFB
由于x86平台文件都是小尾储存,倒过来写就是 FB 9E 42 00,即如图左上红圈所示
说明PE文件在编译好后已经将虚表和虚表中的虚函数地址填写完毕并写入.rdata区
4、多父类继承的虚表如何存放?
多重继承的子类对象实际上是将每个父类的完整数据按顺序依次排布,所以拥有每个父类的虚表,父类每个虚表的位置同样在每个父类的起始位置。
oCBaseTest对象内存分布
5、何为虚表Hook?通过以上对虚表的来龙去脉的分析,有IAT Hook基础的同学可以很容易的想到如何进行虚表Hook了。
5.1 改PE文件
直接改掉PE文件虚表位置的函数指针,指向自己伪造的虚表地址(当然必须保证自己的虚表函数指针有效,且函数调用形式和参数个数一致)
5.2 内存中Hook
当PE文件加载后,直接在内存中修改虚表函数指针(注意要去写保护,当然调试工具是没问题的)。
5.3 Hook测试(内存Hook的方式)
测试代码:
classCVFHook{public:typedefvoid (CVFHook::* MemberFunctionPtr)();public:staticBOOLHook(void* pVirtrulFunctionVA);private:voidPrintData();};
BOOLCVFHook::Hook(void* pVirtrulFunctionVA){HMODULEhHookedModule = ::GetModuleHandle(NULL);if (NULL == hHookedModule){_tprintf(_T("Get module handle fail\n"));returnFALSE;}//取重定位后的虚表地址MemberFunctionPtr* pMemberFunctionPtr = (MemberFunctionPtr*)((INT64)pVirtrulFunctionVA + (INT64)hHookedModule);//去除读写保护DWORDdwOldProtect = 0;::VirtualProtect(pMemberFunctionPtr, sizeof(pMemberFunctionPtr), PAGE_READWRITE, &dwOldProtect);*pMemberFunctionPtr = &CVFHook::PrintData;returnTRUE;}voidCVFHook::PrintData(){printf("PrintData is facked!!!\n");}然后再dll的加载位置传入虚表的VA参数调用即可:
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:{CVFHook::Hook((void*)0x0007DF2C);break;}case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break;}return TRUE;}
注意:这里我们伪造的虚函数 CVFHook::PrintData() 我直接用的是与要 Hook 的虚函数相同的成员函数形式,由于Release版的代码可能会被编译器优化掉函数调用形式,如果如此,需要我们手动编写汇编形式的虚函数代码。
启动测试程序 Console.exe ,然后用 APIMonitor 工具将 VirtrualFunctionHook.dll 注入,然后按任意键观察结果如下:我们来对前面的测试代码进行反汇编后观察:
1 0
- C++浅析——虚表和虚表Hook
- Hook导入表 —— 实现挂钩FreeLibaray和HOOK延迟加载模块的API
- C++虚表的hook
- hook浅析
- C++多态和虚表浅析
- hook虚表监控虚表
- C语言中结构和链表浅析
- 浅析 虚函数表
- 虚表浅析
- 360HOOK表,Hook过滤架构搭建
- 360HOOK表,Hook过滤架构搭建
- 浅析char*和char c[]
- 虚函数HOOK
- 虚函数Hook代码
- 输入表与HOOK
- Dll导出表Hook
- IAT HOOK、EAT HOOK和Inline Hook
- C#.Net 鼠标和键盘全局监控勾子(hook )
- 树莓派2引脚
- 左手代码,右手诗——那些年我写给老婆的诗
- 手动扩大栈内存
- 常见浏览器内核概述
- javascript基本知识学习第二天
- C++浅析——虚表和虚表Hook
- VMWare 虚拟机中无法启用键盘的解决办法(PS/2标准键盘)
- 远程桌面连接记录保存方法
- 在64位CAD上配置合适的ARX程序
- 使用weblogic的虚拟路径virtual-directory-mapping 在页面上展示文件服务器上的图片
- 排序专题之插入排序
- TP开启令牌验证
- Mybatis
- Python字符串操作集锦之ASCII码与字符互换