After KERNEL32.DLL is loaded, Defender goes through the familiar
sequence of allocating a random address in memory and produces the same
name checksum/RVA table from all the KERNEL32.DLLexports. After the
copied module is ready for use the function makes one other call to NtDelay
Executionfor good luck and then you get to another funny jump that skips
30 bytes or so. Dumping the memory that immediately follows the CALL
instruction as text reveals the following:
00404138 44 65 66 65 6E 64 65 72 Defender
00404140 20 56 65 72 73 69 6F 6E Version
00404148 20 31 2E 30 20 2D 20 57 1.0 - W
00404150 72 69 74 74 65 6E 20 62 ritten b
00404158 79 20 45 6C 64 61 64 20 y Eldad
00404160 45 69 6C 61 6D Eilam
Finally, you’re looking at something familiar. This is Defender’s welcome
message, and Defender is obviously preparing to print it out. The CALL
instruction skips the string and takes us to the following code.
00404167 PUSH DWORD PTR SS:[ESP]
0040416A CALL Defender.004012DF
The code is taking the “return address” pushed by the CALLinstruction and
pushes it into the stack (even though it was already in the stack) and calls a
function. You don’t even have to look inside this function (which is undoubt-
edly full of indirect calls to copied KERNEL32.DLLcode) to know that this
function is going to be printing that welcome message that you just pushed
into the stack. You just step over it and unsurprisingly Defender prints its wel-
come message.
Reencrypting the Function
Immediately afterward you have yet another call to 6DEF20—NtDelay
Executionand that brings us to what seems to be the end of this function.
OllyDbg shows us the following code:
004041E2 MOV EAX,Defender.004041FD
004041E7 MOV DWORD PTR DS:[4034D6],EAX
004041ED MOV DWORD PTR SS:[EBP-8],0
004041F4 JMP Defender.00403401
004041F9 LODS DWORD PTR DS:[ESI]
004041FA DEC EDI
004041FB ADC AL,0F2
004041FD POP EDI
004041FE POP ESI
004041FF POP EBX
00404200 LEAVE
00404201 RETN
Breaking Protections 401