前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >调试器编写第一讲,调试器基本框架

调试器编写第一讲,调试器基本框架

作者头像
IBinary
发布2018-01-08 11:48:26
1.7K0
发布2018-01-08 11:48:26
举报
文章被收录于专栏:逆向技术逆向技术

                  调试器编写第一讲,调试器基本框架

今天开始调试器第一讲,调试器的基本框架,我们用过很多调试器,比如 WinDbg,OllyDbg,那为什么我们还要自己编写调试器哪?

原因是,OllyDbg等等的各种调试器都太容易被针对了,写调试器,主要是理解别人怎么反调试,并且我们怎么在安全开发的时候,让我们的软件针对调试器.今天就开始调试器第一讲,调试器的基本框架

很多人认为调试器怎么写,没思路,其实调试器就是调用API,熟练运用这些API,则可以进行软件调试

一丶写调试器注意的问题

首先,我们思考一个问题,我们要调试我们的程序,要怎么让我们的程序知道被调试了

是这样的,微软已经帮我们提供了API了,比如我们常用WriteProcessMemory这个API,想一下,微软怎么可能提供在别人进程里面写内存的API哪?

其实这个就是调试器用的,只不过被我们玩坏了.

那么我们MSDN搜索一下这个API,就可以找到所有和调试器相关的API

可以在下方看到,所以和调试器相关的API了.

API就怎么多,熟练运用即可.

二丶调试器API各个API的意思

 这里介绍下各个API的意思,并不细讲,等到用到的时候才会细讲怎么用.主要是熟悉一下,算是翻译一下API吧.

代码语言:javascript
复制
/*
ContinueDebugEvent      :看名字就知道,继续调试事件,意思就是调试程序的时候有事件来,你处理完了要继续.

DebugActiveProcess      :调试程序,附加进程,这个API就是,如果我们的程序打开了,那么调用这个API,传入进程ID是可以附加调试的.

DebugActiveProcessStop    :停止调试器,调试的指定进程,也就是调试器要停止对某一个进程的调试

debugBreak           :如果程序处于调试的状态,,如果发生断点异常(下断点),允许线程,通知我们的调试器来调试,处理这个异常.否则系统接收
DebugBreakProcess       :在指定的进程中,产生一个断点异常
DebugSetProcessKillOnExit  :设置调试的线程,退出的时候进行的操作.

FatalExit            :强制退出调用的进程,并将控制权交给调试器
FlushInstructionCache       :刷新指令的高速缓存

GetThreadContext          :获取寄存器的信息,具体获取那个,要设置标志位,标志位在注释中(MSDN查不到)
GetThreadSelectorEntry     :获取指定选择器和线程的描述的入口表.
IsDebuggerPresent         :判断进程是否在调试器下面运行(和我们前面说的反调试那个差不多,都是判断调试是否运行)
OutPutDebugString           :调试输出字符串.

ReadProcessMemory          :读取指定进程的某块数据

SetThreadContext      :设置寄存器

WaitForDebugEvent      :等待调试事件
WriteProcessMemory       :往指定进程写某块数据
*/

三丶查阅MSDN,看下调试器的说明

我们要调试一个程序,第一步就要创建这个程序,那么创建程序是用CreateProcess,那么我们看下MSDN有没有特别说明

随便进去一个调试的API,看到下方说了一个基本的调试,点击去看看.

第一个说,关于基本调试,也就是介绍一下

第二个说,调试的参考,我们先看下第一个怎么说把

可以看到,他告诉了我们,关于基本调试个各种步骤.

第一个: 说的是,调试的函数,也就是上面的我们那些调试API

第二个: 说的是,调试的时候,进程,线程,和异常函数的各种特性,也就是说调试进程,线程,还有异常的时候,该怎么做.

第三个: 告诉了我们使用基本的调试函数可以创建一个基本的调试器.这些函数,可以下断点,异常等等.

第四个: 这个则是告诉了我们,调试程序的时候来的各种事件.

看下第二个把,调试的时候的各种特性.

说的是,进程函数,线程函数,异常函数,我们现在首要任务是调试进程,所以看第一个

告诉了我们,要调试一个进程,你要用CreateProcess,并且要设置标志为上面画框框的地方.

下面还说了,我们要还可以通过OpenPeocess获得一个进程ID,通过DebugActiveProcess附加这个进程调试.

那么我们现在知道了,要调试一个程序,首先要创建进程,并且给出特定的参数.

四丶编写调试器的基本框架(汇编编写,C/C++一样编写)

 我们知道了,要调试一个程序,要先创建进程,然后我们应该要等待事件的到来,进行处理,如果是否继续处理,交给

ContinueDebugEvent

开始编写程序:

RadAsm创建控制台程序

汇编代码

1.创建调试进程
代码语言:c
复制
LOCAL @si:STARTUPINFO 
    LOCAL @di:PROCESS_INFORMATION
    mov @si.cb,sizeof STARTUPINFO
    ;创建调试进程
    invoke CreateProcess,offset g_szAppName,NULL,NULL,NULL,FALSE,DEBUG_PROCESS,NULL,NULL,addr 
    @si,addr @di

CTRL + D 调试,看下计算器是否启动.

2.调用调试函数,等待事件到来.

注重第一个参数,说了一个DEBUG_EVENT,看下这个结构体

