You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 15:46:31