现有硬件断点和内存断点失效的原因
现象及原因
像 ReadFile 和 ReadProcessMemory 这种需要缓冲区,并且通过 SysEnter 指令进入内核的,
在内核中向指定的缓冲区写入数据,使用硬件断点和内存断点设置内存写入断点是无效的。
主要是因为 Ring3
调试器无法接收内核中产生的异常。内核中产生的异常会被内核异常处理器处理,并以 API 的返回值作为错误码返回
#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <atomic>
void readFileWithReadFileEx(const std::string& fileName,char * fileBuffer) {
HANDLE hFile = CreateFileA(
fileName.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
nullptr
);
if (hFile == INVALID_HANDLE_VALUE) {
std::cerr << "无法打开文件: " << fileName << ", 错误码: " << GetLastError() << std::endl;
return;
}
LARGE_INTEGER fileSize;
if (!GetFileSizeEx(hFile, &fileSize)) {
std::cerr << "获取文件大小失败, 错误码: " << GetLastError() << std::endl;
CloseHandle(hFile);
return;
}
OVERLAPPED overlapped = {};
if (!ReadFileEx(
hFile,
fileBuffer,
0x1000,
&overlapped,
0
)) {
std::cerr << "异步读取失败, 错误码: " << GetLastError() << std::endl;
CloseHandle(hFile);
return;
}
CloseHandle(hFile);
}
int main() {
std::string fileName = R"(D:\learn\kanxue.vmp\checkVM\ConsoleApplication5\example.txt)"; // 替换为你的文件名
char fileBuffer[0x1000] = { 0, }; // 存储文件内容
readFileWithReadFileEx(fileName, fileBuffer);
// 打印文件内容
std::cout << "文件内容:\n" << fileBuffer << std::endl;
return 0;
}
在 fileBuffer
下硬件写入断点和内存写入断点是无法中断的。硬件写入断点会被内核忽略,而内存写入断点会造成 ReadFileEx
失败,返回错误码
微软官方的说明
数据断点在下列情况下无效:
- 将未经调试的进程写入内存位置。
- 在两个或多个进程间共享内存位置。
- 内存位置在内核内更新。例如,如果内存传递给 32 位 Windows ReadFile 函数,则内存将从内核模式进行更新,因此调试器不会在更新时中断。
- 其中,监视表达式在 32 位硬件上大于 4 字节,在 64 位硬件上大于 8 字节。这是 x 86 体系结构的一个限制。
本文作者:乘舟凉
本文链接:https://www.cnblogs.com/czlnb/p/18649898
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端