From b40222f0ae5d771d23f252cdbc547025160dc7d8 Mon Sep 17 00:00:00 2001 From: York Jasper Niebuhr Date: Mon, 6 Apr 2026 18:53:56 +0200 Subject: [PATCH] Modernized selfpatch interface - awaiting patchcompile update --- selfpatch/CMakeLists.txt | 4 +- selfpatch/include/spslr.h | 2 +- selfpatch/src/env.c | 109 +++++++++++ selfpatch/src/env.h | 17 ++ selfpatch/src/patcher.c | 138 -------------- selfpatch/src/patcher.h | 9 - selfpatch/src/selfpatch.c | 233 +++++++++++++++++------ selfpatch/src/spslr_list.h | 65 +++++++ selfpatch/src/spslr_list_link.h | 21 +++ selfpatch/src/spslr_program.h | 324 -------------------------------- selfpatch/src/targets.c | 30 ++- selfpatch/src/targets.h | 6 +- 12 files changed, 418 insertions(+), 540 deletions(-) create mode 100644 selfpatch/src/env.c create mode 100644 selfpatch/src/env.h delete mode 100644 selfpatch/src/patcher.c delete mode 100644 selfpatch/src/patcher.h create mode 100644 selfpatch/src/spslr_list.h create mode 100644 selfpatch/src/spslr_list_link.h delete mode 100644 selfpatch/src/spslr_program.h diff --git a/selfpatch/CMakeLists.txt b/selfpatch/CMakeLists.txt index a9c837b..14c1dd6 100644 --- a/selfpatch/CMakeLists.txt +++ b/selfpatch/CMakeLists.txt @@ -1,8 +1,8 @@ -add_library(spslr_selfpatch STATIC src/selfpatch.c src/targets.c src/patcher.c) +add_library(spslr_selfpatch STATIC src/selfpatch.c src/targets.c src/env.c) target_include_directories(spslr_selfpatch PUBLIC $ $ ) -target_include_directories(spslr_patchcompile PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) # For spslr_program.h +target_include_directories(spslr_patchcompile PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) # For spslr_list.h diff --git a/selfpatch/include/spslr.h b/selfpatch/include/spslr.h index 22068b3..b472d55 100644 --- a/selfpatch/include/spslr.h +++ b/selfpatch/include/spslr.h @@ -1,6 +1,6 @@ #ifndef SPSLR_SELFPATCH_H #define SPSLR_SELFPATCH_H -void spslr_selfpatch(); +void spslr_selfpatch(void); #endif diff --git a/selfpatch/src/env.c b/selfpatch/src/env.c new file mode 100644 index 0000000..88a2ae2 --- /dev/null +++ b/selfpatch/src/env.c @@ -0,0 +1,109 @@ +#include "env.h" + +#include +#include +#include +#include + +#define PAGE_MASK ~(0x1000ull - 1) + +static int spslr_env_get_prot(void* addr, int* prot) { + FILE* f = fopen("/proc/self/maps", "r"); + if (!f) + return -1; + + uintptr_t query = (uintptr_t)addr; + char line[512]; + + while (fgets(line, sizeof(line), f)) { + uintptr_t start, end; + char perms[5]; + + if (sscanf(line, "%lx-%lx %4s", &start, &end, perms) != 3) + continue; + + if (query < start || query >= end) + continue; + + *prot = 0; + + if (perms[0] == 'r') + *prot |= PROT_READ; + if (perms[1] == 'w') + *prot |= PROT_WRITE; + if (perms[2] == 'x') + *prot |= PROT_EXEC; + + fclose(f); + return 0; + } + + fclose(f); + return -1; +} + +static void spslr_env_poke_safe(void* dst, const void* src, uint32_t n) { + int original_prot; + if (spslr_env_get_prot(dst, &original_prot)) + spslr_env_panic("failed to get prot of text poke destination"); + + uint64_t ptr_uint = (uint64_t)dst; + uint64_t ptr_page = ptr_uint & PAGE_MASK; + uint64_t prot_size = n + (ptr_uint - ptr_page); + + int tmp_prot = original_prot | PROT_WRITE; + + if (tmp_prot != original_prot) + mprotect((void*)ptr_page, prot_size, tmp_prot); + + spslr_env_memcpy(dst, src, n); + + if (tmp_prot != original_prot) + mprotect((void*)ptr_page, prot_size, original_prot); +} + +void spslr_env_panic(const char* reason) { + fprintf(stderr, "[spslr_panic] %s\n", reason); + exit(1); +} + +void spslr_env_poke_text_8(void* dst, uint8_t value) { + spslr_env_poke_safe(dst, &value, sizeof(value)); +} + +void spslr_env_poke_text_16(void* dst, uint16_t value) { + spslr_env_poke_safe(dst, &value, sizeof(value)); +} + +void spslr_env_poke_text_32(void* dst, uint32_t value) { + spslr_env_poke_safe(dst, &value, sizeof(value)); +} + +void spslr_env_poke_text_64(void* dst, uint64_t value) { + spslr_env_poke_safe(dst, &value, sizeof(value)); +} + +void* spslr_env_malloc(uint32_t n) { + void* res = malloc(n); + if (!res) + spslr_env_panic("malloc failed"); + + return res; +} + +void spslr_env_free(void* ptr) { + free(ptr); +} + +void spslr_env_poke_data(void* dst, const void* src, uint32_t n) { + spslr_env_poke_safe(dst, src, n); +} + +void spslr_env_memset(void* dst, int v, uint32_t n) { + memset(dst, v, n); +} + +void spslr_env_memcpy(void* dst, const void* src, uint32_t n) { + memcpy(dst, src, n); +} + diff --git a/selfpatch/src/env.h b/selfpatch/src/env.h new file mode 100644 index 0000000..9bc3c79 --- /dev/null +++ b/selfpatch/src/env.h @@ -0,0 +1,17 @@ +#ifndef SPSLR_ENV_H +#define SPSLR_ENV_H + +#include + +void spslr_env_panic(const char* reason); +void spslr_env_poke_text_8(void* dst, uint8_t value); +void spslr_env_poke_text_16(void* dst, uint16_t value); +void spslr_env_poke_text_32(void* dst, uint32_t value); +void spslr_env_poke_text_64(void* dst, uint64_t value); +void* spslr_env_malloc(uint32_t n); // Either return valid buffer or panic internally +void spslr_env_free(void* ptr); +void spslr_env_poke_data(void* dst, const void* src, uint32_t n); +void spslr_env_memset(void* dst, int v, uint32_t n); +void spslr_env_memcpy(void* dst, const void* src, uint32_t n); + +#endif diff --git a/selfpatch/src/patcher.c b/selfpatch/src/patcher.c deleted file mode 100644 index 70cb3d1..0000000 --- a/selfpatch/src/patcher.c +++ /dev/null @@ -1,138 +0,0 @@ -#include "patcher.h" -#include "targets.h" - -#include -#include -#include -#include - -#define PAGE_MASK ~(0x1000ull - 1) - -static int get_prot(void* addr, int* prot) { - FILE* f = fopen("/proc/self/maps", "r"); - if (!f) - return -1; - - uintptr_t query = (uintptr_t)addr; - char line[512]; - - while (fgets(line, sizeof(line), f)) { - uintptr_t start, end; - char perms[5]; - - if (sscanf(line, "%lx-%lx %4s", &start, &end, perms) != 3) - continue; - - if (query < start || query >= end) - continue; - - *prot = 0; - - if (perms[0] == 'r') - *prot |= PROT_READ; - if (perms[1] == 'w') - *prot |= PROT_WRITE; - if (perms[2] == 'x') - *prot |= PROT_EXEC; - - fclose(f); - return 0; - } - - fclose(f); - return -1; -} - -static int patch_immediate(void* ptr, uint32_t size, uint32_t v) { - if (size != 4) - return -1; - - memcpy(ptr, &v, size); - return 0; -} - -int spslr_ipatch(void* ptr, uint32_t size, uint32_t target, uint32_t field) { - uint32_t field_offset; - if (spslr_get_randomized_field_offset(target, field, &field_offset)) - return -1; - - int original_prot; - if (get_prot(ptr, &original_prot)) - return -1; - - uint64_t ptr_uint = (uint64_t)ptr; - uint64_t ptr_page = ptr_uint & PAGE_MASK; - uint64_t corrected_size = size + (ptr_uint - ptr_page); - - int tmp_prot = original_prot | PROT_WRITE; - - if (tmp_prot != original_prot) - mprotect((void*)ptr_page, corrected_size, tmp_prot); - - if (patch_immediate(ptr, size, field_offset)) - return -1; - - if (tmp_prot != original_prot) - mprotect((void*)ptr_page, corrected_size, original_prot); - - return 0; -} - -static int reorder_object(const void* src, void* dst, uint32_t target) { - if (!src || !dst) - return -1; - - uint32_t field_count; - if (spslr_get_target_fieldcnt(target, &field_count)) - return -1; - - const uint8_t* src_countable = (const uint8_t*)src; - uint8_t* dst_countable = (uint8_t*)dst; - - for (uint32_t i = 0; i < field_count; i++) { - uint32_t field_offset, field_size, field_initial_offset; - if (spslr_get_target_field_ordered(target, i, &field_offset, &field_size, &field_initial_offset)) - return -1; - - memcpy(dst_countable + field_offset, src_countable + field_initial_offset, field_size); - } - - return 0; -} - -int spslr_dpatch(void* ptr, uint32_t target) { - uint32_t target_size; - if (spslr_get_target_size(target, &target_size)) - return -1; - - int original_prot; - if (get_prot(ptr, &original_prot)) - return -1; - - uint64_t ptr_uint = (uint64_t)ptr; - uint64_t ptr_page = ptr_uint & PAGE_MASK; - uint64_t corrected_size = target_size + (ptr_uint - ptr_page); - - int tmp_prot = original_prot | PROT_WRITE | PROT_READ; - - if (tmp_prot != original_prot) - mprotect((void*)ptr_page, corrected_size, tmp_prot); - - void* tmp_obj = malloc(target_size); - if (!tmp_obj) - return -1; - - memset(tmp_obj, 0, target_size); - - if (reorder_object(ptr, tmp_obj, target)) - return -1; - - memcpy(ptr, tmp_obj, target_size); - free(tmp_obj); - - if (tmp_prot != original_prot) - mprotect((void*)ptr_page, corrected_size, original_prot); - - return 0; -} - diff --git a/selfpatch/src/patcher.h b/selfpatch/src/patcher.h deleted file mode 100644 index 633b851..0000000 --- a/selfpatch/src/patcher.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef SPSLR_PATCHER_H -#define SPSLR_PATCHER_H - -#include - -int spslr_ipatch(void* ptr, uint32_t size, uint32_t target, uint32_t field); -int spslr_dpatch(void* ptr, uint32_t target); - -#endif diff --git a/selfpatch/src/selfpatch.c b/selfpatch/src/selfpatch.c index c391e12..5f665f4 100644 --- a/selfpatch/src/selfpatch.c +++ b/selfpatch/src/selfpatch.c @@ -1,71 +1,198 @@ #include -#include -#include +#include -#include "spslr_program.h" #include "targets.h" -#include "patcher.h" +#include "env.h" -extern const uint8_t __spslr_program[]; +#include "spslr_list_link.h" -static int spslr_do(const struct SPSLR_INST* inst) { - if (!inst) - return -1; +#define SPSLR_SANITY_CHECK - static uint32_t pending_fields = 0; - static uint32_t pending_fields_target = 0; +static void spslr_selfpatch_load_targets(void); +static void spslr_selfpatch_randomize_targets(void); +static void spslr_selfpatch_patch_dpins(void); +static void spslr_selfpatch_patch_dpin(void* addr, uint32_t target); +static void spslr_selfpatch_patch_ipins(void); - if (pending_fields) { - if (inst->op != SPSLR_FIELD) { - fprintf(stderr, "spslr_do encountered non field instruction where a field instruction was expected\n"); - return -1; +static void reorder_object(void* dst, const void* src, uint32_t target); +static int64_t spslr_calculate_ipin_value(uint32_t start); + +void spslr_selfpatch(void) { + spslr_selfpatch_load_targets(); + spslr_selfpatch_randomize_targets(); + spslr_selfpatch_patch_dpins(); + spslr_selfpatch_patch_ipins(); + spslr_clear_targets(); +} + +void spslr_selfpatch_load_targets(void) { + for (uint32_t tidx = 0; tidx < spslr_target_cnt; tidx++) { + const struct spslr_target* t = &spslr_targets[tidx]; + +#ifdef SPSLR_SANITY_CHECK + if (t->fieldoff + t->fieldcnt > spslr_target_field_cnt) + spslr_env_panic("target field offset and count reference invalid fields"); +#endif + + if (spslr_register_target(tidx, t->size, t->fieldcnt) < 0) + spslr_env_panic("failed to register target"); + + for (uint32_t fidx = 0; fidx < t->fieldcnt; fidx++) { + const struct spslr_target_field* f = &spslr_target_fields[t->fieldoff + fidx]; + +#ifdef SPSLR_SANITY_CHECK + if (f->offset + f->size > t->size) + spslr_env_panic("target field resides beyond target size"); + + if (f->offset % f->alignment != 0) + spslr_env_panic("target field is misaligned"); +#endif + + if (spslr_register_target_field(tidx, f->offset, f->size, f->alignment, f->flags) < 0) + spslr_env_panic("failed to register target field"); } - - pending_fields--; - } else if (inst->op == SPSLR_FIELD) { - fprintf(stderr, "spslr_do encountered field instruction where none was expected\n"); - return -1; - } - - switch (inst->op) { - case SPSLR_TARGET: - pending_fields = inst->op2.target_fieldcnt; - pending_fields_target = inst->op0.target_uid; - return spslr_target(inst->op0.target_uid, inst->op1.target_size, inst->op2.target_fieldcnt); - case SPSLR_FIELD: - return spslr_field(pending_fields_target, inst->op0.field_offset, inst->op1.field_size, - inst->op2.field_alignment, inst->op3.field_flags); - case SPSLR_RANDOMIZE: - return spslr_randomize(inst->op0.randomize_target); - case SPSLR_IPATCH: - return spslr_ipatch((void*)(uintptr_t)inst->op0.ipatch_ptr, inst->op1.ipatch_size, - inst->op2.ipatch_target, inst->op3.ipatch_field); - case SPSLR_DPATCH: - return spslr_dpatch((void*)(uintptr_t)inst->op0.dpatch_ptr, inst->op1.dpatch_target); - default: - return -1; } } -void spslr_selfpatch() { - const uint8_t* pc = __spslr_program; +void spslr_selfpatch_randomize_targets(void) { + for (uint32_t tidx = 0; tidx < spslr_target_cnt; tidx++) { + if (spslr_randomize(tidx) < 0) + spslr_env_panic("failed to randomize target"); + } +} - int sz; - struct SPSLR_INST inst; - while ((sz = spslr_inst_load(&inst, pc)) > 0) { - if (inst.op == SPSLR_EXIT) { - spslr_targets_clear(); - return; +void spslr_selfpatch_patch_dpins(void) { + for (uint32_t dpidx = 0; dpidx < spslr_dpin_cnt; dpidx++) { + const struct spslr_dpin* dp = &spslr_dpins[dpidx]; + spslr_selfpatch_patch_dpin((void*)dp->addr, dp->target); + } +} + +void reorder_object(void* dst, const void* src, uint32_t target) { + uint32_t field_count; + if (spslr_get_target_fieldcnt(target, &field_count)) + spslr_env_panic("failed to get target field count"); + + const uint8_t* src_countable = (const uint8_t*)src; + uint8_t* dst_countable = (uint8_t*)dst; + + for (uint32_t i = 0; i < field_count; i++) { + uint32_t field_offset, field_size, field_initial_offset; + if (spslr_get_target_field_ordered(target, i, &field_offset, &field_size, &field_initial_offset)) + spslr_env_panic("failed to get ordered field descriptor"); + + spslr_env_memcpy(dst_countable + field_offset, src_countable + field_initial_offset, field_size); + } +} + +void spslr_selfpatch_patch_dpin(void* addr, uint32_t target) { +#ifdef SPSLR_SANITY_CHECK + if (target >= spslr_target_cnt) + spslr_env_panic("dpin refers to invalid target"); +#endif + + const struct spslr_target* t = &spslr_targets[target]; + + void* reorder_buffer = spslr_env_malloc(t->size); + spslr_env_memset(reorder_buffer, 0, t->size); + reorder_object(reorder_buffer, addr, target); + + spslr_env_poke_data(addr, reorder_buffer, t->size); + + spslr_env_free(reorder_buffer); +} + +void spslr_selfpatch_patch_ipins(void) { + for (uint32_t ipidx = 0; ipidx < spslr_ipin_cnt; ipidx++) { + const struct spslr_ipin* ip = &spslr_ipins[ipidx]; + + int64_t value = spslr_calculate_ipin_value(ip->program); + + switch (ip->size) { + case 1: + spslr_env_poke_text_8((void*)ip->addr, (uint8_t)value); + break; + case 2: + spslr_env_poke_text_64((void*)ip->addr, (uint16_t)value); + break; + case 4: + spslr_env_poke_text_32((void*)ip->addr, (uint32_t)value); + break; + case 8: + spslr_env_poke_text_64((void*)ip->addr, (uint64_t)value); + break; +#ifdef SPSLR_SANITY_CHECK + default: + spslr_env_panic("invalid ipin size"); +#endif } + } +} - if (spslr_do(&inst) < 0) { - fprintf(stderr, "spslr_selfpatch failed to execute an instruction\n"); - exit(1); +int64_t spslr_calculate_ipin_value(uint32_t start) { + int64_t res = 0; + + uint32_t pc = start; + while (true) { +#ifdef SPSLR_SANITY_CHECK + if (pc >= spslr_ipin_op_cnt) + spslr_env_panic("ipin op out of bounds"); +#endif + + const struct spslr_ipin_op* op = &spslr_ipin_ops[pc++]; + switch (op->code) { + case SPSLR_IPIN_OP_PATCH: + break; + case SPSLR_IPIN_OP_ADD_INITIAL_OFFSET: + { + uint32_t initial_offset; + if (spslr_get_target_field_ordered(op->op0.add_initial_offset_target, + op->op1.add_initial_offset_field, NULL, NULL, &initial_offset)) + spslr_env_panic("failed to get initial field offset"); + + res += initial_offset; + } + continue; + case SPSLR_IPIN_OP_ADD_OFFSET: + { + uint32_t offset; + if (spslr_get_target_field_ordered(op->op0.add_initial_offset_target, + op->op1.add_initial_offset_field, &offset, NULL, NULL)) + spslr_env_panic("failed to get initial field offset"); + + res += offset; + } + continue; + case SPSLR_IPIN_OP_SUB_INITIAL_OFFSET: + { + uint32_t initial_offset; + if (spslr_get_target_field_ordered(op->op0.add_initial_offset_target, + op->op1.add_initial_offset_field, NULL, NULL, &initial_offset)) + spslr_env_panic("failed to get initial field offset"); + + res -= initial_offset; + } + continue; + case SPSLR_IPIN_OP_SUB_OFFSET: + { + uint32_t offset; + if (spslr_get_target_field_ordered(op->op0.add_initial_offset_target, + op->op1.add_initial_offset_field, &offset, NULL, NULL)) + spslr_env_panic("failed to get initial field offset"); + + res -= offset; + } + continue; + case SPSLR_IPIN_OP_ADD_CONST: + res += op->op0.add_const_value; + continue; +#ifdef SPSLR_SANITY_CHECK + default: + spslr_env_panic("invalid ipin op"); +#endif } - - pc += sz; } - fprintf(stderr, "spslr_selfpatch encountered invalid instruction\n"); - exit(1); + return res; } + diff --git a/selfpatch/src/spslr_list.h b/selfpatch/src/spslr_list.h new file mode 100644 index 0000000..2ec4519 --- /dev/null +++ b/selfpatch/src/spslr_list.h @@ -0,0 +1,65 @@ +#ifndef SPSLR_LIST_H +#define SPSLR_LIST_H + +#include + +#define __packed __attribute__((packed)) + +#define SPSLR_IPIN_OP_PATCH 1 +#define SPSLR_IPIN_OP_ADD_INITIAL_OFFSET 2 +#define SPSLR_IPIN_OP_SUB_INITIAL_OFFSET 3 +#define SPSLR_IPIN_OP_ADD_OFFSET 4 +#define SPSLR_IPIN_OP_SUB_OFFSET 5 +#define SPSLR_IPIN_OP_ADD_CONST 6 + +#define SPSLR_FLAG_FIELD_FIXED 1 + +struct spslr_target { + uint32_t size; + uint32_t fieldcnt; + uint32_t fieldoff; // Offset into spslr_target_field array +} __packed; + +struct spslr_target_field { + uint32_t offset; + uint32_t size; + uint32_t alignment; + uint32_t flags; +} __packed; + +struct spslr_ipin { + uint64_t addr; + uint32_t size; + uint32_t program; // Index in spslr_ipin_op array +} __packed; + +struct spslr_ipin_op { + uint32_t code; + + union { + uint32_t patch_unused; + uint32_t add_initial_offset_target; + uint32_t sub_initial_offset_target; + uint32_t add_offset_target; + uint32_t sub_offset_target; + int32_t add_const_value; + } op0; + + union { + uint32_t patch_unused; + uint32_t add_initial_offset_field; + uint32_t sub_initial_offset_field; + uint32_t add_offset_field; + uint32_t sub_offset_field; + uint32_t add_const_unused; + } op1; +} __packed; + +struct spslr_dpin { + uint64_t addr; + uint32_t target; // Index in spslr_target array +} __packed; + +#undef __packed + +#endif diff --git a/selfpatch/src/spslr_list_link.h b/selfpatch/src/spslr_list_link.h new file mode 100644 index 0000000..0486861 --- /dev/null +++ b/selfpatch/src/spslr_list_link.h @@ -0,0 +1,21 @@ +#ifndef SPSLR_LIST_LINK_H +#define SPSLR_LIST_LINK_H + +#include "spslr_list.h" + +extern uint32_t spslr_target_cnt; +extern struct spslr_target spslr_targets[]; + +extern uint32_t spslr_target_field_cnt; +extern struct spslr_target_field spslr_target_fields[]; + +extern uint32_t spslr_ipin_cnt; +extern struct spslr_ipin spslr_ipins[]; + +extern uint32_t spslr_ipin_op_cnt; +extern struct spslr_ipin_op spslr_ipin_ops[]; + +extern uint32_t spslr_dpin_cnt; +extern struct spslr_dpin spslr_dpins[]; + +#endif diff --git a/selfpatch/src/spslr_program.h b/selfpatch/src/spslr_program.h deleted file mode 100644 index 3c9dbd4..0000000 --- a/selfpatch/src/spslr_program.h +++ /dev/null @@ -1,324 +0,0 @@ -#ifndef SPSLR_PROGRAM_H -#define SPSLR_PROGRAM_H - -#include -#include - -#define SPSLR_FLAG_FIELD_FIXED 1 - -#define OPCODE_SPSLR_TARGET 1 -#define OPCODE_SPSLR_FIELD 2 -#define OPCODE_SPSLR_RANDOMIZE 3 -#define OPCODE_SPSLR_IPATCH 4 -#define OPCODE_SPSLR_DPATCH 5 -#define OPCODE_SPSLR_EXIT 6 - -enum SPSLR_OP { - SPSLR_TARGET, // uid, size, field count - SPSLR_FIELD, // offset, size, alignment, flags - SPSLR_RANDOMIZE, // target uid - SPSLR_IPATCH, // ptr, size, target uid, field idx (not offset!) - SPSLR_DPATCH, // ptr, target uid - SPSLR_EXIT -}; - -struct SPSLR_INST { - enum SPSLR_OP op; - - union { - uint32_t target_uid; - uint32_t field_offset; - uint32_t randomize_target; - uint64_t ipatch_ptr; - uint64_t dpatch_ptr; - } op0; - - union { - uint32_t target_size; - uint32_t field_size; - uint32_t ipatch_size; - uint32_t dpatch_target; - } op1; - - union { - uint32_t target_fieldcnt; - uint32_t field_alignment; - uint32_t ipatch_target; - } op2; - - union { - uint32_t field_flags; - uint32_t ipatch_field; - } op3; -}; - -static inline int spslr_inst_dump_opcode(const struct SPSLR_INST* inst, uint8_t* buf) { - if (!inst || !buf) - return -1; - - switch (inst->op) { - case SPSLR_TARGET: - *buf = OPCODE_SPSLR_TARGET; return 1; - case SPSLR_FIELD: - *buf = OPCODE_SPSLR_FIELD; return 1; - case SPSLR_RANDOMIZE: - *buf = OPCODE_SPSLR_RANDOMIZE; return 1; - case SPSLR_IPATCH: - *buf = OPCODE_SPSLR_IPATCH; return 1; - case SPSLR_DPATCH: - *buf = OPCODE_SPSLR_DPATCH; return 1; - case SPSLR_EXIT: - *buf = OPCODE_SPSLR_EXIT; return 1; - default: - return -1; - } -} - -static inline int spslr_inst_load_opcode(struct SPSLR_INST* inst, const uint8_t* buf) { - if (!inst || !buf) - return -1; - - switch (*buf) { - case OPCODE_SPSLR_TARGET: - inst->op = SPSLR_TARGET; return 1; - case OPCODE_SPSLR_FIELD: - inst->op = SPSLR_FIELD; return 1; - case OPCODE_SPSLR_RANDOMIZE: - inst->op = SPSLR_RANDOMIZE; return 1; - case OPCODE_SPSLR_IPATCH: - inst->op = SPSLR_IPATCH; return 1; - case OPCODE_SPSLR_DPATCH: - inst->op = SPSLR_DPATCH; return 1; - case OPCODE_SPSLR_EXIT: - inst->op = SPSLR_EXIT; return 1; - default: - return -1; - } -} - -#define DUMP_OP_RET(field) { memcpy(buf, &field, sizeof(field)); return sizeof(field); } -#define LOAD_OP_RET(field) { memcpy(&field, buf, sizeof(field)); return sizeof(field); } - -static inline int spslr_inst_dump_op0(const struct SPSLR_INST* inst, uint8_t* buf) { - if (!inst || !buf) - return -1; - - switch (inst->op) { - case SPSLR_TARGET: - DUMP_OP_RET(inst->op0.target_uid); - case SPSLR_FIELD: - DUMP_OP_RET(inst->op0.field_offset); - case SPSLR_RANDOMIZE: - DUMP_OP_RET(inst->op0.randomize_target); - case SPSLR_IPATCH: - DUMP_OP_RET(inst->op0.ipatch_ptr); - case SPSLR_DPATCH: - DUMP_OP_RET(inst->op0.dpatch_ptr); - case SPSLR_EXIT: - return 0; - default: - return -1; - } -} - -static inline int spslr_inst_load_op0(struct SPSLR_INST* inst, const uint8_t* buf) { - if (!inst || !buf) - return -1; - - switch (inst->op) { - case SPSLR_TARGET: - LOAD_OP_RET(inst->op0.target_uid); - case SPSLR_FIELD: - LOAD_OP_RET(inst->op0.field_offset); - case SPSLR_RANDOMIZE: - LOAD_OP_RET(inst->op0.randomize_target); - case SPSLR_IPATCH: - LOAD_OP_RET(inst->op0.ipatch_ptr); - case SPSLR_DPATCH: - LOAD_OP_RET(inst->op0.dpatch_ptr); - case SPSLR_EXIT: - return 0; - default: - return -1; - } -} - -static inline int spslr_inst_dump_op1(const struct SPSLR_INST* inst, uint8_t* buf) { - if (!inst || !buf) - return -1; - - switch (inst->op) { - case SPSLR_TARGET: - DUMP_OP_RET(inst->op1.target_size); - case SPSLR_FIELD: - DUMP_OP_RET(inst->op1.field_size); - case SPSLR_IPATCH: - DUMP_OP_RET(inst->op1.ipatch_size); - case SPSLR_DPATCH: - DUMP_OP_RET(inst->op1.dpatch_target); - case SPSLR_RANDOMIZE: - case SPSLR_EXIT: - return 0; - default: - return -1; - } -} - -static inline int spslr_inst_load_op1(struct SPSLR_INST* inst, const uint8_t* buf) { - if (!inst || !buf) - return -1; - - switch (inst->op) { - case SPSLR_TARGET: - LOAD_OP_RET(inst->op1.target_size); - case SPSLR_FIELD: - LOAD_OP_RET(inst->op1.field_size); - case SPSLR_IPATCH: - LOAD_OP_RET(inst->op1.ipatch_size); - case SPSLR_DPATCH: - LOAD_OP_RET(inst->op1.dpatch_target); - case SPSLR_RANDOMIZE: - case SPSLR_EXIT: - return 0; - default: - return -1; - } -} - -static inline int spslr_inst_dump_op2(const struct SPSLR_INST* inst, uint8_t* buf) { - if (!inst || !buf) - return -1; - - switch (inst->op) { - case SPSLR_TARGET: - DUMP_OP_RET(inst->op2.target_fieldcnt); - case SPSLR_FIELD: - DUMP_OP_RET(inst->op2.field_alignment); - case SPSLR_IPATCH: - DUMP_OP_RET(inst->op2.ipatch_target); - case SPSLR_DPATCH: - case SPSLR_RANDOMIZE: - case SPSLR_EXIT: - return 0; - default: - return -1; - } -} - -static inline int spslr_inst_load_op2(struct SPSLR_INST* inst, const uint8_t* buf) { - if (!inst || !buf) - return -1; - - switch (inst->op) { - case SPSLR_TARGET: - LOAD_OP_RET(inst->op2.target_fieldcnt); - case SPSLR_FIELD: - LOAD_OP_RET(inst->op2.field_alignment); - case SPSLR_IPATCH: - LOAD_OP_RET(inst->op2.ipatch_target); - case SPSLR_DPATCH: - case SPSLR_RANDOMIZE: - case SPSLR_EXIT: - return 0; - default: - return -1; - } -} - -static inline int spslr_inst_dump_op3(const struct SPSLR_INST* inst, uint8_t* buf) { - if (!inst || !buf) - return -1; - - switch (inst->op) { - case SPSLR_FIELD: - DUMP_OP_RET(inst->op3.field_flags); - case SPSLR_IPATCH: - DUMP_OP_RET(inst->op3.ipatch_field); - case SPSLR_TARGET: - case SPSLR_DPATCH: - case SPSLR_RANDOMIZE: - case SPSLR_EXIT: - return 0; - default: - return -1; - } -} - -static inline int spslr_inst_load_op3(struct SPSLR_INST* inst, const uint8_t* buf) { - if (!inst || !buf) - return -1; - - switch (inst->op) { - case SPSLR_FIELD: - LOAD_OP_RET(inst->op3.field_flags); - case SPSLR_IPATCH: - LOAD_OP_RET(inst->op3.ipatch_field); - case SPSLR_TARGET: - case SPSLR_DPATCH: - case SPSLR_RANDOMIZE: - case SPSLR_EXIT: - return 0; - default: - return -1; - } -} - -static inline int spslr_inst_dump(const struct SPSLR_INST* inst, uint8_t* buf) { - if (!inst || !buf) - return -1; - - int opcode_sz, op0_sz, op1_sz, op2_sz, op3_sz; - - if ((opcode_sz = spslr_inst_dump_opcode(inst, buf)) < 0) - return -1; - buf += opcode_sz; - - if ((op0_sz = spslr_inst_dump_op0(inst, buf)) < 0) - return -1; - buf += op0_sz; - - if ((op1_sz = spslr_inst_dump_op1(inst, buf)) < 0) - return -1; - buf += op1_sz; - - if ((op2_sz = spslr_inst_dump_op2(inst, buf)) < 0) - return -1; - buf += op2_sz; - - if ((op3_sz = spslr_inst_dump_op3(inst, buf)) < 0) - return -1; - buf += op3_sz; - - return opcode_sz + op0_sz + op1_sz + op2_sz + op3_sz; -} - -static inline int spslr_inst_load(struct SPSLR_INST* inst, const uint8_t* buf) { - if (!inst || !buf) - return -1; - - int opcode_sz, op0_sz, op1_sz, op2_sz, op3_sz; - - if ((opcode_sz = spslr_inst_load_opcode(inst, buf)) < 0) - return -1; - buf += opcode_sz; - - if ((op0_sz = spslr_inst_load_op0(inst, buf)) < 0) - return -1; - buf += op0_sz; - - if ((op1_sz = spslr_inst_load_op1(inst, buf)) < 0) - return -1; - buf += op1_sz; - - if ((op2_sz = spslr_inst_load_op2(inst, buf)) < 0) - return -1; - buf += op2_sz; - - if ((op3_sz = spslr_inst_load_op3(inst, buf)) < 0) - return -1; - buf += op3_sz; - - return opcode_sz + op0_sz + op1_sz + op2_sz + op3_sz; -} - -#endif diff --git a/selfpatch/src/targets.c b/selfpatch/src/targets.c index 96850cd..54325ed 100644 --- a/selfpatch/src/targets.c +++ b/selfpatch/src/targets.c @@ -1,5 +1,6 @@ #include "targets.h" -#include "spslr_program.h" + +#include "spslr_list.h" #include #include @@ -96,14 +97,14 @@ static void clear_targets() { targets = NULL; } -int spslr_target(uint32_t uid, uint32_t size, uint32_t fieldcnt) { +int spslr_register_target(uint32_t uid, uint32_t size, uint32_t fieldcnt) { if (find_target(uid)) return -1; return add_target(uid, size, fieldcnt); } -int spslr_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t alignment, uint32_t flags) { +int spslr_register_target_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t alignment, uint32_t flags) { struct Target* t = find_target(target); if (!t) return -1; @@ -380,30 +381,39 @@ int spslr_get_target_size(uint32_t target, uint32_t* size) { int spslr_get_target_fieldcnt(uint32_t target, uint32_t* cnt) { const struct Target* t = find_target(target); - if (!t || !cnt) + if (!t) return -1; - *cnt = t->field_count; + if (cnt) + *cnt = t->field_count; + return 0; } int spslr_get_target_field_ordered(uint32_t target, uint32_t field, uint32_t* offset, uint32_t* size, uint32_t* initial_offset) { const struct Target* t = find_target(target); - if (!t || !offset || !size || !initial_offset) + if (!t) return -1; if (field >= t->field_count) return -1; const struct Field* f = &t->fields[field]; - *offset = f->offset; - *size = f->size; - *initial_offset = f->initial_offset; + + if (offset) + *offset = f->offset; + + if (size) + *size = f->size; + + if (initial_offset) + *initial_offset = f->initial_offset; + return 0; } -void spslr_targets_clear() { +void spslr_clear_targets() { clear_targets(); } diff --git a/selfpatch/src/targets.h b/selfpatch/src/targets.h index c02c98d..097788b 100644 --- a/selfpatch/src/targets.h +++ b/selfpatch/src/targets.h @@ -3,8 +3,8 @@ #include -int spslr_target(uint32_t uid, uint32_t size, uint32_t fieldcnt); -int spslr_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t alignment, uint32_t flags); +int spslr_register_target(uint32_t uid, uint32_t size, uint32_t fieldcnt); +int spslr_register_target_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t alignment, uint32_t flags); int spslr_randomize(uint32_t target); int spslr_get_randomized_field_offset(uint32_t target, uint32_t field, uint32_t* offset); @@ -13,6 +13,6 @@ int spslr_get_target_fieldcnt(uint32_t target, uint32_t* cnt); int spslr_get_target_field_ordered(uint32_t target, uint32_t field, uint32_t* offset, uint32_t* size, uint32_t* initial_offset); -void spslr_targets_clear(); +void spslr_clear_targets(); #endif