Beginnings of selfpatch

This commit is contained in:
York Jasper Niebuhr 2025-10-26 21:31:07 +01:00
parent cd10fce382
commit a3191d6101
2 changed files with 318 additions and 1 deletions

View File

@ -0,0 +1,284 @@
#ifndef SPSLR_PROGRAM_H
#define SPSLR_PROGRAM_H
#include <stdint.h>
#include <string.h>
enum SPSLR_OPCODE {
SPSLR_TARGET, // uid, size, field count
SPSLR_FIELD, // offset, size, flags
SPSLR_RANDOMIZE, // target uid
SPSLR_MPROT, // ptr, page count, perm
SPSLR_IPATCH, // ptr, target uid, field idx (not offset!)
SPSLR_DPATCH, // ptr, target uid
SPSLR_EXIT
};
struct SPSLR_INST {
enum SPSLR_OPCODE opcode;
union {
uint32_t target_uid;
uint32_t field_offset;
uint32_t randomize_target;
uint64_t mprot_ptr;
uint64_t ipatch_ptr;
uint64_t dpatch_ptr;
} op0;
union {
uint32_t target_size;
uint32_t field_size;
uint32_t mprot_pagecnt;
uint32_t ipatch_target;
uint32_t dpatch_target;
} op1;
union {
uint32_t target_fieldcnt;
uint32_t field_flags;
uint8_t mprot_perm;
uint32_t ipatch_field;
} op2;
};
static inline int spslr_inst_dump_opcode(const struct SPSLR_INST* inst, uint8_t* buf) {
if (!inst || !buf)
return -1;
switch (inst->opcode) {
case SPSLR_TARGET:
*buf = 1; return 1;
case SPSLR_FIELD:
*buf = 2; return 1;
case SPSLR_RANDOMIZE:
*buf = 3; return 1;
case SPSLR_MPROT:
*buf = 4; return 1;
case SPSLR_IPATCH:
*buf = 5; return 1;
case SPSLR_DPATCH:
*buf = 6; return 1;
case SPSLR_EXIT:
*buf = 7; 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 1:
inst->opcode = SPSLR_TARGET; return 1;
case 2:
inst->opcode = SPSLR_FIELD; return 1;
case 3:
inst->opcode = SPSLR_RANDOMIZE; return 1;
case 4:
inst->opcode = SPSLR_MPROT; return 1;
case 5:
inst->opcode = SPSLR_IPATCH; return 1;
case 6:
inst->opcode = SPSLR_DPATCH; return 1;
case 7:
inst->opcode = 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->opcode) {
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_MPROT:
DUMP_OP_RET(inst->op0.mprot_ptr);
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->opcode) {
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_MPROT:
LOAD_OP_RET(inst->op0.mprot_ptr);
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->opcode) {
case SPSLR_TARGET:
DUMP_OP_RET(inst->op1.target_size);
case SPSLR_FIELD:
DUMP_OP_RET(inst->op1.field_size);
case SPSLR_MPROT:
DUMP_OP_RET(inst->op1.mprot_pagecnt);
case SPSLR_IPATCH:
DUMP_OP_RET(inst->op1.ipatch_target);
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->opcode) {
case SPSLR_TARGET:
LOAD_OP_RET(inst->op1.target_size);
case SPSLR_FIELD:
LOAD_OP_RET(inst->op1.field_size);
case SPSLR_MPROT:
LOAD_OP_RET(inst->op1.mprot_pagecnt);
case SPSLR_IPATCH:
LOAD_OP_RET(inst->op1.ipatch_target);
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->opcode) {
case SPSLR_TARGET:
DUMP_OP_RET(inst->op2.target_fieldcnt);
case SPSLR_FIELD:
DUMP_OP_RET(inst->op2.field_flags);
case SPSLR_MPROT:
DUMP_OP_RET(inst->op2.mprot_perm);
case SPSLR_IPATCH:
DUMP_OP_RET(inst->op2.ipatch_field);
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->opcode) {
case SPSLR_TARGET:
LOAD_OP_RET(inst->op2.target_fieldcnt);
case SPSLR_FIELD:
LOAD_OP_RET(inst->op2.field_flags);
case SPSLR_MPROT:
LOAD_OP_RET(inst->op2.mprot_perm);
case SPSLR_IPATCH:
LOAD_OP_RET(inst->op2.ipatch_field);
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;
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;
return opcode_sz + op0_sz + op1_sz + op2_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;
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;
return opcode_sz + op0_sz + op1_sz + op2_sz;
}
#endif

View File

@ -1,6 +1,39 @@
#include <spslr.h> #include <spslr.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <spslr_program.h>
/*
To allow ASLR, all patcher addresses are relative to &__spslr_program
*/
const uint8_t* __spslr_program = NULL;
static int spslr_do(const struct SPSLR_INST* inst) {
// TODO -> dispatch different instructions, make args/pointers absolute
return 0;
}
void spslr_selfpatch() { void spslr_selfpatch() {
printf("SPSLR -> selfpatch()\n"); if (!__spslr_program) {
fprintf(stderr, "spslr_selfpatch has no patcher program (finalize this binary to use SPSLR)\n");
return;
}
int sz;
struct SPSLR_INST inst;
while ((sz = spslr_inst_load(&inst, __spslr_program)) > 0) {
if (inst.opcode == SPSLR_EXIT)
return;
if (spslr_do(&inst) < 0) {
fprintf(stderr, "spslr_selfpatch failed to execute an instruction\n");
exit(1);
}
__spslr_program += sz;
}
fprintf(stderr, "spslr_selfpatch encountered invalid instruction\n");
exit(1);
} }