/* * Copyright (c) 2023 Simone 'evilsocket' Margaritelli - evilsocket@gmail.com. * * 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 . */ #include #include #include #include #include // 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 \n", argv[0]); return 1; } char *serialNumber = argv[1], *inputFileName = argv[2]; printf("Input file name: %s\n", inputFileName); // Split into the path and the file name char *path = strrchr(inputFileName, '/'); if (path == NULL) { printf("No path found in %s\n", inputFileName); return 1; } unsigned long serialSize = strlen(serialNumber); if (serialSize != 9 && serialSize != 0) { printf("the serial number must be empty or 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 and save the decrypted file for (int i = 0; i < outlen; i++) { printf("%c", plaintext[i]); } printf("\n"); // Save the decrypted file to disk // It should be saved to the same directory as the encrypted file with the extension .dec char *outputFileName = (char *)malloc(strlen(inputFileName) + 5); strcpy(outputFileName, inputFileName); strcat(outputFileName, ".dec"); fp = fopen(outputFileName, "wb"); if (!fp) { printf("can't open %s\n", outputFileName); return 1; } fwrite(plaintext, 1, outlen, fp); fclose(fp); free(key_material); free(input); free(plaintext); free(outputFileName); EVP_CIPHER_CTX_free(ctx); return 0; }