Believe it or not, I have been told that some people rely on Cryptozor(us) software for file encryption.
Cryptozor(us) is from Thomas Nerrant. The author's primary web site seems down currently, but it is possible to find a working mirror: there are some available on .
First impression is that the GUI is ... poor, to say the least.
The software claims using PC1 and CARACACHS algorithms, which are mostly unknown from the community. This is often bad news ... for the software :)
First of all, let's try to encrypt a simple, plaintext file (such as "README.TXT"). The original file size is 15,331 bytes. A "README.TXT.CTZ" file is created on output. Here are the results using different passwords and the CARACACHS-128 algorithm:
- File #1, input password "a", output file size 15,402 bytes.
- File #2, input password "aa", output file size 15,402 bytes.
But the really bad news is that file #2 has exactly the same distribution:
What kind of "encryption" algorithm could give such results ? Having a closer look, file #1 and #2 differ on byte ranges [0x00..0x1C] and [0x3C00..0x3C1F]. Both files are otherwise exactly the same !
At this point, we are pretty confident in the fact that the output file is "scrambled" with a fixed key, and that the encryption key is useless in the process of decryption. Now let's have a look at "CRYPTOZORUS.EXE".
Having unpacked the file (upx -d cryptozorus.exe), we begin analysis. An idea to start with would be searching for a string reference to "!#? Bad Password ?#!". Such a reference can be found in the following piece of code (comments have been added later):
.text:0040314D case6_bad_password: ; CODE XREF: dispatch_sub+181j
.text:0040314D cmp ebx, 6
.text:00403150 jnz short case7_stopped
.text:00403152 mov word ptr [edi+10h], 50h
.text:00403158 mov edx, offset a?BadPassword? ; " !#? Bad Password ?#!"
.text:0040315D lea eax, [ebp+var_1C]
.text:00403160 call wrap_LStrFromPChar
The function at 0x00402F88 is clearly a switch/case related to the program's internal state. We call it "dispatch_sub()". When state == 6, "bad password" is displayed.
There are many references to dispatch_sub(), so it is better to trace the program with a debugger (namely OllyDbg) to find the caller on case 6. The result is pretty obvious:
.text:00408218 bad_password: ; CODE XREF: maybe_write_file+FFj
.text:00408218 push 6 ; 6 = BAD PASSWORD
.text:0040821A mov eax, [esi]
.text:0040821C mov edx, [eax]
.text:0040821E push edx
.text:0040821F call dispatch_sub
This piece of code is entered on the following condition:
.text:00408071 call test_password
.text:00408076 add esp, 8
.text:00408079 test al, al
.text:0040807B jz bad_password ; 6 = BAD PASSWORD
By replacing "jz bad_password" with "nop", it is possible to completly bypass password checking.
By patching 2 bytes inside the program file, we made a program that will decrypt any file without knowing the password. Total analysis time is under 20 minutes. Would you call that security software ?
PS. Having a closer look at test_password(), it seems that this function relies on the "CRYPTOZORUS_THOMASNERRANT.COM" string. The exact purpose of this string is left as an exercise to the reader. There are 2 possibilities:
- This is the fixed encryption key;
- This string, encrypted with user password, is used for password checking on decryption.