Windows用户级调试器(debugger)编写框架

    技术2022-05-11  81

        这几天帮朋友做了个内存补丁,大致熟悉了一下Windows下用户级调试器(Debugger)程序编写的基本框架。做一个小小的总结,由于本人能力所限,这里只是根据MSDN的说明,给出一个大致的框架结构,还请高手批评指正。其实,要编写实际可用或是更加完善的程序,还需要学习掌握更多的技术,花费更多的努力!

        我想对于Debugger不用多说什么了。我认为除了SoftIce之外,做得比较好的调试器应该算是OllyDbg,但它只能作为用户级的调试器。作者(德国人)宣称,OllyDbg完全使用Windows公开的API写成,因此兼容性很好,经过众多网友的试用也的确如此,并且用它来调试和分析程序能带来事半功倍的效果。有兴趣的朋友可以试用一下!

        其实,Windows向系统开发者提供了比较完善的调试用API。应用这些API,再加上进程、线程等相关API就能写出实用的调试器。下面就是一个调试器的基本框架:

    int main(int args,char* argv[]) {      STARTUPINFO StartUpInfo;    //模块启动信息  CONTEXT ProcessContext;     //进程的上下文环境  DEBUG_EVENT DebugEv;       // debugging event information  DWORD dwContinueStatus = DBG_CONTINUE; // exception continuation  PROCESS_INFORMATION ProcessInfo;  //创建的子进程信息  int ReturnSize;       //内存操作API函数返回的字节数    //  //获得模块信息  //  GetStartupInfo(&StartUpInfo);  //  //建立要打补丁的子进程  //  if( ! CreateProcess(ExecFileName,NULL,NULL,NULL,NULL,DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS,   NULL,NULL,&StartUpInfo,&ProcessInfo) )  {   MessageBox(NULL,"无法加载相应可执行文件,请检查文件是否存在!","严重错误",MB_OK | MB_ICONSTOP);   return -1;  }  for(;;)  {  // Wait for a debugging event to occur. The second parameter indicates  // that the function does not return until a debugging event occurs.     WaitForDebugEvent(&DebugEv, INFINITE);    // Process the debugging event code.     switch (DebugEv.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.       switch(DebugEv.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.       ProcessContext.ContextFlags=CONTEXT_FULL;       GetThreadContext(ProcessInfo.hThread,&ProcessContext);       if (ProcessContext.Eip == BreakPoint1 + 1)       {        ProcessContext.Eip --;        //设定断点0,用于再次中断时设定断点1        WriteProcessMemory(ProcessInfo.hProcess,(LPVOID)BreakPoint0,&InstructInt3,1,(SIZE_T*)&ReturnSize);        //恢复int 3前的原指令        WriteProcessMemory(ProcessInfo.hProcess,(LPVOID)BreakPoint1,&OldInstruct1,1,(SIZE_T*)&ReturnSize);        SetThreadContext(ProcessInfo.hThread,&ProcessContext);        //内存打补丁        WriteProcessMemory(ProcessInfo.hProcess,(LPVOID)ProcessContext.Ecx,&NewIp,sizeof(NewIp),(SIZE_T*)&ReturnSize);       }       else if (ProcessContext.Eip == BreakPoint0 + 1)       {        ProcessContext.Eip --;        //设定断点1,用于再次中断        WriteProcessMemory(ProcessInfo.hProcess,(LPVOID)BreakPoint1,&InstructInt3,1,(SIZE_T*)&ReturnSize);        //恢复int 3前的原指令        WriteProcessMemory(ProcessInfo.hProcess,(LPVOID)BreakPoint0,&OldInstruct0,1,(SIZE_T*)&ReturnSize);        SetThreadContext(ProcessInfo.hThread,&ProcessContext);       }              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.      //这里用DBG_EXCEPTION_NOT_HANDLED继续,是为了使原有的程序有机会做异常处理,否则系统用锁死       ContinueDebugEvent(DebugEv.dwProcessId,            DebugEv.dwThreadId,            DBG_EXCEPTION_NOT_HANDLED);       continue;       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.     //设置内在补丁断点1     WriteProcessMemory(ProcessInfo.hProcess,(LPVOID)BreakPoint1,&InstructInt3,1,(SIZE_T*)&ReturnSize);     break;    case EXIT_THREAD_DEBUG_EVENT:    // Display the thread's exit code.     break;      case EXIT_PROCESS_DEBUG_EVENT:    // Display the process's exit code.     CloseHandle(ProcessInfo.hProcess);     CloseHandle(ProcessInfo.hThread);     return 0;     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(DebugEv.dwProcessId,         DebugEv.dwThreadId,         DBG_CONTINUE);  } }

        上面是一个简单的框架,供有兴趣的朋友参考!

    最新回复(0)