From 9199d5bef72c91d45fe061568a21dde00229ce3b Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Wed, 6 Apr 2022 22:07:23 -0700 Subject: [PATCH] about half way done with transformations... imm's cant be 8 bytes, only 4... --- CMakeLists.txt | 2 - include/obf/passes/reloc_transform_pass.hpp | 6 ++- include/obf/transform/add_op.hpp | 8 +-- include/obf/transform/operation.hpp | 56 ++++++++++++++++---- include/obf/transform/sub_op.hpp | 17 ++++++ include/obf/transform/transform.hpp | 13 ++--- include/recomp/reloc.hpp | 15 +++++- src/theo/obf/passes/reloc_transform_pass.cpp | 46 ++++++++++++++-- src/theo/obf/transform/add_op.cpp | 14 ----- src/theo/obf/transform/sub_op.cpp | 0 10 files changed, 135 insertions(+), 42 deletions(-) delete mode 100644 src/theo/obf/transform/add_op.cpp delete mode 100644 src/theo/obf/transform/sub_op.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c96d53e..1751302 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,8 +82,6 @@ list(APPEND Theodosius_SOURCES "src/theo/obf/passes/jcc_rewrite_pass.cpp" "src/theo/obf/passes/next_inst_pass.cpp" "src/theo/obf/passes/reloc_transform_pass.cpp" - "src/theo/obf/transform/add_op.cpp" - "src/theo/obf/transform/sub_op.cpp" "src/theo/recomp/recomp.cpp" "src/theo/recomp/symbol_table.cpp" "src/theo/theo.cpp" diff --git a/include/obf/passes/reloc_transform_pass.hpp b/include/obf/passes/reloc_transform_pass.hpp index 651c202..6785ee7 100644 --- a/include/obf/passes/reloc_transform_pass.hpp +++ b/include/obf/passes/reloc_transform_pass.hpp @@ -1,5 +1,7 @@ #pragma once #include +#include +#include namespace theo::obf { class reloc_transform_pass_t : public pass_t { @@ -10,6 +12,6 @@ class reloc_transform_pass_t : public pass_t { void run(decomp::symbol_t* sym); private: - bool has_legit_reloc(decomp::symbol_t* sym); + std::optional has_legit_reloc(decomp::symbol_t* sym); }; -} // namespace theo::comp::obf \ No newline at end of file +} // namespace theo::obf \ No newline at end of file diff --git a/include/obf/transform/add_op.hpp b/include/obf/transform/add_op.hpp index f8cd965..18fff6e 100644 --- a/include/obf/transform/add_op.hpp +++ b/include/obf/transform/add_op.hpp @@ -6,10 +6,12 @@ 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; }, - type_t::add_op) {} + XED_ICLASS_ADD) {} public: - static add_op_t* get(); - std::vector native(xed_inst_t* inst, std::size_t imm); + static add_op_t* get() { + static add_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 1c4b31b..6e9af06 100644 --- a/include/obf/transform/operation.hpp +++ b/include/obf/transform/operation.hpp @@ -1,6 +1,8 @@ #pragma once +#include #include #include +#include #define XED_ENCODER extern "C" { @@ -13,24 +15,56 @@ using transform_t = std::function; class operation_t { public: - enum type_t { add_op, sub_op, and_op, or_op, rol_op, ror_op, xor_op }; - - explicit operation_t(transform_t op, type_t type) + explicit operation_t(transform_t op, xed_iclass_enum_t type) : m_transform(op), m_type(type) {} - virtual std::vector native(xed_inst_t* inst, - std::size_t imm) = 0; + std::vector native(const xed_decoded_inst_t* inst, + std::size_t imm) { + xed_error_enum_t err; + xed_encoder_request_t req; + 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); + + std::uint8_t inst_buff[XED_MAX_INSTRUCTION_BYTES]; + std::uint32_t 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)); + + assert(err == XED_ERROR_NONE); + } + + return std::vector(inst_buff, inst_buff + inst_len); + } + + xed_iclass_enum_t inverse() { return m_inverse_op[m_type]; } + transform_t* get_transform() { return &m_transform; } - type_t inverse() { return m_inverse_op[m_type]; } - transform_t get_transform() { return m_transform; } + static std::size_t random(std::size_t lowest, std::size_t largest) { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution distr(lowest, largest); + return distr(gen); + } private: transform_t m_transform; - type_t m_type; + xed_iclass_enum_t m_type; - std::map m_inverse_op = { - {add_op, sub_op}, {sub_op, add_op}, {and_op, or_op}, {or_op, and_op}, - {rol_op, ror_op}, {ror_op, rol_op}, {xor_op, xor_op}}; + std::map m_inverse_op = { + {XED_ICLASS_ADD, XED_ICLASS_SUB}, {XED_ICLASS_SUB, XED_ICLASS_ADD}, + {XED_ICLASS_AND, XED_ICLASS_OR}, {XED_ICLASS_OR, XED_ICLASS_AND}, + {XED_ICLASS_ROL, XED_ICLASS_ROR}, {XED_ICLASS_ROR, XED_ICLASS_ROL}, + {XED_ICLASS_XOR, XED_ICLASS_XOR}}; }; } // 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 e69de29..6f7e8cb 100644 --- a/include/obf/transform/sub_op.hpp +++ b/include/obf/transform/sub_op.hpp @@ -0,0 +1,17 @@ +#pragma once +#include + +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; }, + XED_ICLASS_SUB) {} + + public: + static sub_op_t* get() { + static sub_op_t obj; + return &obj; + } +}; +} // namespace theo::obf::transform \ No newline at end of file diff --git a/include/obf/transform/transform.hpp b/include/obf/transform/transform.hpp index 26b9960..a867ed7 100644 --- a/include/obf/transform/transform.hpp +++ b/include/obf/transform/transform.hpp @@ -1,9 +1,10 @@ #pragma once -#include -#include -#include +#include +#include +#include -namespace theo::comp::obf::transform { -std::map operations = { - {operation_t::type_t::add_op, add_op_t::get()}}; +namespace theo::obf::transform { +inline std::map operations = { + {XED_ICLASS_ADD, add_op_t::get()}, + {XED_ICLASS_SUB, sub_op_t::get()}}; } \ No newline at end of file diff --git a/include/recomp/reloc.hpp b/include/recomp/reloc.hpp index 3b0c4f4..4e3c01b 100644 --- a/include/recomp/reloc.hpp +++ b/include/recomp/reloc.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include namespace theo::recomp { class reloc_t { @@ -14,9 +15,21 @@ class reloc_t { std::string name() { return m_sym_name; } std::uint16_t offset() { return m_offset; } + void add_transform( + std::pair entry) { + m_transforms.push_back(entry); + } + + std::vector>& + get_transforms() { + return m_transforms; + } + private: + std::vector> + m_transforms; std::string m_sym_name; std::size_t m_hash; std::uint16_t m_offset; }; -} // namespace theo::comp \ No newline at end of file +} // namespace theo::recomp \ No newline at end of file diff --git a/src/theo/obf/passes/reloc_transform_pass.cpp b/src/theo/obf/passes/reloc_transform_pass.cpp index cbf7dba..a3286b5 100644 --- a/src/theo/obf/passes/reloc_transform_pass.cpp +++ b/src/theo/obf/passes/reloc_transform_pass.cpp @@ -7,7 +7,8 @@ reloc_transform_pass_t* reloc_transform_pass_t::get() { } void reloc_transform_pass_t::run(decomp::symbol_t* sym) { - if (!has_legit_reloc(sym)) + std::optional reloc; + if (!(reloc = has_legit_reloc(sym)).has_value()) return; spdlog::info("adding transformations to relocation in symbol: {}", @@ -25,9 +26,47 @@ void reloc_transform_pass_t::run(decomp::symbol_t* sym) { assert(err == XED_ERROR_NONE); } + + // determine how many transformations we will generate... + // + auto num_transforms = transform::operation_t::random(1, 10); + auto num_ops = transform::operations.size(); + + for (auto cnt = 0u; cnt < num_transforms; ++cnt) { + // generate random imm value... + // + std::size_t imm = transform::operation_t::random( + 0, std::numeric_limits::max()); + + // get a random transformation... + // + auto itr = transform::operations.begin(); + std::advance(itr, transform::operation_t::random(0, num_ops - 1)); + + // generate the native code for the transformation... + // + auto transform_bytes = itr->second->native(&inst, imm); + + // insert the bytes of the native instruction into the data buffer... + // + sym->data().insert(sym->data().end(), transform_bytes.begin(), + transform_bytes.end()); + + // add the inverse operation to the relocation for encrypting the relocation + // pointer... + // + reloc.value()->add_transform( + {transform::operations[itr->second->inverse()]->get_transform(), imm}); + } + + // inverse the order in which the transformations are executed... + // + std::reverse(reloc.value()->get_transforms().begin(), + reloc.value()->get_transforms().end()); }; -bool reloc_transform_pass_t::has_legit_reloc(decomp::symbol_t* sym) { +std::optional reloc_transform_pass_t::has_legit_reloc( + decomp::symbol_t* sym) { auto res = // see if there are any relocations with offset not equal to // zero... relocations with zero mean its a relocation to the next // instruction... @@ -35,6 +74,7 @@ bool reloc_transform_pass_t::has_legit_reloc(decomp::symbol_t* sym) { sym->relocs().begin(), sym->relocs().end(), [&](recomp::reloc_t& reloc) -> bool { return reloc.offset(); }); - return res != sym->relocs().end(); + return res != sym->relocs().end() ? res._Ptr + : std::optional(); } } // namespace theo::obf \ No newline at end of file diff --git a/src/theo/obf/transform/add_op.cpp b/src/theo/obf/transform/add_op.cpp deleted file mode 100644 index c9d3a69..0000000 --- a/src/theo/obf/transform/add_op.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include - -namespace theo::obf::transform { -add_op_t* add_op_t::get() { - static add_op_t obj; - return &obj; -} - -std::vector add_op_t::native(xed_inst_t* inst, std::size_t imm) { - auto op = xed_inst_operand(inst, 0); - auto reg = xed_operand_reg(op); - return {}; -} -} // namespace theo::comp::obf::transform \ No newline at end of file diff --git a/src/theo/obf/transform/sub_op.cpp b/src/theo/obf/transform/sub_op.cpp deleted file mode 100644 index e69de29..0000000