#ifndef SPSLR_PROGRAM_H #define SPSLR_PROGRAM_H #include #include 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