Challenge:
We received a crypter and a cypher, the aim is to decrypt the cypher and get the original key that is Alphanum and 11 bytes length : Crypter : in attachment Cypher : 7f e7 ff ce 0 98 15 dd 88 fb 6e Also we have found that the crc-Xmodem of the plaintext (key) = 0x8124 PS : If you think you found the right key and doesn't work (a collision), please be sure that the CRC-XMODEM value is equal to 0x8124 before sending us request
We have the crypter which is a ELF 64-bit executable and 11 byte cipher text. First we tried analysing the output giving random inputs and also looked for one to one mapping. But this attempt failed.
[ctf@renorobert Crypto]# file crypt crypt: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, not stripped [ctf@renorobert Crypto]# ./crypt qwerty your encrypted key is : ce be 56 e6 8a 77 0 0 0 0 0 [ctf@renorobert Crypto]# cat decipher.py #!/usr/bin/env python import subprocess crypter = "./crypt" data = '' for i in range(32,127): var = chr(i) data = var+': '+subprocess.check_output((crypter,var)) print data [ctf@renorobert Crypto]# python decipher.py | grep 7f S: your encrypted key is : 7f 0 0 0 0 0 0 0 0 0 0 T: your encrypted key is : 7f 0 0 0 0 0 0 0 0 0 0 m: your encrypted key is : 7f 0 0 0 0 0 0 0 0 0 0 [ctf@renorobert Crypto]# python decipher.py | grep e7 h: your encrypted key is : e7 0 0 0 0 0 0 0 0 0 0 [ctf@renorobert Crypto]# python decipher.py | grep ff 1: your encrypted key is : ff 0 0 0 0 0 0 0 0 0 0 [ctf@renorobert Crypto]# python decipher.py | grep ce I: your encrypted key is : ce 0 0 0 0 0 0 0 0 0 0 q: your encrypted key is : ce 0 0 0 0 0 0 0 0 0 0 [ctf@renorobert Crypto]# python decipher.py | grep ': 0' s: your encrypted key is : 0 0 0 0 0 0 0 0 0 0 0 [ctf@renorobert Crypto]# python decipher.py | grep 98 [ctf@renorobert Crypto]# python decipher.py | grep 15 [ctf@renorobert Crypto]# python decipher.py | grep ddThen we decided to look more into the binary to understand what's really happening. After some analysis and reversing we wrote the python version of the crypter.
#!/usr/bin/env python #crypt.py import sys arg_2 = [0x01,0xab,0xbf,0x0e,0x1b,0xc9,0xe6,0x8c,0x4d,0xe5,0x56,0x44,0x2d,0x92,0xe4,0x9e,0xdb,0x50,0xe3,0xed,0x82,0xfa,0xda,0x79,0x1f,0x6e,0xa4,0xfc,0xc5,0xbe,0x66,0xb5,0x78,0xcc,0xc2,0xb3,0xd0,0xb0,0x5c,0xe2,0x9f,0x52,0xa1,0x72,0x35,0x24,0x8e,0xa7,0x5e,0xe8,0x5b,0xc0,0xb2,0x49,0xb6,0xfe,0x09,0x06,0x04,0x20,0x1d,0xf5,0x3f,0x51,0x76,0xd7,0xff,0xf2,0xc1,0x83,0x87,0x28,0x99,0xc4,0x90,0xbd,0xbb,0xd3,0xbc,0xea,0xa2,0xe0,0x81,0xa9,0xdd,0x86,0x94,0x74,0x8f,0x5d,0xd6,0x37,0x2f,0xd2,0x88,0xe7,0x62,0x6c,0x10,0xde,0x7b,0x47,0x17,0xa0,0x97,0x26,0x9a,0xee,0xef,0xa3,0x69,0x0b,0xfd,0x8a,0xac,0x61,0x84,0xb1,0xa8,0xb9,0x7a,0xc7,0x22,0x0a,0xf9,0x68,0xba,0x64,0x32,0x89,0x13,0xb8,0xa5,0x73,0x67,0x6f,0x7d,0x3c,0x48,0x30,0xae,0x2c,0xeb,0x38,0x19,0x75,0xaf,0x41,0x12,0xc8,0x70,0x1e,0x29,0x45,0x7e,0x9d,0x43,0x7f,0x65,0x3a,0x08,0xe1,0x2a,0x60,0xcf,0x36,0x31,0x5f,0x85,0x23,0x4e,0x2b,0x18,0xfb,0x5a,0x80,0x77,0x8b,0x7c,0xa6,0x93,0x34,0x46,0xcb,0xdc,0xe9,0xf0,0x0c,0x8d,0x42,0x14,0x59,0x40,0xd9,0xd4,0x4b,0x6a,0x11,0x16,0x6b,0x0d,0x4a,0xcd,0x53,0x54,0x96,0x07,0x9c,0xf8,0x55,0x71,0xf7,0xd8,0x4f,0x3b,0xce,0x39,0xec,0xd1,0x3e,0x03,0xf1,0x25,0xd5,0x58,0x2e,0x3d,0x00,0x05,0xaa,0xb7,0x98,0xdf,0x02,0x57,0x9b,0xb4,0x95,0x33,0x91,0x21,0x27,0x15,0x4c,0x1a,0x6d,0xf6,0xf3,0xca,0xc3,0x1c,0x0f,0xc6,0xf4,0xad,0x63] def encrypt(arg_1,arg_2): match = 0 var_2 = 0 var_3 = 0 while 1: if len(arg_1) > var_3: for var_4 in range(256): edx = arg_1[var_3] eax = arg_2[var_4] if eax == edx: match = 1 var_5 = var_4 if match == 1: comp = arg_1[var_3] ^ var_5 arg_1[var_2] = comp var_2 += 1 match = 0 var_3 += 1 if comp == 0: # Effect of string length calculation return arg_1 else: var_3 += 1 else: return arg_1 arg_1 = [] plain = sys.argv[1] for i in plain: arg_1.append(ord(i)) r1 = encrypt(arg_1, arg_2) r2 = encrypt(r1, arg_2) for k in r2: sys.stdout.write(hex(k)+': ') print ' 'We can see that crypter performs two rounds of operation over the plain text. The collision mentioned is the effect of xor operation. Whenever the xor operation returned 0, the crypter returns with no further operation as string length calculation stops with null byte. Since the cipher was only 11 bytes long, we decided to grep through the results of cipher text for a given plain text.
[ctf@renorobert Brute]# python decipher.py T | grep e7 Th: your encrypted key is : 7f e7 0 0 0 0 0 0 0 0 0 [ctf@renorobert Brute]# python decipher.py S | grep e7 Sh: your encrypted key is : 7f e7 0 0 0 0 0 0 0 0 0 [ctf@renorobert Brute]# python decipher.py Th | grep ff Th1: your encrypted key is : 7f e7 ff 0 0 0 0 0 0 0 0 [ctf@renorobert Brute]# python decipher.py Th1 | grep ce Th1I: your encrypted key is : 7f e7 ff ce 0 0 0 0 0 0 0 Th1q: your encrypted key is : 7f e7 ff ce 0 0 0 0 0 0 0 [ctf@renorobert Brute]# python decipher.py Th1I | grep 'ff ce 0' Th1Is: your encrypted key is : 7f e7 ff ce 0 0 0 0 0 0 0Finally we got the following possible characters [['T','m','S'],'h','1',['I','q'],'s',['m','S','T'],'h','3','K','e',['y','Q']]. This can be easily bruteforced against the CRC-XMODEM value of 0x8124. But we didn't do that, the string "Th1IsTh3Key" made more sense to us. Checking its CRC-XMODEM value, we were right. So the key is Th1IsTh3Key
>>> hex(crc16.crc16xmodem('Th1IsTh3Key')) '0x8124'
No comments :
Post a Comment