简单调试器的实现(二)使用反汇编引擎&建立第一个程序

让程序停下来:

动态调试器的一个重要特点就是:让程序停下来,这样我们才可以观测到程序的即时情况。

不过现在我们并不需要研究怎么下断点,系统已经帮我们激活了第一个断点。在创建调试进程时,系统会帮我们在ntdll.dll中设置一个INT3断点,我们就让程序在这里断下来。

switch (DebugEvent->u.Exception.ExceptionRecord.ExceptionCode)//Int3断点的事件
{

  case EXCEPTION_BREAKPOINT: // ((DWORD )0x80000003L)
  // First chance: Display the current
  // instruction and register values.
    BreakPoint_Int3(DebugEvent);//这个函数中我们对被调试程序进行各种处理

}

获得调试程序的寄存器与标志位:

我们只需要使用GetThreadContext 获得被调试进程的上下文环境

BOOL WINAPI GetThreadContext(
     HANDLE hThread,      //线程句柄
     LPCONTEXT lpContext    //结构指针
);

(线程句柄可以在CreateProcess时的pInfo.hThread保存)

对于标志寄存器,比价麻烦,我们需要按位进行与计算。

//CF 在第0位
printf(" CF :%d", (context.EFlags & 0x1) != 0);

//PF 在第2位
printf(" PF :%d", (context.EFlags & 0x4) != 0);

//AF 在第4位
printf(" AF :%d", (context.EFlags & 0x10) != 0);

//ZF 在第6位
printf(" ZF :%d", (context.EFlags & 0x40) != 0);

//SF 在第7位
printf(" SF :%d", (context.EFlags & 0x80) != 0);

//OF 在第11位
printf(" OF :%d", (context.EFlags & 0x400) != 0);

//DF 在第10位
printf(" DF :%d", (context.EFlags & 0x200) != 0);

反汇编引擎的使用:

先介绍一个API:ReadProcessMemory,他读取指定的地址的内容

BOOL WINAPI ReadProcessMemory(
  HANDLE hProcess,                    //进程句柄,在CreateProcess时的pInfo.hProcess保存
     LPCVOID lpBaseAddress,               //要读取的地址
      LPVOID lpBuffer,                         //一个缓冲区的指针,保存读取到的内容
      SIZE_T nSize,                                //要读取的字节数
      SIZE_T* lpNumberOfBytesRead       //一个变量的指针,保存实际读取到的字节数
  );

如何使用Disasm这个函数:

在给予反汇编引擎源码中,我们需要的是Disasm这个函数

ulong Disasm(

    char *src,       //需要反汇编的机器码

      ulong srcsize,     //机器码长度

        ulong srcip,       //反汇编机器码地址

t_disasm *disasm,      //输出

int disasmmode          //反汇编形式

)

参数:

