From 54002646b02b84ee0340a7fb5b186f53ad4707c5 Mon Sep 17 00:00:00 2001 From: York Jasper Niebuhr Date: Mon, 27 Oct 2025 15:28:20 +0100 Subject: [PATCH] Updated patcher program --- finalize/finalize.cpp | 14 ++++++ selfpatch/src/patcher.c | 2 +- selfpatch/src/patcher.h | 2 +- selfpatch/src/selfpatch.c | 6 ++- selfpatch/src/spslr_program.h | 83 ++++++++++++++++++++++++++++------- selfpatch/src/targets.c | 20 ++++----- selfpatch/src/targets.h | 2 +- 7 files changed, 99 insertions(+), 30 deletions(-) diff --git a/finalize/finalize.cpp b/finalize/finalize.cpp index dda1fe6..9089c1e 100644 --- a/finalize/finalize.cpp +++ b/finalize/finalize.cpp @@ -1,5 +1,17 @@ #include +/* +TODO +1. getopt -> --spslr=, --bin= +2. Recursively gather all spslr CU files +3. Loop over all symbols of the binary + -> associate blocks via CU uid symbol + -> find __spslr_program symbol (spslr vaddr pivot) +4. Find virtual address and file address for all pins +5. Calculate target randomization order +6. Emit patcher program into final executable and set __spslr_program +*/ + /* .spslr: @@ -23,6 +35,8 @@ The CU uid symbol helps differentiating between e.g. "file.c" and "sub/file.c" ( Between CUs, types with the same name HAVE TO HAVE the same layout -> randomized together To begin with, anonymous types are not allowed for randomization (later solved with hash(type) instead of name)! +Note -> field alignment should probably be gathered by pinpoint plugin! + */ int main(int argc, char** argv) { diff --git a/selfpatch/src/patcher.c b/selfpatch/src/patcher.c index e8e952a..674dca2 100644 --- a/selfpatch/src/patcher.c +++ b/selfpatch/src/patcher.c @@ -6,7 +6,7 @@ int spslr_mprot(void* base, uint32_t pagecnt, uint8_t perm) { return 0; } -int spslr_ipatch(void* ptr, uint32_t target, uint32_t field) { +int spslr_ipatch(void* ptr, uint32_t size, uint32_t target, uint32_t field) { return 0; } diff --git a/selfpatch/src/patcher.h b/selfpatch/src/patcher.h index 27c8b28..bc83339 100644 --- a/selfpatch/src/patcher.h +++ b/selfpatch/src/patcher.h @@ -4,7 +4,7 @@ #include int spslr_mprot(void* base, uint32_t pagecnt, uint8_t perm); -int spslr_ipatch(void* ptr, uint32_t target, uint32_t field); +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 7767bdc..2b744ee 100644 --- a/selfpatch/src/selfpatch.c +++ b/selfpatch/src/selfpatch.c @@ -45,13 +45,15 @@ static int spslr_do(const struct SPSLR_INST* inst) { 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_flags); + 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_MPROT: return spslr_mprot(spslr_ptr_absolute(inst->op0.mprot_ptr), inst->op1.mprot_pagecnt, inst->op2.mprot_perm); case SPSLR_IPATCH: - return spslr_ipatch(spslr_ptr_absolute(inst->op0.ipatch_ptr), inst->op1.ipatch_target, inst->op2.ipatch_field); + return spslr_ipatch(spslr_ptr_absolute(inst->op0.ipatch_ptr), inst->op1.ipatch_size, + inst->op2.ipatch_target, inst->op3.ipatch_field); case SPSLR_DPATCH: return spslr_dpatch(spslr_ptr_absolute(inst->op0.dpatch_ptr), inst->op1.dpatch_target); default: diff --git a/selfpatch/src/spslr_program.h b/selfpatch/src/spslr_program.h index abf4f57..9377a56 100644 --- a/selfpatch/src/spslr_program.h +++ b/selfpatch/src/spslr_program.h @@ -8,10 +8,10 @@ enum SPSLR_OPCODE { SPSLR_TARGET, // uid, size, field count - SPSLR_FIELD, // offset, size, flags + SPSLR_FIELD, // offset, size, alignment, flags SPSLR_RANDOMIZE, // target uid SPSLR_MPROT, // ptr, page count, perm - SPSLR_IPATCH, // ptr, target uid, field idx (not offset!) + SPSLR_IPATCH, // ptr, size, target uid, field idx (not offset!) SPSLR_DPATCH, // ptr, target uid SPSLR_EXIT }; @@ -32,16 +32,21 @@ struct SPSLR_INST { uint32_t target_size; uint32_t field_size; uint32_t mprot_pagecnt; - uint32_t ipatch_target; + uint32_t ipatch_size; uint32_t dpatch_target; } op1; union { uint32_t target_fieldcnt; - uint32_t field_flags; + uint32_t field_alignment; uint8_t mprot_perm; - uint32_t ipatch_field; + 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) { @@ -155,7 +160,7 @@ static inline int spslr_inst_dump_op1(const struct SPSLR_INST* inst, uint8_t* bu case SPSLR_MPROT: DUMP_OP_RET(inst->op1.mprot_pagecnt); case SPSLR_IPATCH: - DUMP_OP_RET(inst->op1.ipatch_target); + DUMP_OP_RET(inst->op1.ipatch_size); case SPSLR_DPATCH: DUMP_OP_RET(inst->op1.dpatch_target); case SPSLR_RANDOMIZE: @@ -178,7 +183,7 @@ static inline int spslr_inst_load_op1(struct SPSLR_INST* inst, const uint8_t* bu case SPSLR_MPROT: LOAD_OP_RET(inst->op1.mprot_pagecnt); case SPSLR_IPATCH: - LOAD_OP_RET(inst->op1.ipatch_target); + LOAD_OP_RET(inst->op1.ipatch_size); case SPSLR_DPATCH: LOAD_OP_RET(inst->op1.dpatch_target); case SPSLR_RANDOMIZE: @@ -197,11 +202,11 @@ static inline int spslr_inst_dump_op2(const struct SPSLR_INST* inst, uint8_t* bu case SPSLR_TARGET: DUMP_OP_RET(inst->op2.target_fieldcnt); case SPSLR_FIELD: - DUMP_OP_RET(inst->op2.field_flags); + DUMP_OP_RET(inst->op2.field_alignment); case SPSLR_MPROT: DUMP_OP_RET(inst->op2.mprot_perm); case SPSLR_IPATCH: - DUMP_OP_RET(inst->op2.ipatch_field); + DUMP_OP_RET(inst->op2.ipatch_target); case SPSLR_DPATCH: case SPSLR_RANDOMIZE: case SPSLR_EXIT: @@ -219,11 +224,51 @@ static inline int spslr_inst_load_op2(struct SPSLR_INST* inst, const uint8_t* bu case SPSLR_TARGET: LOAD_OP_RET(inst->op2.target_fieldcnt); case SPSLR_FIELD: - LOAD_OP_RET(inst->op2.field_flags); + LOAD_OP_RET(inst->op2.field_alignment); case SPSLR_MPROT: LOAD_OP_RET(inst->op2.mprot_perm); case SPSLR_IPATCH: - LOAD_OP_RET(inst->op2.ipatch_field); + 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->opcode) { + 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_MPROT: + 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->opcode) { + 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_MPROT: case SPSLR_DPATCH: case SPSLR_RANDOMIZE: case SPSLR_EXIT: @@ -237,7 +282,7 @@ 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; + int opcode_sz, op0_sz, op1_sz, op2_sz, op3_sz; if ((opcode_sz = spslr_inst_dump_opcode(inst, buf)) < 0) return -1; @@ -255,14 +300,18 @@ static inline int spslr_inst_dump(const struct SPSLR_INST* inst, uint8_t* buf) { return -1; buf += op2_sz; - return opcode_sz + op0_sz + op1_sz + 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; + int opcode_sz, op0_sz, op1_sz, op2_sz, op3_sz; if ((opcode_sz = spslr_inst_load_opcode(inst, buf)) < 0) return -1; @@ -280,7 +329,11 @@ static inline int spslr_inst_load(struct SPSLR_INST* inst, const uint8_t* buf) { return -1; buf += op2_sz; - return opcode_sz + op0_sz + op1_sz + 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 ecc125f..d0bd662 100644 --- a/selfpatch/src/targets.c +++ b/selfpatch/src/targets.c @@ -18,6 +18,7 @@ struct Field { uint32_t offset; uint32_t size; + uint32_t alignment; uint32_t flags; }; @@ -102,7 +103,7 @@ int spslr_target(uint32_t uid, uint32_t size, uint32_t fieldcnt) { return add_target(uid, size, fieldcnt); } -int spslr_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t flags) { +int spslr_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; @@ -113,6 +114,9 @@ int spslr_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t flags) if (t->present_field_count >= t->field_count) return -1; + if (offset % alignment != 0) + return -1; + if (t->present_field_count) { struct Field* pred = &t->fields[t->present_field_count - 1]; if (offset < pred->offset + pred->size) @@ -126,6 +130,7 @@ int spslr_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t flags) f->initial_idx = idx; f->offset = offset; f->size = size; + f->alignment = alignment; f->flags = flags; return 0; @@ -136,10 +141,6 @@ struct ShuffleRegion { uint32_t fill_begin, fill_end; }; -static uint32_t field_alignment(const struct Field* field) { - return field->size; // Note -> alignments should be gathered by pinpoint plugin -} - static void target_get_origin_region(const struct Target* target, struct ShuffleRegion* region, uint32_t idx) { region->fill_begin = target->fields[idx].offset; region->fill_end = region->fill_begin + target->fields[idx].size; @@ -184,9 +185,8 @@ static uint32_t target_get_shuffle_options(const struct Target* target, uint32_t } // Could field be placed in origin? - uint32_t falign = field_alignment(f); - if (origin_region_ptr % falign != 0) - origin_region_ptr += falign - (origin_region_ptr % falign); + if (origin_region_ptr % f->alignment != 0) + origin_region_ptr += f->alignment - (origin_region_ptr % f->alignment); origin_region_ptr += f->size; @@ -217,7 +217,7 @@ static void target_swap(struct Target* target, uint32_t origin_idx, const struct if (target->fields[it].offset >= option_fill_end) break; - uint32_t falign = field_alignment(&target->fields[it]); + uint32_t falign = target->fields[it].alignment; if (origin_region_ptr % falign != 0) origin_region_ptr += falign - (origin_region_ptr % falign); @@ -258,7 +258,7 @@ static void target_shuffle_one(struct Target* target) { if (target->fields[origin].flags & SPSLR_FLAG_FIELD_FIXED) return; - uint32_t origin_alignment = field_alignment(&target->fields[origin]); + uint32_t origin_alignment = target->fields[origin].alignment; uint32_t max_options = target->size / origin_alignment; uint32_t* swap_options = (uint32_t*)malloc(sizeof(uint32_t) * max_options); // match fill_begin diff --git a/selfpatch/src/targets.h b/selfpatch/src/targets.h index 30566ae..dc7221e 100644 --- a/selfpatch/src/targets.h +++ b/selfpatch/src/targets.h @@ -4,7 +4,7 @@ #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 flags); +int spslr_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t alignment, uint32_t flags); int spslr_randomize(uint32_t target); void spslr_targets_clear();