diff --git a/src/vmlocate.cpp b/src/vmlocate.cpp index 7a64720..9e6f3f7 100644 --- a/src/vmlocate.cpp +++ b/src/vmlocate.cpp @@ -186,16 +186,34 @@ namespace vm::locate if ( !found_valid_jmp ) return false; - // second instruction in the flattened stream should be a push... - // this is also an optimization so we dont have to hit that 0^2 std::find_if every time... - if ( instr_stream[ 1 ].mnemonic != ZYDIS_MNEMONIC_PUSH ) + // find the first PUSH IMM (encrypted RVA to virtual instructions...) + auto first_push = std::find_if( instr_stream.begin(), instr_stream.end(), + [ & ]( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_PUSH && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE; + } ); + + if ( first_push == instr_stream.end() ) return false; - if ( std::find_if( instr_stream.begin() + 1, instr_stream.end(), - [ & ]( const ZydisDecodedInstruction &instr ) { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSH && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE; - } ) == instr_stream.end() ) + // find the second PUSH IMM... + auto second_push = + std::find_if( first_push + 1, instr_stream.end(), [ & ]( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_PUSH && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE; + } ); + + if ( second_push == instr_stream.end() ) + return false; + + // if there is a third push IMM then we have an invalid instruction stream... + auto third_push = + std::find_if( second_push + 1, instr_stream.end(), [ & ]( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_PUSH && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE; + } ); + + if ( third_push != instr_stream.end() ) return false; // scan over the instruction stream to see if it contains an lea r12, xxxx which is a known vm handler table