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
|
## ``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).
|
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.
|
This method replaces a function with another function.
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
@ -21,7 +21,7 @@ This method replaces a function with another function.
|
|||||||
- **target:** The function you are replacing it with.
|
- **target:** The function you are replacing it with.
|
||||||
|
|
||||||
#### Return Value
|
#### Return Value
|
||||||
The original contents of the function.
|
None
|
||||||
|
|
||||||
#### Warning
|
#### Warning
|
||||||
This should never be used on functions that are only 1 byte long because it overwrites 2 bytes.
|
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)``
|
### ``void overwrite_calls(void *start, void *original)``
|
||||||
This allows you to revert ``overwrite()``. This can be used to call the original version of a function.
|
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
|
#### Parameters
|
||||||
- **start:** The function that was overwritten.
|
- **start:** The function call to overwrite;
|
||||||
- **original:** The return value of ``overwrite()``.
|
- **target:** The function call you are replacing it with.
|
||||||
|
|
||||||
#### Return Value
|
#### Return Value
|
||||||
None
|
None
|
||||||
|
|
||||||
|
#### Warning
|
||||||
|
This method can only be safely used 512 times in total.
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
```c
|
```c
|
||||||
typedef int (*func_t)(int a, int b);
|
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 void *func_original = NULL;
|
||||||
|
|
||||||
static int func_injection(int a, int b) {
|
static int func_injection(int a, int b) {
|
||||||
revert_overwrite((void *) func, func_original);
|
|
||||||
(*func)(a, b);
|
(*func)(a, b);
|
||||||
revert_overwrite((void *) func, func_original);
|
|
||||||
|
|
||||||
return a + 4;
|
return a + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((constructor)) static void init() {
|
__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 INFO(msg, ...) fprintf(stderr, "[INFO]: " msg "\n", __VA_ARGS__);
|
||||||
#define ERR(msg, ...) fprintf(stderr, "[ERR]: " msg "\n", __VA_ARGS__); exit(1);
|
#define ERR(msg, ...) fprintf(stderr, "[ERR]: " msg "\n", __VA_ARGS__); exit(1);
|
||||||
|
|
||||||
void *_overwrite(const char *file, int line, void *start, void *target);
|
void _overwrite_calls(const char *file, int line, void *start, void *target);
|
||||||
#define overwrite(start, target) _overwrite(__FILE__, __LINE__, start, 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[]);
|
void _patch(const char *file, int line, void *start, unsigned char patch[]);
|
||||||
#define patch(start, patch) _patch(__FILE__, __LINE__, start, 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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <elf.h>
|
||||||
|
|
||||||
#include <libcore/libcore.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) {
|
// Map File To Pointer
|
||||||
void *original = malloc(ORIGINAL_SIZE);
|
unsigned char *file_map = mmap(0, size, PROT_READ, MAP_PRIVATE, fileno(file_obj), 0);
|
||||||
memcpy(original, start, ORIGINAL_SIZE);
|
|
||||||
|
|
||||||
int thumb = ((uint32_t) start) & 1;
|
// Parse ELF
|
||||||
unsigned char *patch_data;
|
Elf32_Ehdr *elf_header = (Elf32_Ehdr *) file_map;
|
||||||
if (thumb) {
|
Elf32_Shdr *elf_section_headers = (Elf32_Shdr *) (file_map + elf_header->e_shoff);
|
||||||
unsigned char patch_data_temp[4] = {0xdf, 0xf8, 0x00, 0xf0};
|
int elf_section_header_count = elf_header->e_shnum;
|
||||||
patch_data = patch_data_temp;
|
|
||||||
} else {
|
// Locate Section Names
|
||||||
unsigned char patch_data_temp[4] = {0x04, 0xf0, 0x1f, 0xe5};
|
Elf32_Shdr elf_strtab = elf_section_headers[elf_header->e_shstrndx];
|
||||||
patch_data = patch_data_temp;
|
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(file, line, start, patch_data);
|
||||||
_patch_address(file, line, start + 4, target);
|
_patch_address(file, line, start + 4, target);
|
||||||
|
|
||||||
return original;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void revert_overwrite(void *start, void *original) {
|
// Print Patch Debug Data
|
||||||
unsigned char *data = (unsigned char *) start;
|
#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]);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Patch Instruction
|
||||||
void _patch(const char *file, int line, void *start, unsigned char patch[]) {
|
void _patch(const char *file, int line, void *start, unsigned char patch[]) {
|
||||||
size_t page_size = sysconf(_SC_PAGESIZE);
|
size_t page_size = sysconf(_SC_PAGESIZE);
|
||||||
uintptr_t end = ((uintptr_t) start) + 4;
|
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);
|
mprotect((void *) page_start, end - page_start, PROT_READ | PROT_WRITE);
|
||||||
|
|
||||||
unsigned char *data = (unsigned char *) start;
|
unsigned char *data = (unsigned char *) start;
|
||||||
int thumb = ((uint32_t) start) & 1;
|
|
||||||
if (thumb) {
|
|
||||||
data--;
|
|
||||||
}
|
|
||||||
|
|
||||||
PATCH_PRINTF(file, line, start, "original");
|
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);
|
__clear_cache(start, (void *) end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Patch Address
|
||||||
void _patch_address(const char *file, int line, void *start, void *target) {
|
void _patch_address(const char *file, int line, void *start, void *target) {
|
||||||
uint32_t addr = (uint32_t) target;
|
uint32_t addr = (uint32_t) target;
|
||||||
unsigned char patch_data[4] = {addr & 0xff, (addr >> 8) & 0xff, (addr >> 16) & 0xff, (addr >> 24) & 0xff};
|
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);
|
typedef void (*Minecraft_tickInput_t)(unsigned char *minecraft);
|
||||||
static Minecraft_tickInput_t Minecraft_tickInput = (Minecraft_tickInput_t) 0x15ffc;
|
static Minecraft_tickInput_t Minecraft_tickInput = (Minecraft_tickInput_t) 0x15ffc;
|
||||||
static void *Minecraft_tickInput_original = NULL;
|
|
||||||
|
|
||||||
typedef int (*Player_isUsingItem_t)(unsigned char *player);
|
typedef int (*Player_isUsingItem_t)(unsigned char *player);
|
||||||
static Player_isUsingItem_t Player_isUsingItem = (Player_isUsingItem_t) 0x8f15c;
|
static Player_isUsingItem_t Player_isUsingItem = (Player_isUsingItem_t) 0x8f15c;
|
||||||
|
|
||||||
static void Minecraft_tickInput_injection(unsigned char *minecraft) {
|
static void Minecraft_tickInput_injection(unsigned char *minecraft) {
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
revert_overwrite((void *) Minecraft_tickInput, Minecraft_tickInput_original);
|
|
||||||
(*Minecraft_tickInput)(minecraft);
|
(*Minecraft_tickInput)(minecraft);
|
||||||
revert_overwrite((void *) Minecraft_tickInput, Minecraft_tickInput_original);
|
|
||||||
|
|
||||||
// GameMode Is Offset From minecraft By 0x160
|
// GameMode Is Offset From minecraft By 0x160
|
||||||
// Player Is Offset From minecraft By 0x18c
|
// 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 *);
|
typedef void (*Gui_tickItemDrop_t)(unsigned char *);
|
||||||
static Gui_tickItemDrop_t Gui_tickItemDrop = (Gui_tickItemDrop_t) 0x27778;
|
static Gui_tickItemDrop_t Gui_tickItemDrop = (Gui_tickItemDrop_t) 0x27778;
|
||||||
static void *Gui_tickItemDrop_original = NULL;
|
|
||||||
|
|
||||||
#include <SDL/SDL_events.h>
|
#include <SDL/SDL_events.h>
|
||||||
|
|
||||||
static void Gui_tickItemDrop_injection(unsigned char *this) {
|
static void Gui_tickItemDrop_injection(unsigned char *this) {
|
||||||
if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) {
|
if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) {
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
revert_overwrite((void *) Gui_tickItemDrop, Gui_tickItemDrop_original);
|
|
||||||
(*Gui_tickItemDrop)(this);
|
(*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);
|
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 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) {
|
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) {
|
if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) {
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
revert_overwrite((void *) Gui_handleClick, Gui_handleClick_original);
|
|
||||||
(*Gui_handleClick)(this, param_2, param_3, param_4);
|
(*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);
|
typedef void (*Minecraft_setIsCreativeMode_t)(unsigned char *, int32_t);
|
||||||
static Minecraft_setIsCreativeMode_t Minecraft_setIsCreativeMode = (Minecraft_setIsCreativeMode_t) 0x16ec4;
|
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) {
|
static void Minecraft_setIsCreativeMode_injection(unsigned char *this, int32_t new_game_mode) {
|
||||||
set_is_survival(!new_game_mode);
|
set_is_survival(!new_game_mode);
|
||||||
|
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
revert_overwrite((void *) Minecraft_setIsCreativeMode, Minecraft_setIsCreativeMode_original);
|
|
||||||
(*Minecraft_setIsCreativeMode)(this, new_game_mode);
|
(*Minecraft_setIsCreativeMode)(this, new_game_mode);
|
||||||
revert_overwrite((void *) Minecraft_setIsCreativeMode, Minecraft_setIsCreativeMode_original);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *get_username() {
|
static char *get_username() {
|
||||||
@ -121,15 +109,12 @@ static char *get_username() {
|
|||||||
return 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 Minecraft_init_t Minecraft_init = (Minecraft_init_t) 0x1700c;
|
||||||
static void *Minecraft_init_original = NULL;
|
|
||||||
|
|
||||||
static void Minecraft_init_injection(unsigned char *this) {
|
static void Minecraft_init_injection(unsigned char *this) {
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
revert_overwrite((void *) Minecraft_init, Minecraft_init_original);
|
|
||||||
(*Minecraft_init)(this);
|
(*Minecraft_init)(this);
|
||||||
revert_overwrite((void *) Minecraft_init, Minecraft_init_original);
|
|
||||||
|
|
||||||
// Enable Fancy Graphics
|
// Enable Fancy Graphics
|
||||||
*(this + 83) = 1;
|
*(this + 83) = 1;
|
||||||
@ -205,7 +190,7 @@ __attribute__((constructor)) static void init() {
|
|||||||
|
|
||||||
// Dynamic Game Mode Switching
|
// Dynamic Game Mode Switching
|
||||||
set_is_survival(1);
|
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
|
// Get Default Game Mode
|
||||||
if (!is_server) {
|
if (!is_server) {
|
||||||
@ -218,13 +203,13 @@ __attribute__((constructor)) static void init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Disable Item Dropping Using The Cursor When Cursor Is Hidden
|
// 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
|
// 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")) {
|
if (extra_has_feature("Fix Bow & Arrow")) {
|
||||||
// Fix Bow
|
// 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")) {
|
if (extra_has_feature("Fix Attacking")) {
|
||||||
@ -257,7 +242,7 @@ __attribute__((constructor)) static void init() {
|
|||||||
|
|
||||||
if (extra_has_feature("Fancy Graphics")) {
|
if (extra_has_feature("Fancy Graphics")) {
|
||||||
// Enable 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
|
// Allow Connecting To Non-Pi Servers
|
||||||
|
@ -54,16 +54,13 @@ extern "C" {
|
|||||||
|
|
||||||
typedef void (*Screen_updateEvents_t)(unsigned char *screen);
|
typedef void (*Screen_updateEvents_t)(unsigned char *screen);
|
||||||
static Screen_updateEvents_t Screen_updateEvents = (Screen_updateEvents_t) 0x28eb8;
|
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_keyboardNewChar_t)(unsigned char *screen, char key);
|
||||||
typedef void (*Screen_keyPressed_t)(unsigned char *screen, int32_t key);
|
typedef void (*Screen_keyPressed_t)(unsigned char *screen, int32_t key);
|
||||||
|
|
||||||
static void Screen_updateEvents_injection(unsigned char *screen) {
|
static void Screen_updateEvents_injection(unsigned char *screen) {
|
||||||
// Call Original
|
// Call Original
|
||||||
revert_overwrite((void *) Screen_updateEvents, Screen_updateEvents_original);
|
|
||||||
(*Screen_updateEvents)(screen);
|
(*Screen_updateEvents)(screen);
|
||||||
revert_overwrite((void *) Screen_updateEvents, Screen_updateEvents_original);
|
|
||||||
|
|
||||||
if (*(char *)(screen + 4) == '\0') {
|
if (*(char *)(screen + 4) == '\0') {
|
||||||
uint32_t vtable = *((uint32_t *) screen);
|
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);
|
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 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) {
|
static void inventory_add_item(unsigned char *inventory, unsigned char *item, bool is_tile) {
|
||||||
unsigned char *item_instance = (unsigned char *) ::operator new(0xc);
|
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) {
|
static int32_t FillingContainer_addItem_injection(unsigned char *filling_container, unsigned char *item_instance) {
|
||||||
// Call Original
|
// Call Original
|
||||||
revert_overwrite((void *) FillingContainer_addItem, FillingContainer_addItem_original);
|
|
||||||
int32_t ret = (*FillingContainer_addItem)(filling_container, item_instance);
|
int32_t ret = (*FillingContainer_addItem)(filling_container, item_instance);
|
||||||
revert_overwrite((void *) FillingContainer_addItem, FillingContainer_addItem_original);
|
|
||||||
|
|
||||||
// Add After Sign
|
// Add After Sign
|
||||||
if (*(int32_t *) (item_instance + 0x4) == *(int32_t *) (*item_sign + 0x4)) {
|
if (*(int32_t *) (item_instance + 0x4) == *(int32_t *) (*item_sign + 0x4)) {
|
||||||
@ -152,12 +146,12 @@ extern "C" {
|
|||||||
if (extra_has_feature("Fix Sign Placement")) {
|
if (extra_has_feature("Fix Sign Placement")) {
|
||||||
// Fix Signs
|
// Fix Signs
|
||||||
patch_address((void *) 0x106460, (void *) LocalPlayer_openTextEdit);
|
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")) {
|
if (extra_has_feature("Expand Creative Inventory")) {
|
||||||
// Add Extra Items To 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);
|
typedef void (*Minecraft_update_t)(unsigned char *minecraft);
|
||||||
static Minecraft_update_t Minecraft_update = (Minecraft_update_t) 0x16b74;
|
static Minecraft_update_t Minecraft_update = (Minecraft_update_t) 0x16b74;
|
||||||
static void *Minecraft_update_original = NULL;
|
|
||||||
|
|
||||||
struct LevelSettings {
|
struct LevelSettings {
|
||||||
unsigned long seed;
|
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);
|
typedef void (*Level_saveLevelData_t)(unsigned char *level);
|
||||||
static Level_saveLevelData_t Level_saveLevelData = (Level_saveLevelData_t) 0xa2e94;
|
static Level_saveLevelData_t Level_saveLevelData = (Level_saveLevelData_t) 0xa2e94;
|
||||||
static void *Level_saveLevelData_original = NULL;
|
|
||||||
|
|
||||||
static void Level_saveLevelData_injection(unsigned char *level) {
|
static void Level_saveLevelData_injection(unsigned char *level) {
|
||||||
// Print Log Message
|
// Print Log Message
|
||||||
INFO("%s", "Saving Game");
|
INFO("%s", "Saving Game");
|
||||||
|
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
revert_overwrite((void *) Level_saveLevelData, Level_saveLevelData_original);
|
|
||||||
(*Level_saveLevelData)(level);
|
(*Level_saveLevelData)(level);
|
||||||
revert_overwrite((void *) Level_saveLevelData, Level_saveLevelData_original);
|
|
||||||
|
|
||||||
// Save Player Data
|
// Save Player Data
|
||||||
playerdata_save(level);
|
playerdata_save(level);
|
||||||
@ -384,9 +380,7 @@ static void Minecraft_update_injection(unsigned char *minecraft) {
|
|||||||
print_progress(minecraft);
|
print_progress(minecraft);
|
||||||
|
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
revert_overwrite((void *) Minecraft_update, Minecraft_update_original);
|
|
||||||
(*Minecraft_update)(minecraft);
|
(*Minecraft_update)(minecraft);
|
||||||
revert_overwrite((void *) Minecraft_update, Minecraft_update_original);
|
|
||||||
|
|
||||||
// Handle Commands
|
// Handle Commands
|
||||||
handle_commands(minecraft);
|
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);
|
typedef void (*Gui_addMessage_t)(unsigned char *gui, std::string const& text);
|
||||||
static Gui_addMessage_t Gui_addMessage = (Gui_addMessage_t) 0x27820;
|
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) {
|
static void Gui_addMessage_injection(unsigned char *gui, std::string const& text) {
|
||||||
// Print Log Message
|
// Print Log Message
|
||||||
fprintf(stderr, "[CHAT]: %s\n", text.c_str());
|
fprintf(stderr, "[CHAT]: %s\n", text.c_str());
|
||||||
|
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
revert_overwrite((void *) Gui_addMessage, Gui_addMessage_original);
|
|
||||||
(*Gui_addMessage)(gui, text);
|
(*Gui_addMessage)(gui, text);
|
||||||
revert_overwrite((void *) Gui_addMessage, Gui_addMessage_original);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef bool (*RakNet_RakPeer_IsBanned_t)(unsigned char *rakpeer, const char *ip);
|
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 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) {
|
static bool RakNet_RakPeer_IsBanned_injection(__attribute__((unused)) 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
|
// Check banned-ips.txt
|
||||||
std::string banned_ips_file_path = get_banned_ips_file();
|
std::string banned_ips_file_path = get_banned_ips_file();
|
||||||
std::ifstream banned_ips_file(banned_ips_file_path);
|
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");
|
ERR("%s", "Unable To Read banned-ips.txt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const char *server_get_motd() {
|
const char *server_get_motd() {
|
||||||
return get_server_properties().get_string("motd", DEFAULT_MOTD).c_str();
|
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};
|
unsigned char player_patch[4] = {0x00, 0x20, 0xa0, 0xe3};
|
||||||
patch((void *) 0x1685c, player_patch);
|
patch((void *) 0x1685c, player_patch);
|
||||||
// Start World On Launch
|
// 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
|
// 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
|
// Exit handler
|
||||||
signal(SIGINT, exit_handler);
|
signal(SIGINT, exit_handler);
|
||||||
// Print Chat To Log
|
// 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
|
// Allow All IPs To Join
|
||||||
unsigned char allow_all_ip_patch[4] = {0x00, 0xf0, 0x20, 0xe3};
|
unsigned char allow_all_ip_patch[4] = {0x00, 0xf0, 0x20, 0xe3};
|
||||||
patch((void *) 0xe1f6c, allow_all_ip_patch);
|
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};
|
unsigned char max_players_patch[4] = {server_get_max_players(), 0x30, 0xa0, 0xe3};
|
||||||
patch((void *) 0x166d0, max_players_patch);
|
patch((void *) 0x166d0, max_players_patch);
|
||||||
// Custom Banned IP List
|
// 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
|
// Load Player Data
|
||||||
playerdata_init();
|
playerdata_init();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
// Replace gettimeofday() With clock_gettime()
|
||||||
int gettimeofday(struct timeval *tv, __attribute__((unused)) void *tz) {
|
int gettimeofday(struct timeval *tv, __attribute__((unused)) void *tz) {
|
||||||
struct timespec tp;
|
struct timespec tp;
|
||||||
int ret = clock_gettime(CLOCK_MONOTONIC, &tp);
|
int ret = clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||||
|
Loading…
Reference in New Issue
Block a user