深入理解逆向工程之断点
Aking9 发表于 河南 技术文章 3838浏览 · 2024-05-31 01:16

断点学习

逆向工程中的断点是一种非常关键的工具,它允许你控制程序的执行流程。你可以在指定的地址处设置断点,当程序运行到该地址时,程序的执行会停止,由此,你便可以检查并分析程序在那一点的状态,包括寄存器的值,内存中的数据,堆栈的状态等。

  1. 软件断点:这是最基础的断点类型。它通过替换目标地址的指令为停止指令(例如x86中的 0xCC,它对应的指令是 INT 3)来工作。当CPU执行到这个指令时,就会抛出一个断点异常,程序的执行也就跳转到调试器中。这类断点对于反汇编和阅读程序代码非常有用。
  2. 内存断点:内存断点会在内存被访问或者修改时触发。这再程序中跟踪
  3. 硬件断点:硬件断点利用处理器自身的硬件特性来实现断点。你可以设置硬件断点来监视特定的内存读写,这在你想要知道某个数据是在哪里被修改的时候非常有用。

其中还有这些断点,他们的本质上也是CC断点

  • API断点
  • 条件断点
  • 条件记录断点
  • 消息断点

断点详解

软件断点

软件断点:这是最基础的断点类型。它通过替换目标地址的指令为停止指令(例如x86中的 0xCC,它对应的指令是 INT 3)来工作。当CPU执行到这个指令时,就会抛出一个断点异常,程序的执行也就跳转到调试器中。这类断点对于反汇编和阅读程序代码非常有用。

软件断点设置

软件断点又称CC断点、INT 3 断点。

软件断点设置方法:我们以第一行为例

  1. 选取要设置断点的位置,使用快捷键F2即可切换断点。

  2. 选取要设置断点的位置。双击该行即可切换断点。

  3. 右键点击要设置断点的行,断点-->切换

PS:当设置果断点后,实际上该地址的首字节值已经变为了CC

  • 这是未设置断点的值

  • 这是设置过断点的值,我们可以看到在Cheat Engine已经修改了

    OllyDbg之所以未修改,是为了我们方便观察原内存地址的值,方便调试

软件断点执行流程

软件断点的基本执行流程如下:

  1. 设置断点:首先,需要选择需要暂停的程序代码位置。在这个位置上,原始指令会被调试器替换为特殊的“断点指令”。在x86架构中,这个断点指令通常是INT 3,对应的字节码是0xCC
  2. 程序运行:当程序运行并达到设定断点的位置时,由于这里的指令已经被替换为断点指令,所以会触发一个软件中断。
  3. 中断处理:软件中断会导致CPU将控制权交给操作系统,然后操作系统会将控制权转交给调试器。调试器在接收到控制权后,会停止程序的运行,此时你可以进行调试操作,例如检查变量值、修改内存内容、单步执行等。
  4. 恢复断点:在继续运行程序之前,调试器会将断点位置的指令恢复为原始指令,然后让CPU执行这条原始指令。执行完后,调试器再次将这个位置的内存替换为断点指令。
  5. 继续运行:经过上述步骤后,程序再次处于可以运行的状态。按下"继续"按钮后,程序会继续执行,直到遇到下一个断点或者程序结束。

软件断点查看

对于设置的软件断点可以在BreakPoint窗口查看

内存断点

内存断点是调试器中的一种工具,用于监控程序执行过程中对特定内存地址的访问。

内存断点类型:

  • 在内存访问(读,写,执行)时中断;
  • 在内存写入时中断。

当设置了内存断点,一旦程序尝试读取、写入或者执行被监控的内存地址,调试器就会暂停程序执行,这样开发人员就可以检查那时程序的状态,进行调查和调试。

OllyDbg每一个时刻只允许有一个内存断点。且内存断点在程序重新调试时会删除,即每次调试都需要重新设置内存断点。

内存断点本质

内存断点修改的不是机器码,而是修改物理页的属性。调试器进程通过调用VirtualProtectEx函数(Ex:跨进程)来修改被调试进程的物理页属性来达到实现内存断点的目的。

VirtualProtectEx函数原型:

//改变内存地址内存页的属性
BOOL VirtualProtectEx(
    IN HANDLE hProcess,     // 要修改内存的进程句柄
    IN LPVOID lpAddress,        // 要修改内存的起始地址
    IN SIZE_T dwSize,       // 页区域大小
    IN DWORD flNewProtect,      // 新内存页属性
    OUT PDWORD lpflOldProtect   //原内存页属性 用于保存改变前的属性
)

这里主要关注的是第四个参数flNewProtect,修改它的值,达到修改所指内存所在物理页的PTE属性

  • PAGE_NOACCESS:不可访问(PTE.P位 = 1)
  • PAGE_EXECUTE_READ:可读可执行,不可写(PTE.P位 = 1, PTE.R/W = 0)

内存断点设置

内存地址

