Debug registers (DR0 through DR7) are used to set hardware breakpoints. A protection can manipulate them to either detect that hardware breakpoints have been set (and therefore, that it is being debugged), reset them or set them to particular values used to perform code checks later. A packer such as tElock makes use of the debug registers to prevent reverse-engineers from using them.
From a user-mode perspective, debug registers cannot be set using the privileged 'mov drx, ...' instruction. Other ways exist:
- An exception can be generated, the thread context modified (it contains the CPU registers at the time the exception was thrown), and then resumed to normal execution with the new context.
- The other way is to use the NtGetContextThread and NtSetContextThread syscalls (available in kernel32 with GetThreadContext and SetThreadContext).
0:000> g
ModLoad: 76200000 7621f000 C:\Windows\system32\IMM32.DLL
ModLoad: 75c10000 75cdc000 C:\Windows\system32\MSCTF.dll (23b4.880): Single step exception - code 80000004 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=7ffd5000 ecx=0012f7a4 edx=777b70b4 esi=0012f7c4 edi=0012fe54
eip=00411727 esp=0012f7c4 ebp=0012fe54 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
*** WARNING: Unable to verify checksum for testC.exe
testC!DataBP+0xd7:
00411727 8bf4 mov esi,esp
但实际上是硬件断点,看看debug register的值,dr6表明硬件断点dr1命中。
0:000> r dr6, dr7
dr6=ffff0ff1 dr7=00010501