Beginnings of selfpatch
This commit is contained in:
parent
cd10fce382
commit
a3191d6101
284
selfpatch/include/spslr_program.h
Normal file
284
selfpatch/include/spslr_program.h
Normal 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
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user