该函数并未在用户态中导出,不过有个用户态函数IsMenu调用了它,可以通过判断IsMenu中相关字节码的位置获取HMValidateHandle的地址。
bool FindHMValidateHandle(HMODULE user32)
{
bool result = false;
do {
PBYTE is_menu = (PBYTE)GetProcAddress(user32, "IsMenu");
if (!is_menu)
break;
for (int i = 0; i < 0x100; ++i) {
if (0xe8 == *is_menu++) {
ULONG offset = *(PULONG)is_menu;
kHMValidateHandle = (HMValidateHandle)(is_menu + 4 + offset);
break;
}
}
if (!kHMValidateHandle)
break;
result = true;
} while (false);
return result;
}
为什么可以这样做呢?我们用ida 分析一下 user32.dll
来看 ismenu 的代码,这个程序很短,只有几行,其中只有一个call指令,就是HMValidateHandle 。call 的机器码就是0xe8。
然后再看它的机器码,更短从0x77d46f0e 到 0x77d46f27 其中唯一的一个e8 就是call 指令。因此可以根据这个来找到HMValidateHandle 的地址,0xe8后面4个字节就是地址。