使用hippomocks模拟WinAPI时,如何在模拟函数内调用原函数?
在Hippomocks中模拟WinAPI并调用原函数的解决方法
要在Hippomocks的模拟函数里调用原WinAPI函数,核心是绕过Hippomocks的钩子,直接获取系统DLL中原始函数的地址,而非直接取进程内被替换后的函数地址。以下是针对CreateFile的具体实现步骤:
步骤1:定义原函数的类型别名
WinAPI的CreateFile分ANSI(CreateFileA)和Unicode(CreateFileW)两个版本,先对应定义函数指针类型:
// 以Unicode版本为例,ANSI版本替换为CreateFileA即可 typedef HANDLE(WINAPI* CreateFileWFunc)( LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile );
步骤2:获取原始函数的真实地址
在创建Hippomocks模拟之前,从kernel32.dll中加载未被钩子修改的原始函数地址:
// 全局/静态变量存储原始函数指针 CreateFileWFunc pOriginalCreateFileW = nullptr; // 在初始化阶段(创建mock前)执行 void InitOriginalFunc() { HMODULE hKernel32 = GetModuleHandle(L"kernel32.dll"); if (hKernel32) { pOriginalCreateFileW = reinterpret_cast<CreateFileWFunc>( GetProcAddress(hKernel32, "CreateFileW") ); } }
步骤3:编写模拟函数并调用原API
在模拟函数里直接调用上面获取的原始函数指针,再添加你的记录逻辑:
HANDLE WINAPI MyCreateFileMock( LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ) { // 调用原始WinAPI函数 HANDLE hFile = pOriginalCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); // 这里添加你的记录逻辑,比如日志、结果存储 if (hFile != INVALID_HANDLE_VALUE) { wprintf(L"[Mock记录] CreateFileW打开文件: %s,句柄: %p\n", lpFileName, hFile); } else { wprintf(L"[Mock记录] CreateFileW打开文件失败: %s,错误码: %lu\n", lpFileName, GetLastError()); } // 返回原API的结果 return hFile; }
步骤4:注册模拟函数
最后正常注册Hippomocks模拟即可:
// 先初始化原始函数指针 InitOriginalFunc(); MockRepository mocks; // 注意对应版本,这里是CreateFileW,用ANSI就写CreateFileA mocks.OnCallFunc(::CreateFileW).Do(MyCreateFileMock);
为什么之前的方法不行?
Hippomocks是通过修改进程内的函数地址表(比如IAT钩子、inline钩子)来替换目标函数的,直接取::CreateFile的地址时,这个地址已经被Hippomocks替换为模拟函数的入口,所以调用这个地址还是会走到模拟函数本身。而从kernel32.dll获取的是系统DLL里未被修改的原始函数地址,就能绕过钩子直接调用原API。
内容的提问来源于stack exchange,提问作者golosovsky
相关产品推荐
相关产品推荐

