Skip to content

Commit

Permalink
Auto detect save data type
Browse files Browse the repository at this point in the history
  • Loading branch information
illusion0001 committed Feb 29, 2024
1 parent 7b56a6b commit ffb78a8
Showing 1 changed file with 98 additions and 70 deletions.
168 changes: 98 additions & 70 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdint.h>

char g_erronoMsg[256] = { 0 };
#define strerror_s_(buffer, sizeInBytes, errnum) \
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -88,13 +89,15 @@ 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)
{
Sleep(ONE_SEC);
s++;
putchar('.');
}
#endif
putchar('\n');
exit(EXIT_FAILURE);
}
Expand All @@ -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
Expand Down

0 comments on commit ffb78a8

Please sign in to comment.