Updated patcher program

This commit is contained in:
York Jasper Niebuhr 2025-10-27 15:28:20 +01:00
parent 49ebe6ed8e
commit 54002646b0
7 changed files with 99 additions and 30 deletions

View File

@ -1,5 +1,17 @@
#include <iostream> #include <iostream>
/*
TODO
1. getopt -> --spslr=<dir>, --bin=<file>
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
*/
/* /*
<sourcefile>.spslr: <sourcefile>.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 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)! 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) { int main(int argc, char** argv) {

View File

@ -6,7 +6,7 @@ int spslr_mprot(void* base, uint32_t pagecnt, uint8_t perm) {
return 0; 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; return 0;
} }

View File

@ -4,7 +4,7 @@
#include <stdint.h> #include <stdint.h>
int spslr_mprot(void* base, uint32_t pagecnt, uint8_t perm); 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); int spslr_dpatch(void* ptr, uint32_t target);
#endif #endif

View File

@ -45,13 +45,15 @@ static int spslr_do(const struct SPSLR_INST* inst) {
pending_fields_target = inst->op0.target_uid; pending_fields_target = inst->op0.target_uid;
return spslr_target(inst->op0.target_uid, inst->op1.target_size, inst->op2.target_fieldcnt); return spslr_target(inst->op0.target_uid, inst->op1.target_size, inst->op2.target_fieldcnt);
case SPSLR_FIELD: 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: case SPSLR_RANDOMIZE:
return spslr_randomize(inst->op0.randomize_target); return spslr_randomize(inst->op0.randomize_target);
case SPSLR_MPROT: case SPSLR_MPROT:
return spslr_mprot(spslr_ptr_absolute(inst->op0.mprot_ptr), inst->op1.mprot_pagecnt, inst->op2.mprot_perm); return spslr_mprot(spslr_ptr_absolute(inst->op0.mprot_ptr), inst->op1.mprot_pagecnt, inst->op2.mprot_perm);
case SPSLR_IPATCH: 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: case SPSLR_DPATCH:
return spslr_dpatch(spslr_ptr_absolute(inst->op0.dpatch_ptr), inst->op1.dpatch_target); return spslr_dpatch(spslr_ptr_absolute(inst->op0.dpatch_ptr), inst->op1.dpatch_target);
default: default:

View File

@ -8,10 +8,10 @@
enum SPSLR_OPCODE { enum SPSLR_OPCODE {
SPSLR_TARGET, // uid, size, field count SPSLR_TARGET, // uid, size, field count
SPSLR_FIELD, // offset, size, flags SPSLR_FIELD, // offset, size, alignment, flags
SPSLR_RANDOMIZE, // target uid SPSLR_RANDOMIZE, // target uid
SPSLR_MPROT, // ptr, page count, perm 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_DPATCH, // ptr, target uid
SPSLR_EXIT SPSLR_EXIT
}; };
@ -32,16 +32,21 @@ struct SPSLR_INST {
uint32_t target_size; uint32_t target_size;
uint32_t field_size; uint32_t field_size;
uint32_t mprot_pagecnt; uint32_t mprot_pagecnt;
uint32_t ipatch_target; uint32_t ipatch_size;
uint32_t dpatch_target; uint32_t dpatch_target;
} op1; } op1;
union { union {
uint32_t target_fieldcnt; uint32_t target_fieldcnt;
uint32_t field_flags; uint32_t field_alignment;
uint8_t mprot_perm; uint8_t mprot_perm;
uint32_t ipatch_field; uint32_t ipatch_target;
} op2; } 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) { 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: case SPSLR_MPROT:
DUMP_OP_RET(inst->op1.mprot_pagecnt); DUMP_OP_RET(inst->op1.mprot_pagecnt);
case SPSLR_IPATCH: case SPSLR_IPATCH:
DUMP_OP_RET(inst->op1.ipatch_target); DUMP_OP_RET(inst->op1.ipatch_size);
case SPSLR_DPATCH: case SPSLR_DPATCH:
DUMP_OP_RET(inst->op1.dpatch_target); DUMP_OP_RET(inst->op1.dpatch_target);
case SPSLR_RANDOMIZE: 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: case SPSLR_MPROT:
LOAD_OP_RET(inst->op1.mprot_pagecnt); LOAD_OP_RET(inst->op1.mprot_pagecnt);
case SPSLR_IPATCH: case SPSLR_IPATCH:
LOAD_OP_RET(inst->op1.ipatch_target); LOAD_OP_RET(inst->op1.ipatch_size);
case SPSLR_DPATCH: case SPSLR_DPATCH:
LOAD_OP_RET(inst->op1.dpatch_target); LOAD_OP_RET(inst->op1.dpatch_target);
case SPSLR_RANDOMIZE: 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: case SPSLR_TARGET:
DUMP_OP_RET(inst->op2.target_fieldcnt); DUMP_OP_RET(inst->op2.target_fieldcnt);
case SPSLR_FIELD: case SPSLR_FIELD:
DUMP_OP_RET(inst->op2.field_flags); DUMP_OP_RET(inst->op2.field_alignment);
case SPSLR_MPROT: case SPSLR_MPROT:
DUMP_OP_RET(inst->op2.mprot_perm); DUMP_OP_RET(inst->op2.mprot_perm);
case SPSLR_IPATCH: case SPSLR_IPATCH:
DUMP_OP_RET(inst->op2.ipatch_field); DUMP_OP_RET(inst->op2.ipatch_target);
case SPSLR_DPATCH: case SPSLR_DPATCH:
case SPSLR_RANDOMIZE: case SPSLR_RANDOMIZE:
case SPSLR_EXIT: 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: case SPSLR_TARGET:
LOAD_OP_RET(inst->op2.target_fieldcnt); LOAD_OP_RET(inst->op2.target_fieldcnt);
case SPSLR_FIELD: case SPSLR_FIELD:
LOAD_OP_RET(inst->op2.field_flags); LOAD_OP_RET(inst->op2.field_alignment);
case SPSLR_MPROT: case SPSLR_MPROT:
LOAD_OP_RET(inst->op2.mprot_perm); LOAD_OP_RET(inst->op2.mprot_perm);
case SPSLR_IPATCH: 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_DPATCH:
case SPSLR_RANDOMIZE: case SPSLR_RANDOMIZE:
case SPSLR_EXIT: case SPSLR_EXIT:
@ -237,7 +282,7 @@ static inline int spslr_inst_dump(const struct SPSLR_INST* inst, uint8_t* buf) {
if (!inst || !buf) if (!inst || !buf)
return -1; 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) if ((opcode_sz = spslr_inst_dump_opcode(inst, buf)) < 0)
return -1; return -1;
@ -255,14 +300,18 @@ static inline int spslr_inst_dump(const struct SPSLR_INST* inst, uint8_t* buf) {
return -1; return -1;
buf += op2_sz; 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) { static inline int spslr_inst_load(struct SPSLR_INST* inst, const uint8_t* buf) {
if (!inst || !buf) if (!inst || !buf)
return -1; 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) if ((opcode_sz = spslr_inst_load_opcode(inst, buf)) < 0)
return -1; return -1;
@ -280,7 +329,11 @@ static inline int spslr_inst_load(struct SPSLR_INST* inst, const uint8_t* buf) {
return -1; return -1;
buf += op2_sz; 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 #endif

View File

@ -18,6 +18,7 @@ struct Field {
uint32_t offset; uint32_t offset;
uint32_t size; uint32_t size;
uint32_t alignment;
uint32_t flags; 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); 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); struct Target* t = find_target(target);
if (!t) if (!t)
return -1; 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) if (t->present_field_count >= t->field_count)
return -1; return -1;
if (offset % alignment != 0)
return -1;
if (t->present_field_count) { if (t->present_field_count) {
struct Field* pred = &t->fields[t->present_field_count - 1]; struct Field* pred = &t->fields[t->present_field_count - 1];
if (offset < pred->offset + pred->size) 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->initial_idx = idx;
f->offset = offset; f->offset = offset;
f->size = size; f->size = size;
f->alignment = alignment;
f->flags = flags; f->flags = flags;
return 0; return 0;
@ -136,10 +141,6 @@ struct ShuffleRegion {
uint32_t fill_begin, fill_end; 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) { 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_begin = target->fields[idx].offset;
region->fill_end = region->fill_begin + target->fields[idx].size; 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? // Could field be placed in origin?
uint32_t falign = field_alignment(f); if (origin_region_ptr % f->alignment != 0)
if (origin_region_ptr % falign != 0) origin_region_ptr += f->alignment - (origin_region_ptr % f->alignment);
origin_region_ptr += falign - (origin_region_ptr % falign);
origin_region_ptr += f->size; 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) if (target->fields[it].offset >= option_fill_end)
break; break;
uint32_t falign = field_alignment(&target->fields[it]); uint32_t falign = target->fields[it].alignment;
if (origin_region_ptr % falign != 0) if (origin_region_ptr % falign != 0)
origin_region_ptr += falign - (origin_region_ptr % falign); 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) if (target->fields[origin].flags & SPSLR_FLAG_FIELD_FIXED)
return; 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 max_options = target->size / origin_alignment;
uint32_t* swap_options = (uint32_t*)malloc(sizeof(uint32_t) * max_options); // match fill_begin uint32_t* swap_options = (uint32_t*)malloc(sizeof(uint32_t) * max_options); // match fill_begin

View File

@ -4,7 +4,7 @@
#include <stdint.h> #include <stdint.h>
int spslr_target(uint32_t uid, uint32_t size, uint32_t fieldcnt); 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); int spslr_randomize(uint32_t target);
void spslr_targets_clear(); void spslr_targets_clear();