Back to the console, the ls command shows that there are two different key-files, a key-server and a key (none of them readable with the cat command).
The aeslite_encrypt command encrypts a given 16-byte message. We thought that the communication was encrypted with the aeslite algorithm using the key key as pre-shared-key and the challenge goal is to obtain the other key key-server.
1 2 3 4 5
key-server% ls key-server key key-server% aeslite_encrypt AAAAAAAAAAAAAAAA Here you go: SECRET31b43860ea4bfed82a04e38ae7770c5c
After these speculations, we analyzed the assembly code: the client communicate with the server using the aeslite algorithm and a preshared key: thisisnotthekey!. The aeslite encryption algorithm is the following:
Assuming that the AddRoundKey, SubBytes, ShiftRows and MixColumns work like in AES, aeslite provides a faster and unsafe version. In fact, knowing both the plaintext and the ciphertext, the following operation returns the key:
Thanks to Wikipedia ( AES, Sbox, MixColumn ), we implemented the aeslite operations in python, testing it with the sniffed packets, which are encrypted with the key thisisnotthekey!.
S 00000000 20 00 00 00 ... S 00000004 5e e2 91 fd 35 a6 08 5a 8c 9c 41 be 3d 31 67 6e ^...5..Z ..A.=1gn S ... S 00000434 7d 88 96 31 b9 b0 d5 52 e3 02 c8 c1 0d a5 8b 86 }..1...R ........ S 00000444 7d 88 96 31 b9 b0 d5 52 e3 02 c8 c1 0d a5 8b 86 }..1...R ........ S 00000454 7d 88 96 31 b9 b0 d5 52 e3 02 c8 c1 }..1...R .... C 00000000 30 00 00 00 0... C 00000004 b1 c9 4e fd 2c 9e 2f 4b 52 c9 88 6e 30 f1 43 47 ..N.,./K R..n0.CG C 00000014 27 f4 8f 9c ed 29 c9 8b 68 97 9b c1 06 bd 30 e8 '....).. h.....0. C 00000024 cf c4 ea 25 7d 88 96 31 b9 b0 d5 52 e3 02 c8 c1 ...%}..1 ...R.... S 00000460 40 00 00 00 @... S 00000464 0b db f8 cb 5d a0 42 55 42 62 9d 95 ac 4d d6 e0 ....].BU Bb...M.. S 00000474 a2 f6 5a b1 06 d1 18 2f 57 b3 68 19 60 76 7d 09 ..Z..../ W.h.`v}. S 00000484 b2 37 07 99 b7 90 d9 4b ed af b0 e4 50 17 76 58 .7.....K ....P.vX S 00000494 c9 c7 e9 20 44 b1 dd 43 27 09 f2 cc f8 10 c1 c8 ... D..C '....... S 000004A4 10 00 00 00 4c 8d 46 1e 00 e5 52 94 d6 89 27 a9 ....L.F. ..R...'. S 000004B4 6e 1b 39 16 n.9. C 00000034 10 00 00 00 .... C 00000038 e4 5c 72 96 33 c0 4a a3 23 05 fa c8 db db 29 20 .\r.3.J. #.....) S 000004B8 20 00 00 00 ... S 000004BC a8 f9 a2 39 bc ea d9 88 1e 3a 43 7b 01 c3 2a f9 ...9.... .:C{..*. S 000004CC f5 25 d3 fe 82 4b 6b 90 bc fe 8c 31 40 3b 52 ea .%...Kk. ...1@;R.
Why that data wasn’t displayed? The solution lies in the main code. After receiving a message, the client checks if the message starts with the string SECRET (0x804bc7a). In such case, it stores the message in 0x804e6e0, without printing it to the standard output.
By debugging or patching the program or decoding the sniffed packet, comes out that the server sends a string to the client (we have encoded the raw byte for the sake of printability :D )
SECRETS = ["d1e70b1c3496ee591dcb51c64abf9c94".decode('hex'), "6411dee67c1722f4479342193cc74675".decode('hex'), "9cbc36a69d1b78337b86beae34acb003".decode('hex')] final = "" for s in SECRETS: final += ''.join([chr(c) for c in decrypt(s, key)]) print final
The result The key is: Good enough for government work was the challenge solution.