00401DBC CMP EDI,1
00401DBF MOV EAX,0FFC
00401DC4 JA SHORT cryptex.00401DCB
00401DC6 MOV EAX,DS:[405050]
00401DCB ...
At any given moment during this loop EDIcontains the number of clusters
left to go. When there is more than one cluster to go (EDI > 1), the number of
bytes to be read (stored in EAX) is hard-coded to 0xFFC(4092 bytes), which is
probably just the maximum number of bytes in a cluster. When Cryptex writes
the last cluster in the file, it takes the number of bytes to write from the first
DWORD in the cluster—the very same spot where the next cluster index is
usually stored. Get it? Because Cryptex knows that this is the last cluster, the
location where the next cluster index is stored is unused, so Cryptex uses that
location to store the actual number of bytes that were stored in the last cluster.
This is how Cryptex works around the problem of not directly storing the
actual file size but merely storing the number of clusters it uses.
Verifying the Hash Value
After the final cluster is decrypted and written into the extracted file, Cryptex
calls CryptGetHashParamto recover the MD5 hash value that was calcu-
lated out of the entire decrypted data. This is compared against that 16-bytes
sequence that was returned from 004017B0(recall that these 16-bytes were
retrieved from the file’s entry in the file table). If there’s a mismatch Cryptex
prints an error message saying the file is corrupted. Clearly the MD5 hash is
used here as a conventional checksum; for every file that is encrypted an MD5
hash is calculated, and Cryptex verifies that the data hasn’t been tampered
with inside the archive.
The Big Picture
At this point, we have developed a fairly solid understanding of the .crxfile
format. This section provides a brief overview of all the information gathered
in this reversing session. You have deciphered the meaning of most of the
.crxfields, at least the ones that matter if you were to write a program that
views or dumps an archive. Figure 6.2 illustrates what you know about the
Cryptex header.
The Cryptex header comprises a standard 8-byte signature that contains the
string CrYpTeX9. The header contains a 16-byte MD5 checksum that is used
for confirming the user-supplied password. Cryptex archives are encrypted
using a Crypto-API implementation of the triple-DES algorithm. The triple-
DES key is generated by hashing the user-supplied password using the SHA
Deciphering File Formats 239