reloc_transform_pass are all done....3.0
parent
df0ba19093
commit
c7eb3c83bf
@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include <obf/transform/operation.hpp>
|
||||
|
||||
namespace theo::obf::transform {
|
||||
class and_op_t : public operation_t {
|
||||
explicit and_op_t()
|
||||
: operation_t([&](std::size_t val,
|
||||
std::uint32_t imm) -> std::size_t { return val & imm; },
|
||||
XED_ICLASS_AND) {}
|
||||
|
||||
public:
|
||||
static and_op_t* get() {
|
||||
static and_op_t obj;
|
||||
return &obj;
|
||||
}
|
||||
};
|
||||
} // namespace theo::obf::transform
|
@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include <obf/transform/operation.hpp>
|
||||
|
||||
namespace theo::obf::transform {
|
||||
class or_op_t : public operation_t {
|
||||
explicit or_op_t()
|
||||
: operation_t([&](std::size_t val,
|
||||
std::uint32_t imm) -> std::size_t { return val | imm; },
|
||||
XED_ICLASS_OR) {}
|
||||
|
||||
public:
|
||||
static or_op_t* get() {
|
||||
static or_op_t obj;
|
||||
return &obj;
|
||||
}
|
||||
};
|
||||
} // namespace theo::obf::transform
|
@ -0,0 +1,53 @@
|
||||
#include <obf/passes/jcc_rewrite_pass.hpp>
|
||||
#include <obf/passes/next_inst_pass.hpp>
|
||||
|
||||
namespace theo::obf {
|
||||
jcc_rewrite_pass_t* jcc_rewrite_pass_t::get() {
|
||||
static jcc_rewrite_pass_t obj;
|
||||
return &obj;
|
||||
}
|
||||
|
||||
void jcc_rewrite_pass_t::run(decomp::symbol_t* sym) {
|
||||
std::int32_t disp = {};
|
||||
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);
|
||||
xed_decode(&inst, sym->data().data(), XED_MAX_INSTRUCTION_BYTES);
|
||||
|
||||
// if the instruction is branching...
|
||||
if ((disp = xed_decoded_inst_get_branch_displacement(&inst))) {
|
||||
disp += xed_decoded_inst_get_length(&inst);
|
||||
|
||||
// update displacement...
|
||||
xed_decoded_inst_set_branch_displacement(
|
||||
&inst, sym->data().size() - xed_decoded_inst_get_length(&inst),
|
||||
xed_decoded_inst_get_branch_displacement_width(&inst));
|
||||
|
||||
xed_encoder_request_init_from_decode(&inst);
|
||||
xed_encoder_request_t* req = &inst;
|
||||
|
||||
// update jcc in the buffer...
|
||||
std::uint32_t len = {};
|
||||
xed_encode(req, sym->data().data(), xed_decoded_inst_get_length(&inst),
|
||||
&len);
|
||||
|
||||
// create a relocation to the instruction the branch would normally go
|
||||
// too...
|
||||
auto offset = disp < 0 ? sym->offset() - std::abs(disp)
|
||||
: sym->offset() + std::abs(disp);
|
||||
|
||||
auto sym_name =
|
||||
std::string(
|
||||
sym->sym()->name.to_string(sym->img()->get_strings()).data())
|
||||
.append("@")
|
||||
.append(std::to_string(offset));
|
||||
|
||||
sym->relocs().push_back(
|
||||
recomp::reloc_t(0, decomp::symbol_t::hash(sym_name), sym_name.data()));
|
||||
|
||||
// run next_inst_pass on this symbol to generate the transformations for the
|
||||
// relocation to the jcc branch dest instruction...
|
||||
next_inst_pass_t::get()->run(sym);
|
||||
}
|
||||
};
|
||||
} // namespace theo::obf
|
@ -0,0 +1,73 @@
|
||||
#include <obf/passes/next_inst_pass.hpp>
|
||||
|
||||
namespace theo::obf {
|
||||
next_inst_pass_t* next_inst_pass_t::get() {
|
||||
static next_inst_pass_t obj;
|
||||
return &obj;
|
||||
}
|
||||
void next_inst_pass_t::run(decomp::symbol_t* sym) {
|
||||
std::optional<recomp::reloc_t*> reloc;
|
||||
if (!(reloc = has_next_inst_reloc(sym)).has_value())
|
||||
return;
|
||||
|
||||
xed_decoded_inst_t inst = m_tmp_inst;
|
||||
std::vector<std::uint8_t> new_inst_bytes =
|
||||
generate_transforms(&inst, reloc.value(), 3, 6);
|
||||
|
||||
// add a push [rip+offset] and update reloc->offset()...
|
||||
//
|
||||
std::uint32_t inst_len = {};
|
||||
std::uint8_t inst_buff[XED_MAX_INSTRUCTION_BYTES];
|
||||
|
||||
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, XED_ICLASS_PUSH);
|
||||
|
||||
xed_encoder_request_set_mem0(&req);
|
||||
xed_encoder_request_set_operand_order(&req, 0, XED_OPERAND_MEM0);
|
||||
|
||||
xed_encoder_request_set_base0(&req, XED_REG_RIP);
|
||||
xed_encoder_request_set_seg0(&req, XED_REG_INVALID);
|
||||
xed_encoder_request_set_index(&req, XED_REG_INVALID);
|
||||
xed_encoder_request_set_scale(&req, 0);
|
||||
|
||||
xed_encoder_request_set_memory_operand_length(&req, 8);
|
||||
xed_encoder_request_set_memory_displacement(&req, new_inst_bytes.size() + 1,
|
||||
1);
|
||||
|
||||
if ((err = xed_encode(&req, inst_buff, sizeof(inst_buff), &inst_len)) !=
|
||||
XED_ERROR_NONE) {
|
||||
spdlog::info("failed to encode instruction... reason: {}",
|
||||
xed_error_enum_t2str(err));
|
||||
|
||||
assert(err == XED_ERROR_NONE);
|
||||
}
|
||||
|
||||
new_inst_bytes.insert(new_inst_bytes.begin(), inst_buff,
|
||||
inst_buff + inst_len);
|
||||
|
||||
// put a return instruction at the end of the decrypt instructions...
|
||||
//
|
||||
new_inst_bytes.push_back(0xC3);
|
||||
|
||||
sym->data().insert(sym->data().end(), new_inst_bytes.begin(),
|
||||
new_inst_bytes.end());
|
||||
|
||||
reloc.value()->offset(sym->data().size());
|
||||
sym->data().resize(sym->data().size() + 8);
|
||||
}
|
||||
|
||||
std::optional<recomp::reloc_t*> next_inst_pass_t::has_next_inst_reloc(
|
||||
decomp::symbol_t* sym) {
|
||||
auto res = std::find_if(
|
||||
sym->relocs().begin(), sym->relocs().end(),
|
||||
[&](recomp::reloc_t& reloc) -> bool { return !reloc.offset(); });
|
||||
|
||||
return res != sym->relocs().end() ? res._Ptr
|
||||
: std::optional<recomp::reloc_t*>();
|
||||
}
|
||||
} // namespace theo::obf
|
Loading…
Reference in new issue