C++读取PE文件NT头时触发STATUS_ACCESS_VIOLATION异常怎么解决?
问题根因及修复方案
1. 文件大小计算逻辑错误(核心原因)
std::ifstream::seekg 传入参数错误,你当前的写法没有正确定位到文件末尾:
// 错误写法 fichier.seekg(std::ios::end); auto length = fichier.tellg(); fichier.seekg(std::ios::beg);
seekg 带起始位置的重载需要传入两个参数:偏移量、参考位置,正确写法如下:
// 正确写法 fichier.seekg(0, std::ios::end); auto length = fichier.tellg(); fichier.seekg(0, std::ios::beg);
你原来的写法只会把文件指针定位到偏移量为std::ios::end枚举值(通常为2)的位置,拿到的length不是真实的文件大小,后续分配的缓冲区大小、读取的文件内容全部错误,拿到的DOS头、e_lfanew都是垃圾值,最终计算出来的ntHeader指针越界触发访问异常。
2. 缺少错误分支的终止逻辑
你校验DOS头魔数失败后仅打印日志,没有终止后续逻辑:
// 错误写法:校验失败后继续执行 if (dosHeader->e_magic != 0x5A4D)std::cout << "[23] Getting the dosHeader failed" << std::endl;
如果读取到的文件内容不是合法PE,DOS头魔数不匹配,dosHeader->e_lfanew就是无效的随机值,后续计算的ntHeader必然是非法地址,需要在校验失败后直接终止流程:
// 正确写法:校验失败后直接返回 if (dosHeader->e_magic != 0x5A4D) { std::cout << "[23] Getting the dosHeader failed" << std::endl; delete[] pData; return -1; }
3. 缺少偏移合法性校验
拿到e_lfanew后需要校验偏移是否在缓冲区范围内,避免越界访问:
if (dosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) > static_cast<uintptr_t>(length)) { std::cout << "Invalid e_lfanew offset" << std::endl; delete[] pData; return -1; }
4. 缺少文件操作结果校验
你没有校验文件打开、读取是否成功,如果文件路径错误、权限不足导致读取失败,后续的所有指针操作都是非法的,需要补充校验:
fichier.open(exeFile, std::ios::binary); if (!fichier.is_open()) { std::cout << "Failed to open exe file" << std::endl; return -1; } // ... 读取文件后校验 if (!fichier) { std::cout << "Failed to read exe file" << std::endl; delete[] pData; fichier.close(); return -1; }
内容的提问来源于stack exchange,提问作者Meiziro
相关产品推荐
相关产品推荐

