Shadow VTable钩子实现失败求助:类地址已变更但钩子未生效
Shadow VTable钩子实现失败求助:类地址已变更但钩子未生效
嘿,我仔细看了你的Shadow VMT钩子代码,发现几个关键问题导致钩子没生效,咱们逐个拆解分析:
核心问题:修改的是局部变量,而非实际的虚表指针
你代码里的*(void**)&vtable = allocated_vtable;完全没作用到目标程序的虚表上——vtable是你do_stuff函数里的局部指针变量,你修改的只是这个局部变量本身的地址,和目标程序里的类实例、全局虚表一点关系都没有。
Shadow VMT的核心是替换类实例中的虚表指针(类实例的第一个成员就是虚表指针),而不是折腾你自己函数里的局部变量。
虚表方法数量计算的潜在风险
你用while (vtable[num_virtual_methods])统计虚表方法数的逻辑很不靠谱,很多编译器生成的虚表结尾并没有NULL值,这样会导致越界读取内存,轻则统计错误的方法数,重则直接触发崩溃。建议你通过反汇编或者查看目标程序的类定义,手动确认Example类的虚函数数量。
修正后的代码示例
假设你能拿到Example类的有效实例指针,修正后的do_stuff函数大概是这样:
__int64(__fastcall* sub_original)(void*); __int64 sub_hooked(void* arg) { std::printf("~ welcome\n"); return sub_original(arg); } void do_stuff() { // 第一步:获取Example类的有效实例指针(需要你自己实现,比如通过全局变量/内存扫描) Example* pExample = ...; // 拿到实例中的虚表指针(类实例的第一个成员就是虚表指针) std::uintptr_t** vtable_ptr = reinterpret_cast<std::uintptr_t**>(pExample); std::uintptr_t* original_vtable = *vtable_ptr; // 手动确认虚函数数量,这里假设Example有3个虚函数,要替换索引为1的第二个方法 const std::size_t num_virtual_methods = 3; auto allocated_vtable = new std::uintptr_t[num_virtual_methods]; std::memcpy(allocated_vtable, original_vtable, num_virtual_methods * sizeof(std::uintptr_t)); // 保存原始函数地址 *(void**)&sub_original = reinterpret_cast<void*>(allocated_vtable[1]); // 替换为钩子函数 allocated_vtable[1] = reinterpret_cast<std::uintptr_t>(&sub_hooked); // 关键操作:替换实例中的虚表指针为新创建的虚表 *vtable_ptr = allocated_vtable; }
额外注意事项
- 如果目标实例所在的内存是只读权限,需要先用
VirtualProtect修改内存权限为可写,替换完成后再改回去,避免触发内存保护错误。 - 一定要确保你获取的
pExample是有效的类实例指针,否则会直接导致崩溃。 - 全局虚表通常在只读数据段(.rdata),直接修改全局虚表会触发保护错误,Shadow VMT的正确姿势就是替换单个实例的虚表指针。
备注:内容来源于stack exchange,提问作者reiizl
相关产品推荐
相关产品推荐

