调试器学习

来源:互联网 发布:淘宝客服不回话怎么办 编辑:程序博客网 时间:2024/06/05 14:43

#include "stdafx.h"#include <stdlib.h>#define WINVER 0x0501#include <windows.h>BOOLDbgNewProcess( LPTSTR szCmdLine){STARTUPINFO           StartupInfo;PROCESS_INFORMATION   ProcessInfo;memset ( &StartupInfo , NULL , sizeof ( STARTUPINFO ) ) ;memset ( &ProcessInfo , NULL , sizeof ( PROCESS_INFORMATION ) ) ;StartupInfo.cb = sizeof ( STARTUPINFO ) ;//-- create the Debuggee processif( !CreateProcess( 0L, szCmdLine, (LPSECURITY_ATTRIBUTES) 0L, (LPSECURITY_ATTRIBUTES) 0L, TRUE, DEBUG_PROCESS | CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS, (LPVOID) 0L, (LPTSTR) 0L, &StartupInfo, &ProcessInfo ) ) {TCHAR szMsg[MAX_PATH];FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,GetLastError(),0, // Default language(LPTSTR) szMsg,MAX_PATH,NULL );printf("Failed in CreateProcess() with error:\n  ");printf(szMsg);printf("\n");return( FALSE );}else{CloseHandle( ProcessInfo.hProcess );CloseHandle( ProcessInfo.hThread );}return( TRUE );}#define MAX_DBG_EVENT 9LPTSTR DbgEventName[ MAX_DBG_EVENT+1] = {    "EXCEPTION_DEBUG_EVENT",    "CREATE_THREAD_DEBUG_EVENT",    "CREATE_PROCESS_DEBUG_EVENT",    "EXIT_THREAD_DEBUG_EVENT",    "EXIT_PROCESS_DEBUG_EVENT",    "LOAD_DLL_DEBUG_EVENT",    "UNLOAD_DLL_DEBUG_EVENT","OUTPUT_DEBUG_STRING_EVENT","RIP_EVENT",    "Unknown Debug Event"};//////////////////////////////在处理完调试事件后,调试器会调用 ContinueDebugEvent API来恢复调试事件BOOL DbgMainLoop(DWORD dwWaitMS){DEBUG_EVENT DbgEvt;                   // debugging event information DWORD dwContinueStatus = DBG_CONTINUE; // exception continuation BOOL bExit=FALSE;while(!bExit) { // Wait for a debugging event to occur. The second parameter indicates // number of milliseconds to wait for a debugging event. If the parameter// is INFINITE the function does not return until a debugging event occurs.  if(!WaitForDebugEvent(&DbgEvt, dwWaitMS)){printf("WaitForDebugEvent() returned False %d.\n",GetLastError());bExit=TRUE;continue;} // Process the debugging event code. printf("Debug event received from process %d thread %d: %s.\n",DbgEvt.dwProcessId,DbgEvt.dwThreadId,DbgEventName[DbgEvt.dwDebugEventCode>MAX_DBG_EVENT?MAX_DBG_EVENT:DbgEvt.dwDebugEventCode-1]); switch (DbgEvt.dwDebugEventCode) { case EXCEPTION_DEBUG_EVENT: // Process the exception code. When handling // exceptions, remember to set the continuation // status parameter (dwContinueStatus). This value // is used by the ContinueDebugEvent function. printf("-Debuggee breaks into debugger; press any key to continue.\n");getchar();//return TRUE;switch (DbgEvt.u.Exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: // First chance: Pass this on to the system. // Last chance: Display an appropriate error. break; case EXCEPTION_BREAKPOINT: // First chance: Display the current // instruction and register values. break; case EXCEPTION_DATATYPE_MISALIGNMENT: // First chance: Pass this on to the system. // Last chance: Display an appropriate error. break; case EXCEPTION_SINGLE_STEP: // First chance: Update the display of the // current instruction and register values. break; case DBG_CONTROL_C: // First chance: Pass this on to the system. // Last chance: Display an appropriate error. break; default:// Handle other exceptions. break;}  case CREATE_THREAD_DEBUG_EVENT: // As needed, examine or change the thread's registers // with the GetThreadContext and SetThreadContext functions; // and suspend and resume thread execution with the // SuspendThread and ResumeThread functions. break;case CREATE_PROCESS_DEBUG_EVENT: // As needed, examine or change the registers of the // process's initial thread with the GetThreadContext and // SetThreadContext functions; read from and write to the // process's virtual memory with the ReadProcessMemory and // WriteProcessMemory functions; and suspend and resume // thread execution with the SuspendThread and ResumeThread // functions. Be sure to close the handle to the process image // file with CloseHandle.break; case EXIT_THREAD_DEBUG_EVENT: // Display the thread's exit code. break; case EXIT_PROCESS_DEBUG_EVENT: // Display the process's exit code. bExit=TRUE;break; case LOAD_DLL_DEBUG_EVENT: // Read the debugging information included in the newly // loaded DLL. Be sure to close the handle to the loaded DLL // with CloseHandle.break; case UNLOAD_DLL_DEBUG_EVENT: // Display a message that the DLL has been unloaded. break; case OUTPUT_DEBUG_STRING_EVENT: // Display the output debugging string. break; }  // Resume executing the thread that reported the debugging event.  ContinueDebugEvent(DbgEvt.dwProcessId, DbgEvt.dwThreadId, dwContinueStatus); //Enables a debugger to continue a thread that previously reported a debugging event. }return TRUE;}void Help(){   printf ( "TinyDbgr <PID of Program to Debug>|\n    "             "<Full Exe File Name> [Prgram Parameters]\n" ) ;}int main(int argc, char* argv[]){if(argc<=1) {Help();return -1;}if (strstr(strupr(argv[1]),".EXE"))//将字符串s转换为大写形式说明:只转换s中出现的小写字母,不改变其它字符...{//从字符串str1中查找是否有字符串str2,如果有,从str1中的str2位置起,返回str1中str2起始位置的指针,如果没有,返回null。TCHAR szCmdLine[ MAX_PATH ] ;szCmdLine[ 0 ] = '\0' ;for ( int i = 1 ; i < argc ; i++ ){   strcat ( szCmdLine , argv[ i ] ) ;if ( i < argc ){strcat ( szCmdLine , " " ) ;}}if(!DbgNewProcess(szCmdLine)){return -2;}}else{if(!DebugActiveProcess(atoi(argv[1])))//If the function succeeds, the return value is nonzero.{printf("Failed in DebugActiveProcess() with %d.\n",GetLastError());return -2;}if(argc>2 && stricmp(argv[2],"-e")==0){// try the DebugSetProcessKillOnExit() APIif(!DebugSetProcessKillOnExit(FALSE)){//Sets the action to be performed when the calling thread exits.printf("Failed in DebugSetProcessKillOnExit() with %d.\n",GetLastError());}}if(argc>2 && stricmp(argv[2],"-s")==0){DbgMainLoop(10);// try the DebugActiveProcessStop() APIif(!DebugActiveProcessStop(atoi(argv[1]))){printf("Failed in DebugActiveProcessStop() with %d.\n",GetLastError());}elseprintf("Detach debuggee successfully.\n");return 0;}}return DbgMainLoop(INFINITE);}
上面是学习的小调试器代码   看看就行·························

