Hook CreateFile触发读取访问违例异常 技术求助
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; }
快速排查步骤
- 立即在
GetProcAddress后加返回值检查,确认TrueCreateFile不是nullptr; - 对比你的typedef和微软官方CreateFile的签名,确保完全一致;
- 替换
"CreateFile"为CreateFileA或CreateFileW,匹配编译环境; - 检查Hook函数调用原函数时的参数是否完整。
内容的提问来源于stack exchange,提问作者user7220753




