简单调试器的实现(一)调试循环与反汇编引擎

最近对调试器的原理感兴趣,自己写了一个简单的demo

打开调试进程:

要调试一个进程,需要在使用CreateProcess打开一个文件时,将第6个参数设为DEBUG_PROCESS。

BOOL WINAPI CreateProcess(
  _In_opt_     LPCTSTR lpApplicationName,
  _Inout_opt_  LPTSTR lpCommandLine,
  _In_opt_     LPSECURITY_ATTRIBUTES lpProcessAttributes,
  _In_opt_     LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_         BOOL bInheritHandles,
  _In_         DWORD dwCreationFlags,   //设为DEBUG_PROCESS
  _In_opt_     LPVOID lpEnvironment,
  _In_opt_     LPCTSTR lpCurrentDirectory,
  _In_         LPSTARTUPINFO lpStartupInfo,
  _Out_        LPPROCESS_INFORMATION lpProcessInformation
);

例如:

STARTUPINFO sInfo;
PROCESS_INFORMATION pInfo;
ZeroMemory(&sInfo, sizeof(sInfo));
sInfo.cb = sizeof(sInfo);
sInfo.dwFlags = STARTF_USESHOWWINDOW;
sInfo.wShowWindow = SW_SHOWNORMAL;
ZeroMemory(&pInfo, sizeof(pInfo));

CreateProcess(szProcessPath, NULL, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &sInfo, &pInfo);

G_Process = pInfo.hProcess;//记录主线程句柄
G_hThread = pInfo.hThread;//记录进程句柄

EnterDebugLoop(); //进入调试循环的函数

调试循环:

对于调试循环,msdn上已经有十分清晰的说明了

https://msdn.microsoft.com/en-us/library/windows/desktop/ms681675(v=vs.85).aspx

我们这里将几个比较重要的事件列举一下

void EnterDebugLoop(const LPDEBUG_EVENT DebugEv)
{
   DWORD dwContinueStatus = DBG_CONTINUE; // exception continuation 

   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); 

      switch (DebugEv->dwDebugEventCode)
      {
         case EXCEPTION_DEBUG_EVENT: //异常事件,断点,异常都会触发并在这个事件中处理

            switch(DebugEv->u.Exception.ExceptionRecord.ExceptionCode)
            {
               case EXCEPTION_ACCESS_VIOLATION:   //STATUS_ACCESS_VIOLATION   ((DWORD   )0xC0000005L)
               // First chance: Pass this on to the system.
               // Last chance: Display an appropriate error.
                  break;

               case EXCEPTION_BREAKPOINT:       //  ((DWORD   )0x80000003L)   即INT3断点
               // 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;
            } 

            break;

         case CREATE_THREAD_DEBUG_EVENT: //线程建立

            dwContinueStatus = OnCreateThreadDebugEvent(DebugEv);
            break;

         case CREATE_PROCESS_DEBUG_EVENT: //调试进程建立

            dwContinueStatus = OnCreateProcessDebugEvent(DebugEv);
            break;

         case EXIT_THREAD_DEBUG_EVENT: //线程退出
         // Display the thread‘s exit code. 

            dwContinueStatus = OnExitThreadDebugEvent(DebugEv);
            break;

         case EXIT_PROCESS_DEBUG_EVENT: //调试进程退出
         // Display the process‘s exit code. 

            dwContinueStatus = OnExitProcessDebugEvent(DebugEv);
            break;

         case LOAD_DLL_DEBUG_EVENT: //dll加载

            dwContinueStatus = OnLoadDllDebugEvent(DebugEv);
            break;

         case UNLOAD_DLL_DEBUG_EVENT: //dll卸载

            dwContinueStatus = OnUnloadDllDebugEvent(DebugEv);
            break;

         case OUTPUT_DEBUG_STRING_EVENT: //输出调试信息,这个事件当被调试进程使用OutputDebugString等API时会触发

            dwContinueStatus = OnOutputDebugStringEvent(DebugEv);
            break;

         case RIP_EVENT:
            dwContinueStatus = OnRipEvent(DebugEv);
            break;
      } 

   // Resume executing the thread that reported the debugging event. 

   ContinueDebugEvent(DebugEv->dwProcessId, DebugEv->dwThreadId, dwContinueStatus);
   }
}

反汇编引擎:反汇编引擎是调试器最核心的部分之一,它将我们获得的机器码翻译成汇编语言。这里我仍使用OD的反调试引擎,这个引擎只能对x86平台下的程序进行处理,如果需要调试64位的程序,需要自己找到支持64位的反汇编引擎。

下载以及文档地址:http://www.ollydbg.de/srcdescr.htm#_Toc531975954

下一节将介绍如何使用以及写出一个最基本的调试器。
时间: 2024-12-15 07:03:39

简单调试器的实现(一)调试循环与反汇编引擎的相关文章

调试器开发实例_调试器框架设计

作为一个安全开发人员离不开调试器,它可以动态显示程序的执行过程,对于解决程序问题有极大的帮助,这些文章记录了我开发一个调试器雏形的过程,希望对你有帮助.或许我写的代码很拙劣,还请大家多多见谅! 我们使用  Microsoft Visual Studio 6.0 VC编译器来作为我们的开发工具想对一个程序进行调试,首先要做的当然是启动这个程序,这要使用CreateProcess这个Windows API来完成.例如: 1 // LilisiDebug.cpp : Defines the entry

