2022-01-10调试器00
请注意,本文编写于 322 天前,最后修改于 204 天前,其中某些信息可能已经过时。

目录


硬件断点

由CPU提供的断点类型,CPU提供了8个寄存器用来帮助实现和判断硬件断点

硬件断点支持三种类型:硬件执行断点、硬件写入断点、硬件访问断点

八个寄存器就是用来支持,最多4个3种类型的硬件断点。

DR0 ~ DR3 线性地址寄存器,用于存储地址
DR4 ~ DR5 保留

DR6 状态寄存器
B0 ~ B3,表示DR0 ~ DR3哪一个生效
BS = 1 硬件断点 ,表示是单步中断引发的断点。即EFLAGS的TF置位时引发的调试陷阱
BT 任务切换
BD 保护位,不允许修改
DR6寄存器的值, 建议在每次异常提交之前清除

DR7 控制寄存器
0 ~ 7位 L局部断点(本线程),G全局断点(所有线程),L0 ~ L3表示DR0 ~ DR3哪一个生效
GL、GE精确断点
GD 保护标志,置1保护
LEN(R/W)0 ~ LEN(R/W)3描述断点类型,分别对应DR0 ~ DR3

LEN写入(访问)数据的长度

R/W0到R/W3
指定各个断点的触发条件。它们对应于DR0到DR3中的地址以及DR6中的4个断点条件标志。
00 只执行
01 写入数据断点
10 I/O端口断点(只用于pentium+,需设置CR4的DE位,DE是CR4的第3位 )
11 读或写数据断点

硬件断点格式
hardware

asm
bh addr len a/e/w
bhl
bhc

a - access  访问
e - execute 执行
w - write   写入

内存断点

内存断点就是当程序读写某块内存的时候能够中断的调试器。

整个调试机制实际上依赖的是异常机制,如果想要内存断点,那么就需要他在读写某块内存的时候修改内存属性 给抛个异常c05 这样就断下来了。

内存属性该怎么改呢? 比如有段内存是读属性,如果要让这段内存抛异常,那就把这段内存属性改成不可读,如果有段内存是写属性,如果要让这段内存抛异常,那就把这段内存属性改成不可写。但是如果这两段内存在 同一个分页里面时,相互之间就会排斥

设置内存断点的时候把整个分页的内存属性改成不可访问的,当异常来时候判断一下,异常是否命中了我们断点的范围,如果命中了断点的范围就开始断点,如果没有命中断点的范围就把内存属性改回去,让他继续执行。

asm
OnAccessVoilation proc uses esi pER:ptr EXCEPTION_RECORD
    LOCAL @dwStatus:DWORD
    LOCAL @ctx:CONTEXT
    LOCAL @dwOldProtect:dword
    
    mov @dwStatus, DBG_CONTINUE

    mov esi, pER
    assume esi:ptr EXCEPTION_RECORD
    
    
    ;恢复内存属性
    invoke VirtualProtectEx,g_hProcess, g_dwMemBpAddr, 4, g_dwOldProtect, addr @dwOldProtect
    
    ;设置单步
    invoke SetTFAndDecEip,TRUE, 0
    mov b_bIsMemBpStep, TRUE
    
    lea eax, [esi].ExceptionInformation
    mov eax, [eax+4];获取异常访问的地址
    
    mov ebx, g_dwMemBpAddr
    add ebx, 4

        
    .if g_dwMemBpAddr <= eax && eax <= ebx
        invoke ParseCommand
        mov eax, DBG_CONTINUE
        ret
    .endif
    
    assume esi:nothing
    
    mov eax, @dwStatus
    ret

OnAccessVoilation endp

本文作者:Na1r

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!