You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

62 lines
2.9 KiB

#include <vm_lifters.hpp>
namespace vm
{
lifters_t::lifter_callback_t lifters_t::vmexit = [ & ]( vm::devirt_t *rtn,
const vm::instrs::code_block_t &vm_code_block,
const vm::instrs::virt_instr_t &vinstr,
llvm::IRBuilder<> *ir_builder ) {
std::stringstream rtn_name;
llvm::Function *exit_func = nullptr;
rtn_name << "vmexit_" << std::hex << vinstr.trace_data.vm_handler_rva + rtn->vmp2_file->image_base;
if ( !( exit_func = rtn->llvm_module->getFunction( rtn_name.str() ) ) )
{
auto vmexit_func_type = llvm::FunctionType::get(
ir_builder->getVoidTy(), llvm::PointerType::getInt8PtrTy( ir_builder->getContext() ) );
exit_func = llvm::Function::Create( vmexit_func_type, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
rtn_name.str().c_str(), *rtn->llvm_module );
auto entry_block = llvm::BasicBlock::Create( ir_builder->getContext(), "", exit_func );
auto vmexit_handler_addr = reinterpret_cast< std::uintptr_t >( rtn->vmp2_file ) +
rtn->vmp2_file->module_offset + vinstr.trace_data.vm_handler_rva;
zydis_routine_t vmexit_handler;
vm::util::flatten( vmexit_handler, vmexit_handler_addr );
vm::util::deobfuscate( vmexit_handler );
std::string asm_str( "mov rsp, rcx; " );
ZydisFormatter formatter;
ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL );
for ( const auto &instr_data : vmexit_handler )
{
if ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_POP ||
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_POPFQ )
{
char buffer[ 256 ];
ZydisFormatterFormatInstruction( &formatter, &instr_data.instr, buffer, sizeof( buffer ), 0ull );
asm_str.append( buffer ).append( "; " );
}
}
asm_str.append( "ret" );
auto ib = ir_builder->GetInsertBlock();
ir_builder->SetInsertPoint( entry_block );
auto exit_stub = llvm::InlineAsm::get( llvm::FunctionType::get( ir_builder->getVoidTy(), false ), asm_str,
"", false, false, llvm::InlineAsm::AD_Intel );
ir_builder->CreateCall( exit_stub );
ir_builder->CreateRetVoid();
ir_builder->SetInsertPoint( ib );
}
auto &vmp_rtn = rtn->vmp_rtns.back();
auto stack_ptr = ir_builder->CreateLoad( vmp_rtn->stack );
ir_builder->CreateCall( exit_func, stack_ptr );
ir_builder->CreateRet( stack_ptr );
};
} // namespace vm