From df0ba1909303a31bd2bbdd059187b1b0fcad512b Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Thu, 7 Apr 2022 02:20:54 -0700 Subject: [PATCH] finished relocation transformation pass... todo write other passes and also move the code that checks to see if the section is .obf to outside of routine_t so that you can re-use routine_t to decompose entire functions after running them through obfuscation passes.... --- include/obf/transform/add_op.hpp | 2 +- include/obf/transform/and_op.hpp | 17 ++++++++++++++++ include/obf/transform/operation.hpp | 30 +++++++++++++++++------------ include/obf/transform/or_op.hpp | 17 ++++++++++++++++ include/obf/transform/rol_op.hpp | 19 ++++++++++++++++++ include/obf/transform/ror_op.hpp | 19 ++++++++++++++++++ include/obf/transform/sub_op.hpp | 2 +- include/obf/transform/transform.hpp | 14 +++++++++++--- include/obf/transform/xor_op.hpp | 17 ++++++++++++++++ src/tests/demo/main.cpp | 1 + src/theo/recomp/recomp.cpp | 24 ++++++++++++++++------- src/theo/theo.cpp | 4 ++++ 12 files changed, 142 insertions(+), 24 deletions(-) diff --git a/include/obf/transform/add_op.hpp b/include/obf/transform/add_op.hpp index 18fff6e..961295e 100644 --- a/include/obf/transform/add_op.hpp +++ b/include/obf/transform/add_op.hpp @@ -5,7 +5,7 @@ namespace theo::obf::transform { class add_op_t : public operation_t { explicit add_op_t() : operation_t([&](std::size_t val, - std::size_t imm) -> std::size_t { return val + imm; }, + std::uint32_t imm) -> std::size_t { return val + imm; }, XED_ICLASS_ADD) {} public: diff --git a/include/obf/transform/and_op.hpp b/include/obf/transform/and_op.hpp index e69de29..2303a5d 100644 --- a/include/obf/transform/and_op.hpp +++ b/include/obf/transform/and_op.hpp @@ -0,0 +1,17 @@ +#pragma once +#include + +namespace theo::obf::transform { +class and_op_t : public operation_t { + explicit and_op_t() + : operation_t([&](std::size_t val, + std::uint32_t imm) -> std::size_t { return val & imm; }, + XED_ICLASS_AND) {} + + public: + static and_op_t* get() { + static and_op_t obj; + return &obj; + } +}; +} // namespace theo::obf::transform \ No newline at end of file diff --git a/include/obf/transform/operation.hpp b/include/obf/transform/operation.hpp index 6e9af06..daee10e 100644 --- a/include/obf/transform/operation.hpp +++ b/include/obf/transform/operation.hpp @@ -11,7 +11,7 @@ extern "C" { } namespace theo::obf::transform { -using transform_t = std::function; +using transform_t = std::function; class operation_t { public: @@ -20,22 +20,28 @@ class operation_t { std::vector native(const xed_decoded_inst_t* inst, std::size_t imm) { + std::uint32_t inst_len = {}; + std::uint8_t inst_buff[XED_MAX_INSTRUCTION_BYTES]; + xed_error_enum_t err; - xed_encoder_request_t req; + xed_encoder_request_init_from_decode((xed_decoded_inst_s*)inst); + xed_encoder_request_t* req = (xed_encoder_request_t*)inst; xed_state_t istate{XED_MACHINE_MODE_LONG_64, XED_ADDRESS_WIDTH_64b}; - xed_encoder_request_zero_set_mode(&req, &istate); - xed_encoder_request_set_effective_operand_width(&req, 64); - xed_encoder_request_set_iclass(&req, m_type); - xed_encoder_request_set_reg(&req, XED_OPERAND_REG0, XED_REG_RAX); - xed_encoder_request_set_operand_order(&req, 0, XED_OPERAND_REG0); - xed_encoder_request_set_uimm0(&req, imm, 4); - xed_encoder_request_set_operand_order(&req, 1, XED_OPERAND_IMM0); + switch (m_type) { + case XED_ICLASS_ROR: + case XED_ICLASS_ROL: + xed_encoder_request_set_uimm0(req, imm, 1); + break; + default: + xed_encoder_request_set_uimm0(req, imm, 4); + break; + } - std::uint8_t inst_buff[XED_MAX_INSTRUCTION_BYTES]; - std::uint32_t inst_len = {}; + xed_encoder_request_set_iclass(req, m_type); + xed_encoder_request_set_operand_order(req, 1, XED_OPERAND_IMM0); - if ((err = xed_encode(&req, inst_buff, sizeof(inst_buff), &inst_len)) != + if ((err = xed_encode(req, inst_buff, sizeof(inst_buff), &inst_len)) != XED_ERROR_NONE) { spdlog::error("failed to encode instruction... reason: {}", xed_error_enum_t2str(err)); diff --git a/include/obf/transform/or_op.hpp b/include/obf/transform/or_op.hpp index e69de29..1976dab 100644 --- a/include/obf/transform/or_op.hpp +++ b/include/obf/transform/or_op.hpp @@ -0,0 +1,17 @@ +#pragma once +#include + +namespace theo::obf::transform { +class or_op_t : public operation_t { + explicit or_op_t() + : operation_t([&](std::size_t val, + std::uint32_t imm) -> std::size_t { return val | imm; }, + XED_ICLASS_OR) {} + + public: + static or_op_t* get() { + static or_op_t obj; + return &obj; + } +}; +} // namespace theo::obf::transform \ No newline at end of file diff --git a/include/obf/transform/rol_op.hpp b/include/obf/transform/rol_op.hpp index e69de29..2a9e7c1 100644 --- a/include/obf/transform/rol_op.hpp +++ b/include/obf/transform/rol_op.hpp @@ -0,0 +1,19 @@ +#pragma once +#include + +namespace theo::obf::transform { +class rol_op_t : public operation_t { + explicit rol_op_t() + : operation_t( + [&](std::size_t val, std::uint32_t imm) -> std::size_t { + return _rotl64(val, (std::uint8_t)imm); + }, + XED_ICLASS_ROL) {} + + public: + static rol_op_t* get() { + static rol_op_t obj; + return &obj; + } +}; +} // namespace theo::obf::transform \ No newline at end of file diff --git a/include/obf/transform/ror_op.hpp b/include/obf/transform/ror_op.hpp index e69de29..ad77945 100644 --- a/include/obf/transform/ror_op.hpp +++ b/include/obf/transform/ror_op.hpp @@ -0,0 +1,19 @@ +#pragma once +#include + +namespace theo::obf::transform { +class ror_op_t : public operation_t { + explicit ror_op_t() + : operation_t( + [&](std::size_t val, std::uint32_t imm) -> std::size_t { + return _rotr64(val, (std::uint8_t)imm); + }, + XED_ICLASS_ROR) {} + + public: + static ror_op_t* get() { + static ror_op_t obj; + return &obj; + } +}; +} // namespace theo::obf::transform \ No newline at end of file diff --git a/include/obf/transform/sub_op.hpp b/include/obf/transform/sub_op.hpp index 6f7e8cb..e88776f 100644 --- a/include/obf/transform/sub_op.hpp +++ b/include/obf/transform/sub_op.hpp @@ -5,7 +5,7 @@ namespace theo::obf::transform { class sub_op_t : public operation_t { explicit sub_op_t() : operation_t([&](std::size_t val, - std::size_t imm) -> std::size_t { return val - imm; }, + std::uint32_t imm) -> std::size_t { return val - imm; }, XED_ICLASS_SUB) {} public: diff --git a/include/obf/transform/transform.hpp b/include/obf/transform/transform.hpp index a867ed7..8623a6b 100644 --- a/include/obf/transform/transform.hpp +++ b/include/obf/transform/transform.hpp @@ -1,10 +1,18 @@ #pragma once -#include #include + +#include +#include +#include +#include +#include #include +#include namespace theo::obf::transform { inline std::map operations = { - {XED_ICLASS_ADD, add_op_t::get()}, - {XED_ICLASS_SUB, sub_op_t::get()}}; + {XED_ICLASS_ADD, add_op_t::get()}, {XED_ICLASS_SUB, sub_op_t::get()}, + {XED_ICLASS_AND, and_op_t::get()}, {XED_ICLASS_OR, or_op_t::get()}, + {XED_ICLASS_ROL, rol_op_t::get()}, {XED_ICLASS_ROR, ror_op_t::get()}, + {XED_ICLASS_XOR, xor_op_t::get()}}; } \ No newline at end of file diff --git a/include/obf/transform/xor_op.hpp b/include/obf/transform/xor_op.hpp index e69de29..2c153cb 100644 --- a/include/obf/transform/xor_op.hpp +++ b/include/obf/transform/xor_op.hpp @@ -0,0 +1,17 @@ +#pragma once +#include + +namespace theo::obf::transform { +class xor_op_t : public operation_t { + explicit xor_op_t() + : operation_t([&](std::size_t val, + std::uint32_t imm) -> std::size_t { return val ^ imm; }, + XED_ICLASS_XOR) {} + + public: + static xor_op_t* get() { + static xor_op_t obj; + return &obj; + } +}; +} // namespace theo::obf::transform \ No newline at end of file diff --git a/src/tests/demo/main.cpp b/src/tests/demo/main.cpp index 924ceb4..2009a74 100644 --- a/src/tests/demo/main.cpp +++ b/src/tests/demo/main.cpp @@ -48,4 +48,5 @@ int main(int argc, char* argv[]) { auto entry_pnt = t.compose("EntryPoint"); spdlog::info("entry point address: {:X}", entry_pnt); // reinterpret_cast(entry_pnt)(); + std::getchar(); } \ No newline at end of file diff --git a/src/theo/recomp/recomp.cpp b/src/theo/recomp/recomp.cpp index a8b204e..f2ce3f3 100644 --- a/src/theo/recomp/recomp.cpp +++ b/src/theo/recomp/recomp.cpp @@ -3,9 +3,9 @@ namespace theo::recomp { recomp_t::recomp_t(decomp::decomp_t* dcmp) : m_dcmp(dcmp) {} recomp_t::recomp_t(decomp::decomp_t* dcmp, - allocator_t alloc, - copier_t copy, - resolver_t resolve) + allocator_t alloc, + copier_t copy, + resolver_t resolve) : m_dcmp(dcmp), m_allocator(alloc), m_copier(copy), m_resolver(resolve) {} void recomp_t::allocate() { @@ -96,10 +96,20 @@ void recomp_t::resolve() { break; } case decomp::sym_type_t::inst_split: { - // TODO: run the vector of transformation operations here if the - // symbol is of type inst_split... the transformations will be applied - // to allocate_at() result on the symbol... + // TODO: change this if statement into a sanity check with an assert + // after coding the next_inst_pass to ensure it works... // + if (reloc.offset()) { + auto& transforms = reloc.get_transforms(); + std::for_each( + transforms.begin(), transforms.end(), + [&](std::pair& t) { + allocated_at = (*t.first)(allocated_at, t.second); + }); + + *reinterpret_cast(sym.data().data() + + reloc.offset()) = allocated_at; + } break; } default: @@ -133,4 +143,4 @@ std::uintptr_t recomp_t::resolve(const std::string&& sym) { auto res = m_dcmp->syms()->sym_from_hash(decomp::symbol_t::hash(sym)); return res.has_value() ? res->allocated_at() : 0; } -} // namespace theo::comp \ No newline at end of file +} // namespace theo::recomp \ No newline at end of file diff --git a/src/theo/theo.cpp b/src/theo/theo.cpp index c5890cf..3047cb4 100644 --- a/src/theo/theo.cpp +++ b/src/theo/theo.cpp @@ -43,6 +43,10 @@ std::uintptr_t theo_t::compose(const std::string&& entry_sym) { m_sym_tbl.for_each([&](decomp::symbol_t& sym) { engine->run(&sym); }); m_recmp.allocate(); + m_sym_tbl.for_each([&](decomp::symbol_t& sym) { + spdlog::info("{} allocated at {:X}", sym.name(), sym.allocated_at()); + }); + m_recmp.resolve(); m_recmp.copy_syms(); return m_recmp.resolve(entry_sym.data());