From ede70ec582160b7cdb8fbd0f00a8fd94d5658481 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Tue, 8 Jun 2021 03:58:24 -0700 Subject: [PATCH] fixed crashing when trying to emulate vmentry on packed bins... --- src/vmemu_t.cpp | 28 +++++++++++++++++++++++----- src/vmemu_t.hpp | 2 +- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index c65d7eb..7f0bb54 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -89,9 +89,6 @@ namespace vm { std::printf( "failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror( err ) ); - for ( auto &[ code_block, uc_code_block_context ] : code_blocks ) - entries.push_back( code_block ); - return false; } @@ -208,7 +205,8 @@ namespace vm void emu_t::hook_code( uc_engine *uc, uint64_t address, uint32_t size, vm::emu_t *obj ) { - std::printf( ">>> Tracing instruction at 0x%p, instruction size = 0x%x\n", address, size ); + // std::printf( ">>> Tracing instruction at 0x%p, instruction size = 0x%x\n", + //( address - obj->vmctx->module_base ) + obj->vmctx->image_base, size ); // bad code... but i need to skip JMP instructions when tracing branches since i save context // on the jmp instruction... so it needs to be skipped... @@ -223,7 +221,7 @@ namespace vm static ZydisDecoder decoder; static ZydisDecodedInstruction instr; - static std::uintptr_t reg_val = 0u; + static std::uintptr_t reg_val = 0u, rsi = 0u; // init zydis decoder only a single time... if ( static std::atomic< bool > once = true; once.exchange( false ) ) @@ -281,6 +279,13 @@ namespace vm } obj->code_blocks.back().first.vinstrs.push_back( virt_instr.value() ); + uc_reg_read( obj->uc, UC_X86_REG_RSI, &rsi ); + std::printf( "> %s handler = 0x%p vip = 0x%p\n", + obj->vmctx->vm_handlers[ new_entry.handler_idx ].profile + ? obj->vmctx->vm_handlers[ new_entry.handler_idx ].profile->name + : "UNK", + ( reg_val - obj->vmctx->module_base ) + obj->vmctx->image_base, + ( rsi - obj->vmctx->module_base ) + obj->vmctx->image_base ); // if there is a virtual JMP instruction then we need to grab jcc data for the current code_block_t // and then create a new code_block_t... @@ -289,8 +294,16 @@ namespace vm { const auto code_block_address = vm::instrs::code_block_addr( *obj->vmctx, new_entry ); auto jcc = vm::instrs::get_jcc_data( *obj->vmctx, obj->code_blocks.back().first ); + if ( jcc.has_value() ) + { obj->code_blocks.back().first.jcc = jcc.value(); + } + else // the branch(s) dont start with SREGQ... stopping... + { + uc_emu_stop( uc ); + return; + } // save cpu state as well as stack... obj->code_blocks.back().second = std::make_shared< cpu_ctx >(); @@ -336,6 +349,11 @@ namespace vm // vmexit's cannot have a branch... obj->code_blocks.back().first.jcc.has_jcc = false; } + else if ( instr.mnemonic == ZYDIS_MNEMONIC_CALL && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER ) + { + const auto rip = address + instr.length; + uc_reg_write( obj->uc, UC_X86_REG_RIP, &rip ); + } } bool emu_t::hook_mem_invalid( uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, diff --git a/src/vmemu_t.hpp b/src/vmemu_t.hpp index 4e02503..baf1040 100644 --- a/src/vmemu_t.hpp +++ b/src/vmemu_t.hpp @@ -16,7 +16,7 @@ namespace vm struct cpu_ctx { uc_context *context; - std::uint8_t stack[ PAGE_4K * 20 ]; + std::uint8_t stack[ PAGE_4K * 100 ]; }; class emu_t