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>
/*
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:
@ -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) {

View File

@ -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;
}

View File

@ -4,7 +4,7 @@
#include <stdint.h>
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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -4,7 +4,7 @@
#include <stdint.h>
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();