Debug API 硬件断点实现 补丁程序

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进行分析以确定合适的断点代码位置。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值