Patch Callsites Instead Of Reverting Patches
This commit is contained in:
parent
55feb34251
commit
50af254e2a
19
MODDING.md
19
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);
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -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);
|
||||
|
150
mods/src/core.c
150
mods/src/core.c
@ -1,55 +1,132 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdint.h>
|
||||
#include <elf.h>
|
||||
|
||||
#include <libcore/libcore.h>
|
||||
|
||||
#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};
|
||||
|
@ -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 <SDL/SDL_events.h>
|
||||
|
||||
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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,31 +391,19 @@ 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 {
|
||||
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);
|
||||
@ -449,7 +431,6 @@ static bool RakNet_RakPeer_IsBanned_injection(unsigned char *rakpeer, const char
|
||||
ERR("%s", "Unable To Read banned-ips.txt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *server_get_motd() {
|
||||
return get_server_properties().get_string("motd", DEFAULT_MOTD).c_str();
|
||||
@ -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();
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
// Replace gettimeofday() With clock_gettime()
|
||||
int gettimeofday(struct timeval *tv, __attribute__((unused)) void *tz) {
|
||||
struct timespec tp;
|
||||
int ret = clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
|
Loading…
Reference in New Issue
Block a user