如果设置了 GD 标志,读取调试寄存器是否会引发异常?
Does reading a debug register raise an exception if the GD flag is set?
我最近一直在研究调试寄存器,以及一些恶意程序如何能够将它们作为一种反调试策略来操纵。我现在读过几次的一件事是,这可以通过使用 DR7 中的通用检测标志来防止,如果使用 MOV 指令访问 DR0-DR7 中的任何一个,它会引发调试异常。
但是,我不清楚访问的确切含义 - 例如,如果使用 mov 指令仅将 DR0-DR3 的地址放入通用寄存器以便可以读取,那么这仍然会导致在设置 GD 标志时引发调试异常?还是仅当使用 MOV 指令实际更改寄存器的内容时才会发生这种情况?到目前为止,我所读到的内容对此有些含糊。
我在一段显示调试寄存器操作的文本中遇到了下面的程序集,但在这种情况下 mov 仅用于获取调试寄存器的地址,实际修改是由 or 指令完成的,所以我如果设置了 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>
英特尔对此非常清楚:
An attempt to read or write the debug registers
from any other privilege level generates a general-protection exception (#GP).
因此,在 CPL 0 不 运行 时读取或写入调试寄存器将引发异常,与 GD
标志无关。
事实上,我分析了相当多的恶意软件,其中 none 直接访问调试寄存器。
他们获取当前线程上下文(GetThreadContext or NtGetContextThread 或类似的 WOW64 变体)并从那里检查调试寄存器的值,注意在这种情况下是 Windows' 内核读取调试寄存器。
这个反调试技巧可以手动解决(在 API 检索上下文时使用断点)或使用调试器插件。
CPL 0 的恶意软件 运行 可以使用 GD 标志,但到目前为止我还没有找到。
回答您的标题问题,如果设置了 GD
,对调试寄存器的任何读或写访问(在 CPL 0)都会引发 #GP。
我没有测试过它,但考虑到它的预期用途(支持硬件调试器仿真器),我的想法是“虚拟化”调试寄存器。
软件中模拟的硬件调试器可以使用调试寄存器,即使被调试的 OS 已经在使用它们。
这是通过在每次访问时出错并正确地换入和换出 OS 与模拟器值来完成的。
如果只有写入出错,仿真器无法阻止被调试的 OS 从调试寄存器中读取不正确的值(由仿真器放置在那里)。
Enables (when set) debug-register protection, which causes a
debug exception to be generated prior to any MOV instruction that accesses a debug register.
When such a
condition is detected, the BD flag in debug status register DR6 is set prior to generating the exception. This
condition is provided to support in-circuit emulators.
When the emulator needs to access the debug registers, emulator software can set the GD flag to prevent
interference from the program currently executing on the processor.
The processor clears the GD flag upon entering to the debug exception handler, to allow the handler access to
the debug registers.
我最近一直在研究调试寄存器,以及一些恶意程序如何能够将它们作为一种反调试策略来操纵。我现在读过几次的一件事是,这可以通过使用 DR7 中的通用检测标志来防止,如果使用 MOV 指令访问 DR0-DR7 中的任何一个,它会引发调试异常。
但是,我不清楚访问的确切含义 - 例如,如果使用 mov 指令仅将 DR0-DR3 的地址放入通用寄存器以便可以读取,那么这仍然会导致在设置 GD 标志时引发调试异常?还是仅当使用 MOV 指令实际更改寄存器的内容时才会发生这种情况?到目前为止,我所读到的内容对此有些含糊。
我在一段显示调试寄存器操作的文本中遇到了下面的程序集,但在这种情况下 mov 仅用于获取调试寄存器的地址,实际修改是由 or 指令完成的,所以我如果设置了 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>
英特尔对此非常清楚:
An attempt to read or write the debug registers from any other privilege level generates a general-protection exception (#GP).
因此,在 CPL 0 不 运行 时读取或写入调试寄存器将引发异常,与 GD
标志无关。
事实上,我分析了相当多的恶意软件,其中 none 直接访问调试寄存器。 他们获取当前线程上下文(GetThreadContext or NtGetContextThread 或类似的 WOW64 变体)并从那里检查调试寄存器的值,注意在这种情况下是 Windows' 内核读取调试寄存器。 这个反调试技巧可以手动解决(在 API 检索上下文时使用断点)或使用调试器插件。 CPL 0 的恶意软件 运行 可以使用 GD 标志,但到目前为止我还没有找到。
回答您的标题问题,如果设置了 GD
,对调试寄存器的任何读或写访问(在 CPL 0)都会引发 #GP。
我没有测试过它,但考虑到它的预期用途(支持硬件调试器仿真器),我的想法是“虚拟化”调试寄存器。
软件中模拟的硬件调试器可以使用调试寄存器,即使被调试的 OS 已经在使用它们。
这是通过在每次访问时出错并正确地换入和换出 OS 与模拟器值来完成的。
如果只有写入出错,仿真器无法阻止被调试的 OS 从调试寄存器中读取不正确的值(由仿真器放置在那里)。
Enables (when set) debug-register protection, which causes a debug exception to be generated prior to any MOV instruction that accesses a debug register.
When such a condition is detected, the BD flag in debug status register DR6 is set prior to generating the exception. This condition is provided to support in-circuit emulators. When the emulator needs to access the debug registers, emulator software can set the GD flag to prevent interference from the program currently executing on the processor.
The processor clears the GD flag upon entering to the debug exception handler, to allow the handler access to the debug registers.