ez8-co / emock

🐞 下一代C/C++跨平台mock库 (Next generation cross-platform mock library for C/C++)
Apache License 2.0
118 stars 35 forks source link

VS2019 MSVC x64场景下mock类的普通成员函数时会奔溃,不能成功,详情分析见描述 #27

Closed hongch911 closed 2 years ago

hongch911 commented 2 years ago

分析过程如下: HookMockObject::method函数中api的地址为0x00007ff797a93680 JmpOnlyApiHookImpl结构体初始化时api地址为0x00007ff797a93680,stub地址为0x0000021cf1320000 进入JmpCodeImpl结构体初始化时,from地址0x00007ff797a93680, to地址为0x0000021cf1320000 使用(unsigned long)to - (unsigned long)from公式计算后的结果为FFFF 8225 5988 C980。这个数值明显大于unsigned int能存放的大小。 因此m_code中存放的计算数值已经不对了。

然后我又参考mockcpp的源代码,在JmpCodeImpl的构造函数中,修改为

if BUILD_FOR_X64

   ::memcpy(m_code, jmpCodeTemplateLong, sizeof(jmpCodeTemplateLong));
   set_jmp_code_long(m_code, from, to);

elif BUILD_FOR_X86

   ::memcpy(m_code, jmpCodeTemplate, sizeof(jmpCodeTemplate));
   set_jmp_code(m_code, from, to);

endif

其中 const unsigned char jmpCodeTemplateLong[] = { 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

inline void set_jmp_code_long(unsigned char base[], const void from, const void to) { (uintptr_t)(base + 6) = (uintptr_t)to; } 这样处理后mock类的普通成员函数可以成功,但是类实例的成员变量地址被修改到了,导致类析构时奔溃。

mock的思路没有看懂,所以代码修改不动,还请指导一下。

orca-zhang commented 2 years ago

你好,收到反馈,非常感谢详尽的信息,可以看出长跳应该是unsigned long数值范围超了,应该考虑改用int64,近期尝试修复。

hongch911 commented 2 years ago

498a38b这次提交后的代码,在msvc x64上会在hook的函数执行时异常。 0x00007FF66F1E0000 处(位于 LibTest.exe 中)引发的异常: 0xC0000005: 执行位置 0x00007FF66F1E0000 时发生访问冲突。 为了能编译成功,JmpCode.h中需要添加 #include

orca-zhang commented 2 years ago

你好,#26 有朋友发现是因为数值类型问题导致的,目前已尝试修复