在数据窗口中,选择要设置的地方,右键 -->断点,就可以看到内存断点设置

内存段

在内存窗口,点击内存区段 CODE 右键 设置内存访问断点,则在这个程序区段内的每一条指令都会中断

内存断点执行流程

  1. 设置内存断点:首先,需要选择所要监视的内存位置,并在调试器中设置为内存断点,同时指定触发条件,如读取、写入或者执行这段内存。
  2. 程序运行:程序开始运行,在运行过程中,每一次内存访问(按照你所设定的触发条件)都会被检查。
  3. 断点触发:当有一次内存访问满足触发条件——即访问到你设置的那块内存,那么断点就会触发,程序会在此时被暂停。
  4. 中断处理:一旦断点触发,程序就进入暂停状态,你可以查看此时的内存值以及相关的CPU寄存器状态,甚至修改它们。
  5. 继续运行:确认无误后,可以让程序继续运行,一直到下一次内存访问再次满足触发条件,或者执行到另一个断点,或者程序结束。

硬件断点

硬件断点含义

  • 与CC断点与内存断点不同,硬件断点不依赖被调试程序,而是依赖于CPU中的调试寄存器
  • 硬件断点使用 1 号中断(INT1)实现,INT1 一般被用于硬件断点和单步事件。
  • 调试寄存器有8个,分别为Dr0~Dr7
  • 用户最多能够设置4个硬件断点,这是由于只有Dr0~Dr3用于存储线性地址。
  • 其中,Dr4和Dr5是保留的。

调试寄存器:

  • DR7:Dr7是最重要的寄存器,它控制着断点的各类属性:

    • L0/G0-L3/G3:控制Dr0-Dr3是否有效,是局部还是全局的。每次异常后,Lx都被清零,Gx不清零。
    • LENx(断点长度):00(1字节),01(2字节),11(4字节)
    • R/Wx(断点类型):00(执行断点),01(写入断点),11(访问断点)
  • DR6:调试状态寄存器,记录上一次断点触发所产生的调试事件类型信息。

    • 硬件调试断点产生的异常是 STATUS_SINGLE_STEP(单步异常)

    • B0~B3:哪个寄存器触发的异常。

    • 但是还有一种情况也会产生单步异常。当Eflags的TF位置1时,产生的异常也是单步异常。

    • DR6的作用就是用来确定产生的是哪一种单步异常

      • 当B0-B3中有值时,则可以确定是某一个硬件断点触发产生的单步异常。
      • 若B0-B3的值均为空,说明是Eflags的TF值置1产生的单步异常。
  • Dr0~Dr3:断点寄存器

    用户最多能够设置4个硬件断点,这是由于只有Dr0~Dr3用于存储线性地址。

硬件断点种类

  • 硬件执行(Execute):最常见的一种硬件断点,当程式执行到设定断点的位置时,程式就会停止。可以用来跟踪程序的执行流程,找到错误出现的地方。
  • 硬件写入(Write):当程式写入数据到设定断点的位置时,程式就会停止。可以用来追踪谁在写入某个变量的值。
  • 硬件访问:当程式读取或写入设定断点的位置上的数据时,程式就会停止。可以用来追踪谁在使用某个变量。
  • 对于数据长度,硬件断点可以设置为单个字节、两个字节(16位)、四个字节(32位)或八个字节(64位),对应于单字节、双字节、四字节和八字节变量的读写操作,以匹配不同的操作长度需求。

下断时将需要下断的线性地址写入Dr0~Dr3中任意一个寄存器中,当CPU执行到该线性地址时,发现与调试寄存器中的值相同,便会断下,触发异常

注意一点,这里下断是修改当前线程Context中记录的调试寄存器的值,线程间是隔离的,因为设置硬件断点不会影响到别的线程。

硬件断点设置

对于反汇编窗口,即代码段

对于数据窗口,即数据段有三种断点

硬件断点查看

导航栏-->调试-->硬件断点

硬件断点执行流程

  1. 设置硬件断点:首先,你需要在调试器中选择要跟踪的内存地址,并设置为硬件断点。同时,需要设定触发该断点的条件(例如,是在读取、写入还是执行此内存地址时触发)。
  2. 程序运行:程序开始运行,并且处理器会自动监控你设置的内存地址。
  3. 断点触发:当程序执行过程中的内存访问行为满足断点触发条件时,例如读取、写入或执行你设置的内存地址,硬件断点就被触发了。此时,程序会立即暂停。
  4. 检查和调试:在硬件断点被触发后,你可以检查此时程序中变量的数值、堆栈状态以及硬件寄存器状态等信息,进行分析调试。
  5. 继续运行:调试完成后,你可以让程序继续运行,直到下一次满足硬件断点条件,再次触发硬件断点。

相对于普通的断点,硬件断点的优点是可以无条件地断在任何地址,对编译优化的代码更具有优越性。但是,由于硬件资源的限制(一般只有四个),同时只能设置有限个硬件断点。

