Theodosius  v3.0
Jit linker, mapper, obfuscator, and mutator
recomp.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 
31 #include <recomp/recomp.hpp>
32 
33 namespace theo::recomp {
35  allocator_t alloc,
36  copier_t copy,
37  resolver_t resolve)
38  : m_dcmp(dcmp), m_allocator(alloc), m_copier(copy), m_resolver(resolve) {}
39 
41  // map code & data/rdata/bss sections first...
42  //
43  m_dcmp->syms()->for_each([&](theo::decomp::symbol_t& sym) {
44  switch (sym.type()) {
45  case decomp::sym_type_t::section:
46  case decomp::sym_type_t::function:
47  case decomp::sym_type_t::instruction: {
48  sym.allocated_at(m_allocator(sym.size(), sym.scn()->characteristics));
49  break;
50  }
51  default:
52  break;
53  }
54  });
55 
56  // then map data/rdata/bss symbols to the allocated sections...
57  //
58  m_dcmp->syms()->for_each([&](theo::decomp::symbol_t& sym) {
59  if (sym.type() == decomp::sym_type_t::data) {
60  // if the symbol has a section then we will refer to the allocation made
61  // for that section...
62  //
63  if (sym.scn()) {
64  auto scn_sym =
65  m_dcmp->syms()->sym_from_hash(m_dcmp->scn_hash_tbl()[sym.scn()]);
66 
67  if (!scn_sym.has_value()) {
68  spdlog::error("failed to locate section: {} for symbol: {}",
69  sym.scn()->name.to_string(), sym.name());
70 
71  assert(scn_sym.has_value());
72  }
73 
74  sym.allocated_at(scn_sym.value()->allocated_at() + sym.offset());
75  } else { // else if there is no section then we allocate based upon the
76  // size of the symbol... this is only done for symbols that are
77  // bss...
78  //
79 
80  // bss is read write...
81  //
82  coff::section_characteristics_t prot = {};
83  prot.mem_read = true;
84  prot.mem_write = true;
85 
86  sym.allocated_at(m_allocator(sym.size(), sym.scn()->characteristics));
87  }
88  }
89  });
90 }
91 
92 void recomp_t::resolve() {
93  // resolve relocations in all symbols...
94  //
95  m_dcmp->syms()->for_each([&](theo::decomp::symbol_t& sym) {
96  auto& relocs = sym.relocs();
97  std::for_each(relocs.begin(), relocs.end(), [&](reloc_t& reloc) {
98  if (reloc.offset() > sym.data().size()) {
99  spdlog::error(
100  "invalid relocation... writing outside of symbol length... offset: "
101  "{} sym size: {}",
102  sym.offset(), sym.data().size());
103 
104  assert(reloc.offset() > sym.data().size());
105  }
106 
107  // try and resolve the symbol by refering to the internal symbol table
108  // first... if there is no symbol then refer to the resolver...
109  //
110  auto reloc_sym = m_dcmp->syms()->sym_from_hash(reloc.hash());
111  auto allocated_at = reloc_sym.has_value()
112  ? reloc_sym.value()->allocated_at()
113  : m_resolver(reloc.name());
114 
115  if (!allocated_at) {
116  spdlog::error("failed to resolve reloc from symbol: {} to symbol: {}",
117  sym.name(), reloc.name());
118 
119  assert(allocated_at);
120  }
121 
122  switch (sym.type()) {
124  auto scn_sym =
125  m_dcmp->syms()->sym_from_hash(m_dcmp->scn_hash_tbl()[sym.scn()]);
126 
127  *reinterpret_cast<std::uintptr_t*>(scn_sym.value()->data().data() +
128  reloc.offset()) = allocated_at;
129  break;
130  }
132  *reinterpret_cast<std::uintptr_t*>(sym.data().data() +
133  reloc.offset()) = allocated_at;
134  break;
135  }
137  auto& transforms = reloc.get_transforms();
138  std::for_each(
139  transforms.begin(), transforms.end(),
140  [&](std::pair<obf::transform::transform_t*, std::uint32_t>& t) {
141  allocated_at = (*t.first)(allocated_at, t.second);
142  });
143 
144  *reinterpret_cast<std::uintptr_t*>(sym.data().data() +
145  reloc.offset()) = allocated_at;
146  break;
147  }
148  default:
149  break;
150  }
151  });
152  });
153 }
154 
155 void recomp_t::copy_syms() {
156  // copy symbols into memory using the copier supplied...
157  //
158  m_dcmp->syms()->for_each([&](theo::decomp::symbol_t& sym) {
159  m_copier(sym.allocated_at(), sym.data().data(), sym.data().size());
160  });
161 }
162 
163 void recomp_t::allocator(allocator_t alloc) {
164  m_allocator = alloc;
165 }
166 
167 void recomp_t::copier(copier_t copy) {
168  m_copier = copy;
169 }
170 
171 void recomp_t::resolver(resolver_t resolve) {
172  m_resolver = resolve;
173 }
174 
175 std::uintptr_t recomp_t::resolve(const std::string&& sym) {
176  auto res = m_dcmp->syms()->sym_from_hash(decomp::symbol_t::hash(sym));
177  return res.has_value() ? res.value()->allocated_at() : 0;
178 }
179 } // namespace theo::recomp
the main decomposition class which is responsible for breaking down lib file into coff files,...
Definition: decomp.hpp:61
recomp::symbol_table_t * syms()
gets the symbol table.
Definition: decomp.cpp:293
symbol_t is an abstraction upon the coff symbol. this allows for easier manipulation of the symbol....
Definition: symbol.hpp:53
sym_type_t type() const
returns the type of the symbol.
Definition: symbol.cpp:80
coff::section_header_t * scn() const
gets the section header of the section in which the symbol is contained.
Definition: symbol.cpp:64
std::string name() const
gets the name of the symbol.
Definition: symbol.cpp:52
std::size_t hash()
gets the hash of the symbol name.
Definition: symbol.cpp:88
std::vector< std::uint8_t > & data()
returns a vector by reference of bytes containing the data of the symbol.
Definition: symbol.cpp:76
std::vector< recomp::reloc_t > & relocs()
returns a vector of relocations.
Definition: symbol.cpp:96
std::uint32_t size() const
returns the size of the symbol.
Definition: symbol.cpp:72
std::uintptr_t allocated_at() const
returns the address where the symbol is allocated.
Definition: symbol.cpp:60
void allocate()
when called, this function allocates space for every symbol.
Definition: recomp.cpp:40
recomp_t(decomp::decomp_t *dcmp, allocator_t alloc, copier_t copy, resolver_t resolve)
the explicit constructor for the recomp_t class.
Definition: recomp.cpp:34
meta data about a relocation for a symbol
Definition: reloc.hpp:41
std::uint32_t offset()
returns the offset into the symbol to which the relocation will be applied. the offset is in bytes....
Definition: reloc.hpp:75
std::string name()
returns the name of the relocation symbol.
Definition: reloc.hpp:67
std::size_t hash()
returns the hash of the relocation symbol.
Definition: reloc.hpp:61
std::vector< std::pair< obf::transform::transform_t *, std::uint32_t > > & get_transforms()
gets the vector of transformation.
Definition: reloc.hpp:101
void for_each(std::function< void(decomp::symbol_t &sym)> fn)
this function is a wrapper function that allows you to get at each entry in the symbol table by refer...
this namespace encompasses all recomposition related code.
Definition: recomp.hpp:39
std::function< void(std::uintptr_t, void *, std::uint32_t)> copier_t
a function which is called by recomp_t to copy symbols into memory.
Definition: recomp.hpp:49
std::function< std::uintptr_t(std::string)> resolver_t
a function which is called by recomp_t to resolve external symbols
Definition: recomp.hpp:44
std::function< std::uintptr_t(std::uint32_t, coff::section_characteristics_t)> allocator_t
a function which is called to allocate space for a symbol.
Definition: recomp.hpp:59