|
|
@ -1,8 +1,9 @@
|
|
|
|
#include <string>
|
|
|
|
#include <string>
|
|
|
|
#include <vmemu_t.hpp>
|
|
|
|
#include <vmemu_t.hpp>
|
|
|
|
|
|
|
|
|
|
|
|
namespace vm {
|
|
|
|
namespace vm {
|
|
|
|
emu_t::emu_t(vm::vmctx_t* vm_ctx) : m_vm(vm_ctx) {}
|
|
|
|
emu_t::emu_t(vm::vmctx_t* vm_ctx, bool log) : m_vm(vm_ctx),
|
|
|
|
|
|
|
|
log_bytecode(log) {}
|
|
|
|
|
|
|
|
emu_t::emu_t(vm::vmctx_t* vm_ctx) : m_vm(vm_ctx) {};
|
|
|
|
|
|
|
|
|
|
|
|
emu_t::~emu_t() {
|
|
|
|
emu_t::~emu_t() {
|
|
|
|
if (uc) uc_close(uc);
|
|
|
|
if (uc) uc_close(uc);
|
|
|
@ -86,14 +87,14 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) {
|
|
|
|
cc_trace.m_vip = cc_blk->m_vm.vip;
|
|
|
|
cc_trace.m_vip = cc_blk->m_vm.vip;
|
|
|
|
cc_trace.m_vsp = cc_blk->m_vm.vsp;
|
|
|
|
cc_trace.m_vsp = cc_blk->m_vm.vsp;
|
|
|
|
|
|
|
|
|
|
|
|
std::printf("> beginning execution at = %p\n", rip);
|
|
|
|
std::printf("> beginning execution at = %p (%p)\n", rip, rip - m_vm->m_module_base + m_vm->m_image_base);
|
|
|
|
if ((err = uc_emu_start(uc, rip, 0ull, 0ull, 0ull))) {
|
|
|
|
if ((err = uc_emu_start(uc, rip, 0ull, 0ull, 0ull))) {
|
|
|
|
std::printf("> error starting emu... reason = %d\n", err);
|
|
|
|
std::printf("> error starting emu... reason = %d\n", err);
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extract_branch_data();
|
|
|
|
extract_branch_data();
|
|
|
|
std::printf("> emulated blk_%p\n\n", cc_blk->m_vip.img_base);
|
|
|
|
std::printf("> emulated blk_%p\n\n", cc_blk->m_vip.img_based);
|
|
|
|
|
|
|
|
|
|
|
|
// keep track of the emulated blocks... by their addresses...
|
|
|
|
// keep track of the emulated blocks... by their addresses...
|
|
|
|
std::vector<std::uintptr_t> blk_addrs;
|
|
|
|
std::vector<std::uintptr_t> blk_addrs;
|
|
|
@ -124,14 +125,14 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) {
|
|
|
|
|
|
|
|
|
|
|
|
// emulate the branch...
|
|
|
|
// emulate the branch...
|
|
|
|
uc_mem_write(uc, vsp, &br, sizeof br);
|
|
|
|
uc_mem_write(uc, vsp, &br, sizeof br);
|
|
|
|
std::printf("> beginning execution at = %p\n", blk.m_jmp.rip);
|
|
|
|
std::printf("> beginning execution at = %p (%p)\n", rip, rip - m_vm->m_module_base + m_vm->m_image_base);
|
|
|
|
if ((err = uc_emu_start(uc, blk.m_jmp.rip, 0ull, 0ull, 0ull))) {
|
|
|
|
if ((err = uc_emu_start(uc, blk.m_jmp.rip, 0ull, 0ull, 0ull))) {
|
|
|
|
std::printf("> error starting emu... reason = %d\n", err);
|
|
|
|
std::printf("> error starting emu... reason = %d\n", err);
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extract_branch_data();
|
|
|
|
extract_branch_data();
|
|
|
|
std::printf("> emulated blk_%p\n", cc_blk->m_vip.img_base);
|
|
|
|
std::printf("> emulated blk_%p\n", cc_blk->m_vip.img_based);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -373,7 +374,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size,
|
|
|
|
obj->cc_trace.m_instrs.end());
|
|
|
|
obj->cc_trace.m_instrs.end());
|
|
|
|
|
|
|
|
|
|
|
|
// set the virtual code block vip address information...
|
|
|
|
// set the virtual code block vip address information...
|
|
|
|
if (!obj->cc_blk->m_vip.rva || !obj->cc_blk->m_vip.img_base) {
|
|
|
|
if (!obj->cc_blk->m_vip.rva || !obj->cc_blk->m_vip.img_based) {
|
|
|
|
// find the last write done to VIP...
|
|
|
|
// find the last write done to VIP...
|
|
|
|
auto vip_write = std::find_if(
|
|
|
|
auto vip_write = std::find_if(
|
|
|
|
obj->cc_trace.m_instrs.rbegin(), obj->cc_trace.m_instrs.rend(),
|
|
|
|
obj->cc_trace.m_instrs.rbegin(), obj->cc_trace.m_instrs.rend(),
|
|
|
@ -393,14 +394,35 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size,
|
|
|
|
uc_reg_read(uc, vm::instrs::reg_map[obj->cc_trace.m_vip], &vip_addr);
|
|
|
|
uc_reg_read(uc, vm::instrs::reg_map[obj->cc_trace.m_vip], &vip_addr);
|
|
|
|
|
|
|
|
|
|
|
|
obj->cc_blk->m_vip.rva = vip_addr -= obj->m_vm->m_module_base;
|
|
|
|
obj->cc_blk->m_vip.rva = vip_addr -= obj->m_vm->m_module_base;
|
|
|
|
obj->cc_blk->m_vip.img_base = vip_addr += obj->m_vm->m_image_base;
|
|
|
|
obj->cc_blk->m_vip.img_based = vip_addr += obj->m_vm->m_image_base;
|
|
|
|
|
|
|
|
|
|
|
|
uc_context_restore(uc, backup);
|
|
|
|
uc_context_restore(uc, backup);
|
|
|
|
uc_context_free(backup);
|
|
|
|
uc_context_free(backup);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
const auto vinstr = vm::instrs::determine(obj->cc_trace);
|
|
|
|
const auto vinstr = vm::instrs::determine(obj->cc_trace);
|
|
|
|
if (vinstr.mnemonic != vm::instrs::mnemonic_t::unknown) {
|
|
|
|
if (vinstr.mnemonic != vm::instrs::mnemonic_t::unknown) {
|
|
|
|
|
|
|
|
if (obj->log_bytecode)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
obj->il_bytecode.emplace_back(static_cast<uint8_t>(vinstr.mnemonic));
|
|
|
|
|
|
|
|
if (vinstr.imm.has_imm)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
obj->il_bytecode.emplace_back(vinstr.imm.size);
|
|
|
|
|
|
|
|
for(int i = 0; i < (vinstr.imm.size / 8); ++i)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
obj->il_bytecode.emplace_back(*(reinterpret_cast<const uint8_t*>(&vinstr.imm.val) + i));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
obj->il_bytecode.emplace_back<uint8_t>(0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
std::printf("%p: ", obj->cc_trace.m_begin + obj->m_vm->m_image_base - obj->m_vm->m_module_base);
|
|
|
|
if (vinstr.imm.has_imm)
|
|
|
|
if (vinstr.imm.has_imm)
|
|
|
|
|
|
|
|
if (vinstr.mnemonic == instrs::mnemonic_t::lreg || vinstr.mnemonic == instrs::mnemonic_t::sreg)
|
|
|
|
|
|
|
|
std::printf("> %s %s_%s\n",
|
|
|
|
|
|
|
|
vm::instrs::get_profile(vinstr.mnemonic)->name.c_str(),
|
|
|
|
|
|
|
|
vm::reg_names::prefixes[(vinstr.imm.val / 8) % 8].c_str(),
|
|
|
|
|
|
|
|
vm::reg_names::suffixes[(vinstr.imm.val / 8) / 8].c_str());
|
|
|
|
|
|
|
|
else
|
|
|
|
std::printf("> %s %p\n",
|
|
|
|
std::printf("> %s %p\n",
|
|
|
|
vm::instrs::get_profile(vinstr.mnemonic)->name.c_str(),
|
|
|
|
vm::instrs::get_profile(vinstr.mnemonic)->name.c_str(),
|
|
|
|
vinstr.imm.val);
|
|
|
|
vinstr.imm.val);
|
|
|
@ -592,4 +614,9 @@ std::optional<std::pair<std::uintptr_t, std::uintptr_t>> emu_t::could_have_jcc(
|
|
|
|
|
|
|
|
|
|
|
|
return {{lconst1->imm.val, lconst2->imm.val}};
|
|
|
|
return {{lconst1->imm.val, lconst2->imm.val}};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<uint8_t>& emu_t::get_il_bytecode()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return il_bytecode;
|
|
|
|
|
|
|
|
}
|
|
|
|
} // namespace vm
|
|
|
|
} // namespace vm
|