特殊CC断点

也许你也可能听懂过其他断点

  • API断点
  • 条件断点
  • 条件记录断点
  • 消息断点

这些断点的本质上其实也是软件断点、即CC断点。

API断点

程序调用API函数时就停下来让我们分析。

比如,一个程序,即将弹窗,而弹窗需要调用API函数MessageBox,那么,当MessageBox这个API函数存在API断点时,程序就会暂停等待我们的分析。

断点设置

  • 设置API断点1:大小写敏感

    • BP API函数名 例如:BP MessageBoxA来进行设置

      在该函数的位置下断点,即该函数内部第一条语句

    • BPX命令可以给引用或者调用了指定API函数的指令都下断点。

      例如:BPX MessageBoxA来进行设置,这几个就是调用了MessageBoxA的地址

  • 设置API断点2:api工具插件

    在插件->api断点设置工具勾选

我们再次使用工具查看,可以看到也是首字节变成了CC

条件断点

条件断点, 是指在达到设置的条件时才触发的断点。这个条件不是访问,写入,或者执行,而是由逻辑表达式构成的条件,显然它的功能更加强大。

条件断点设置 右键要设置断点的位置 -->断点 -->条件断点

当我们设置后,地址处会变为粉红色

我们也可以在BreakPoint窗口查看

使用工具查看其内存值

条件记录断点

条件记录断点除了具有条件断点的作用,还能记录断点处函数表达式或参数的值。

也可以设置通过断点的次数,每次符合暂停条件时,计数器的值都将减1。

条件记录断点设置 右键要设置断点的位置 -->断点 -->条件记录断点

各参数解释:

  • 条件:是程序暂停的条件
  • 说明:是对表达式值的一个说明
  • 表达式:是指程序中断时需要打印的值,一次只能打印一个值
  • 解码表达式的值为:用于解析表达式的值的方法,如果你表达式写的是"[esp + 4]",那你就要在下拉框中选择“Pointer to ASCII String(指向ASCII字符串的指针)”,才能得到地址的值,相当于“[STRING [esp+4]]”的效果。
  • 暂停程序:用于在断点满足条件时,是否暂停程序,以及配置暂停的次数,每暂停一次,后面的计数配置就会减1
  • 记录表达式的值:用于在断点满足条件时,日志面板记录表达式的值。
  • 记录函数参数:用于在断点满足条件时,日志面板记录函数的参数。
  • 命令插件窗:用于编写需要程序暂停时,需要执行的命令

设置后也会和条件断点一样,地址处变为粉红色,在BreakPoint也可以看到该断点

下面是日志面板的情况:导航栏 -->查看 -->记录 或者直接Alt +L

消息断点

Windows本身是由消息驱动的,对于标准窗口来说我们每点击一下按钮,每移动一次鼠标windows都会产生一个消息,这些消息最终会由消息处理函数(Wndproc函数)处理。

Windows本身是由消息驱动的,如果调试时没有合适的断点,可以尝试使用消息断点,当某个特定窗口函数接受到某个特定消息时,消息断点将使程序中断。

消息断点与INT3断点的区别在于:INT3断点可以在程序启动之前设置,消息断点只有在窗口被创建之后才能被设置并拦截消息。

但是程序一般都是用一个对话框来实现注册,而这个对话框是基于标准窗口的,但是其又有着不同。

  • 不同在于标准窗口消息都通过我们自己写的WndProc函数处理,而对于对话框而言系统会给其维护一个对话框管理器

  • 消息先经过对话框管理器,再由对话框管理器把消息传给我们自己写的WndProc函数。

    首先我们要知道我们设置消息断点的目的是为了找到在Wndproc函数(回调函数)中处理此消息的代码,从而分析其具体做了什么操作。

断点设置:

F9让程序跑起来,来到输入的地方,点OD的“W”按钮,进去刷新,找标题ok和类botton

右键下消息断点,选202断点(不知道可以下button)

点击消息,下拉找到开头202的消息(202_WM_LBUTTONUP)即按钮抬起。

然后回程序单击按钮上的“OK”,此时当点击OK再抬起来,程序被中断,[ESP+8] ==WM_LBUTTONUP

我们可以查看LOG窗口,里面有记录

当我们在程序断点处,右键 -->断点 -->条件记录断点,可以看到,消息断点就类似于条件记录断点

[ESP+8] ==WM_LBUTTONUP 也可以是 [ESP+8] ==0x202

当我们修改条件,让其不中断,而是记录我们想要的值

此时我们再打开 L - Log Data 窗口

然后,我们就可以在注册窗口,继续尝试,这时候,我们在窗口的所有信息的[ESP+8]都会被记录

我们在断点窗口查看,这里面可能和前面的不一样,因为我用重新设置了,每次调试其地址可能发生变化

使用软件查看

1 条评论
某人
表情
可输入 255