src:用ReadProcessMemory获得需反汇编代码地址的机器码内容。

  srcsize:这里直接填写20即可。

  srcip:当前反汇编进程的EIP,这里需要地址是因为一些指令(例如E8 Call)需要计算偏移,否则没法正确显示。

  *disasm:输出的指针。

  disasmmode:就如同例子中使用DISASM_CODE即可.

  (#define DISASM_CODE    4               // Full disassembly)。

返回值:

  返回实际处理的机器码的长度。

它还有几个需要设置的全局变量:(这里是为1, 否为 0)

ideal:是否使用IDEAL 形式的MODE否则为MASM形式;

lowercase:是否输出小写字母;

putdefseg:是否显示段寄存器。

部分代码:

ideal = 0; lowercase = 1; putdefseg = 0;

for (i = 0; i < 5; i++)//输出5行
{
  if (FALSE == ReadProcessMemory(G_Process, DisasmAddr,

                     lpBuff, 10, &bytesRead))//DisasmAddr,反汇编地址
  {
    switch (GetLastError())
    {
    case 299: return 3;  //表示该地址无法被正确读取
    default: return 1;

    }
  }
  l = Disasm(lpBuff, 10, DisasmAddr, &da, DISASM_CODE);
  printf("%-10x %-12s %-12s \n", DisasmAddr, da.dump, da.result);
  DisasmAddr = DisasmAddr + l;
}

现在我们可以编写最简单的汇编查看器了:

时间: 2024-12-28 02:15:52

简单调试器的实现(二)使用反汇编引擎&建立第一个程序的相关文章

windows简单调试器源码2700行左右代码

简单调试器项目中on开头的函数为接收系统的调试事件并做相应的处理,简单调试器实现过程中主要的调试事件为异常事件,相应的处理函数为DispatchException. 在异常事件中访问异常.int3异常.单步异常是跟实现调试器功能密切相关的异常事件,这里用三个函数分别处理三个函数分别为OnExceptionAccess.OnExceptionBreakPoint.OnExceptionSingleStep. 异常处理函数中如果为调试器自己设置的异常程序就会停下来接收用户输入等待下一步处理,相应的用

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

最近对调试器的原理感兴趣,自己写了一个简单的demo 打开调试进程: 要调试一个进程,需要在使用CreateProcess打开一个文件时,将第6个参数设为DEBUG_PROCESS. BOOL WINAPI CreateProcess( _In_opt_     LPCTSTR lpApplicationName, _Inout_opt_  LPTSTR lpCommandLine, _In_opt_     LPSECURITY_ATTRIBUTES lpProcessAttributes,

MyDebugeer 一个简单调试器的实现

学习的是网上的帖子,所以就不贴源码了. 整个程序以调试循环为主体,实现了启动调试,继续执行,内存查看,读取寄存器值,显示源代码,断点的设置.查看.删除,三种单步执行:StepIn.StepOver.StepOut,显示变量列表.显示指定类型内存内容,显示函数调用栈等功能. 原贴写的很好,从中学到了很多,特别是对<DbgHelp.h>有了接触和了解,学习了Windows提供给用户调试的API,当然这可能是这个程序的不足,因为基本上所有的功能都是利用API实现的,没有提及一些特别的知识和方法.不过

简单调试器的实现(三)

单步的实现 就是之前设置的TF标志位 //设置TF标志位 void SetTrapFlag() { CONTEXT context = {0}; GetDebuggeeContext(&context); context.EFlags |= 0x100; SetDebuggeeContext(&context); } 步出则是在ebp+4的地址设置断点 BOOL MoveOut() { // 获取ebp CONTEXT Context = {0}; GetDebuggeeContext(&

简单调试器的实现(四)断点

Int3断点原理: 在一个指令处设置断点有2步,1.将指令的第1个字节保存起来,2.将这个字节替换成 0xCC 我们可以用我写的调试器看一下: u指令显示了在地址 14e1bbb处的指令   E8 3EAC000;   Call  14ec7fe  . 然后查看这个地址存放的内容. 接着,在14e1bbb设置一个断点, bp 14e1bbb . 再次查看14e1bbb的内容,明显发现  前1个字节设置成了0xCC. 断点实现流程: 以下是设置INT3 断点的实现代码. DWORD SetBrea

二、Python安装和第一个程序

<1.Python语言介绍1.官方介绍:Python 是一款易于学习且功能强大的编程语言. 它具有高效率的数据结构,能够简单又有效地实现面向对象编程.Python 简洁的语法与动态输入之特性,加之其解释性语言的本质,使得它成为一种在多种领域与绝大多数平台都能进行脚本编写与应用快速开发工作的理想语言.2.特点:简单.易于学习.自由且开放.跨平台.可嵌入性.丰富的库.3.Python使用情况:目前已经超越java成为第一,一下为部分使用的公司.4.Python使用领域:1).常规的软件开发2).科学

简易调试器的实现(二)

先说一下上次对于软件断点CC还原的位置,int 3断点,属于陷阱类异常,恢复的地方应该是发生异常指令的下一条指令,但是我们在收到信息的时候FirstChance的时候是下一条,在第二次的时候确是断点发生的地方. 最近看了下<软件调试>得到了解释 首先写个小程序 int _tmain(int argc,_TCHAR* argv[]) { __asm int 3; printf("Hello INT 3"); return 0l } 当调试的时候,进入反汇编窗口我们看到发生异常

简单调试器的实现(三)完善调试器

Dll加载: 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. //Dll加载时会进行这个事件 dwContinueStatus = OnLoadDllDebugEvent(DebugEvent); break; DWO

JavaWeb开发之二《JSP&#160;+&#160;Tomcat的第一个程序“Hello&#160;World”》

搬以前写的博客[2014-12-10 22:41] 前一篇博客讲了Tomcat环境搭建,于是开始第一个“Hello JSP”程序. 服务器环境搭建好之后,我们开始写自己的网站,这里简单的写一个没有后台程序的显示“Hello JSP”的网站: 1.找到Tomcat安装目录,如D:\Apache Software Foundation\Tomcat 6.0\,进入\webapps\ROOT目录下找到WEB-INF, 将他复制到电脑中的任意一个地方,如 2.在这个目录下新建一个txt文件里面输入Hel