The next instruction loads the file name address from [ESP+24]to EAXand
proceeds to another unusual instruction called XORPS, which takes an unusual
operand called XMM0. This is part of a completely separate instruction set
called SSE2 that is supported by most currently available implementations of
IA-32 processors. The SSE2 instruction set contains Single Instruction Multiple
Data (SIMD) instructions that can operate on several groups of operands at the
same time. This can create significant performance boosts for computationally
intensive programs such as multimedia and content creation applications.
XMM0is the first of 8 special, 128-bit registers names: XMM0through XMM7. These
registers can only be accessed using SSE instructions, and their contents are
usually made up of several smaller operands. In this particular case, the XORPS
instruction XORs the entire contents of the first SSE register with the second
SSE register. Because XORPSis XORing a value with itself, it is essentially set-
ting the value of XMM0to zero.
The FSTPinstruction that comes next stores the value from the top of the
floating-point stack into [ESP+34]. As you can see from the DWORD PTRthat
precedes the address, the instruction treats the memory address as a 32-bit
location, and will convert the value to a 32-bit floating-point representation.
As a reminder, the value currently stored at the top of the floating-point stack
is the result of the earlier division operation.
The Decryption Loop
At this point, we enter into what is clearly a loop that continuously reads
and decrypts additional clusters using 00401030 , hashes that data using
CryptHashData, and writes the block to the file that was opened earlier using
the WriteFileAPI.
At this point, you can also easily see what all of this floating-point business
was about. With each cluster that is decrypted Cryptex is printing an accurate
floating-point number that shows the percentage of the file that has been writ-
ten so far. By dividing 100.0 by the total number of clusters earlier, Cryptex
simply determined a step size by which it will increment the current com-
pleted percentage after each written cluster.
One thing that is interesting is how Cryptex knows which cluster to read
next. Because Cryptex supports deleting files from archives, files are not guar-
anteed to be stored sequentially within the archive. Because of this, Cryptex
always reads the next cluster index from 00405050 and passes that to
00401030 when reading the next cluster. 00405050 is the beginning of the
currently active cluster buffer. This indicates that, just like in the file list, the
first DWORD in a cluster contains the next cluster index in the current chain.
One interesting aspect of this design is revealed in the following lines.
238 Chapter 6