added vmp2 file format v3 (which adds support for virtual jcc's)

merge-requests/9/head
_xeroxz 4 years ago
commit e95ef25371

@ -139,4 +139,4 @@ namespace vmp2
} vsp; } vsp;
}; };
} // namespace v2 } // namespace v2
} }

@ -144,14 +144,14 @@ namespace vm
auto imm_fetch = auto imm_fetch =
std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
// mov/movsx/movzx rax/eax/ax/al, [rsi] // mov/movsx/movzx rax/eax/ax/al, [rsi]
return ( instr_data.instr.operand_count > 1 && return instr_data.instr.operand_count > 1 &&
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) &&
instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX &&
instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI ); instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI;
} ); } );
if ( imm_fetch == vm_handler.end() ) if ( imm_fetch == vm_handler.end() )

@ -124,32 +124,28 @@ namespace vm
bool get_rva_decrypt( const zydis_routine_t &vm_entry, std::vector< zydis_decoded_instr_t > &transform_instrs ) bool get_rva_decrypt( const zydis_routine_t &vm_entry, std::vector< zydis_decoded_instr_t > &transform_instrs )
{ {
//
// find mov esi, [rsp+0xA0] // find mov esi, [rsp+0xA0]
//
auto result = auto result =
std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool { std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool {
if ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr_data.instr.operand_count == 2 && return instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_ESI && instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSP && instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_ESI &&
instr_data.instr.operands[ 1 ].mem.disp.has_displacement && instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr_data.instr.operands[ 1 ].mem.disp.value == 0xA0 ) instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSP &&
return true; instr_data.instr.operands[ 1 ].mem.disp.value == 0xA0;
return false;
} ); } );
if ( result == vm_entry.end() ) if ( result == vm_entry.end() )
return false; return false;
// // find the next three instructions with ESI as
// find the next three instruction with ESI as the dest... // the first operand... and make sure actions & writes...
//
for ( auto idx = 0u; idx < 3; ++idx ) for ( auto idx = 0u; idx < 3; ++idx )
{ {
result = std::find_if( ++result, vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool { result = std::find_if( ++result, vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool {
return instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_ESI; return vm::transform::valid( instr_data.instr.mnemonic ) &&
instr_data.instr.operands[ 0 ].actions == ZYDIS_OPERAND_ACTION_WRITE &&
instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_ESI;
} ); } );
if ( result == vm_entry.end() ) if ( result == vm_entry.end() )
@ -228,14 +224,13 @@ namespace vm
// instruction rva's ontop of the virtual stack... // instruction rva's ontop of the virtual stack...
result = std::find_if( code_block.vinstrs.rbegin(), code_block.vinstrs.rend(), result = std::find_if( code_block.vinstrs.rbegin(), code_block.vinstrs.rend(),
[ & ]( const vm::instrs::virt_instr_t &vinstr ) -> bool { [ & ]( const vm::instrs::virt_instr_t &vinstr ) -> bool {
auto profile = vm::handler::get_profile( vinstr.mnemonic_t ); if ( auto profile = vm::handler::get_profile( vinstr.mnemonic_t );
if ( profile && profile->mnemonic == vm::handler::PUSHVSP ) profile && profile->mnemonic == vm::handler::PUSHVSP )
{ {
const auto possible_block_1 = const auto possible_block_1 = code_block_addr(
code_block_addr( vmctx, vinstr.trace_data.vsp.qword[ 0 ] ^ xor_key ); vmctx, vinstr.trace_data.vsp.qword[ 0 ] ^ xor_key ),
possible_block_2 = code_block_addr(
const auto possible_block_2 = vmctx, vinstr.trace_data.vsp.qword[ 1 ] ^ xor_key );
code_block_addr( vmctx, vinstr.trace_data.vsp.qword[ 1 ] ^ xor_key );
// if this returns too many false positives we might have to get // if this returns too many false positives we might have to get
// our hands dirty and look into trying to emulate each branch // our hands dirty and look into trying to emulate each branch
@ -253,7 +248,6 @@ namespace vm
if ( result == code_block.vinstrs.rend() ) if ( result == code_block.vinstrs.rend() )
{ {
jcc.block_addr[ 0 ] = code_block_addr( vmctx, last_trace ); jcc.block_addr[ 0 ] = code_block_addr( vmctx, last_trace );
jcc.has_jcc = false; jcc.has_jcc = false;
jcc.type = jcc_type::absolute; jcc.type = jcc_type::absolute;
} }

Loading…
Cancel
Save