#pragma once #include #include #include #include #define XED_ENCODER extern "C" { #include #include } namespace theo::obf::transform { using transform_t = std::function; class operation_t { public: explicit operation_t(transform_t op, xed_iclass_enum_t type) : m_transform(op), m_type(type) {} std::vector native(const xed_decoded_inst_t* inst, std::uint32_t imm) { std::uint32_t inst_len = {}; std::uint8_t inst_buff[XED_MAX_INSTRUCTION_BYTES]; xed_error_enum_t err; xed_encoder_request_init_from_decode((xed_decoded_inst_s*)inst); xed_encoder_request_t* req = (xed_encoder_request_t*)inst; switch (m_type) { case XED_ICLASS_ROR: case XED_ICLASS_ROL: xed_encoder_request_set_uimm0(req, imm, 1); break; default: xed_encoder_request_set_uimm0(req, imm, 4); break; } xed_encoder_request_set_iclass(req, m_type); xed_encoder_request_set_operand_order(req, 1, XED_OPERAND_IMM0); if ((err = xed_encode(req, inst_buff, sizeof(inst_buff), &inst_len)) != XED_ERROR_NONE) { spdlog::error("failed to encode instruction... reason: {}", xed_error_enum_t2str(err)); assert(err == XED_ERROR_NONE); } return std::vector(inst_buff, inst_buff + inst_len); } xed_iclass_enum_t inverse() { return m_inverse_op[m_type]; } transform_t* get_transform() { return &m_transform; } xed_iclass_enum_t type() { return m_type; } static std::size_t random(std::size_t lowest, std::size_t largest) { std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution distr(lowest, largest); return distr(gen); } private: transform_t m_transform; xed_iclass_enum_t m_type; std::map m_inverse_op = { {XED_ICLASS_ADD, XED_ICLASS_SUB}, {XED_ICLASS_SUB, XED_ICLASS_ADD}, {XED_ICLASS_ROL, XED_ICLASS_ROR}, {XED_ICLASS_ROR, XED_ICLASS_ROL}, {XED_ICLASS_XOR, XED_ICLASS_XOR}}; }; } // namespace theo::obf::transform