调试器开发实例_调试器事件处理(一.事件到达)

上一章既然说到了调试循环事件,那么接下来我们该说说对调试器事件的处理了. 调试器的事件处理虽然有很多,但是并不是每一个都用得上的,接下来的文章中我们挑选一些经常用到的来给大家说说. CREATE_PROCESS_DEBUG_EVENT  创建进程之后的第一个调试事件,CREATE_PROCESS_DEBUG_INFO结构体描述了该类调试事件的详细信息. 该结构体有三个字段是句柄,分别是hFile,hProcess和hThread,同样要记得使用CloseHandle关闭它们! EXIT_PROC

嵌入式调试器原理和各类调试器集锦(JLINK、STLINK、CCDEBUG)

工欲善其事,必先善其器.调试器在嵌入式开发调试中的重要性不言而喻,单步.断点和监察的效率远高于串口打印.但是,调试器对于一般开发人员往往是一个黑匣子.今天我们就来谈谈调试器的原理,顺便把自己的几类调试器接线和注意事项记录下来,以便查找.我常常要面对几个方案,而各个方案的调试器都不一样,接线有时连自己都记不住.所以这个帖子应值得嵌入式开发工程师收藏. 一.嵌入式调试多样性 我们先来回想调试的场景,思考一下这几个问题: 1. ARM开发环境有Keil.IAR.ADS等等,我们发现这几个平台都能用同一

嵌入式调试器原理和各类调试器集锦

工欲善其事,必先善其器.调试器在嵌入式开发调试中的重要性不言而喻,单步.断点和监察的效率远高于串口打印.但是,调试器对于一般开发人员往往是一个黑匣子.今天我们就来谈谈调试器的原理,顺便把自己的几类调试器接线和注意事项记录下来,以便查找.我常常要面对几个方案,而各个方案的调试器都不一样,接线有时连自己都记不住.所以这个帖子应值得嵌入式开发工程师收藏. 一.嵌入式调试多样性 我们先来回想调试的场景,思考一下这几个问题: 1. ARM开发环境有Keil.IAR.ADS等等,我们发现这几个平台都能用同一

[Win32]一个调试器的实现(一)调试事件与调试循环

[Win32]一个调试器的实现(一)调试事件与调试循环 作者:Zplutor 出处:http://www.cnblogs.com/zplutor/ 本文版权归作者和博客园共有,欢迎转载.但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 前言 程序员离不开调试器,它可以动态显示程序的执行过程,对于解决程序问题有极大的帮助.如果你和我一样对调试器的工作原理很感兴趣,那么这一系列文章很适合你,这些文章记录了我开发一个调试器雏形的过程,希望对你有帮助.或许我

打造简单的调试器

本文转自:http://www.freebuf.com/sectool/92279.html 0×1 概述 在Fuzzing过程中,必须要监控程序的执行状态,若程序发生异常,立即保存测试用例,以便将来对其进行重现.监控器的作用就是监控程序的执行,如果程序有异常时通知给Fuzzing主线程. 目前Fuzzing工具各种各样,监控器也有很多种,但大多都是以调试器的方式实现.一个简单的监控器是这样实现的: (一)以调试模式启动进程,为目标进程开启调试端口,可使用参数DEBUG_ONLY_THIS_PR

[Win32]一个调试器的实现(七)断点

[Win32]一个调试器的实现(七)断点 作者:Zplutor 出处:http://www.cnblogs.com/zplutor/ 本文版权归作者和博客园共有,欢迎转载.但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 断点是最基本和最重要的调试技术之一,本文讲解了如何在调试器中实现断点功能. 什么是断点 在进行调试的时候,只有被调试进程暂停执行时调试器才可以对它执行操作,例如观察内存内容等.如果被调试进程不停下来的话,调试器是什么也做不了的.要使

《python灰帽子》学习笔记:写一个windos 调试器(一)

一.开发内容介绍 为了对一个进程进行调试,你首先必须用一些方法把调试器和进程连接起来.所以, 我们的调试器要不然就是装载一个可执行程序然后运行它, 要不然就是动态的附加到一个运行的进程.Windows 的调试接口(Windows debugging API)提供了一个非常简单的方法完成这两点. 运行一个程序和附加到一个程序有细微的差别. 打开一个程序的优点在于他能在程序运行任何代码之前完全的控制程序. 这在分析病毒或者恶意代码的时候非常有用. 附加到一个进程,仅仅是强行的进入一个已经运行了的进程

简易调试器的实现(一)

看过SEH结构化异常处理,看了<软件调试>这本书,觉得调试真是一件特别棒的事情,于是在网上搜索调试器怎么做,跟着大牛的脚步慢慢的往前走,于是借用大牛提供的代码,自己也开始慢慢做一个调试器 前期基本按照这个大牛的思路 http://www.cnblogs.com/zplutor/archive/2011/03/04/1971279.html 前期的分析也照着来点0.0 这一部分实现的功能是显示寄存器状态.显示字节码(感觉有一些问题,以后再修正),处理异常,断点处理(本来想在OEP断下来的,结果不