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