From ffb78a867488570c46c8312dd1e7149c8b6ab03d Mon Sep 17 00:00:00 2001 From: illusion0001 <37698908+illusion0001@users.noreply.github.com> Date: Thu, 29 Feb 2024 12:12:49 -0600 Subject: [PATCH] Auto detect save data type --- main.c | 168 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 98 insertions(+), 70 deletions(-) diff --git a/main.c b/main.c index dde316f..0e9769e 100644 --- a/main.c +++ b/main.c @@ -2,6 +2,7 @@ #include #include #include +#include char g_erronoMsg[256] = { 0 }; #define strerror_s_(buffer, sizeInBytes, errnum) \ @@ -42,7 +43,7 @@ unsigned char* read_file(const char* file_name, size_t* size) return data; } -void write_file(const char* file_name, const unsigned char* data, size_t size) +void write_file(const char* file_name, const unsigned char* data, const size_t size) { FILE* file = NULL; if (fopen_s(&file, file_name, "wb") != 0) @@ -88,6 +89,7 @@ static void show_invalid_arg(const char* program_name) "Example: %s decrypt SaveData0001.sav\n\n" "Program will exit in %d seconds", program_name, program_name, program_name, WAIT_TIME); +#ifndef _DEBUG int s = 0; while (s < WAIT_TIME) { @@ -95,6 +97,7 @@ static void show_invalid_arg(const char* program_name) s++; putchar('.'); } +#endif putchar('\n'); exit(EXIT_FAILURE); } @@ -107,104 +110,129 @@ const char* g_OrSaveKey = SAVE_KEY; const size_t g_keylen = (sizeof(SAVE_KEY) - 1); #undef SAVE_KEY +enum +{ + ENCRYPT_GVAS_MAGIC = 0x0B650015, + DECRYPT_GVAS_MAGIC = 0x53415647, +}; + +static void tell_save_magic(const uint32_t file_magic) +{ + switch (file_magic) + { + case ENCRYPT_GVAS_MAGIC: + { + printf_s("Detected encrypted save file. (0x%08x == 0x%08x)\n", file_magic, ENCRYPT_GVAS_MAGIC); + break; + } + case DECRYPT_GVAS_MAGIC: + { + printf_s("Detected decrypted save file. (0x%08x == 0x%08x)\n", file_magic, DECRYPT_GVAS_MAGIC); + break; + } + default: + { + printf_s("Unknown save file. (0x%08x)\n", file_magic); + break; + } + } +} + +static int check_magic(const unsigned char* data, const size_t data_size, const uint32_t magic, uint32_t* out_magic) +{ + if (data_size < sizeof(uint32_t)) + { + return 0; + } + uint32_t file_magic = *((uint32_t*)data); + if (out_magic) + { + *out_magic = file_magic; + } + return file_magic == magic; +} + int main(int argc, char** argv) { printf_s("p3r-save: Built " __DATE__ " @ " __TIME__ "\n"); - if (argc < 3) + if (argc < 2) { show_invalid_arg(argv[0]); } - size_t filesize = 0; - if (strcmp(argv[1], "decrypt") == 0 || strcmp(argv[1], "-d") == 0) + const char* save_path = argv[1]; + if (save_path && *save_path != '\0') { - unsigned char* test_data = read_file(argv[2], &filesize); - unsigned char* decrypted_data = (unsigned char*)malloc(filesize); - if (!decrypted_data) + size_t filesize = 0; + unsigned char* save_data = read_file(save_path, &filesize); + uint32_t file_magic = 0; + if (check_magic(save_data, filesize, ENCRYPT_GVAS_MAGIC, &file_magic)) { - strerror_s_(g_erronoMsg, sizeof(g_erronoMsg), errno); - printf_s("Error allocating memory: %s\n", g_erronoMsg); - exit(EXIT_FAILURE); - } + tell_save_magic(file_magic); + unsigned char* decrypted_data = (unsigned char*)malloc(filesize); + if (!decrypted_data) + { + strerror_s_(g_erronoMsg, sizeof(g_erronoMsg), errno); + printf_s("Error allocating memory: %s\n", g_erronoMsg); + exit(EXIT_FAILURE); + } - size_t key_idx = 0; + size_t key_idx = 0; - for (size_t i = 0; i < filesize; ++i) - { - if (key_idx >= g_keylen) + for (size_t i = 0; i < filesize; ++i) { - // reset index - key_idx = 0; + if (key_idx >= g_keylen) + { + // reset index + key_idx = 0; + } + decrypted_data[i] = decrypt_byte(save_data[i], g_OrSaveKey[key_idx]); + key_idx++; } - decrypted_data[i] = decrypt_byte(test_data[i], g_OrSaveKey[key_idx]); - key_idx++; - } - - write_file("decrypt_out.sav", decrypted_data, filesize); - if (test_data) - { - printf_s("free test_data: 0x%p\n", test_data); - free(test_data); - } - else - { - printf_s("failed to free test_data: 0x%p\n", test_data); + write_file("decrypt_out.sav", decrypted_data, filesize); } - if (decrypted_data) - { - printf_s("free decrypted_data: 0x%p\n", decrypted_data); - free(decrypted_data); - } - else - { - printf_s("failed to free decrypted_data: 0x%p\n", decrypted_data); - } - } - else if (strcmp(argv[1], "encrypt") == 0 || strcmp(argv[1], "-e") == 0) - { - unsigned char* test_data = read_file(argv[2], &filesize); - unsigned char* encrypted_data = (unsigned char*)malloc(filesize); - - if (!encrypted_data) + else if (check_magic(save_data, filesize, DECRYPT_GVAS_MAGIC, &file_magic)) { - strerror_s_(g_erronoMsg, sizeof(g_erronoMsg), errno); - printf_s("Error allocating memory: %s\n", g_erronoMsg); - exit(EXIT_FAILURE); - } + tell_save_magic(file_magic); + unsigned char* encrypted_data = (unsigned char*)malloc(filesize); + if (!encrypted_data) + { + strerror_s_(g_erronoMsg, sizeof(g_erronoMsg), errno); + printf_s("Error allocating memory: %s\n", g_erronoMsg); + exit(EXIT_FAILURE); + } - size_t key_idx = 0; + size_t key_idx = 0; - for (size_t i = 0; i < filesize; ++i) - { - if (key_idx >= g_keylen) + for (size_t i = 0; i < filesize; ++i) { - // reset index - key_idx = 0; + if (key_idx >= g_keylen) + { + // reset index + key_idx = 0; + } + encrypted_data[i] = encrypt_byte(save_data[i], g_OrSaveKey[key_idx]); + key_idx++; } - encrypted_data[i] = encrypt_byte(test_data[i], g_OrSaveKey[key_idx]); - key_idx++; - } - - write_file("encrypt_out.sav", encrypted_data, filesize); - if (test_data) - { - printf_s("free test_data: 0x%p\n", test_data); - free(test_data); + write_file("encrypt_out.sav", encrypted_data, filesize); } else { - printf_s("failed to free test_data: 0x%p\n", test_data); + tell_save_magic(file_magic); + printf_s("Invalid save file.\n"); + exit(EXIT_FAILURE); } - if (encrypted_data) + + if (save_data) { - printf_s("free encrypted_data: 0x%p\n", encrypted_data); - free(encrypted_data); + printf_s("free save_data: 0x%p\n", save_data); + free(save_data); } else { - printf_s("failed to free encrypted_data: 0x%p\n", encrypted_data); + printf_s("failed to free save_data: 0x%p\n", save_data); } } else