代码语言:javascript
复制
typedef struct _DEBUG_EVENT { 
  DWORD dwDebugEventCode; 
  DWORD dwProcessId; 
  DWORD dwThreadId; 
  union { 
      EXCEPTION_DEBUG_INFO Exception; 
      CREATE_THREAD_DEBUG_INFO CreateThread; 
      CREATE_PROCESS_DEBUG_INFO CreateProcessInfo; 
      EXIT_THREAD_DEBUG_INFO ExitThread; 
      EXIT_PROCESS_DEBUG_INFO ExitProcess; 
      LOAD_DLL_DEBUG_INFO LoadDll; 
      UNLOAD_DLL_DEBUG_INFO UnloadDll; 
      OUTPUT_DEBUG_STRING_INFO DebugString; 
      RIP_INFO RipInfo; 
  } u; 
} DEBUG_EVENT, *LPDEBUG_EVENT;

说了异常来的时候,这个结构体会有异常的代码,进程的ID,线程的ID,以及根据不同异常,产生不同的结构体

(因为是共用体,所以什么异常来了,就会有不同的结构体,保存了不同的异常信息)

举个例子,第一个:

异常信息是EXCEPTION_DEBUG_EVENT 表示调试的时候异常信息事件来了,我们看下它的结构体是什么

代码语言:javascript
复制
typedef struct _EXCEPTION_DEBUG_INFO { 
  EXCEPTION_RECORD ExceptionRecord; 
  DWORD dwFirstChance; 
} EXCEPTION_DEBUG_INFO, *LPEXCEPTION_DEBUG_INFO; 

它的结构体则保存了和异常信息,什么的,(和筛选器异常的结构体差不多.)

上面一个框是一个参数,下面说了,只有线程,被创建调试进程的时候才能用,也就是创建调试进程使用.

下面有例子,抄例子

我就不截图看了.

 直接编写汇编代码:

代码语言:javascript
复制
   assume ecx:ptr DEBUG_EVENT
    
    
    ;EXCEPTION_DEBUG_EVENT  代表我不处理,DBG_CONTINUE代表我处理,这就是OD的F9运行起来的功能
    .while TRUE
          invoke WaitForDebugEvent,addr @DebugEv,INFINITE         ;等待事件到来
          lea ecx,@DebugEv                                        ;结果放到ecx当中,因为ecx已经假设为DebugEvent结构体了
          mov ebx,[ecx].dwDebugEventCode                          ;将结构体的异常代码给ebx,然后下方通过ebx判断是哪个事件来了
        .if     ebx == EXCEPTION_DEBUG_EVENT    ;检测事件是什么
         invoke  crt_puts,offset g_szEcpt
         mov @dwContinueStatus,EXCEPTION_DEBUG_EVENT
         
        .elseif ebx == CREATE_THREAD_DEBUG_EVENT
        
        invoke  crt_puts,offset g_szEcpt
        mov @dwContinueStatus,EXCEPTION_DEBUG_EVENT
        
        .elseif ebx == CREATE_PROCESS_DEBUG_EVENT
        
        invoke  crt_puts,offset g_szEcpt
        mov @dwContinueStatus,EXCEPTION_DEBUG_EVENT
        
        .elseif ebx == EXIT_THREAD_DEBUG_EVENT
        
        invoke  crt_puts,offset g_szEcpt
        mov @dwContinueStatus,EXCEPTION_DEBUG_EVENT
        
        .elseif ebx == EXIT_PROCESS_DEBUG_EVENT
        mov @dwContinueStatus,EXCEPTION_DEBUG_EVENT
        
        .elseif ebx == LOAD_DLL_DEBUG_EVENT
        
        mov @dwContinueStatus,EXCEPTION_DEBUG_EVENT
        
        .elseif ebx == UNLOAD_DLL_DEBUG_EVENT
        mov @dwContinueStatus,EXCEPTION_DEBUG_EVENT
        
        .elseif ebx == OUTPUT_DEBUG_STRING_EVENT
        mov @dwContinueStatus,EXCEPTION_DEBUG_EVENT
        .endif
        invoke ContinueDebugEvent,[ecx].dwProcessId,
                                  [ecx].dwThreadId,       ;继续处理事件
                                   @dwContinueStatus
    .endw

代码很简单,利用waitforDebugEvent获取异常代码,然后异常代码给ebx,通过ebx模拟switch,看看那个异常事件回来.当然,汇编代码会放到课堂资料中,带着C代码一起发布,这里只是简单解释一下.

五丶异常事件是什么

上面说了,异常事件和ebx(异常代码比较)那么分别代表什么意思?

代码语言:javascript
复制
EXCEPTION_DEBUG_EVENT          :被调试的调试程序的时候来,会在调试的程序中下一个int3断点.如果被调试的时候,则回来,属于系统断点

CREATE_THREAD_DEBUG_EVENT      :被调试的程序创建线程的时候会来

CREATE_PROCESS_DEBUG_EVENT     :被调试的程序创建进程的时候会来

EXIT_THREAD_DEBUG_EVENT       :被调试的程序退出线程的时候会来

EXIT_PROCESS_DEBUG_EVENT      :被调试的程序退出进程的时候会来

LOAD_DLL_DEBUG_EVENT        :被调试的程序加载DLL的时候会来

UNLOAD_DLL_DEBUG_EVENT       :被调试的程序卸载DLL会来

OUTPUT_DEBUG_STRING_EVENT     :被调试的程序调试输出的时候会来

RIP_EVENT                :64位系统的事件,如果编写32位调试器,这个则不重要.

今天主要是讲了一个框架,具体可以回去自己写一下就明白,很简单.

课堂资料:

链接:http://pan.baidu.com/s/1jHDJOUU 密码:mbn4

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-09-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  •                   调试器编写第一讲,调试器基本框架
    • 一丶写调试器注意的问题
      • 二丶调试器API各个API的意思
        • 三丶查阅MSDN,看下调试器的说明
          • 四丶编写调试器的基本框架(汇编编写,C/C++一样编写)
            • 五丶异常事件是什么
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档