I'm trying to understand some of the anti-debugger functions in https://github.com/nemesisqp/al-khaser/blob/0f74c40dde8ba060807e031271f81457a187fa08/DebuggerDetection.cpp#L603
Would
__asm {
mov eax, fs:[30h]
mov al, [eax + 2h]
mov IsDbg, al
}
function the same as
__asm mov IsDbg, [fs:[0x30] + 0x2]
If not, why not?
Also, how could this be converted to pure C/C++? How can I get thread info (specifically fs:[30h])?
And would
BOOL Int2DCheck()
{
// The Int2DCheck function will check to see if a debugger
// is attached to the current process. It does this by setting up
// SEH and using the Int 2D instruction which will only cause an
// exception if there is no debugger. Also when used in OllyDBG
// it will skip a byte in the disassembly and will create
__try
{
__asm
{
int 2dh
xor eax, eax
add eax, 2
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return false;
}
return true;
}
Be the same as
__try
{
__asm
{
xor eax, eax
int 0x2d
inc eax
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return false;
}
If not, why not?
Both of those techniques are relatively old. I think they were in use in the early 2000s, if not the late 90s.
The first uses the fact that the Thread-Information Block (TIB) resides at fs:[0]
for windows processes (at least as late as WinXP...I haven't looked since then).
Offset 0x30 into the TIB is a pointer to the Process Environment Block (PEB). From that link, we see that offset 0x2 into the PEB is the 'being debugged' flag. This is the value that is read by the API call IsDebuggerPresent
.
The second example demonstrates two detection mechanisms:
This answer gives good detail on the function of int 0x2d
on windows. For the moment, we'll just note that it's part of Windows' built-in debugging support.
The simpler mechanism is this: Structured exception handling in Windows would catch things that the language-based exceptions couldn't, because it was hooked into the OS's exception handling framework, not the language-runtime's.
So the int 0x2d
would generate a fault; any debugger present would handle the fault, and because this interrupt is for debugging, the debugger would return to control-flow as usual. Thus the structured-exception handling mechanism wouldn't be invoked...so the 'catch' would never be reached, and the return value of the function would thereby change. This method was pretty trivially defeated by later SEH-aware debuggers, by telling the debugger to pass the exception to the program, in which case the SEH would fire.
The other mechanism is based in the detail of the of way int 0x2d
is processed by windows, which was apparently not emulated perfectly by OllyDbg (a once phenomenal debugger that went defunct and came back full of malware). I am not personally familiar with this method, so I would direct you to the linked answer.
Just for context, the early days of anti-debugger techniques were studies of particularly popular debug tools. In whatever document you've dug these techniques from, you will no doubt also see ones dedicated to detecting NuMega Softice --- probably the first kernel debugger for Windows (circa NT 4.0). The instruction sequence from whence my handle is derived was used as a method of detecting this debugger.
Thanks for the trip down memory lane ;)