SetLastError
to set the current error code to an arbitrary value. If OutputDebugString
is called and there is no debugger attached, GetLastError
should no longer contain our arbitrary value, because an error code will be set by the OutputDebugString
function if it fails. If OutputDebugString
is called and there is a debugger attached, the call to OutputDebugString
should succeed, and the value in GetLastError
should not be changed.BeingDebugged
flag. Finally, EBX is checked to see if it is zero. If so, a debugger is not attached, and the jump will be taken.Another example is shown on the right side of . The location of the PEB is moved into EDX using a push/pop combination of instructions, and then the BeingDebugged
flag at offset 2 is directly compared to 1.
This check can take many forms, and, ultimately, the conditional jump determines the code path. You can take one of the following approaches to surmount this problem:
Force the jump to be taken (or not) by manually modifying the zero flag immediately before the jump instruction is executed. This is the easiest approach.
Manually change the BeingDebugged
flag to zero.
Both options are generally effective against all of the techniques described in this section.
ProcessHeap
, is set to the location of a process’s first heap allocated by the loader. ProcessHeap
is located at 0x18 in the PEB structure. This first heap contains a header with fields used to tell the kernel whether the heap was created within a debugger. These are known as the ForceFlags
and Flags
fields.Offset 0x10 in the heap header is the ForceFlags
field on Windows XP, but for Windows 7, it is at offset 0x44 for 32-bit applications. Malware may also look at offset 0x0C on Windows XP or offset 0x40 on Windows 7 for the Flags
field. This field is almost always equal to the ForceFlags
field, but is usually ORed with the value 2.
shows the assembly code for this technique. (Note that two separate dereferences must occur.)