Int3断点原理:
在一个指令处设置断点有2步,1.将指令的第1个字节保存起来,2.将这个字节替换成 0xCC
我们可以用我写的调试器看一下:
u指令显示了在地址 14e1bbb处的指令 E8 3EAC000; Call 14ec7fe 。
然后查看这个地址存放的内容。
接着,在14e1bbb设置一个断点, bp 14e1bbb 。
再次查看14e1bbb的内容,明显发现 前1个字节设置成了0xCC。
断点实现流程:
以下是设置INT3 断点的实现代码。
DWORD SetBreakPoint(DWORD Address) //传入需要设置的地址
{
BYTE lpBYTE;
BYTE Check = 0xCC;
SIZE_T bytesRead;
//1.获得该地址的前1字节
if (ReadProcessMemory(G_Process, (LPCVOID)Address, &lpBYTE, sizeof(BYTE), &bytesRead) == 0)
{
printf("\nError in the SetBreakPoint ->ReadProcessMemory, LastError:%d", GetLastError());
return 2;
}
//2.判断这一点是否已经存在 int3 断点
if (memcmp(&lpBYTE, &Check, sizeof(BYTE)) == 0)
{
printf("This Address Had set BreakPoint\n");
return 1;
}
//3.操作链表加入这个节点,记录断点地址与原来的内容
if (FALSE == Record_Breakpoint_List(Address, lpBYTE))
{
return 5;
}
//修改地址BYTE —> INT 3
if( 0 == WriteProcessMemory(G_Process, (LPCVOID)Address, &Check, sizeof(BYTE), &bytesRead))
{
printf("\nError in the SetBreakPoint->WriteProcessMemory, LastError:%d", GetLastError());
return 3;
}
return 0;
}
接着是删除断点的实现代码
DWORD DeleteBreakPoint(DWORD Address)
{
BYTE lpBYTE;
BYTE Check = 0xCC;
SIZE_T bytesRead;
//获得该地址的字节
if (ReadProcessMemory(G_Process, (LPCVOID)Address, &lpBYTE, sizeof(BYTE), &bytesRead) == 0)
{
printf("\nError in the SetBreakPoint->ReadProcessMemory, LastError:%d", GetLastError());
return 2;
}
//先判断这一点是否存在 int3
if (memcmp(&lpBYTE, &Check, sizeof(BYTE)) != 0)
{
printf("This Address don‘t has BreakPoint\n");
return 1;
}
//操作链表删除这个节点 ,并且实现修改地址 INT 3 -> BYTE
if (FALSE == Delete_Breakpoint_List(Address))
{
return 3;
}
return 0;
}