created a pass system... starting to code transformation system for

relocations...
3.0
_xeroxz 3 years ago
parent c666bf8dbe
commit 9cf6cc8f03

@ -55,22 +55,33 @@ set(Theodosius_SOURCES "")
list(APPEND Theodosius_SOURCES list(APPEND Theodosius_SOURCES
"include/comp/comp.hpp" "include/comp/comp.hpp"
"include/comp/obf.hpp" "include/comp/obf/engine.hpp"
"include/comp/obf/pass.hpp"
"include/comp/obf/passes/jcc_rewrite_pass.hpp"
"include/comp/obf/passes/next_inst_pass.hpp"
"include/comp/obf/passes/reloc_transform_pass.hpp"
"include/comp/obf/transform/add_op.hpp"
"include/comp/obf/transform/and_op.hpp"
"include/comp/obf/transform/operation.hpp"
"include/comp/obf/transform/or_op.hpp"
"include/comp/obf/transform/rol_op.hpp"
"include/comp/obf/transform/ror_op.hpp"
"include/comp/obf/transform/sub_op.hpp"
"include/comp/obf/transform/transform.hpp"
"include/comp/obf/transform/xor_op.hpp"
"include/comp/reloc.hpp" "include/comp/reloc.hpp"
"include/comp/symbol_table.hpp" "include/comp/symbol_table.hpp"
"include/comp/transform/add_op.hpp"
"include/comp/transform/and_op.hpp"
"include/comp/transform/operation.hpp"
"include/comp/transform/or_op.hpp"
"include/comp/transform/rol_op.hpp"
"include/comp/transform/ror_op.hpp"
"include/comp/transform/sub_op.hpp"
"include/comp/transform/xor_op.hpp"
"include/decomp/decomp.hpp" "include/decomp/decomp.hpp"
"include/decomp/routine.hpp" "include/decomp/routine.hpp"
"include/decomp/symbol.hpp" "include/decomp/symbol.hpp"
"include/theo.hpp" "include/theo.hpp"
"src/theo/comp/comp.cpp" "src/theo/comp/comp.cpp"
"src/theo/comp/obf/engine.cpp"
"src/theo/comp/obf/passes/jcc_rewrite_pass.cpp"
"src/theo/comp/obf/passes/next_inst_pass.cpp"
"src/theo/comp/obf/passes/reloc_transform_pass.cpp"
"src/theo/comp/obf/transform/add_op.cpp"
"src/theo/comp/obf/transform/sub_op.cpp"
"src/theo/comp/symbol_table.cpp" "src/theo/comp/symbol_table.cpp"
"src/theo/decomp/decomp.cpp" "src/theo/decomp/decomp.cpp"
"src/theo/decomp/routine.cpp" "src/theo/decomp/routine.cpp"

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <comp/obf/engine.hpp>
#include <comp/symbol_table.hpp> #include <comp/symbol_table.hpp>
#include <decomp/decomp.hpp> #include <decomp/decomp.hpp>

@ -0,0 +1,18 @@
#pragma once
#include <algorithm>
#include <comp/obf/pass.hpp>
#include <vector>
namespace theo::comp::obf {
class engine_t {
explicit engine_t(){};
public:
static engine_t* get();
void add_pass(pass_t* pass);
void run(decomp::symbol_t* sym);
private:
std::vector<pass_t*> passes;
};
} // namespace theo::comp::obf

@ -0,0 +1,21 @@
#pragma once
#include <spdlog/spdlog.h>
#include <decomp/symbol.hpp>
#define XED_ENCODER
extern "C" {
#include <xed-decode.h>
#include <xed-interface.h>
}
namespace theo::comp::obf {
class pass_t {
public:
explicit pass_t(decomp::sym_type_t sym_type) : m_sym_type(sym_type){};
virtual void run(decomp::symbol_t* sym) = 0;
decomp::sym_type_t sym_type() { return m_sym_type; }
private:
decomp::sym_type_t m_sym_type;
};
} // namespace theo::comp::obf

@ -0,0 +1,16 @@
#pragma once
#include <comp/obf/pass.hpp>
namespace theo::comp::obf {
class jcc_rewrite_pass_t : public pass_t {
explicit jcc_rewrite_pass_t() : pass_t(decomp::sym_type_t::inst_split){};
public:
static jcc_rewrite_pass_t* get() {
static jcc_rewrite_pass_t obj;
return &obj;
}
void run(decomp::symbol_t* sym){};
};
} // namespace theo::comp::obf

@ -0,0 +1,16 @@
#pragma once
#include <comp/obf/pass.hpp>
namespace theo::comp::obf {
class next_inst_pass_t : public pass_t {
explicit next_inst_pass_t() : pass_t(decomp::sym_type_t::inst_split){};
public:
static next_inst_pass_t* get() {
static next_inst_pass_t obj;
return &obj;
}
void run(decomp::symbol_t* sym){};
};
} // namespace theo::comp::obf

@ -0,0 +1,15 @@
#pragma once
#include <comp/obf/pass.hpp>
namespace theo::comp::obf {
class reloc_transform_pass_t : public pass_t {
explicit reloc_transform_pass_t() : pass_t(decomp::sym_type_t::inst_split){};
public:
static reloc_transform_pass_t* get();
void run(decomp::symbol_t* sym);
private:
bool has_legit_reloc(decomp::symbol_t* sym);
};
} // namespace theo::comp::obf

@ -0,0 +1,15 @@
#pragma once
#include <comp/obf/transform/operation.hpp>
namespace theo::comp::obf::transform {
class add_op_t : 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) {}
public:
static add_op_t* get();
std::vector<std::uint8_t> native(xed_inst_t* inst, std::size_t imm);
};
} // namespace theo::comp::obf::transform

