up with a kernel debugger if you’re serious about reversing—certain reversing
scenarios are just undoable without a kernel debugger.
In this case, stepping into SYSENTERin SoftICE bring you into the KiFast
CallEntryin NTOSKRNL. This flows right into KiSystemService, which
is the generic system call dispatcher in Windows—all system calls go through
it. Quickly tracing over most of the function, you get to the CALL EBXinstruc-
tion near the end. This CALL EBXis where control is transferred to the specific
system service that was called. Here, stepping into the function reveals that the
program has called NtAllocateVirtualMemoryagain! You can hit F12 sev-
eral times to jump back up to user mode and run into the next call from
Defender. This is another API call that goes through the bizarre copied NTDLL
interface. This time Defender is calling NtCreateThread. You can ignore this
new thread for now and keep on stepping through the same function. It imme-
diately returns after creating the new thread.
The sequence that comes right after the call to the thread-creating function
again iterates through the checksum table, but this time it’s looking for check-
sum 006DEF20. Immediately afterward another function is called from the
copied NTDLL. You can step into this one as well and will find that it’s a
call to NtDelayExecution. In case you’re not familiar with it, NtDelay
Executionis the native API equivalent of the Win32 API SleepEx. SleepEx
simply relinquishes the CPU for the time period requested. In this case,
NtDelayExecutionis being called immediately after a thread has been cre-
ated. It would appear that Defender wants to let the newly created thread start
running immediately.
Immediately after NtDelayExecution returns, Defender calls into
another (internal) function at 403A41. This address is interesting because this
function starts approximately 30 bytes after the place from which it’s called.
Also, SoftICE isn’t recognizing any valid instructions after the CALLinstruc-
tion until the beginning of the function itself. It almost looks like Defender is
skipping a little chunk of data that’s sitting right in the middle of the function!
Indeed, dumping 4039FA, the address that immediately follows the CALL
instruction reveals the following:
004039FA K.E.R.N.E.L.3.2...D.L.L.
So, it looks like the Unicode string KERNEL32.DLLis sitting right in the
middle of this function. Apparently all the CALLinstruction is doing is just
skipping over this string to make sure the processor doesn’t try to “execute” it.
The code after the string again searches through our table, looking for two val-
ues: 6DEF20and 1974C. You may recall that 6DEF20is the name checksum
for NtDelayExecution. We’re not sure which API is represented by
1974C—we’ll soon find out.
Breaking Protections 395