Assuming an attacker can compromise the anti-debugging protection scheme, then
he or she is free to make clever use of hardware breakpoints to disable other
protection systems (such as hardcoded base addresses of modules, checks on the
authenticity of a CheckRevision caller, and soforth) by setting execute fetch
breakpoints on choice code locations. Then, the attacker could simply alter
the execution context when the breakpoints are hit, in order to bypass other
protection mechanisms. For example, an attacker could set a read breakpoint
on the hardcoded base address for the main process image inside the Lockdown
module, and change the base address accordingly. The attacker would also
have to patch GetModuleHandleA in order to complete this example attack.
Suggested counters to attacks based on hardware breakpoints include:
- Validation of the vectored exception handler chain, which might be used to
intercept STATUS_SINGLE_STEP exceptions when hardware breakpoints are hit.
This is risky, as there are legitimate reasons for there to be "foreign"
vectored exception handlers, however.
- Checks to stop debuggers from attaching to the process, period. This is not
considered to be a viable solution since there are a number of legitimate
reasons for a debugger to be attached to a process, many of them which may
be unknown completely to the end user (such as profilers, crash control and
reporting systems, and other types of security software). Attempting to
block debuggers may also prevent the normal operation of Windows Error
Reporting or a preconfigured JIT debugger in the event of a game crash,
depending on the implementation used. Ways of detecting debuggers include
calls to IsDebuggerPresent, NtQueryInformationProcess(...ProcessDebugPort..),
checks against NtCurrentPeb()->BeingDebugged, and soforth.
- Duplication of checks (perhaps in slightly altered forms) throughout the
execution of the checksum implementation. It is important for this
duplication to be inline as much as possible in order to eliminate single
points of failure that could be used to short-circuit protection schemes by
- Strengthening of the anti-debugging mechanism, as previously described.