@ -0,0 +1,36 @@
#pragma once
#include <functional>
#include <map>
#define XED_ENCODER
extern "C" {
#include <xed-decode.h>
#include <xed-interface.h>
}
namespace theo::comp::obf::transform {
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)
: m_transform(op), m_type(type) {}
virtual std::vector<std::uint8_t> native(xed_inst_t* inst,
std::size_t imm) = 0;
type_t inverse() { return m_inverse_op[m_type]; }
transform_t get_transform() { return m_transform; }
private:
transform_t m_transform;
type_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}};
};
} // namespace theo::comp::obf::transform

@ -0,0 +1,8 @@
#pragma once
#include <comp/obf/transform/add_op.hpp>
#include <comp/obf/transform/operation.hpp>
#include <comp/obf/transform/sub_op.hpp>
namespace theo::comp::obf::transform {
std::map<operation_t::type_t, operation_t*> operations;
}

@ -25,7 +25,7 @@ class symbol_t {
coff::section_header_t* scn() const; coff::section_header_t* scn() const;
std::vector<std::uint8_t>& data(); std::vector<std::uint8_t>& data();
coff::symbol_t* sym() const; coff::symbol_t* sym() const;
sym_type_t sym_type() const; sym_type_t type() const;
std::vector<comp::reloc_t>& relocs(); std::vector<comp::reloc_t>& relocs();
void allocated_at(std::uintptr_t allocated_at); void allocated_at(std::uintptr_t allocated_at);

@ -1,8 +1,13 @@
#pragma once #pragma once
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <comp/comp.hpp> #include <comp/comp.hpp>
#include <comp/obf/engine.hpp>
#include <decomp/decomp.hpp> #include <decomp/decomp.hpp>
#include <comp/obf/passes/reloc_transform_pass.hpp>
#include <comp/obf/passes/next_inst_pass.hpp>
#include <comp/obf/passes/jcc_rewrite_pass.hpp>
#include <optional> #include <optional>
#include <tuple> #include <tuple>
#include <vector> #include <vector>

@ -1,9 +1,9 @@
#define OBF __declspec(code_seg(".obf")) #define OBF __declspec(code_seg(".obf"))
extern "C" int MessageBoxA(void* hWnd, extern "C" int MessageBoxA(void* hWnd,
char* lpText, char* lpText,
char* lpCaption, char* lpCaption,
void* uType); void* uType);
struct test_t { struct test_t {
char buff[0x2000]; char buff[0x2000];
@ -14,6 +14,10 @@ test_t t = {};
OBF extern "C" void EntryPoint() { OBF extern "C" void EntryPoint() {
t.buff[0] = 1; t.buff[0] = 1;
t.buff[1] = 2; t.buff[1] = 2;
MessageBoxA(nullptr, "Hello World", "Hello World", nullptr);
MessageBoxA(nullptr, "Hello World 1", "Hello World 1", nullptr); if (t.buff[0])
MessageBoxA(nullptr, "Hello World", "Hello World", nullptr);
if (t.buff[1])
MessageBoxA(nullptr, "Hello World 1", "Hello World 1", nullptr);
} }

@ -12,16 +12,11 @@ void comp_t::allocate() {
// map code & data/rdata/bss sections first... // map code & data/rdata/bss sections first...
// //
m_dcmp->syms()->for_each([&](theo::decomp::symbol_t& sym) { m_dcmp->syms()->for_each([&](theo::decomp::symbol_t& sym) {
switch (sym.sym_type()) { switch (sym.type()) {
case decomp::sym_type_t::section: case decomp::sym_type_t::section:
case decomp::sym_type_t::function: { case decomp::sym_type_t::function:
sym.allocated_at(m_allocator(sym.size(), sym.scn()->characteristics));
break;
}
case decomp::sym_type_t::inst_split: { case decomp::sym_type_t::inst_split: {
// TODO: call into reloc_t static methods to generate random code to sym.allocated_at(m_allocator(sym.size(), sym.scn()->characteristics));
// obfuscate relocations...
//
break; break;
} }
default: default:
@ -32,7 +27,7 @@ void comp_t::allocate() {
// then map data/rdata/bss symbols to the allocated sections... // then map data/rdata/bss symbols to the allocated sections...
// //
m_dcmp->syms()->for_each([&](theo::decomp::symbol_t& sym) { m_dcmp->syms()->for_each([&](theo::decomp::symbol_t& sym) {
if (sym.sym_type() == decomp::sym_type_t::data) { if (sym.type() == decomp::sym_type_t::data) {
// if the symbol has a section then we will refer to the allocation made // if the symbol has a section then we will refer to the allocation made
// for that section... // for that section...
// //
@ -59,7 +54,7 @@ void comp_t::allocate() {
prot.mem_read = true; prot.mem_read = true;
prot.mem_write = true; prot.mem_write = true;
sym.allocated_at(m_allocator(sym.size(), prot)); sym.allocated_at(m_allocator(sym.size(), sym.scn()->characteristics));
} }
} }
}); });
@ -94,7 +89,7 @@ void comp_t::resolve() {
assert(allocated_at); assert(allocated_at);
} }
switch (sym.sym_type()) { switch (sym.type()) {
case decomp::sym_type_t::function: { case decomp::sym_type_t::function: {
*reinterpret_cast<std::uintptr_t*>(sym.data().data() + *reinterpret_cast<std::uintptr_t*>(sym.data().data() +
reloc.offset()) = allocated_at; reloc.offset()) = allocated_at;

@ -0,0 +1,20 @@
#include <comp/obf/engine.hpp>
namespace theo::comp::obf {
engine_t* engine_t::get() {
static engine_t obj;
return &obj;
}
void engine_t::add_pass(pass_t* pass) {
passes.push_back(pass);
}
void engine_t::run(decomp::symbol_t* sym) {
std::for_each(passes.begin(), passes.end(), [&](pass_t* pass) {
if (sym->type() == pass->sym_type())
pass->run(sym);
});
}
} // namespace theo::comp::obf

@ -0,0 +1,39 @@
#include <comp/obf/passes/reloc_transform_pass.hpp>
namespace theo::comp::obf {
reloc_transform_pass_t* reloc_transform_pass_t::get() {
static reloc_transform_pass_t obj;
return &obj;
}
void reloc_transform_pass_t::run(decomp::symbol_t* sym) {
if (!has_legit_reloc(sym))
return;
spdlog::info("adding transformations to relocation in symbol: {}",
sym->name());
xed_error_enum_t err;
xed_decoded_inst_t inst;
xed_state_t istate{XED_MACHINE_MODE_LONG_64, XED_ADDRESS_WIDTH_64b};
xed_decoded_inst_zero_set_mode(&inst, &istate);
if ((err = xed_decode(&inst, sym->data().data(), sym->data().size())) !=
XED_ERROR_NONE) {
spdlog::error("failed to decode instruction, reason: {} in symbol: {}",
xed_error_enum_t2str(err), sym->name());
assert(err == XED_ERROR_NONE);
}
};
bool 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...
std::find_if(sym->relocs().begin(), sym->relocs().end(),
[&](reloc_t& reloc) -> bool { return reloc.offset(); });
return res != sym->relocs().end();
}
} // namespace theo::comp::obf

@ -0,0 +1,14 @@
#include <comp/obf/transform/add_op.hpp>
namespace theo::comp::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

@ -35,7 +35,7 @@ std::optional<comp::symbol_table_t*> decomp_t::decompose() {
.append("!") .append("!")
.append(std::to_string(img->file_header.timedate_stamp)); .append(std::to_string(img->file_header.timedate_stamp));
// hash the name of the section + the index + thhe timestamp of the obj // hash the name of the section + the index + the timestamp of the obj
// file it is in... // file it is in...
// //
m_scn_hash_tbl.insert({scn, decomp::symbol_t::hash(scn_sym_name)}); m_scn_hash_tbl.insert({scn, decomp::symbol_t::hash(scn_sym_name)});
@ -122,12 +122,7 @@ std::optional<comp::symbol_table_t*> decomp_t::decompose() {
// the linker to allocate space for // the linker to allocate space for
// them... // them...
// the data is init to all zeros...
//
std::vector<std::uint8_t> data(sym->value, 0); std::vector<std::uint8_t> data(sym->value, 0);
// the symbol is data, it has no section...
//
decomp::symbol_t bss_sym(sym->name.to_string(img->get_strings()).data(), decomp::symbol_t bss_sym(sym->name.to_string(img->get_strings()).data(),
{}, data, {}, sym, {}, sym_type_t::data); {}, data, {}, sym, {}, sym_type_t::data);

@ -41,7 +41,7 @@ std::vector<std::uint8_t>& symbol_t::data() {
return m_data; return m_data;
} }
sym_type_t symbol_t::sym_type() const { sym_type_t symbol_t::type() const {
return m_sym_type; return m_sym_type;
} }

@ -3,11 +3,20 @@
namespace theo { namespace theo {
theo_t::theo_t(std::vector<std::uint8_t>& lib, lnk_fns_t lnkr_fns) theo_t::theo_t(std::vector<std::uint8_t>& lib, lnk_fns_t lnkr_fns)
: m_dcmp(lib, &m_sym_tbl), m_cmp(&m_dcmp) { : m_dcmp(lib, &m_sym_tbl), m_cmp(&m_dcmp) {
// init enc/dec tables only once... // init enc/dec tables only once... add obfuscation passes to the engine...
// //
if (static std::atomic_bool v = true; v.exchange(false)) if (static std::atomic_bool v = true; v.exchange(false)) {
xed_tables_init(); xed_tables_init();
// order matters, the order in which the pass is added is the order they
// will be executed!
//
auto engine = comp::obf::engine_t::get();
engine->add_pass(comp::obf::reloc_transform_pass_t::get());
engine->add_pass(comp::obf::next_inst_pass_t::get());
engine->add_pass(comp::obf::jcc_rewrite_pass_t::get());
}
m_cmp.allocator(std::get<0>(lnkr_fns)); m_cmp.allocator(std::get<0>(lnkr_fns));
m_cmp.copier(std::get<1>(lnkr_fns)); m_cmp.copier(std::get<1>(lnkr_fns));
m_cmp.resolver(std::get<2>(lnkr_fns)); m_cmp.resolver(std::get<2>(lnkr_fns));
@ -28,6 +37,11 @@ std::optional<std::uint32_t> theo_t::decompose() {
} }
std::uintptr_t theo_t::compose(const std::string&& entry_sym) { std::uintptr_t theo_t::compose(const std::string&& entry_sym) {
// run obfuscation engine on all symbols...
//
auto engine = comp::obf::engine_t::get();
m_sym_tbl.for_each([&](decomp::symbol_t& sym) { engine->run(&sym); });
m_cmp.allocate(); m_cmp.allocate();
m_cmp.resolve(); m_cmp.resolve();
m_cmp.copy_syms(); m_cmp.copy_syms();

Loading…
Cancel
Save