Debug API 硬件断点实例,两个断点,修改寄存器的值,以及EBP-xx指向的内存数据
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
HINSTANCE GhInstance;
STARTUPINFO gstStartUp;
PROCESS_INFORMATION gpsInfo;
DEBUG_EVENT gDBEvent;
CONTEXT gContext;
BYTE ebpxx1[2]={0xD,0x00};
BYTE ebpxx2[2]={0x16,0x00};
unsigned long MyEip1=0x00xxxx2;//
unsigned long MyEip2=0x00xxxx1; //0x00xxx;
TCHAR szExe[] = _T("xxxxxx.exe"); // 目标文件名 Path.dat
long LastErrorCode;
char LpErrorText[40];
char LpDesCripeText[2048];
bool WhileDoFlag;
int LoaderBkFlag;
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
GhInstance=hInstance;
SetLastError(0);
GetStartupInfo(&gstStartUp);
if (CreateProcess(szExe,NULL,NULL,NULL,FALSE,DEBUG_ONLY_THIS_PROCESS,0,0,&gstStartUp,&gpsInfo)==0)
{
LastErrorCode=GetLastError();
wsprintfA(LpErrorText,"创建进程失败,检查目标程序是否存在ErrorCode=%2d",LastErrorCode);
MessageBoxA(NULL,LpErrorText,"",MB_ICONERROR);
return 0;
}
LoaderBkFlag=-1;
WhileDoFlag=true;
SetLastError(0);
while(WhileDoFlag)//调试循环
{
WaitForDebugEvent(&gDBEvent,INFINITE);
gContext.ContextFlags=CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(gpsInfo.hThread,&gContext);
LastErrorCode=GetLastError();
switch(gDBEvent.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT://1debug 事件
if (gDBEvent.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT)//断点
{
//ContinueDebugEvent(gDBEvent.dwProcessId,gDBEvent.dwThreadId, DBG_CONTINUE);
//ContinueDebugEvent(gDBEvent.dwProcessId,gDBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
//
}
else if (gDBEvent.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_SINGLE_STEP)
{
gContext.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(gpsInfo.hThread,&gContext);
if (LoaderBkFlag==1 && gContext.Eip==MyEip1)
{
//MessageBoxA(0,"找到myEip1","找到",MB_OK);
//gContext.EFlags = gContext.EFlags | 0x40; //ZF //gContext.EFlags = gContext.EFlags | 0x100 | 0x40; //ZF
gContext.Eip = 0x00xxxx8;
gContext.Ecx = 0x1;
gContext.Edx = 0x2;
gContext.Dr0 = MyEip2;
gContext.Dr7 = 0x101;
SetThreadContext(gpsInfo.hThread,&gContext);
LoaderBkFlag++;
ContinueDebugEvent(gDBEvent.dwProcessId, gDBEvent.dwThreadId, DBG_CONTINUE);
break;
}
else if (LoaderBkFlag==2 && gContext.Eip==MyEip2)
{
//MessageBoxA(0,"找到myEip2","找到",MB_OK);
//gContext.EFlags = gContext.EFlags | 0x40; //ZF
WriteProcessMemory(gpsInfo.hProcess,(void *) (gContext.Ebp-0x1),&ebpxx1,2,0);//修补
WriteProcessMemory(gpsInfo.hProcess,(void *) (gContext.Ebp-0x2),&ebpxx2,2,0);//修补
gContext.Dr0 = 0; // 清除硬件断点
gContext.Dr7 = 0; // 清除硬件断点
SetThreadContext(gpsInfo.hThread,&gContext);
LoaderBkFlag++;
ContinueDebugEvent(gDBEvent.dwProcessId, gDBEvent.dwThreadId, DBG_CONTINUE);
WhileDoFlag =false; //完成补丁退出循环
break;
}
}
if(gDBEvent.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT)
{
ContinueDebugEvent(gDBEvent.dwProcessId, gDBEvent.dwThreadId, DBG_CONTINUE);
}
else
{
if (LoaderBkFlag==0)//第一次设置断点
{
gContext.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(gpsInfo.hThread,&gContext);
gContext.Dr0=MyEip1;
gContext.Dr7=0x101; //必须的,标记位
SetThreadContext(gpsInfo.hThread,&gContext);
LoaderBkFlag++;
}
ContinueDebugEvent(gDBEvent.dwProcessId, gDBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
}
break;
case CREATE_THREAD_DEBUG_EVENT://2
//gContext.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
//gpsInfo.hThread=gDBEvent.u.CreateThread.hThread;
//GetThreadContext(gpsInfo.hThread,&gContext);
ContinueDebugEvent(gDBEvent.dwProcessId, gDBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
break;
case CREATE_PROCESS_DEBUG_EVENT://创建进程事件3
LoaderBkFlag = 0;
ContinueDebugEvent(gDBEvent.dwProcessId, gDBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
break;
case EXIT_THREAD_DEBUG_EVENT: //4.
ContinueDebugEvent(gDBEvent.dwProcessId, gDBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
break;
case EXIT_PROCESS_DEBUG_EVENT: //5.退出事件
WhileDoFlag=false;
break;
case LOAD_DLL_DEBUG_EVENT: //6.
ContinueDebugEvent(gDBEvent.dwProcessId, gDBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
break;
case UNLOAD_DLL_DEBUG_EVENT: //7.
ContinueDebugEvent(gDBEvent.dwProcessId, gDBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
break;
case OUTPUT_DEBUG_STRING_EVENT: //8.
ContinueDebugEvent(gDBEvent.dwProcessId, gDBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
break;
case RIP_EVENT: //9.
ContinueDebugEvent(gDBEvent.dwProcessId, gDBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
break;
default:
//MessageBoxA(0,"default处理 异常","调试程序",MB_OK);
ContinueDebugEvent(gDBEvent.dwProcessId, gDBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
}//endswitch
}//.end while
/*
#define EXCEPTION_DEBUG_EVENT 1
#define CREATE_THREAD_DEBUG_EVENT 2
#define CREATE_PROCESS_DEBUG_EVENT 3
#define EXIT_THREAD_DEBUG_EVENT 4
#define EXIT_PROCESS_DEBUG_EVENT 5
#define LOAD_DLL_DEBUG_EVENT 6
#define UNLOAD_DLL_DEBUG_EVENT 7
#define OUTPUT_DEBUG_STRING_EVENT 8
#define RIP_EVENT 9
*/
DebugSetProcessKillOnExit(FALSE); //退出补丁程序时保持目标进程继续运行!!!
CloseHandle(gpsInfo.hProcess);
CloseHandle(gpsInfo.hThread);
return 0; //Winmain Return
}
在实际测试时发现程序异常比较多,选择合适的情况进行第一个断点很重要,参考 http://www.cnblogs.com/zplutor/archive/2011/03/08/1977702.htmlj中的Demo MiniDebugger3.rar进行分析以确定合适的断点代码位置。