about half way done with transformations... imm's cant be 8 bytes, only

4...
3.0
_xeroxz 3 years ago
parent 78f2b39b71
commit 9199d5bef7

@ -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"

@ -1,5 +1,7 @@
#pragma once
#include <obf/pass.hpp>
#include <obf/transform/operation.hpp>
#include <obf/transform/transform.hpp>
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<recomp::reloc_t*> has_legit_reloc(decomp::symbol_t* sym);
};
} // namespace theo::comp::obf
} // namespace theo::obf

@ -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<std::uint8_t> 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

@ -1,6 +1,8 @@
#pragma once
#include <spdlog/spdlog.h>
#include <functional>
#include <map>
#include <random>
#define XED_ENCODER
extern "C" {
@ -13,24 +15,56 @@ using transform_t = std::function<std::size_t(std::size_t, std::size_t)>;
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<std::uint8_t> native(xed_inst_t* inst,
std::size_t imm) = 0;
std::vector<std::uint8_t> 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<std::uint8_t>(inst_buff, inst_buff + inst_len);
}
type_t inverse() { return m_inverse_op[m_type]; }
transform_t get_transform() { return m_transform; }
xed_iclass_enum_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<std::size_t> distr(lowest, largest);
return distr(gen);
}
private:
transform_t m_transform;
type_t m_type;
xed_iclass_enum_t m_type;
std::map<type_t, type_t> 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<xed_iclass_enum_t, xed_iclass_enum_t> 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

@ -0,0 +1,17 @@
#pragma once
#include <obf/transform/operation.hpp>
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

@ -1,9 +1,10 @@
#pragma once
#include <comp/obf/transform/add_op.hpp>
#include <comp/obf/transform/operation.hpp>
#include <comp/obf/transform/sub_op.hpp>
#include <obf/transform/add_op.hpp>
#include <obf/transform/operation.hpp>
#include <obf/transform/sub_op.hpp>
namespace theo::comp::obf::transform {
std::map<operation_t::type_t, operation_t*> operations = {
{operation_t::type_t::add_op, add_op_t::get()}};
namespace theo::obf::transform {
inline std::map<xed_iclass_enum_t, operation_t*> operations = {
{XED_ICLASS_ADD, add_op_t::get()},
{XED_ICLASS_SUB, sub_op_t::get()}};
}

@ -1,6 +1,7 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <obf/transform/transform.hpp>
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<obf::transform::transform_t*, std::size_t> entry) {
m_transforms.push_back(entry);
}
std::vector<std::pair<obf::transform::transform_t*, std::size_t>>&
get_transforms() {
return m_transforms;
}
private:
std::vector<std::pair<obf::transform::transform_t*, std::size_t>>
m_transforms;
std::string m_sym_name;
std::size_t m_hash;
std::uint16_t m_offset;
};
} // namespace theo::comp
} // namespace theo::recomp

@ -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<recomp::reloc_t*> 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<std::size_t>::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<recomp::reloc_t*> 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<recomp::reloc_t*>();
}
} // namespace theo::obf

@ -1,14 +0,0 @@
#include <obf/transform/add_op.hpp>
namespace theo::obf::transform {
add_op_t* add_op_t::get() {
static add_op_t obj;
return &obj;
}
std::vector<std::uint8_t> 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
Loading…
Cancel
Save