selfpatch-slr/selfpatch/src/selfpatch.c

89 lines
2.6 KiB
C

#include <spslr.h>
#include <stdio.h>
#include <stdlib.h>
#include "spslr_program.h"
#include "targets.h"
#include "patcher.h"
/*
TODO
Postprocessing tool patches the value of __spslr_program to point to the SPSLR program section.
With ASLR, there are 2 options to make it function correctly:
1. Make sure __spslr_program is relocated with program image shift (preferred)
2. __spslr_program = spslr_ptr_absolute((uint64_t)__spslr_program) and postprocessor inserts relative value (kinda weird)
*/
const uint8_t* __spslr_program = NULL;
static void* spslr_ptr_absolute(uint64_t relative) {
// To allow ASLR, all patcher addresses are relative to &__spslr_program
return ((uint8_t*)&__spslr_program) + relative;
}
static int spslr_do(const struct SPSLR_INST* inst) {
if (!inst)
return -1;
static uint32_t pending_fields = 0;
static uint32_t pending_fields_target = 0;
if (pending_fields) {
if (inst->opcode != SPSLR_FIELD) {
fprintf(stderr, "spslr_do encountered non field instruction where a field instruction was expected\n");
return -1;
}
pending_fields--;
} else if (inst->opcode == SPSLR_FIELD) {
fprintf(stderr, "spslr_do encountered field instruction where none was expected\n");
return -1;
}
switch (inst->opcode) {
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_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_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:
return -1;
}
}
void spslr_selfpatch() {
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) {
spslr_targets_clear();
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);
}