Theodosius v3.0
Jit linker, symbol mapper, and obfuscator
Public Member Functions | Static Public Member Functions
theo::obf::next_inst_pass_t Class Reference

This pass is used to generate transformations and jmp code to change RIP to the next instruction. More...

#include "next_inst_pass.hpp"

Inheritance diagram for theo::obf::next_inst_pass_t:
theo::obf::pass_t

Public Member Functions

void run (decomp::symbol_t *sym)
 virtual method which must be implimented by the pass that inherits this class. More...
 
- Public Member Functions inherited from theo::obf::pass_t
 pass_t (decomp::sym_type_t sym_type)
 the explicit constructor of the pass_t base class. More...
 
virtual void run (decomp::symbol_t *sym)=0
 virtual method which must be implimented by the pass that inherits this class. More...
 
decomp::sym_type_t sym_type ()
 gets the passes symbol type. More...
 

Static Public Member Functions

static next_inst_pass_tget ()
 

Detailed Description

This pass is used to generate transformations and jmp code to change RIP to the next instruction.

given the following code (get pml4 address from cr3):

get_pml4: 0: 48 c7 c0 ff 0f 00 00 mov rax,0xfff 7: 48 f7 d0 not rax a: 0f 20 da mov rdx,cr3 d: 48 21 c2 and rdx,rax 10: b1 00 mov cl,0x0 12: 48 d3 e2 shl rdx,cl 15: 48 89 d0 mov rax,rdx 18: c3 ret

this pass will break up each instruction so that it can be anywhere in a linear virtual address space. this pass will not work on rip relative code, however clang will not generate such code when compiled with "-mcmodel=large"

get_pml4@0: mov rax, 0xFFF push [next_inst_addr_enc] xor [rsp], 0x3243342 ; a random number of transformations here... ret next_inst_addr_enc: ; encrypted address of the next instruction goes here.

get_pml4@7: not rax push [next_inst_addr_enc] xor [rsp], 0x93983498 ; a random number of transformations here... ret next_inst_addr_enc: ; encrypted address of the next instruction goes here.

this process is continued for each instruction in the function. the last instruction "ret" will have no code generated for it as there is no next instruction.

this pass also only runs at the instruction level, theodosius internally breaks up functions inside of the ".split" section into individual instruction symbols. this process also creates a psuedo relocation which simply tells this pass that there needs to be a relocation to the next symbol. the offset for these psuedo relocations is zero.

Definition at line 85 of file next_inst_pass.hpp.

Member Function Documentation

◆ get()

next_inst_pass_t * theo::obf::next_inst_pass_t::get ( )
static

Definition at line 34 of file next_inst_pass.cpp.

34 {
35 static next_inst_pass_t obj;
36 return &obj;
37}

Referenced by main(), and theo::obf::jcc_rewrite_pass_t::run().

◆ run()

void theo::obf::next_inst_pass_t::run ( decomp::symbol_t sym)
virtual

virtual method which must be implimented by the pass that inherits this class.

Parameters
syma symbol of the same type of m_sym_type.

Implements theo::obf::pass_t.

Definition at line 38 of file next_inst_pass.cpp.

38 {
39 std::optional<recomp::reloc_t*> reloc;
40 if (!(reloc = has_next_inst_reloc(sym)).has_value())
41 return;
42
43 xed_decoded_inst_t inst = m_tmp_inst;
44 std::vector<std::uint8_t> new_inst_bytes =
45 transform::generate(&inst, reloc.value(), 3, 6);
46
47 // add a push [rip+offset] and update reloc->offset()...
48 //
49 std::uint32_t inst_len = {};
50 std::uint8_t inst_buff[XED_MAX_INSTRUCTION_BYTES];
51
52 xed_error_enum_t err;
53 xed_encoder_request_t req;
54 xed_state_t istate{XED_MACHINE_MODE_LONG_64, XED_ADDRESS_WIDTH_64b};
55
56 xed_encoder_request_zero_set_mode(&req, &istate);
57 xed_encoder_request_set_effective_operand_width(&req, 64);
58 xed_encoder_request_set_iclass(&req, XED_ICLASS_PUSH);
59
60 xed_encoder_request_set_mem0(&req);
61 xed_encoder_request_set_operand_order(&req, 0, XED_OPERAND_MEM0);
62
63 xed_encoder_request_set_base0(&req, XED_REG_RIP);
64 xed_encoder_request_set_seg0(&req, XED_REG_INVALID);
65 xed_encoder_request_set_index(&req, XED_REG_INVALID);
66 xed_encoder_request_set_scale(&req, 0);
67
68 xed_encoder_request_set_memory_operand_length(&req, 8);
69 xed_encoder_request_set_memory_displacement(&req, new_inst_bytes.size() + 1,
70 1);
71
72 if ((err = xed_encode(&req, inst_buff, sizeof(inst_buff), &inst_len)) !=
73 XED_ERROR_NONE) {
74 spdlog::info("failed to encode instruction... reason: {}",
75 xed_error_enum_t2str(err));
76
77 assert(err == XED_ERROR_NONE);
78 }
79
80 new_inst_bytes.insert(new_inst_bytes.begin(), inst_buff,
81 inst_buff + inst_len);
82
83 // put a return instruction at the end of the decrypt instructions...
84 //
85 new_inst_bytes.push_back(0xC3);
86
87 sym->data().insert(sym->data().end(), new_inst_bytes.begin(),
88 new_inst_bytes.end());
89
90 reloc.value()->offset(sym->data().size());
91 sym->data().resize(sym->data().size() + 8);
92}

References theo::decomp::symbol_t::data(), and theo::obf::transform::generate().

Referenced by theo::obf::jcc_rewrite_pass_t::run().


The documentation for this class was generated from the following files: