Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions patcher/patcher.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>

#define INPUT_EXE_HASH (uint32_t)(0xE220C635)
#define OUTPUT_EXE_HASH (uint32_t)(0xE5E5AF0C)
#define OUTPUT_EXE_SUFFIX (const char*)".patched.exe"
#define OUTPUT_EXE_SUFFIX_SIZE strlen(OUTPUT_EXE_SUFFIX)

#define PATCH_BLOB_SIZE (sizeof(PATCH_BLOB_INFO))
#define PATCH_BLOB_INFO_SIZE (sizeof(blobs))
#define PATCH_GET_COUNT(b) (PATCH_BLOB_INFO_SIZE/PATCH_BLOB_SIZE)
#define PATCH_APPLY_BLOB(b,d,pb) memcpy(&d[b.offset], &pb[b.pos], b.size)

typedef struct
{
uint32_t offset;
uint32_t pos;
uint32_t size;
} PATCH_BLOB_INFO;

const uint8_t patch_blob[] = {
0xC3,
0x48,0x89,0x5C,0x24,0x08,0x48,0x89,0x74,0x24,0x10,0x48,0x89,0x7C,0x24,0x18,0x65,0x48,0x8B,0x04,0x25,0x60,
0x00,0x00,0x48,0x8B,0x40,0x18,0x48,0x8B,0x40,0x10,0x48,0x8B,0x48,0x60,0x41,0xBA,0xDB,0xB2,0x46,0xA1,0x0F,0xB7,0x50,0x58,0x48,0xD1,0xEA,0x4C,0x8D,0x1C,0x51,0x49,0x3B,0xCB,0x74,0x39,0x66,0x0F,0x1F,0x44,0x00,0x00,0x0F,0xBE,0x11,0x44,0x8B,0xC2,0x80,0xEA,0x41,0x45,0x8B,0xC8,0x41,0x83,0xC9,0x20,0x80,0xFA,0x19,0x45,0x0F,0x47,0xC8,0x48,0x83,0xC1,0x02,0x45,0x33,0xCA,0x45,0x69,0xD1,0x93,0x01,0x00,0x01,0x49,0x3B,0xCB,0x75,0xD6,0x41,0x81,0xFA,0x39,0x48,0xEF,0xAA,0x74,0x05,
0x8B,0x00,0xEB,0xA8,0x4C,0x8B,0x58,0x30,0x45,0x33,0xD2,0x49,0x63,0x43,0x3C,0x42,0x8B,0xBC,0x18,0x88,0x00,0x00,0x00,0x42,0x8B,0x74,0x1F,0x20,0x4A,0x8D,0x04,0x96,0x41,0xB9,0x48,0xB1,0x46,0xA0,0x42,0x8B,0x14,0x18,0x49,0x03,0xD3,0x44,0x0F,0xB6,0x02,0x48,0xFF,0xC2,
0x84,0xC0,0x74,0x38,0x0F,0x1F,0x00,0x41,0x0F,0xBE,0xC0,0x48,0x8D,0x52,0x01,0x41,0x80,0xE8,0x41,0x8B,0xC8,0x83,0xC9,0x20,0x41,0x80,0xF8,0x19,0x44,0x0F,0xB6,0x42,0xFF,0x0F,0x47,0xC8,0x41,0x33,0xC9,0x44,0x69,0xC9,0x93,0x01,
0x01,0x45,0x84,0xC0,0x75,0xD4,0x41,0x81,0xF9,0x0A,0x55,0xC7,0x64,0x74,0x05,0x41,0xFF,0xC2,0xEB,0xA6,0x42,0x8B,0x4C,
0x24,0x48,0x8B,0x5C,0x24,0x08,
0x03,0xCB,0x48,0x8B,0x74,0x24,0x10,0x42,0x0F,0xB7,0x14,0x51,0x42,0x8B,0x4C,0x1F,0x1C,0x48,0x8B,0x7C,0x24,0x18,0x49,0x03,0xCB,
0x04,0x91,0x49,0x03,0xC3,0x48,0x8D,0x0D,0x02,0x00,0x00,
0xFF,0xE0,0x69,0x6E,0x6A,0x65,0x63,0x74,0x2E,0x64,0x6C,0x6C,0x00
};

PATCH_BLOB_INFO blobs[] = {
{0x113C110, 0, 1},
{0x137E000, 1, 21},
{0x137E016, 22, 93},
{0x137E074, 115, 52},
{0x137E0A9, 167, 44},
{0x137E0D6, 211, 23},
{0x137E0EE, 234, 6},
{0x137E0F5, 240, 25},
{0x137E10F, 265, 11},
{0x137E11B, 276, 13}
};

void print_usage(char* program_name)
{
printf("Usage:\n");
printf(" %s <path/to/GameClientApp.exe>\n", program_name);
printf(" CRC32 of unpatched exe: %08x\n", INPUT_EXE_HASH);
printf(" CRC32 of patched exe: %08x\n", OUTPUT_EXE_HASH);
}

int main(int argc, char** argv)
{
if(argc == 1)
{
print_usage(argv[0]);
return 0;
}

/* Read the file */
FILE* fog = fopen(argv[1], "rb");

if(fog == NULL)
{
print_usage(argv[0]);
return 0;
}

uint32_t inexe_size = 0;
uint8_t* inexe_data = NULL;

fseek(fog, 0, SEEK_END);
inexe_size = ftell(fog);
fseek(fog, 0, SEEK_SET);
inexe_data = (uint8_t*)malloc(inexe_size);
fread(inexe_data, inexe_size, 1, fog);
fclose(fog);

/* Name */
uint32_t og_name_size = strlen(argv[1]);
uint32_t new_name_size = og_name_size - 4;

if(strncmp(&argv[1][new_name_size], ".exe", 4) == 0)
{
og_name_size -= 4;
new_name_size += OUTPUT_EXE_SUFFIX_SIZE + 1;
}
else
{
new_name_size = og_name_size + OUTPUT_EXE_SUFFIX_SIZE + 1;
}

char* new_name = (char*)calloc(new_name_size+1, 1);
memcpy(new_name, argv[1], og_name_size);
memcpy(&new_name[og_name_size], OUTPUT_EXE_SUFFIX, OUTPUT_EXE_SUFFIX_SIZE);
printf("New name: %s\n", new_name);

/* Patch */
const uint32_t blobs_count = PATCH_GET_COUNT(blobs);

for(uint32_t i = 0; i != blobs_count; ++i)
{
PATCH_APPLY_BLOB(blobs[i], inexe_data, patch_blob);
}

/* Save */
FILE* fout = fopen(new_name, "wb");
fwrite(inexe_data, inexe_size, 1, fout);
fclose(fout);

/* Cleanup */
free(new_name);
free(inexe_data);
}