From 50af254e2afd885ab193dff2e725aeda58b3c3b8 Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Mon, 9 Nov 2020 19:49:41 -0500 Subject: [PATCH] Patch Callsites Instead Of Reverting Patches --- MODDING.md | 19 +++-- mods/include/libcore/libcore.h | 7 +- mods/src/core.c | 150 ++++++++++++++++++++++++--------- mods/src/extra.c | 27 ++---- mods/src/extra.cpp | 10 +-- mods/src/server/server.cpp | 71 ++++++---------- mods/src/time.c | 1 + 7 files changed, 161 insertions(+), 124 deletions(-) diff --git a/MODDING.md b/MODDING.md index 64d24f1..1da544c 100644 --- a/MODDING.md +++ b/MODDING.md @@ -13,7 +13,7 @@ Minecraft: Pi Edition was compiled with an old version of GCC, so when interacti ## ``libcore.so`` API Header files and the shared library can be download from [Jenkins](https://jenkins.thebrokenrail.com/job/minecraft-pi-docker/job/master/lastSuccessfulBuild/artifact/out/lib). -### ``void *overwrite(void *start, void *target)`` +### ``void overwrite(void *start, void *target)`` This method replaces a function with another function. #### Parameters @@ -21,7 +21,7 @@ This method replaces a function with another function. - **target:** The function you are replacing it with. #### Return Value -The original contents of the function. +None #### Warning This should never be used on functions that are only 1 byte long because it overwrites 2 bytes. @@ -37,16 +37,19 @@ __attribute__((constructor)) static void init() { } ``` -### ``void revert_overwrite(void *start, void *original)`` -This allows you to revert ``overwrite()``. This can be used to call the original version of a function. +### ``void overwrite_calls(void *start, void *original)`` +This allows you to overwrite all calls of a function rather than the function itself. This allows you to call the original function. However, this does not effect VTables. #### Parameters -- **start:** The function that was overwritten. -- **original:** The return value of ``overwrite()``. +- **start:** The function call to overwrite; +- **target:** The function call you are replacing it with. #### Return Value None +#### Warning +This method can only be safely used 512 times in total. + #### Example ```c typedef int (*func_t)(int a, int b); @@ -54,15 +57,13 @@ static func_t func = (func_t) 0xabcde; static void *func_original = NULL; static int func_injection(int a, int b) { - revert_overwrite((void *) func, func_original); (*func)(a, b); - revert_overwrite((void *) func, func_original); return a + 4; } __attribute__((constructor)) static void init() { - func_original = overwrite((void *) func, func_injection); + overwrite_calls((void *) func, func_injection); } ``` diff --git a/mods/include/libcore/libcore.h b/mods/include/libcore/libcore.h index 8015d13..e60100a 100644 --- a/mods/include/libcore/libcore.h +++ b/mods/include/libcore/libcore.h @@ -30,10 +30,11 @@ extern "C" { #define INFO(msg, ...) fprintf(stderr, "[INFO]: " msg "\n", __VA_ARGS__); #define ERR(msg, ...) fprintf(stderr, "[ERR]: " msg "\n", __VA_ARGS__); exit(1); -void *_overwrite(const char *file, int line, void *start, void *target); -#define overwrite(start, target) _overwrite(__FILE__, __LINE__, start, target); +void _overwrite_calls(const char *file, int line, void *start, void *target); +#define overwrite_calls(start, target) _overwrite_calls(__FILE__, __LINE__, start, target); -void revert_overwrite(void *start, void *original); +void _overwrite(const char *file, int line, void *start, void *target); +#define overwrite(start, target) _overwrite(__FILE__, __LINE__, start, target); void _patch(const char *file, int line, void *start, unsigned char patch[]); #define patch(start, patch) _patch(__FILE__, __LINE__, start, patch); diff --git a/mods/src/core.c b/mods/src/core.c index 1c1457f..b4c684e 100644 --- a/mods/src/core.c +++ b/mods/src/core.c @@ -1,55 +1,132 @@ #include +#include #include #include #include #include +#include #include -#define PATCH_PRINTF(file, line, start, str) if (file != NULL) fprintf(stderr, "[PATCH]: (%s:%i) Patching (0x%04x) - "str": 0x%02x 0x%02x 0x%02x 0x%02x\n", file, line, (uint32_t) start, data[0], data[1], data[2], data[3]); +// Find And Iterate Over All .text Sections In Current Binary +typedef void (*text_section_callback)(void *section, Elf32_Word size, void *data); +static void iterate_text_section(text_section_callback callback, void *data) { + // Load Main Binary + char *real_path = realpath("/proc/self/exe", NULL); + FILE *file_obj = fopen(real_path, "rb"); + free(real_path); -#define ORIGINAL_SIZE 8 + // Get File Size + fseek(file_obj, 0L, SEEK_END); + long int size = ftell(file_obj); + fseek(file_obj, 0L, SEEK_SET); -void *_overwrite(const char *file, int line, void *start, void *target) { - void *original = malloc(ORIGINAL_SIZE); - memcpy(original, start, ORIGINAL_SIZE); + // Map File To Pointer + unsigned char *file_map = mmap(0, size, PROT_READ, MAP_PRIVATE, fileno(file_obj), 0); - int thumb = ((uint32_t) start) & 1; - unsigned char *patch_data; - if (thumb) { - unsigned char patch_data_temp[4] = {0xdf, 0xf8, 0x00, 0xf0}; - patch_data = patch_data_temp; - } else { - unsigned char patch_data_temp[4] = {0x04, 0xf0, 0x1f, 0xe5}; - patch_data = patch_data_temp; + // Parse ELF + Elf32_Ehdr *elf_header = (Elf32_Ehdr *) file_map; + Elf32_Shdr *elf_section_headers = (Elf32_Shdr *) (file_map + elf_header->e_shoff); + int elf_section_header_count = elf_header->e_shnum; + + // Locate Section Names + Elf32_Shdr elf_strtab = elf_section_headers[elf_header->e_shstrndx]; + unsigned char *elf_strtab_p = file_map + elf_strtab.sh_offset; + + // Iterate Sections + for (int i = 0; i < elf_section_header_count; ++i) { + Elf32_Shdr header = elf_section_headers[i]; + char *name = (char *) (elf_strtab_p + header.sh_name); + if (strcmp(name, ".text") == 0) { + (*callback)((void *) header.sh_addr, header.sh_size, data); + } } + // Unmap And Close File + munmap(file_map, size); + fclose(file_obj); +} + +// BL Instruction Magic Number +#define BL_INSTRUCTION 0xeb + +// Generate A BL Instruction +static uint32_t generate_bl_instruction(void *from, void *to) { + uint32_t instruction; + unsigned char *instruction_array = (unsigned char *) &instruction; + + instruction_array[3] = BL_INSTRUCTION; + + unsigned char *pc = ((unsigned char *) from) + 8; + int32_t offset = (int32_t) to - (int32_t) pc; + int32_t target = offset >> 2; + + unsigned char *target_array = (unsigned char *) ⌖ + instruction_array[0] = target_array[0]; + instruction_array[1] = target_array[1]; + instruction_array[2] = target_array[2]; + + return instruction; +} + +// Run For Every .text Section +struct overwrite_data { + const char *file; + int line; + void *target; + void *replacement; +}; +static void overwrite_calls_callback(void *section, Elf32_Word size, void *data) { + struct overwrite_data args = *(struct overwrite_data *) data; + + for (uint32_t i = 0; i < size; i = i + 4) { + unsigned char *addr = ((unsigned char *) section) + i; + if (addr[3] == BL_INSTRUCTION) { + uint32_t check_instruction = generate_bl_instruction(addr, args.target); + unsigned char *check_instruction_array = (unsigned char *) &check_instruction; + if (addr[0] == check_instruction_array[0] && addr[1] == check_instruction_array[1] && addr[2] == check_instruction_array[2]) { + uint32_t new_instruction = generate_bl_instruction(addr, args.replacement); + _patch(args.file, args.line, addr, (unsigned char *) &new_instruction); + } + } + } +} + +// Limit To 512 overwrite_calls() Uses +#define CODE_BLOCK_SIZE 4096 +static unsigned char *code_block = NULL; + +// Overwrite Function Calls +void _overwrite_calls(const char *file, int line, void *start, void *target) { + // BL Instructions Can Only Access A Limited Portion of Memory, So This Allocates Memory Closer To The Original Instruction, That When Run, Will Jump Into The Actual Target + if (code_block == NULL) { + code_block = mmap((void *) 0x200000, CODE_BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + INFO("Code Block Allocated At: 0x%08x", (uint32_t) code_block); + } + _overwrite(NULL, -1, code_block, target); + + struct overwrite_data data; + data.file = file; + data.line = line; + data.target = start; + data.replacement = code_block; + iterate_text_section(overwrite_calls_callback, &data); + + code_block = code_block + 8; +} + +// Overwrite Function +void _overwrite(const char *file, int line, void *start, void *target) { + unsigned char patch_data[4] = {0x04, 0xf0, 0x1f, 0xe5}; + _patch(file, line, start, patch_data); _patch_address(file, line, start + 4, target); - - return original; } -void revert_overwrite(void *start, void *original) { - unsigned char *data = (unsigned char *) start; - int thumb = ((uint32_t) start) & 1; - if (thumb) { - data--; - } - - // Store Current Value In Temp - void *temp = malloc(ORIGINAL_SIZE); - memcpy(temp, data, ORIGINAL_SIZE); - - // Insert Original Value - _patch(NULL, -1, start, original); - _patch(NULL, -1, start + 4, original + 4); - - // Complete Memory Swap - memcpy(original, temp, ORIGINAL_SIZE); - free(temp); -} +// Print Patch Debug Data +#define PATCH_PRINTF(file, line, start, str) if (file != NULL) fprintf(stderr, "[PATCH]: (%s:%i) Patching (0x%08x) - "str": 0x%02x 0x%02x 0x%02x 0x%02x\n", file, line, (uint32_t) start, data[0], data[1], data[2], data[3]); +// Patch Instruction void _patch(const char *file, int line, void *start, unsigned char patch[]) { size_t page_size = sysconf(_SC_PAGESIZE); uintptr_t end = ((uintptr_t) start) + 4; @@ -57,10 +134,6 @@ void _patch(const char *file, int line, void *start, unsigned char patch[]) { mprotect((void *) page_start, end - page_start, PROT_READ | PROT_WRITE); unsigned char *data = (unsigned char *) start; - int thumb = ((uint32_t) start) & 1; - if (thumb) { - data--; - } PATCH_PRINTF(file, line, start, "original"); @@ -74,6 +147,7 @@ void _patch(const char *file, int line, void *start, unsigned char patch[]) { __clear_cache(start, (void *) end); } +// Patch Address void _patch_address(const char *file, int line, void *start, void *target) { uint32_t addr = (uint32_t) target; unsigned char patch_data[4] = {addr & 0xff, (addr >> 8) & 0xff, (addr >> 16) & 0xff, (addr >> 24) & 0xff}; diff --git a/mods/src/extra.c b/mods/src/extra.c index 8656856..b5866eb 100644 --- a/mods/src/extra.c +++ b/mods/src/extra.c @@ -20,16 +20,13 @@ typedef void (*releaseUsingItem_t)(unsigned char *game_mode, unsigned char *play typedef void (*Minecraft_tickInput_t)(unsigned char *minecraft); static Minecraft_tickInput_t Minecraft_tickInput = (Minecraft_tickInput_t) 0x15ffc; -static void *Minecraft_tickInput_original = NULL; typedef int (*Player_isUsingItem_t)(unsigned char *player); static Player_isUsingItem_t Player_isUsingItem = (Player_isUsingItem_t) 0x8f15c; static void Minecraft_tickInput_injection(unsigned char *minecraft) { // Call Original Method - revert_overwrite((void *) Minecraft_tickInput, Minecraft_tickInput_original); (*Minecraft_tickInput)(minecraft); - revert_overwrite((void *) Minecraft_tickInput, Minecraft_tickInput_original); // GameMode Is Offset From minecraft By 0x160 // Player Is Offset From minecraft By 0x18c @@ -48,29 +45,23 @@ static void Minecraft_tickInput_injection(unsigned char *minecraft) { typedef void (*Gui_tickItemDrop_t)(unsigned char *); static Gui_tickItemDrop_t Gui_tickItemDrop = (Gui_tickItemDrop_t) 0x27778; -static void *Gui_tickItemDrop_original = NULL; #include static void Gui_tickItemDrop_injection(unsigned char *this) { if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) { // Call Original Method - revert_overwrite((void *) Gui_tickItemDrop, Gui_tickItemDrop_original); (*Gui_tickItemDrop)(this); - revert_overwrite((void *) Gui_tickItemDrop, Gui_tickItemDrop_original); } } typedef void (*Gui_handleClick_t)(unsigned char *this, int32_t param_2, int32_t param_3, int32_t param_4); static Gui_handleClick_t Gui_handleClick = (Gui_handleClick_t) 0x2599c; -static void *Gui_handleClick_original = NULL; static void Gui_handleClick_injection(unsigned char *this, int32_t param_2, int32_t param_3, int32_t param_4) { if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) { // Call Original Method - revert_overwrite((void *) Gui_handleClick, Gui_handleClick_original); (*Gui_handleClick)(this, param_2, param_3, param_4); - revert_overwrite((void *) Gui_handleClick, Gui_handleClick_original); } } @@ -102,15 +93,12 @@ static void set_is_survival(int new_is_survival) { typedef void (*Minecraft_setIsCreativeMode_t)(unsigned char *, int32_t); static Minecraft_setIsCreativeMode_t Minecraft_setIsCreativeMode = (Minecraft_setIsCreativeMode_t) 0x16ec4; -static void *Minecraft_setIsCreativeMode_original = NULL; static void Minecraft_setIsCreativeMode_injection(unsigned char *this, int32_t new_game_mode) { set_is_survival(!new_game_mode); // Call Original Method - revert_overwrite((void *) Minecraft_setIsCreativeMode, Minecraft_setIsCreativeMode_original); (*Minecraft_setIsCreativeMode)(this, new_game_mode); - revert_overwrite((void *) Minecraft_setIsCreativeMode, Minecraft_setIsCreativeMode_original); } static char *get_username() { @@ -121,15 +109,12 @@ static char *get_username() { return username; } -typedef void (*Minecraft_init_t)(unsigned char *); +typedef void (*Minecraft_init_t)(unsigned char *this); static Minecraft_init_t Minecraft_init = (Minecraft_init_t) 0x1700c; -static void *Minecraft_init_original = NULL; static void Minecraft_init_injection(unsigned char *this) { // Call Original Method - revert_overwrite((void *) Minecraft_init, Minecraft_init_original); (*Minecraft_init)(this); - revert_overwrite((void *) Minecraft_init, Minecraft_init_original); // Enable Fancy Graphics *(this + 83) = 1; @@ -205,7 +190,7 @@ __attribute__((constructor)) static void init() { // Dynamic Game Mode Switching set_is_survival(1); - Minecraft_setIsCreativeMode_original = overwrite((void *) Minecraft_setIsCreativeMode, Minecraft_setIsCreativeMode_injection); + overwrite_calls((void *) Minecraft_setIsCreativeMode, Minecraft_setIsCreativeMode_injection); // Get Default Game Mode if (!is_server) { @@ -218,13 +203,13 @@ __attribute__((constructor)) static void init() { } // Disable Item Dropping Using The Cursor When Cursor Is Hidden - Gui_tickItemDrop_original = overwrite((void *) Gui_tickItemDrop, Gui_tickItemDrop_injection); + overwrite_calls((void *) Gui_tickItemDrop, Gui_tickItemDrop_injection); // Disable Opening Inventory Using The Cursor When Cursor Is Hidden - Gui_handleClick_original = overwrite((void *) Gui_handleClick, Gui_handleClick_injection); + overwrite_calls((void *) Gui_handleClick, Gui_handleClick_injection); if (extra_has_feature("Fix Bow & Arrow")) { // Fix Bow - Minecraft_tickInput_original = overwrite((void *) Minecraft_tickInput, Minecraft_tickInput_injection); + overwrite_calls((void *) Minecraft_tickInput, Minecraft_tickInput_injection); } if (extra_has_feature("Fix Attacking")) { @@ -257,7 +242,7 @@ __attribute__((constructor)) static void init() { if (extra_has_feature("Fancy Graphics")) { // Enable Fancy Graphics - Minecraft_init_original = overwrite((void *) Minecraft_init, Minecraft_init_injection); + overwrite_calls((void *) Minecraft_init, Minecraft_init_injection); } // Allow Connecting To Non-Pi Servers diff --git a/mods/src/extra.cpp b/mods/src/extra.cpp index 1cbbb40..5c41065 100644 --- a/mods/src/extra.cpp +++ b/mods/src/extra.cpp @@ -54,16 +54,13 @@ extern "C" { typedef void (*Screen_updateEvents_t)(unsigned char *screen); static Screen_updateEvents_t Screen_updateEvents = (Screen_updateEvents_t) 0x28eb8; - static void *Screen_updateEvents_original = NULL; typedef void (*Screen_keyboardNewChar_t)(unsigned char *screen, char key); typedef void (*Screen_keyPressed_t)(unsigned char *screen, int32_t key); static void Screen_updateEvents_injection(unsigned char *screen) { // Call Original - revert_overwrite((void *) Screen_updateEvents, Screen_updateEvents_original); (*Screen_updateEvents)(screen); - revert_overwrite((void *) Screen_updateEvents, Screen_updateEvents_original); if (*(char *)(screen + 4) == '\0') { uint32_t vtable = *((uint32_t *) screen); @@ -88,7 +85,6 @@ extern "C" { typedef int32_t (*FillingContainer_addItem_t)(unsigned char *filling_container, unsigned char *item_instance); static FillingContainer_addItem_t FillingContainer_addItem = (FillingContainer_addItem_t) 0x92aa0; - static void *FillingContainer_addItem_original = NULL; static void inventory_add_item(unsigned char *inventory, unsigned char *item, bool is_tile) { unsigned char *item_instance = (unsigned char *) ::operator new(0xc); @@ -115,9 +111,7 @@ extern "C" { static int32_t FillingContainer_addItem_injection(unsigned char *filling_container, unsigned char *item_instance) { // Call Original - revert_overwrite((void *) FillingContainer_addItem, FillingContainer_addItem_original); int32_t ret = (*FillingContainer_addItem)(filling_container, item_instance); - revert_overwrite((void *) FillingContainer_addItem, FillingContainer_addItem_original); // Add After Sign if (*(int32_t *) (item_instance + 0x4) == *(int32_t *) (*item_sign + 0x4)) { @@ -152,12 +146,12 @@ extern "C" { if (extra_has_feature("Fix Sign Placement")) { // Fix Signs patch_address((void *) 0x106460, (void *) LocalPlayer_openTextEdit); - Screen_updateEvents_original = overwrite((void *) Screen_updateEvents, (void *) Screen_updateEvents_injection); + patch_address((void *) 0x10531c, (void *) Screen_updateEvents_injection); } if (extra_has_feature("Expand Creative Inventory")) { // Add Extra Items To Creative Inventory - FillingContainer_addItem_original = overwrite((void *) FillingContainer_addItem, (void *) FillingContainer_addItem_injection); + overwrite_calls((void *) FillingContainer_addItem, (void *) FillingContainer_addItem_injection); } } } diff --git a/mods/src/server/server.cpp b/mods/src/server/server.cpp index 1defab7..02b6d22 100644 --- a/mods/src/server/server.cpp +++ b/mods/src/server/server.cpp @@ -62,7 +62,6 @@ static void *read_stdin_thread(__attribute__((unused)) void *data) { typedef void (*Minecraft_update_t)(unsigned char *minecraft); static Minecraft_update_t Minecraft_update = (Minecraft_update_t) 0x16b74; -static void *Minecraft_update_original = NULL; struct LevelSettings { unsigned long seed; @@ -273,16 +272,13 @@ static void list_callback(unsigned char *minecraft, std::string username, unsign typedef void (*Level_saveLevelData_t)(unsigned char *level); static Level_saveLevelData_t Level_saveLevelData = (Level_saveLevelData_t) 0xa2e94; -static void *Level_saveLevelData_original = NULL; static void Level_saveLevelData_injection(unsigned char *level) { // Print Log Message INFO("%s", "Saving Game"); // Call Original Method - revert_overwrite((void *) Level_saveLevelData, Level_saveLevelData_original); (*Level_saveLevelData)(level); - revert_overwrite((void *) Level_saveLevelData, Level_saveLevelData_original); // Save Player Data playerdata_save(level); @@ -384,9 +380,7 @@ static void Minecraft_update_injection(unsigned char *minecraft) { print_progress(minecraft); // Call Original Method - revert_overwrite((void *) Minecraft_update, Minecraft_update_original); (*Minecraft_update)(minecraft); - revert_overwrite((void *) Minecraft_update, Minecraft_update_original); // Handle Commands handle_commands(minecraft); @@ -397,57 +391,44 @@ static void Minecraft_update_injection(unsigned char *minecraft) { typedef void (*Gui_addMessage_t)(unsigned char *gui, std::string const& text); static Gui_addMessage_t Gui_addMessage = (Gui_addMessage_t) 0x27820; -static void *Gui_addMessage_original = NULL; static void Gui_addMessage_injection(unsigned char *gui, std::string const& text) { // Print Log Message fprintf(stderr, "[CHAT]: %s\n", text.c_str()); // Call Original Method - revert_overwrite((void *) Gui_addMessage, Gui_addMessage_original); (*Gui_addMessage)(gui, text); - revert_overwrite((void *) Gui_addMessage, Gui_addMessage_original); } typedef bool (*RakNet_RakPeer_IsBanned_t)(unsigned char *rakpeer, const char *ip); static RakNet_RakPeer_IsBanned_t RakNet_RakPeer_IsBanned = (RakNet_RakPeer_IsBanned_t) 0xda3b4; -static void *RakNet_RakPeer_IsBanned_original = NULL; -static bool RakNet_RakPeer_IsBanned_injection(unsigned char *rakpeer, const char *ip) { - // Call Original - revert_overwrite((void *) RakNet_RakPeer_IsBanned, RakNet_RakPeer_IsBanned_original); - bool ret = (*RakNet_RakPeer_IsBanned)(rakpeer, ip); - revert_overwrite((void *) RakNet_RakPeer_IsBanned, RakNet_RakPeer_IsBanned_original); - - if (ret) { - return true; - } else { - // Check banned-ips.txt - std::string banned_ips_file_path = get_banned_ips_file(); - std::ifstream banned_ips_file(banned_ips_file_path); - if (banned_ips_file) { - bool ret = false; - if (banned_ips_file.good()) { - std::string line; - while (std::getline(banned_ips_file, line)) { - if (line.length() > 0) { - if (line[0] == '#') { - continue; - } - if (strcmp(line.c_str(), ip) == 0) { - ret = true; - break; - } +static bool RakNet_RakPeer_IsBanned_injection(__attribute__((unused)) unsigned char *rakpeer, const char *ip) { + // Check banned-ips.txt + std::string banned_ips_file_path = get_banned_ips_file(); + std::ifstream banned_ips_file(banned_ips_file_path); + if (banned_ips_file) { + bool ret = false; + if (banned_ips_file.good()) { + std::string line; + while (std::getline(banned_ips_file, line)) { + if (line.length() > 0) { + if (line[0] == '#') { + continue; + } + if (strcmp(line.c_str(), ip) == 0) { + ret = true; + break; } } } - if (banned_ips_file.is_open()) { - banned_ips_file.close(); - } - return ret; - } else { - ERR("%s", "Unable To Read banned-ips.txt"); } + if (banned_ips_file.is_open()) { + banned_ips_file.close(); + } + return ret; + } else { + ERR("%s", "Unable To Read banned-ips.txt"); } } @@ -525,13 +506,13 @@ void server_init() { unsigned char player_patch[4] = {0x00, 0x20, 0xa0, 0xe3}; patch((void *) 0x1685c, player_patch); // Start World On Launch - Minecraft_update_original = overwrite((void *) Minecraft_update, (void *) Minecraft_update_injection); + overwrite_calls((void *) Minecraft_update, (void *) Minecraft_update_injection); // Print Log On Game Save - Level_saveLevelData_original = overwrite((void *) Level_saveLevelData, (void *) Level_saveLevelData_injection); + overwrite_calls((void *) Level_saveLevelData, (void *) Level_saveLevelData_injection); // Exit handler signal(SIGINT, exit_handler); // Print Chat To Log - Gui_addMessage_original = overwrite((void *) Gui_addMessage, (void *) Gui_addMessage_injection); + overwrite_calls((void *) Gui_addMessage, (void *) Gui_addMessage_injection); // Allow All IPs To Join unsigned char allow_all_ip_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; patch((void *) 0xe1f6c, allow_all_ip_patch); @@ -539,7 +520,7 @@ void server_init() { unsigned char max_players_patch[4] = {server_get_max_players(), 0x30, 0xa0, 0xe3}; patch((void *) 0x166d0, max_players_patch); // Custom Banned IP List - RakNet_RakPeer_IsBanned_original = overwrite((void *) RakNet_RakPeer_IsBanned, (void *) RakNet_RakPeer_IsBanned_injection); + overwrite((void *) RakNet_RakPeer_IsBanned, (void *) RakNet_RakPeer_IsBanned_injection); // Load Player Data playerdata_init(); diff --git a/mods/src/time.c b/mods/src/time.c index d8fbbbd..9d93bf1 100644 --- a/mods/src/time.c +++ b/mods/src/time.c @@ -1,6 +1,7 @@ #include #include +// Replace gettimeofday() With clock_gettime() int gettimeofday(struct timeval *tv, __attribute__((unused)) void *tz) { struct timespec tp; int ret = clock_gettime(CLOCK_MONOTONIC, &tp);