diff --git a/finalize/accumulation.cpp b/finalize/accumulation.cpp index 51ca6e1..811df5d 100644 --- a/finalize/accumulation.cpp +++ b/finalize/accumulation.cpp @@ -138,9 +138,20 @@ static bool accumulate_file(const fs::path& path) { // Note -> could do sanity checks here + if (target.fields.contains(field.offset)) { + std::cerr << "Duplicate field offset!" << std::endl; + return false; + } + target.fields.emplace(field.offset, field); } + auto fit = target.fields.begin(); + for (std::size_t i = 0; i < field_count; i++) { + fit->second.idx = i; + fit++; + } + std::size_t global_target_uid = accumulate_global_target(std::move(target)); cu.local_targets.emplace(local_uid, global_target_uid); continue; diff --git a/finalize/accumulation.h b/finalize/accumulation.h index 4a347d3..2874b78 100644 --- a/finalize/accumulation.h +++ b/finalize/accumulation.h @@ -43,6 +43,7 @@ struct FIELD { std::size_t size; std::size_t alignment; std::size_t flags; + std::size_t idx; }; struct TARGET { diff --git a/finalize/finalize.cpp b/finalize/finalize.cpp index ae90fb8..934d58c 100644 --- a/finalize/finalize.cpp +++ b/finalize/finalize.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include @@ -7,6 +9,8 @@ #include "accumulation.h" #include "symbol_collection.h" +#include + /* Notes: Datapins for same var/symbol are randomized in order of their level, from bottom of nest to top @@ -16,6 +20,7 @@ Notes: */ static bool disassemble_ipin(const LIEF::ELF::Section* text, IPIN::HIT& pin); +static bool assemble_patcher_program(uint64_t vaddr_pivot, std::vector& program); int main(int argc, char** argv) { static option long_options[] = { @@ -117,18 +122,140 @@ int main(int argc, char** argv) { } } + // Find __spslr_program as anchor of relative addressing in patcher program + if (!global_syms.symbols.contains("__spslr_program")) { + std::cerr << "Unable to locate \"__spslr_program\"!" << std::endl; + return 1; + } + + uint64_t spslr_program_ptr_address = global_syms.symbols.at("__spslr_program"); + + // Serialize patcher program + std::vector patcher_program; + if (!assemble_patcher_program(spslr_program_ptr_address, patcher_program)) { + std::cerr << "Failed to assemble patcher program!" << std::endl; + return 1; + } + // TODO /* - 1. Find __spslr_program - 2. Serialize entire patcher program - -> all pin addresses relative to &__spslr_program - -> dpatch entry components ordered by level - 3. Add new section .spslr with patcher program - 4. Set __spslr_program to (&.spslr - &__spslr_program) - 5. Output final program + 1. Add new section .spslr with patcher program + 2. Set __spslr_program to (&.spslr - &__spslr_program) + 3. Output final program */ } +bool assemble_patcher_program(uint64_t vaddr_pivot, std::vector& program) { + uint8_t buf[sizeof(SPSLR_INST)]; + + auto append_inst = [&](const SPSLR_INST& inst) -> bool { + int n = spslr_inst_dump(&inst, buf); + if (n < 0) { + std::cerr << "Failed to dump patcher instruction!" << std::endl; + return false; + } + + std::size_t program_ptr = program.size(); + + program.resize(program.size() + n); + std::memcpy(program.data() + program_ptr, buf, n); + return true; + }; + + SPSLR_INST inst; + + // Dump all targets, their fields and command randomization + for (const auto& [tuid, target] : targets) { + inst.opcode = SPSLR_TARGET; + inst.op0.target_uid = tuid; + inst.op1.target_size = target.size; + inst.op2.target_fieldcnt = target.fields.size(); + + if (!append_inst(inst)) + return false; + + for (const auto& [foff, field] : target.fields) { + inst.opcode = SPSLR_FIELD; + inst.op0.field_offset = field.offset; + inst.op1.field_size = field.size; + inst.op2.field_alignment = field.alignment; + inst.op3.field_flags = field.flags; // Note -> This should be done explicitely with SPSLR_FLAG_FIELD_FIXED + + if (!append_inst(inst)) + return false; + } + + inst.opcode = SPSLR_RANDOMIZE; + inst.op0.randomize_target = tuid; + + if (!append_inst(inst)) + return false; + } + + // Dump ipins with addresses relative to vaddr_pivot + auto append_ipin = [&](const CU& cu, const IPIN& ipin) -> bool { + inst.opcode = SPSLR_IPATCH; + inst.op0.ipatch_ptr = ipin.hit->vaddr + ipin.hit->imm_offset - vaddr_pivot; + inst.op1.ipatch_size = ipin.hit->imm_size; + inst.op2.ipatch_target = cu.local_targets.at(ipin.local_target); + + if (!targets.at(inst.op2.ipatch_target).fields.contains(ipin.field_offset)) + return false; + + inst.op3.ipatch_field = targets.at(inst.op2.ipatch_target).fields.at(ipin.field_offset).idx; + return append_inst(inst); + }; + + // Dump dpins with addresses relative to vaddr_pivot and components ordered by level + auto append_dpin = [&](const DPIN& dpin) -> bool { + std::list sorted_components = dpin.components; + sorted_components.sort([](const DPIN::COMPONENT& a, const DPIN::COMPONENT& b) { + return a.level > b.level; // Descending order + }); + + for (const DPIN::COMPONENT& comp : sorted_components) { + inst.opcode = SPSLR_DPATCH; + inst.op0.dpatch_ptr = dpin.hit->vaddr + comp.offset - vaddr_pivot; + inst.op1.dpatch_target = comp.target; + + if (!append_inst(inst)) + return false; + } + + return true; + }; + + // Dump all local pins + for (const auto& [cu_uid, cu] : units) { + for (const auto& [ipin_sym, ipin] : cu.ipins) { + if (!append_ipin(cu, ipin)) + return false; + } + + for (const auto& [dpin_sym, dpin] : cu.dpins) { + DPIN global_dpin; + for (DPIN::COMPONENT& comp : global_dpin.components) + comp.target = cu.local_targets.at(comp.target); + + if (!append_dpin(global_dpin)) + return false; + } + } + + // Dump global dpins + for (const auto& [dpin_sym, dpin] : global_dpins) { + if (!append_dpin(dpin)) + return false; + } + + // Exit patcher program + inst.opcode = SPSLR_EXIT; + if (!append_inst(inst)) + return false; + + return true; +} + bool disassemble_ipin(const LIEF::ELF::Section* text, IPIN::HIT& pin) { if (!text) return false; diff --git a/selfpatch/CMakeLists.txt b/selfpatch/CMakeLists.txt index 51ec1cf..00befad 100644 --- a/selfpatch/CMakeLists.txt +++ b/selfpatch/CMakeLists.txt @@ -4,3 +4,5 @@ target_include_directories(spslr_selfpatch PUBLIC $ $ ) + +target_include_directories(spslr_finalize PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) # For spslr_program.h diff --git a/selfpatch/src/patcher.c b/selfpatch/src/patcher.c index 674dca2..3464b6d 100644 --- a/selfpatch/src/patcher.c +++ b/selfpatch/src/patcher.c @@ -2,10 +2,6 @@ // TODO -int spslr_mprot(void* base, uint32_t pagecnt, uint8_t perm) { - return 0; -} - int spslr_ipatch(void* ptr, uint32_t size, uint32_t target, uint32_t field) { return 0; } diff --git a/selfpatch/src/patcher.h b/selfpatch/src/patcher.h index bc83339..633b851 100644 --- a/selfpatch/src/patcher.h +++ b/selfpatch/src/patcher.h @@ -3,7 +3,6 @@ #include -int spslr_mprot(void* base, uint32_t pagecnt, uint8_t perm); int spslr_ipatch(void* ptr, uint32_t size, uint32_t target, uint32_t field); int spslr_dpatch(void* ptr, uint32_t target); diff --git a/selfpatch/src/selfpatch.c b/selfpatch/src/selfpatch.c index 0e1687e..795581c 100644 --- a/selfpatch/src/selfpatch.c +++ b/selfpatch/src/selfpatch.c @@ -49,8 +49,6 @@ static int spslr_do(const struct SPSLR_INST* inst) { 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); diff --git a/selfpatch/src/spslr_program.h b/selfpatch/src/spslr_program.h index 9377a56..38679bc 100644 --- a/selfpatch/src/spslr_program.h +++ b/selfpatch/src/spslr_program.h @@ -10,7 +10,6 @@ enum SPSLR_OPCODE { SPSLR_TARGET, // uid, size, field count SPSLR_FIELD, // offset, size, alignment, flags SPSLR_RANDOMIZE, // target uid - SPSLR_MPROT, // ptr, page count, perm SPSLR_IPATCH, // ptr, size, target uid, field idx (not offset!) SPSLR_DPATCH, // ptr, target uid SPSLR_EXIT @@ -23,7 +22,6 @@ struct SPSLR_INST { 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; @@ -31,7 +29,6 @@ struct SPSLR_INST { union { uint32_t target_size; uint32_t field_size; - uint32_t mprot_pagecnt; uint32_t ipatch_size; uint32_t dpatch_target; } op1; @@ -39,7 +36,6 @@ struct SPSLR_INST { union { uint32_t target_fieldcnt; uint32_t field_alignment; - uint8_t mprot_perm; uint32_t ipatch_target; } op2; @@ -60,14 +56,12 @@ static inline int spslr_inst_dump_opcode(const struct SPSLR_INST* inst, uint8_t* *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; + *buf = 4; return 1; case SPSLR_DPATCH: - *buf = 6; return 1; + *buf = 5; return 1; case SPSLR_EXIT: - *buf = 7; return 1; + *buf = 6; return 1; default: return -1; } @@ -85,12 +79,10 @@ static inline int spslr_inst_load_opcode(struct SPSLR_INST* inst, const uint8_t* 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: + case 5: inst->opcode = SPSLR_DPATCH; return 1; - case 7: + case 6: inst->opcode = SPSLR_EXIT; return 1; default: return -1; @@ -111,8 +103,6 @@ static inline int spslr_inst_dump_op0(const struct SPSLR_INST* inst, uint8_t* bu 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: @@ -135,8 +125,6 @@ static inline int spslr_inst_load_op0(struct SPSLR_INST* inst, const uint8_t* bu 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: @@ -157,8 +145,6 @@ static inline int spslr_inst_dump_op1(const struct SPSLR_INST* inst, uint8_t* bu 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_size); case SPSLR_DPATCH: @@ -180,8 +166,6 @@ static inline int spslr_inst_load_op1(struct SPSLR_INST* inst, const uint8_t* bu 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_size); case SPSLR_DPATCH: @@ -203,8 +187,6 @@ static inline int spslr_inst_dump_op2(const struct SPSLR_INST* inst, uint8_t* bu DUMP_OP_RET(inst->op2.target_fieldcnt); case SPSLR_FIELD: 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_target); case SPSLR_DPATCH: @@ -225,8 +207,6 @@ static inline int spslr_inst_load_op2(struct SPSLR_INST* inst, const uint8_t* bu LOAD_OP_RET(inst->op2.target_fieldcnt); case SPSLR_FIELD: 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_target); case SPSLR_DPATCH: @@ -248,7 +228,6 @@ static inline int spslr_inst_dump_op3(const struct SPSLR_INST* inst, uint8_t* bu 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: @@ -268,7 +247,6 @@ static inline int spslr_inst_load_op3(struct SPSLR_INST* inst, const uint8_t* bu 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: