Trouble getting 3DES decryption to work

Doubts, help and support about QuickBMS and other game research tools
HenryEx
Posts: 27
Joined: Wed Aug 13, 2014 6:43 pm

Trouble getting 3DES decryption to work

Post by HenryEx »

I'm trying to decrypt a save game via QuickBMS. Thankfully, it's a Unity game so it's easy to check how the game does it. Here's some disassembled code from it:

Code: Select all

      TripleDESCryptoServiceProvider tripleDESCryptoServiceProvider = new TripleDESCryptoServiceProvider();
      tripleDESCryptoServiceProvider.Key = key;
      tripleDESCryptoServiceProvider.IV = array;
      tripleDESCryptoServiceProvider.Mode = CipherMode.CFB;
      tripleDESCryptoServiceProvider.Padding = PaddingMode.PKCS7;
      ICryptoTransform cryptoTransform = tripleDESCryptoServiceProvider.CreateDecryptor();
      byte[] decrypted = cryptoTransform.TransformFinalBlock(data, 0, data.Length);

I know how to get the key and IV, but i can't seem to get valid output, no matter which Encryption command i use.

Here's a sample encrypted save game, base64 encoded:
https://pastebin.com/hZrvK4Gu

And here's the sample save game decrypted, read from game memory during run-time:
https://pastebin.com/X4h5cpXX
(keep in mind that THIS IS how it should look immediately after decryption; the game does base64 encode before encryption)

So this is what my script looks like so far to get the key and IV, but as i said, the final file doesn't match up:

Code: Select all

string KEY = "=(*&^%$#@%^**^((*(())=bc=_-420@@#$#9-2@@#$#11_)00xyz2*(*(*((=)(&"
log MEMORY_FILE 0 0
get FILESIZE asize 0
ComType base64
clog MEMORY_FILE 0 FILESIZE FILESIZE 0  # decrypt base64
get MSIZE1 asize MEMORY_FILE

get KEYADD byte MEMORY_FILE  # first byte gets added to key
string KEYADD = KEYADD
string KEY + KEYADD
print "New Key: %KEY%"

Encryption sha1 KEY
print "SHA-1 hash: %QUICKBMS_HEXHASH%"
print "SHA-1 hash binary: %QUICKBMS_HASH%"
set KEY string QUICKBMS_HASH
string KEY - 4  # 16 byte key from hash

xmath POS "MSIZE1 - 1"
goto POS MEMORY_FILE
get IVSIZE byte MEMORY_FILE  # last byte is IV size
print "IV size: %IVSIZE%"
math POS - IVSIZE
goto POS MEMORY_FILE
getdstring IVECTOR IVSIZE MEMORY_FILE

xmath DATASIZE "MSIZE1 - IVSIZE - 2"  # exclude the IV, IV size and key salt in data size
print "Data size: %DATASIZE%"

Encryption 3des-112 KEY IVECTOR 0 16
log "112key-decrypt.bin" 1 DATASIZE MEMORY_FILE


What's strange is that the actual encrypted data size is 440 bytes (without the first and last byte and the IV), but the properly decrypted file size ends up being 432 bytes. All the QuickBMS algorithms i've tried return 440 bytes.
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: Trouble getting 3DES decryption to work

Post by aluigi »

Asymmetric encryption is ever painful to understand and implement. Sorry.
HenryEx
Posts: 27
Joined: Wed Aug 13, 2014 6:43 pm

Re: Trouble getting 3DES decryption to work

Post by HenryEx »

What's strange is that this should be a symmetric algorithm, and the full decryption routine from the game isn't all that complex: https://pastebin.com/a8ZVYEGj

It does basically what i did in the script above, then feeds it to this .NET class: https://msdn.microsoft.com/en-us/librar ... ceprovider
The CreateDecryptor() basically just creates an object of this TripleDESTransform: https://pastebin.com/Pj7SqB10

It doesn't seem to do anything out of the ordinary, and i triple-checked the Key and IV used, they're the same as the ones in game memory during run-time.
When i use the "des_ede_cfb64" OpenSSL algorithm in QuickBMS (or the "tomcrypt des3 cfb" one), at least the FIRST byte of the result is correct. The rest, however...
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: Trouble getting 3DES decryption to work

Post by aluigi »

I don't know, 3des requires a 24 bytes key.
Anyway this is the code as far as I can see but obviously doesn't work:

Code: Select all

set KEY string "=(*&^%$#@%^**^((*(())=bc=_-420@@#$#9-2@@#$#11_)00xyz2*(*(*((=)(&"
comtype base64
get TMP asize
clog MEMORY_FILE 0 TMP TMP

get array_Length asize MEMORY_FILE
get b byte MEMORY_FILE
goto -1 MEMORY_FILE
get b2 byte MEMORY_FILE
math array_Length - 1
xmath TMP "array_Length - b2"
goto TMP MEMORY_FILE
getdstring IVEC b2 MEMORY_FILE
math TMP - 1
log MEMORY_FILE3 1 TMP MEMORY_FILE
strlen KEYSZ KEY
putvarchr KEY KEYSZ b
encryption sha1 ""
string KEY E KEY
print "KEY %QUICKBMS_HEXHASHL%"
encryption "tomcrypt des3 cfb" QUICKBMS_HASH IVEC 0 16
log "dump.dat" 0 TMP MEMORY_FILE3
HenryEx
Posts: 27
Joined: Wed Aug 13, 2014 6:43 pm

Re: Trouble getting 3DES decryption to work

Post by HenryEx »

Wikipedia tells me that 3des can work with 16 byte keys, where key1 = first 8 bytes, key2 = last 8 bytes, and key3 = key1. That's how 3des-112 works, as opposed to 3des-168 which uses the full 24 bytes.

I made a test file via hijacking the game's encrypt function:

Code: Select all

Ou1YIRIIK0QAqhgUCoyDwP3zoTn65+XcCqN9ASO28fU2cQXDOc/utK7viZZPkNAi7Ag=

De-Base64'd and taking the key salt and IV out of it, it should decrypt into this:

Code: Select all

QuickBMS TripleDES encryption test!


It's easier to check immediate success with this. As i noticed before, The first byte decrypts correctly ('Q'), the rest ends up garbage. I wonder why, the triple DES implementation is standard .NET.
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: Trouble getting 3DES decryption to work

Post by aluigi »

That's interesting because by using the "3des-112" encryption the result starts with 0x8c which is, indeed, used for PKCS but also in that case all the rest is garbage.
Since the same happens also with your last test it doesn't seem a coincidence.