Theodosius v3.0
Jit linker, symbol mapper, and obfuscator
next_inst_pass.cpp
Go to the documentation of this file.
1// Copyright (c) 2022, _xeroxz
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9//
10// 2. Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13//
14// 3. Neither the name of the copyright holder nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28// POSSIBILITY OF SUCH DAMAGE.
29//
30
32
33namespace theo::obf {
35 static next_inst_pass_t obj;
36 return &obj;
37}
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}
93
94std::optional<recomp::reloc_t*> next_inst_pass_t::has_next_inst_reloc(
95 decomp::symbol_t* sym) {
96 auto res = std::find_if(
97 sym->relocs().begin(), sym->relocs().end(),
98 [&](recomp::reloc_t& reloc) -> bool { return !reloc.offset(); });
99
100 return res != sym->relocs().end() ? &(*res)
101 : std::optional<recomp::reloc_t*>();
102}
103} // namespace theo::obf