diff options
-rw-r--r-- | qc_decrypt/.gitignore | 1 | ||||
-rw-r--r-- | qc_decrypt/Makefile | 5 | ||||
-rw-r--r-- | qc_decrypt/README.md | 11 | ||||
-rw-r--r-- | qc_decrypt/qc_decrypt.c | 143 |
4 files changed, 160 insertions, 0 deletions
diff --git a/qc_decrypt/.gitignore b/qc_decrypt/.gitignore new file mode 100644 index 0000000..0a38d0d --- /dev/null +++ b/qc_decrypt/.gitignore @@ -0,0 +1 @@ +qc_decrypt
\ No newline at end of file diff --git a/qc_decrypt/Makefile b/qc_decrypt/Makefile new file mode 100644 index 0000000..a0e82db --- /dev/null +++ b/qc_decrypt/Makefile @@ -0,0 +1,5 @@ +all: + @gcc -I/opt/homebrew/opt/openssl/include -L/opt/homebrew/opt/openssl/lib -lcrypto qc_decrypt.c -o qc_decrypt + +clean: + @rm -rf qc_decrypt
\ No newline at end of file diff --git a/qc_decrypt/README.md b/qc_decrypt/README.md new file mode 100644 index 0000000..b434975 --- /dev/null +++ b/qc_decrypt/README.md @@ -0,0 +1,11 @@ +NeuralDSP QuadCortex file decryptor. + +Compile with `make` (requires gcc and openssl-dev installed), then pass the serial number found in `/etc/qc_sn` as command line argument: + +```sh +./qc_decrypt QA00XXXXX /path/to/encrypted.json/cns/ldr/... > decrypted.dat +``` + +## License + +This tool was made with ♥ by [Simone Margaritelli](https://www.evilsocket.net/) and it is released under the GPL 3 license. diff --git a/qc_decrypt/qc_decrypt.c b/qc_decrypt/qc_decrypt.c new file mode 100644 index 0000000..eb02cb4 --- /dev/null +++ b/qc_decrypt/qc_decrypt.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2023 Simone 'evilsocket' Margaritelli - [email protected]. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <openssl/conf.h> +#include <openssl/evp.h> +#include <openssl/err.h> +#include <string.h> +#include <stdio.h> + +// as seen in /usr/lib/libzc.so / SetupKeys +static unsigned char KEY_MATERIAL[] = { + 0x13, 0x27, 0x3f, 0x42, + 0xa5, 0xb6, 0x79, 0xe8, + 0x20, 0x31, 0xc4, 0xf5, + 0x16, 0x17, 0x88, 0x2f, + 0x43, 0xa4, 0x55, 0x69, + 0x77, 0xb8, 0xe2, 0x83, + 0x04, 0x05, 0x60, 0x70, + 0x80, 0x02, 0x03, 0x04, + 0x50, 0x6a, 0x7c, 0x8a, + 0x02, 0x30, 0x40, 0x51, + 0x6a, 0x7d, 0x8d, 0x22, + 0x33, 0x44, 0x59, 0x66, + 0x71, 0x08, 0x02, 0x03, + 0x43, 0x05, 0x67, 0x7a, + 0x8f}; + +int main(int argc, char **argv) +{ + if (argc != 3) + { + printf("Usage: %s <serial number> <encrypted file>\n", argv[0]); + return 1; + } + + char *serialNumber = argv[1], + *inputFileName = argv[2]; + + unsigned long serialSize = strlen(serialNumber); + if (serialSize != 9) + { + printf("the serial number must be 9 characters long.\n"); + return 1; + } + + // concatenate the hardcoded key material with the serial number from /etc/qc_sn + unsigned long key_material_size = sizeof(KEY_MATERIAL) / sizeof(KEY_MATERIAL[0]); + unsigned char *key_material = (unsigned char *)malloc(key_material_size + serialSize); + + memcpy(key_material, KEY_MATERIAL, key_material_size); + memcpy(key_material + key_material_size, serialNumber, serialSize); + + key_material_size += serialSize; + + // derive the actual key and iv from it + unsigned char key[32] = {0}; + unsigned char iv[32] = {0}; + + int iterations = 10; + const EVP_CIPHER *pCipher = EVP_aes_128_ctr(); + const EVP_MD *pDigest = EVP_sha1(); + + int derivedKeySize = EVP_BytesToKey( + pCipher, + pDigest, + NULL, // no salt + key_material, + key_material_size, + iterations, + key, + iv); + + if (derivedKeySize != 16) + { + printf("wrong derived key size: %d\n", derivedKeySize); + return 1; + } + + // read the encrypted file + FILE *fp = fopen(inputFileName, "rb"); + if (!fp) + { + printf("can't open %s\n", inputFileName); + return 1; + } + + fseek(fp, 0, SEEK_END); + long input_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + int ret, final_size, outlen; + unsigned char *input = (unsigned char *)malloc(input_size), + *plaintext = (unsigned char *)malloc(input_size); + + long read = fread(input, 1, input_size, fp); + + fclose(fp); + + // decrypt it + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + + ret = EVP_DecryptInit_ex(ctx, pCipher, NULL, key, iv); + if (ret != 1) + { + printf("EVP_DecryptInit_ex failed: %d\n", ret); + return 1; + } + + ret = EVP_DecryptUpdate(ctx, plaintext, &outlen, input, input_size); + if (ret != 1) + { + printf("EVP_DecryptUpdate failed: %d\n", ret); + return 1; + } + + ret = EVP_DecryptFinal(ctx, &plaintext[outlen], &final_size); + if (ret != 1) + { + printf("EVP_DecryptFinal failed: %d\n", ret); + return 1; + } + + // print it + for (int i = 0; i < outlen; i++) + { + printf("%c", plaintext[i]); + } + printf("\n"); + + return 0; +}
\ No newline at end of file |