Reversing : The Hacker's Guide to Reverse Engineering

(ff) #1
value 0x8003as its algorithm ID, while this function uses 0x8004, which
identifies the CALG_SHAalgorithm. SHA is another hashing algorithm that has
similar properties to MD5, with the difference that an SHA hash is 160 bits
long, as opposed to MD5 hashes which are 128 bits long. You might notice that
160 bits are exactly 20 bytes, which is the length of data being hashed in List-
ing 6.4. Coincidence? You’ll soon find out....
The next sequence calls CryptHashDataagain, but not before some process-
ing is performed on some data block. If you place a breakpoint on this function
and restart the program, you can easily see which data it is that is being
processed: It is the password text, which in this case equals 6666666665. Let’s
take a look at this processing sequence.

00402335 LEA ESI,DS:[EAX+1]
00402338 MOV CL,DS:[EAX]
0040233A ADD EAX,1
0040233D TEST CL,CL
0040233F JNZ SHORT cryptex.00402338

This loop is really quite simple. It reads each character from the string and
checks whether its zero. If it’s not it loops on to the next character. When the
loop is completed, EAXpoints to the string’s terminating NULLcharacter, and
ESIpoints to the second character in the string. The following instruction pro-
duces the final result.

00402347 SUB EAX,ESI

Here the pointer to the second character is subtracted from the pointer to the
NULLterminator. The result is effectively the length of the string, not including
the NULLterminator (because ESIwas holding the address to the second char-
acter, not the first). This sequence is essentially equivalent to the strlenC
runtime library function. You might wonder why the program would imple-
ment its own strlenfunction instead of just calling the runtime library. The
answer is that it probably iscalling the runtime library, but the compiler is
replacing the call with an intrinsicimplementation. Some compilers support
intrinsic implementations of popular functions, which basically means that the
compiler replaces the function call with an actual implementation of the func-
tion that is placed inside the calling function. This improves performance
because it avoids the overhead of performing a function call.
After measuring the length of the string, the function proceeds to hash the
password string using CryptHashDataand to extract the resulting hash
using CryptGetHashParam. The resulting hash value is then passed on to
00402280 , which is the function we investigated in Listing 6.4. This is curious
because as we know the function in Listing 6.4 is going to hash that data again,
this time using the MD5 algorithm. What is the point of rehashing the output

216 Chapter 6

Free download pdf