两种方式:  

1  输入PID   附加到已经启动的进程

DebugActiveProcess  实现  附加功能

BOOL WINAPI DebugSetProcessKillOnExit(  _In_  BOOL KillOnExit);

If this parameter is TRUE, the thread terminates all attached processes on exit (note that this is the default). Otherwise, the thread detaches from all processes being debugged on exit.


2 打开程序调试

通过创建程序时  带调试  

CreateProcess( 0L, szCmdLine, (LPSECURITY_ATTRIBUTES) 0L, (LPSECURITY_ATTRIBUTES) 0L, TRUE, DEBUG_PROCESS | CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS, (LPVOID) 0L, (LPTSTR) 0L, &StartupInfo, &ProcessInfo)


最后

BOOL WINAPI WaitForDebugEvent(  _Out_  LPDEBUG_EVENT lpDebugEvent,   //保存 收到的调试事件  _In_   DWORD dwMilliseconds          //指定等待的毫秒数  INFINITE 无限期等待);

来供 调试器等待和接收调试事件

在处理完调试事件后,调试器会调用 ContinueDebugEvent API来恢复调试事件

BOOL WINAPI ContinueDebugEvent(  _In_  DWORD dwProcessId,  _In_  DWORD dwThreadId,  _In_  DWORD dwContinueStatus);

最后附带一个修改程序的例子:

#include "stdio.h"#include "tchar.h"#include "windows.h"int _tmain(int argc, _TCHAR* argv[]){STARTUPINFO stSi;PROCESS_INFORMATION stPi;DEBUG_EVENT stDe;int nAddrOfBreakPoint = 0x0040E813; //需要下断点的地址int nAddrOfPatch = 0x004010B8;    //需要打补丁处的地址unsigned char cOldByte;        //用于保存nAddrOfBreakPoint断点处的原指令unsigned char cBreakPoint = 0xCC;  //int 3指令unsigned char cPatchByte = 0x75;  //补丁字节    CONTEXT stThreadContext;BOOL bCreated = FALSE;BOOL bFinished = FALSE;//LPTSTR szCmdLine = _tcsdup(TEXT("mengmeng.exe"));LPTSTR szCmdLine = _T("mengmeng.exe");GetStartupInfo(&stSi);bCreated = CreateProcess(NULL,szCmdLine,NULL,NULL,FALSE,DEBUG_ONLY_THIS_PROCESS,NULL,NULL,&stSi,&stPi);if(!bCreated){MessageBox(GetActiveWindow(),TEXT("不能打开test.exe文件!"),TEXT("Result"),MB_OK);//不能打开test.exe时清除资源if(szCmdLine!=NULL)  free(szCmdLine);return 0;}//开始调试运行,等待调试事件发生while(WaitForDebugEvent(&stDe,INFINITE)){//有调试事件发生switch(stDe.dwDebugEventCode){case CREATE_PROCESS_DEBUG_EVENT://写断点(int 3[0xCC])到nAddrOfBreakPoint,之前要保存原始指令ReadProcessMemory(stPi.hProcess,(LPVOID)nAddrOfBreakPoint,&cOldByte,1,NULL);WriteProcessMemory(stPi.hProcess,(LPVOID)nAddrOfBreakPoint,&cBreakPoint,1,NULL);break;case EXCEPTION_DEBUG_EVENT:if(stDe.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT){//断点异常//若不是在nAddrOfBreakPoint处中断,则继续等待stThreadContext.ContextFlags = CONTEXT_CONTROL;GetThreadContext(stPi.hThread,&stThreadContext);if(stThreadContext.Eip!=nAddrOfBreakPoint+1) break;        //执行内存补丁WriteProcessMemory(stPi.hProcess,(LPVOID)0x004010B8,&cPatchByte,1,NULL);//恢复nAddrOfBreakPoint原始指令,并重新执行该指令WriteProcessMemory(stPi.hProcess,(LPVOID)nAddrOfBreakPoint,&cOldByte,1,NULL);stThreadContext.ContextFlags = CONTEXT_FULL;GetThreadContext(stPi.hThread,&stThreadContext);stThreadContext.Eip = nAddrOfBreakPoint;SetThreadContext(stPi.hThread,&stThreadContext);}break;case EXIT_PROCESS_DEBUG_EVENT:  bFinished = TRUE;}ContinueDebugEvent(stPi.dwProcessId,stPi.dwThreadId,DBG_CONTINUE);//继续让被调试的程序执行if(bFinished)break;}//破解成功后清除内存资源if(szCmdLine!=NULL)  free(szCmdLine);CloseHandle(stPi.hThread);CloseHandle(stPi.hProcess);return 0;}

















原创粉丝点击