has a pure user-mode implementation, which forces you to use the function
index method. It turns out the API is GetCommandLineW. Indeed, it returns a
pointer to our test command line.
The next call is to a SHELL32.DLLAPI. Again, a SHELL32 API would prob-
ably never make a direct call down into the kernel, so you’re just stuck with
some long function and you’ve no idea what it is. You have to use the func-
tion’s index again to figure out which API Defender is calling. This time it
turns out that it’s CommandLineToArgvW. CommandLineToArgvWperforms
parsing on a command-line string and returns an array of strings, each con-
taining a single parameter. Defender must call this function directly because it
doesn’t make use of a runtime library, which usually takes care of such things.
After the CommandLineToArgvWcall, you reach an area in Defender that
you’ve been trying to get to for a really long time: the parsing of the command-
line arguments.
You start with simple code that verifies that the parameters are valid. The
code checks the total number of arguments (sent back from CommandLine
ToArgvW) to make sure that it is three (Defender.EXE’s name plus username
and serial number). Then the third parameter is checked for a 16-character
length. If it’s not 16 characters, defender jumps to the same place as if there
aren’t three parameters. Afterward Defender calls an internal function,
401CA8that verifies that the hexadecimal string only contains digits and let-
ters (either lowercase or uppercase). The function returns a Boolean indicating
whether the serial is a valid hexadecimal number. Again, if the return value is
0 the code jumps to the same position (40299C), which is apparently the “bad
parameters” code sequence. The code proceeds to call another function
(401CE3) that confirms that the username only contains letters (either lower-
case or uppercase). After this you reach the following three lines:
00402994 TEST EAX,EAX
00402996 JNZ Defender.00402AC4
0040299C CALL Defender.004029EC
When this code is executed EAXcontains the returns value from the user-
name verification sequence. If it is zero, the code jumps to the failure code, at
40299C, and if not it jumps to 402AC4, which is apparently the success code.
One thing to notice is that 4029ECagain uses the CALLinstruction to skip a
string right in the middle of the code. A quick look at the address right after the
CALLinstruction in OllyDbg’s data view reveals the following:
004029A1 42 61 64 20 70 61 72 61 Bad para
004029A9 6D 65 74 65 72 73 21 0A meters!.
004029B1 55 73 61 67 65 3A 20 44 Usage: D
004029B9 65 66 65 6E 64 65 72 20 efender
004029C1 3C 46 75 6C 6C 20 4E 61 <Full Na
Breaking Protections 405