You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Hook CreateFile触发读取访问违例异常 技术求助

排查CreateFile Hook触发read access violation (pbCode was nullptr)异常的思路

这种指针访问异常我之前在调试API Hook时也踩过坑,结合你给出的代码片段,大概率是函数签名不匹配调用约定错误或者编码版本混用导致的,咱们一步步来定位问题:

1. 优先检查函数typedef和调用约定

CreateFile在kernel32中的调用约定是WINAPI(也就是__stdcall),如果你的_CreateFile定义和Hook函数的签名不一致,会直接导致栈不平衡,触发内存访问异常。

你需要确保typedef完全匹配官方定义:

// 正确的CreateFile函数指针定义
typedef HANDLE(WINAPI* _CreateFile)(
    _In_ LPCTSTR lpFileName,
    _In_ DWORD dwDesiredAccess,
    _In_ DWORD dwShareMode,
    _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    _In_ DWORD dwCreationDisposition,
    _In_ DWORD dwFlagsAndAttributes,
    _In_opt_ HANDLE hTemplateFile
);

// 全局变量存储原函数地址
_CreateFile TrueCreateFile = nullptr;

你的HookCreateFile已经加了WINAPI修饰符,这部分没问题,但要保证参数的数量、类型、顺序和typedef完全一致,不能有遗漏(你给出的代码里参数写到dwS...,要确认后续参数都正确补全)。

2. 注意CreateFile的ANSI/Unicode版本问题

kernel32中导出的是两个独立的函数CreateFileA(ANSI编码)和CreateFileW(Unicode编码),不存在通用的CreateFile导出项。你直接用"CreateFile"调用GetProcAddress会返回nullptr,后续调用TrueCreateFile时自然会触发访问异常!

解决方法是根据编译环境适配:

#ifdef UNICODE
#define CREATE_FILE_FUNC_NAME L"CreateFileW"
#else
#define CREATE_FILE_FUNC_NAME "CreateFileA"
#endif

// 初始化原函数地址
TrueCreateFile = (_CreateFile)GetProcAddress(GetModuleHandle(L"kernel32"), CREATE_FILE_FUNC_NAME);
// 一定要检查GetProcAddress的返回值!
if (!TrueCreateFile) {
    // 处理获取地址失败的情况,比如输出错误码
    DWORD err = GetLastError();
    // ...
}

3. 检查Hook的实现细节

如果你是手动Hook(修改函数开头的跳转指令),要确保内存页是可写的,否则会触发访问保护异常:

// 修改原函数前先修改内存属性
DWORD oldProtect = 0;
if (!VirtualProtect(TrueCreateFile, 5, PAGE_EXECUTE_READWRITE, &oldProtect)) {
    // 处理修改失败
    return;
}

// 写入跳转指令到你的Hook函数(示例,具体 opcode 要根据架构调整)
BYTE jmpCode[5] = {0xE9}; // JMP 指令
*(DWORD*)(jmpCode + 1) = (DWORD)HookCreateFile - (DWORD)TrueCreateFile - 5;
memcpy(TrueCreateFile, jmpCode, 5);

// 恢复内存原属性
VirtualProtect(TrueCreateFile, 5, oldProtect, &oldProtect);

如果用的是第三方Hook库(比如Detours、MinHook),要确保库的初始化和Hook安装步骤正确,比如Detours需要先调用DetourTransactionBegin(),再DetourUpdateThread(),最后DetourAttach()完成Hook。

4. 排查原函数调用时的参数传递

HookCreateFile中调用原函数TrueCreateFile时,必须完整传递所有参数,不能有遗漏或类型转换错误。比如:

HANDLE WINAPI HookCreateFile(
    _In_ LPCTSTR lpFileName,
    _In_ DWORD dwDesiredAccess,
    _In_ DWORD dwShareMode,
    _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    _In_ DWORD dwCreationDisposition,
    _In_ DWORD dwFlagsAndAttributes,
    _In_opt_ HANDLE hTemplateFile
) {
    // 你的自定义Hook逻辑,比如打印文件名
    // ...

    // 调用原函数,确保参数完全传递
    HANDLE hFile = TrueCreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);

    // 后续逻辑
    // ...

    return hFile;
}

快速排查步骤

  1. 立即在GetProcAddress后加返回值检查,确认TrueCreateFile不是nullptr;
  2. 对比你的typedef和微软官方CreateFile的签名,确保完全一致;
  3. 替换"CreateFile"CreateFileACreateFileW,匹配编译环境;
  4. 检查Hook函数调用原函数时的参数是否完整。

内容的提问来源于stack exchange,提问作者user7220753

火山引擎 最新活动