Download the exe found in the previous part: http://canyoucrackit.co.uk/da75370fe15c4148bd4ceec861fbdaa5.exe
Load it up in Olly and we immediately find we need cygcrypt-0.dll. To get this dll, download cygwin and install. This dll is not installed by default – in the installation, search and select all references to ‘ssh’ and ‘crypt’.
Now run the exe. We’re told:
usage: keygen.exe hostname
So, set the execution argument in Olly to canyoucrackit.co.uk. Next, let’s analyse the behaviour of the program – it’s small and basic!
Here’s some pseudo code detailing its operation:
Read first line of file 'license.txt' into buffer
Are the first four characters gchq? If not, error.
Does result of crypt equal hqDTK7b8K2rvw? If not, error.
Create request string /hqDTK7b8K2rvw/AAAAAAAA/BBBBBBBB/CCCCCCCC/key.txt
(AA/BB/CC are the hex representations of the next three groups of four characters)
Perform HTTP request using above string, accessing host provided by the first argument (which we set to canyoucrackit.co.uk)
So, license.txt should contain:
Note that we don’t yet know password. However, let’s just bypass the check of the crypted password:
MOV EAX,DWORD PTR DS: ;ptr to string hqDTK7b8K2rvw
MOV DWORD PTR SS:[ESP+4],EAX ;move onto stack
LEA EAX,DWORD PTR SS:[EBP-38] ;pointer to gchqPASSWORDabcdefghijkl
ADD EAX,4 ;eax now points to PASSWORDabcdefghijkl
MOV DWORD PTR SS:[ESP],EAX ;move onto stack
CALL 0040142C ; <JMP.&cygcrypt-0.crypt> (call crypt)
MOV EAX,DWORD PTR DS:
MOV DWORD PTR SS:[ESP+4],EAX ;put ptr to hqDTK7b8K2rvw onto stack
MOV DWORD PTR SS:[ESP],EDX ;put str to crypt result onto stack
CALL 00401530 ;strcmp
JNZ SHORT 004011A5 ;keygen.004011A5
So, NOP out this last jump and PASSWORD can be anything. Now, given this input, the following request string is made:
GET /hqDTK7b8K2rvw/64636261/68676665/6c6b6a69/key.txt HTTP/1.0
(Note that 0×61 = ‘a’, 0×62 = ‘b’ etc)
Clearly, GCHQ have missed a trick here! Why on earth they didn’t make the first part of the result the plaintext password (requiring the crypt to actually be cracked), is beyond me. This makes the use of crypt completely redundant. However, for a bit of fun I decided to crack the hash anyway.
The cygwin doc explains:
It provides a static library libcrypt.a as well as a shared library
cygcrypt-0.dll together with a link lib libcrypt.dll.a, which export
The passwords created by crypt(3) are 56 bit DES encrypted and are
100% identical to those created by the Linux crypt().
So, we have ourselves an oldschool unix crypt hash. The crypt.h header file tells us:
char * _EXFUN(crypt, (const char *key, const char *salt));
So, hqDTK7b8K2rvw is our salt string. Note, that crypt(3) only uses the first two characters of the salt, and returns (salt+hash). So our actual salt is ‘hq’ and ‘DTK7b8K2rvw’ is the actual hash.
Time to release John the Ripper!
Stick our hash in a unix format passwd file:
And run the following command:
john-mmx --format=DES -i=alpha passwd
format=DES specifies the use of the crypt(3) algorithm, i=alpha means try all alpha combinations. Note that crypt(3) only uses the first 8 characters, so this means from to ‘a’ to ‘zzzzzzzz’. Here’s what John tells us after a total of 35 minutes (note I was testing the ‘restore’ functionality here):
So our plaintext is ‘cyberwin’. We now have the first 12 characters of license.txt:
But we still need to figure out the last bit. The hint is actually the text here:
004011A5 |> \C70424 A82040>MOV DWORD PTR SS:[ESP],4020A8 ; ||ASCII "loading stage1 license key(s)...
004011AC |. E8 A7030000 CALL 00401558 ; |\printf
004011B1 |. 8B45 D4 MOV EAX,DWORD PTR SS:[EBP-2C] ; load first DWORD
004011B4 |. 8945 B8 MOV DWORD PTR SS:[EBP-48],EAX ; |
004011B7 |. C70424 CC2040>MOV DWORD PTR SS:[ESP],4020CC ; |ASCII "loading stage2 license key(s)...
004011BE |. E8 95030000 CALL 00401558 ; \printf
004011C3 |. 8B45 D8 MOV EAX,DWORD PTR SS:[EBP-28]
004011C6 |. 8945 BC MOV DWORD PTR SS:[EBP-44],EAX ;load second DWORD
004011C9 |. 8B45 DC MOV EAX,DWORD PTR SS:[EBP-24]
004011CC |. 8945 C0 MOV DWORD PTR SS:[EBP-40],EAX ;load third DWORD
(scroll right to see the comments above)
firmware: [0xd2ab1f05, 0xda13f110]
We need to go back and have another look at stage one to get any further. Right at the start of the executable code of stage one, we see:
00401000 > $ EB 04 JMP SHORT test.00401006
00401002 AF DB AF
00401003 C2 DB C2
00401004 BF DB BF
00401005 A3 DB A3
00401006 > 81EC 00010000 SUB ESP,100
This is a bit fishy… the JMP and four bytes (a DWORD) are completely redundant! So why don’t we try AF C2 BF A3?
Fiddling around with the endianness results in the following valid request:
Finally, key.txt contains the final password: Pr0t3ct!on#cyber_security@12*12.2011+