由于软件断点与硬件断点不同,它确实会更改代码,因此编写一种程序来对自身进行校验和作为一种反调试器技术相对容易。是否可以对硬件断点执行类似的操作?

评论

是的,您可以获取上下文并检查/ modify /使调试寄存器dr7 dr6等无效

#1 楼

这是一个非常好的问题,因为该主题不像检测软件断点的反调试技术那样流行。既然您没有提到该体系结构,我们就必须牢记,正如其名称所暗示的那样,硬件断点取决于您所运行的硬件,因此,这种断点的实现在每个体系结构之间是不同的。由于我们无法在此答案中涵盖所有架构,因此我在这里假设我们正在谈论Windows上的Intel x86架构。

简而言之,答案是肯定的。基本上有两种检测硬件断点的常用方法:


使用线程的上下文访问调试寄存器
制作SEH(结构化异常处理),然后引发异常并进行访问调试寄存器

为了理解每种方法,我们应该首先了解什么是硬件断点以及(简而言之)它是如何工作的。

硬件断点

在x86体系结构中,调试器使用一组调试寄存器来应用硬件断点。存在8个调试寄存器来控制调试过程,范围从DR0到DR7。这些寄存器不能从ring3特权访问,而只能从CPL0(当前特权级别,ring0)访问。因此,在以任何其他特权级别执行时尝试读取或写入调试寄存器都会导致一般性保护错误。调试寄存器允许调试器在访问内存以进行读写时中断程序的执行并将控制权转移给它。

x86调试寄存器


DR0-线性断点地址0
DR1-线性断点地址1
DR3-线性断点地址3
DR4-保留。未由Intel
DR5定义-保留。未由英特尔定义
DR6-断点状态
DR7-断点控制

DR0-DR3存储断点的线性地址。存储的地址可以与物理地址相同,或者需要将其转换为物理地址。 DR6指示激活了哪个断点。 DR7通过以下访问模式定义断点激活模式:读取,写入或执行。检测硬件断点

方法一-ThreadContext Win API

以下示例基于CodeProject的本文示例。注释该示例以描述每段代码:

bool IsHWBreakpointExists()
{
    // This structure is key to the function and is the 
    CONTEXT ctx;
    ZeroMemory(&ctx, sizeof(CONTEXT));

    // The CONTEXT structure is an in/out parameter therefore we have
    // to set the flags so Get/SetThreadContext knows what to set or get.   
    ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;

    // Get a handle to our thread
    HANDLE hThread = GetCurrentThread();
    // Get the registers
    if(GetThreadContext(hThread, &ctx) == 0)
        return false;   

    if ((ctx.Dr0) || (ctx.Dr1) || (ctx.Dr2) || (ctx.Dr3)) {
        return true;
    }
    else {
        return false;
    }
} 


方法2-SEH
操纵调试寄存器的SEH方法更为常见,并且如下面的示例所示,再次在CodeProject中更容易在组装中实现它:

ClrHwBpHandler proto
 .safeseh ClrHwBpHandler

ClearHardwareBreakpoints proc
     assume fs:nothing
     push offset ClrHwBpHandler
    push fs:[0]
    mov dword ptr fs:[0], esp ; Setup SEH
     xor eax, eax
     div eax ; Cause an exception
     pop dword ptr fs:[0] ; Execution continues here
     add esp, 4
     ret
ClearHardwareBreakpoints endp

ClrHwBpHandler proc 
     xor eax, eax
    mov ecx, [esp + 0ch] ; This is a CONTEXT structure on the stack
     mov dword ptr [ecx + 04h], eax ; Dr0
     mov dword ptr [ecx + 08h], eax ; Dr1
     mov dword ptr [ecx + 0ch], eax ; Dr2
     mov dword ptr [ecx + 10h], eax ; Dr3
     mov dword ptr [ecx + 14h], eax ; Dr6
     mov dword ptr [ecx + 18h], eax ; Dr7
     add dword ptr [ecx + 0b8h], 2 ; We add 2 to EIP to skip the div eax
     ret
ClrHwBpHandler endp

®64和IA-32体系结构软件开发人员手册:第3卷

通过逆向工程识别恶意代码
反逆向工程指南
反调试保护技术