如果设置了GD标志,读取调试寄存器是否会引发异常



我最近一直在研究调试寄存器,以及一些恶意软件程序如何将其作为反调试策略进行操作。我现在读过几次的一件事是,可以通过在DR7中使用General Detect标志来防止这种情况,如果MOV指令用于访问DR0-DR7中的任何一个,则会引发调试异常。

然而,我不清楚的是,访问究竟意味着什么——例如,如果mov指令只用于将DR0-DR3的地址放入通用寄存器中以便读取,那么在设置GD标志时,这是否仍会引发调试异常?还是只有当MOV指令用于实际更改寄存器的内容时才会发生这种情况?到目前为止,我所读到的内容在这方面有点模棱两可。

我在显示调试寄存器操作的文本中遇到了下面的程序集,但在这种情况下,mov仅用于获取调试寄存器的地址,实际修改由或指令完成,因此我不确定如果设置了GD,此代码是否会引发异常。

xor eax, eax
push offset except_callback
push d fs:[eax]
mov fs:[eax], esp
int 3 ;force an exception to occur
...        
except_callback:
mov eax, [esp+0ch] ;get ContextRecord
mov ecx, [eax+4] ;Dr0
or ecx, [eax+8] ;Dr1
or ecx, [eax+0ch] ;Dr2
or ecx, [eax+10h] ;Dr3
jne <Debugger_detected>

Intel对此非常清楚:

尝试读取或写入调试寄存器从任何其他特权级别生成一般保护异常(#GP(。

因此,在不以CPL 0运行时读取或写入调试寄存器将引发异常,与GD标志无关。

事实上,我已经分析了很多恶意软件,但没有一个直接访问调试寄存器。他们获取当前线程上下文(GetThreadContext或NtGetContextThread或类似的WOW64变体(,并从中检查调试寄存器的值,请注意,在这种情况下,是Windows内核读取调试寄存器。这种反调试技巧可以手动解决(通过API上的断点检索上下文(,也可以通过调试器插件解决。在CPL0上运行的恶意软件可能使用GD标志,但到目前为止我从未找到过。

在回答标题问题时,如果设置了GD,则对调试寄存器的任何读或写访问(在CPL 0(都将引发#GP。我没有测试过它,但考虑到它的预期用途(支持硬件调试器模拟器(;虚拟化";调试寄存器。在软件中模拟的硬件调试器可以使用调试寄存器,即使被调试的操作系统已经在使用它们。这是通过在每次访问时出错,并正确地交换操作系统与模拟器的值来实现的。

如果只有写操作出错,则模拟器无法阻止被调试的操作系统从调试寄存器读取不正确的值(由模拟器放置在那里(。

启用(设置时(调试寄存器保护,这会导致要在访问调试寄存器的任何MOV指令之前生成调试异常
当则在生成异常之前设置调试状态寄存器DR6中的BD标志。这提供了支持电路内仿真器的条件。当模拟器需要访问调试寄存器时,模拟器软件可以设置GD标志以防止来自当前在处理器上执行的程序的干扰
处理器在进入调试异常处理程序时清除GD标志,以允许处理程序访问调试寄存器。

最新更新