diff --git a/include/transform.hpp b/include/transform.hpp index d24facb..bc2ef88 100644 --- a/include/transform.hpp +++ b/include/transform.hpp @@ -136,19 +136,24 @@ namespace vm template < class T > inline const auto _dec = []( T a, T b ) -> T { return a - 1; }; template < class T > - inline std::map< ZydisMnemonic, transform_t< T > > transforms = { + inline std::map< zydis_mnemonic_t, transform_t< T > > transforms = { { ZYDIS_MNEMONIC_ADD, _add< T > }, { ZYDIS_MNEMONIC_XOR, _xor< T > }, { ZYDIS_MNEMONIC_BSWAP, _bswap< T > }, { ZYDIS_MNEMONIC_SUB, _sub< T > }, { ZYDIS_MNEMONIC_NEG, _neg< T > }, { ZYDIS_MNEMONIC_NOT, _not< T > }, { ZYDIS_MNEMONIC_ROR, _ror< T > }, { ZYDIS_MNEMONIC_ROL, _rol< T > }, { ZYDIS_MNEMONIC_INC, _inc< T > }, { ZYDIS_MNEMONIC_DEC, _dec< T > } }; - inline std::map< ZydisMnemonic, ZydisMnemonic > inverse = { + inline std::map< zydis_mnemonic_t, zydis_mnemonic_t > inverse = { { ZYDIS_MNEMONIC_ADD, ZYDIS_MNEMONIC_SUB }, { ZYDIS_MNEMONIC_XOR, ZYDIS_MNEMONIC_XOR }, { ZYDIS_MNEMONIC_BSWAP, ZYDIS_MNEMONIC_BSWAP }, { ZYDIS_MNEMONIC_SUB, ZYDIS_MNEMONIC_ADD }, { ZYDIS_MNEMONIC_NEG, ZYDIS_MNEMONIC_NEG }, { ZYDIS_MNEMONIC_NOT, ZYDIS_MNEMONIC_NOT }, { ZYDIS_MNEMONIC_ROR, ZYDIS_MNEMONIC_ROL }, { ZYDIS_MNEMONIC_ROL, ZYDIS_MNEMONIC_ROR }, { ZYDIS_MNEMONIC_INC, ZYDIS_MNEMONIC_DEC }, { ZYDIS_MNEMONIC_DEC, ZYDIS_MNEMONIC_INC } }; + inline bool valid( zydis_mnemonic_t op ) + { + return transforms< std::uint8_t >.find( op ) != transforms< std::uint8_t >.end(); + } + inline void inverse_transforms( transform::map_t &transforms, transform::map_t &inverse ) { inverse[ transform::type::generic0 ] = transforms[ transform::type::generic0 ]; diff --git a/include/vmprofiler.hpp b/include/vmprofiler.hpp index 2e9838d..73a4a90 100644 --- a/include/vmprofiler.hpp +++ b/include/vmprofiler.hpp @@ -31,6 +31,7 @@ namespace vm enum mnemonic_t { INVALID, + LRFLAGS, PUSHVSP, MULQ, DIVQ, @@ -75,7 +76,8 @@ namespace vm SHRW, NANDQ, - NANDDW + NANDDW, + NANDW }; enum extention_t @@ -153,6 +155,7 @@ namespace vm extern vm::handler::profile_t nandq; extern vm::handler::profile_t nanddw; + extern vm::handler::profile_t nandw; extern vm::handler::profile_t writeq; extern vm::handler::profile_t writedw; @@ -164,6 +167,7 @@ namespace vm extern vm::handler::profile_t shrq; extern vm::handler::profile_t shrw; + extern vm::handler::profile_t lrflags; extern vm::handler::profile_t call; extern vm::handler::profile_t pushvsp; extern vm::handler::profile_t mulq; @@ -172,14 +176,14 @@ namespace vm extern vm::handler::profile_t vmexit; inline std::vector< vm::handler::profile_t * > all = { - &sregq, &sregdw, &sregw, &lregq, &lregdw, &lconstq, &lconstbzxw, - &lconstbsxdw, &lconstbsxq, &lconstdwsxq, &lconstwsxq, &lconstwsxdw, &lconstdw, &lconstw, - &addq, &adddw, &addw, + &sregq, &sregdw, &sregw, &lregq, &lregdw, &lconstq, &lconstbzxw, &lconstbsxdw, + &lconstbsxq, &lconstdwsxq, &lconstwsxq, &lconstwsxdw, &lconstdw, &lconstw, &addq, &adddw, + &addw, - &shlq, &shldw, &writeq, &writedw, &writeb, &nandq, &nanddw, + &shlq, &shldw, &writeq, &writedw, &writeb, &nandq, &nanddw, &nandw, - &shrq, &shrw, &readq, &readdw, &mulq, &pushvsp, &divq, - &jmp, &vmexit, &call }; + &shrq, &shrw, &readq, &readdw, &mulq, &pushvsp, &divq, &jmp, + &lrflags, &vmexit, &call }; } // namespace profile } // namespace handler } // namespace vm \ No newline at end of file diff --git a/include/vmutils.h b/include/vmutils.h index aa1811b..9a9bac0 100644 --- a/include/vmutils.h +++ b/include/vmutils.h @@ -12,6 +12,7 @@ using u128 = __m128; using zydis_decoded_instr_t = ZydisDecodedInstruction; using zydis_register_t = ZydisRegister; +using zydis_mnemonic_t = ZydisMnemonic; struct zydis_instr_t { diff --git a/src/calc_jmp.cpp b/src/calc_jmp.cpp index 0902287..e612da1 100644 --- a/src/calc_jmp.cpp +++ b/src/calc_jmp.cpp @@ -9,16 +9,14 @@ namespace vm auto result = std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool { // mov/movsx/movzx rax/eax/ax/al, [rsi] - if ( instr_data.instr.operand_count > 1 && - ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && - instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - 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 ].mem.base == ZYDIS_REGISTER_RSI ) - return true; - return false; + return ( instr_data.instr.operand_count > 1 && + ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && + instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + 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 ].mem.base == ZYDIS_REGISTER_RSI ); } ); if ( result == vm_entry.end() ) @@ -32,8 +30,9 @@ namespace vm { auto result = std::find_if( calc_jmp.begin(), calc_jmp.end(), []( const zydis_instr_t &instr_data ) -> bool { - // look for any instruction with RSI being the first operand... - return instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + // look for any instruction with RSI being the first operand and its being written too.. + return instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && + instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSI; } ); @@ -45,45 +44,22 @@ namespace vm switch ( instr->mnemonic ) { case ZYDIS_MNEMONIC_LEA: - { + // if operand type is memory, then return advancement type + // based off of the disposition value... (neg == backward, pos == forward) if ( instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY ) - { - if ( instr->operands[ 1 ].mem.disp.value > 0 ) - return vmp2::exec_type_t::forward; - else - return vmp2::exec_type_t::backward; - } - // else we dont know what we are looking at... - return {}; - } + return instr->operands[ 1 ].mem.disp.value > 0 ? vmp2::exec_type_t::forward + : vmp2::exec_type_t::backward; + break; case ZYDIS_MNEMONIC_ADD: - { - // ADD RSI, IMM... if ( instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ) - { - // see if IMM is negitive... - if ( instr->operands[ 1 ].imm.value.s > 0 ) - return vmp2::exec_type_t::forward; - else // adding a negitive number is sub... - return vmp2::exec_type_t::backward; - } - // else we dont know what we are looking at... - return {}; - } + return instr->operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::forward + : vmp2::exec_type_t::backward; + break; case ZYDIS_MNEMONIC_SUB: - { - // SUB RSI, IMM... if ( instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ) - { - // see if IMM is negitive... - if ( instr->operands[ 1 ].imm.value.s > 0 ) - return vmp2::exec_type_t::backward; - else // subtracting a negitive number means you are adding... - return vmp2::exec_type_t::forward; - } - // else we dont know what we are looking at... - return {}; - } + return instr->operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::backward + : vmp2::exec_type_t::forward; + break; case ZYDIS_MNEMONIC_INC: return vmp2::exec_type_t::forward; case ZYDIS_MNEMONIC_DEC: diff --git a/src/vmhandler.cpp b/src/vmhandler.cpp index 22b89fb..0d67547 100644 --- a/src/vmhandler.cpp +++ b/src/vmhandler.cpp @@ -19,14 +19,14 @@ namespace vm return false; }; + // find LEA RAX, [RDI+0xE0], else determine if the instruction is inside of calc_jmp... auto result = std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr ) -> bool { - if ( instr.instr.mnemonic == ZYDIS_MNEMONIC_LEA && + return instr.instr.mnemonic == ZYDIS_MNEMONIC_LEA && instr.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && instr.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RDI && - instr.instr.operands[ 1 ].mem.disp.value == 0xE0 ) - return true; - - return calc_jmp_check( instr.addr ); + instr.instr.operands[ 1 ].mem.disp.value == 0xE0 + ? true + : calc_jmp_check( instr.addr ); } ); // remove calc_jmp from the vm handler vector... @@ -42,16 +42,14 @@ namespace vm { result = std::find_if( ++result, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { // mov/movsx/movzx rax/eax/ax/al, [rsi] - if ( instr_data.instr.operand_count > 1 && - ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && - instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - 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 ].mem.base == ZYDIS_REGISTER_RSI ) - return true; - return false; + return instr_data.instr.operand_count > 1 && + ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && + instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + 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 ].mem.base == ZYDIS_REGISTER_RSI; } ); if ( result != vm_handler.end() ) @@ -77,17 +75,15 @@ namespace vm for ( auto idx = 0u; idx < 256; ++idx ) { - const auto decrypt_val = vm::handler::table::decrypt( instr, vm_handler_table[ idx ] ); - handler_t vm_handler; vm::transform::map_t transforms; zydis_routine_t vm_handler_instrs; + const auto decrypt_val = vm::handler::table::decrypt( instr, vm_handler_table[ idx ] ); if ( !vm::handler::get( calc_jmp, vm_handler_instrs, ( decrypt_val - image_base ) + module_base ) ) return false; const auto has_imm = vm::handler::has_imm( vm_handler_instrs ); - const auto imm_size = vm::handler::imm_size( vm_handler_instrs ); if ( has_imm && !vm::handler::get_operand_transforms( vm_handler_instrs, transforms ) ) @@ -109,16 +105,14 @@ namespace vm const auto result = std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { // mov/movsx/movzx rax/eax/ax/al, [rsi] - if ( instr_data.instr.operand_count > 1 && - ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && - instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - 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 ].mem.base == ZYDIS_REGISTER_RSI ) - return true; - return false; + return instr_data.instr.operand_count > 1 && + ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && + instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + 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 ].mem.base == ZYDIS_REGISTER_RSI; } ); return result != vm_handler.end(); @@ -129,16 +123,14 @@ namespace vm const auto result = std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { // mov/movsx/movzx rax/eax/ax/al, [rsi] - if ( 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_MOVSX || instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && 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 ].mem.base == ZYDIS_REGISTER_RSI ) - return true; - return false; + instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; } ); if ( result == vm_handler.end() ) @@ -152,16 +144,14 @@ namespace vm auto imm_fetch = std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { // mov/movsx/movzx rax/eax/ax/al, [rsi] - if ( instr_data.instr.operand_count > 1 && - ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && - instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - 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 ].mem.base == ZYDIS_REGISTER_RSI ) - return true; - return false; + return ( instr_data.instr.operand_count > 1 && + ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && + instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + 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 ].mem.base == ZYDIS_REGISTER_RSI ); } ); if ( imm_fetch == vm_handler.end() ) @@ -169,52 +159,51 @@ namespace vm // this finds the first transformation which looks like: // transform rax, rbx <--- note these registers can be smaller so we to64 them... - auto key_transform = + auto transform_instr = std::find_if( imm_fetch, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { - if ( util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) && - util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX ) ) - return true; - return false; + return vm::transform::valid( instr_data.instr.mnemonic ) && + instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && + util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) && + util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX ); } ); - if ( key_transform == vm_handler.end() ) + if ( transform_instr == vm_handler.end() ) return false; // look for a primer/instruction that alters RAX prior to the 5 transformations... - auto generic0 = std::find_if( imm_fetch + 1, key_transform, []( const zydis_instr_t &instr_data ) -> bool { - return util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) && + auto generic0 = std::find_if( imm_fetch, transform_instr, []( const zydis_instr_t &instr_data ) -> bool { + return vm::transform::valid( instr_data.instr.mnemonic ) && + instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && + util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) && !util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX ); } ); zydis_decoded_instr_t nogeneric0; nogeneric0.mnemonic = ZYDIS_MNEMONIC_INVALID; - - transforms[ transform::type::generic0 ] = generic0 != key_transform ? generic0->instr : nogeneric0; + transforms[ transform::type::generic0 ] = generic0 != transform_instr ? generic0->instr : nogeneric0; // last transformation is the same as the first except src and dest are swwapped... - transforms[ transform::type::rolling_key ] = key_transform->instr; - auto instr_copy = key_transform->instr; - instr_copy.operands[ 0 ].reg.value = key_transform->instr.operands[ 1 ].reg.value; - instr_copy.operands[ 1 ].reg.value = key_transform->instr.operands[ 0 ].reg.value; + transforms[ transform::type::rolling_key ] = transform_instr->instr; + auto instr_copy = transform_instr->instr; + instr_copy.operands[ 0 ].reg.value = transform_instr->instr.operands[ 1 ].reg.value; + instr_copy.operands[ 1 ].reg.value = transform_instr->instr.operands[ 0 ].reg.value; transforms[ transform::type::update_key ] = instr_copy; // three generic transformations... - auto generic_transform = key_transform; - - for ( auto idx = 2u; idx < 5; ++idx ) + for ( auto idx = static_cast< unsigned >( vm::transform::type::generic1 ); + idx < static_cast< unsigned >( vm::transform::type::update_key ); ++idx ) { - generic_transform = - std::find_if( ++generic_transform, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { - if ( util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) ) - return true; - - return false; + transform_instr = + std::find_if( ++transform_instr, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { + return vm::transform::valid( instr_data.instr.mnemonic ) && + instr_data.instr.operands[0].actions & ZYDIS_OPERAND_ACTION_WRITE && + util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ); } ); - if ( generic_transform == vm_handler.end() ) + if ( transform_instr == vm_handler.end() ) return false; - transforms[ ( transform::type )( idx ) ] = generic_transform->instr; + transforms[ static_cast< vm::transform::type >( idx ) ] = transform_instr->instr; } return true; @@ -255,13 +244,10 @@ namespace vm std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool { const auto instr = &instr_data.instr; // lea r12, vm_handlers... (always r12)... - if ( instr->mnemonic == ZYDIS_MNEMONIC_LEA && - instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_R12 && - !instr->raw.sib.base ) // no register used for the sib base... - return true; - - return false; + return instr->mnemonic == ZYDIS_MNEMONIC_LEA && + instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_R12 && + !instr->raw.sib.base; // no register used for the sib base... } ); if ( result == vm_entry.end() ) @@ -275,42 +261,35 @@ namespace vm bool get_transform( const zydis_routine_t &vm_entry, zydis_decoded_instr_t *transform_instr ) { - zydis_register_t rcx_or_rdx = ZYDIS_REGISTER_NONE; - auto handler_fetch = std::find_if( vm_entry.begin(), vm_entry.end(), [ & ]( const zydis_instr_t &instr_data ) -> bool { const auto instr = &instr_data.instr; - if ( instr->mnemonic == ZYDIS_MNEMONIC_MOV && instr->operand_count == 2 && - instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr->operands[ 1 ].mem.base == ZYDIS_REGISTER_R12 && - instr->operands[ 1 ].mem.index == ZYDIS_REGISTER_RAX && - instr->operands[ 1 ].mem.scale == 8 && - instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - ( instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX || - instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RCX ) ) - { - rcx_or_rdx = instr->operands[ 0 ].reg.value; - return true; - } - - return false; + return instr->mnemonic == ZYDIS_MNEMONIC_MOV && instr->operand_count == 2 && + instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr->operands[ 1 ].mem.base == ZYDIS_REGISTER_R12 && + instr->operands[ 1 ].mem.index == ZYDIS_REGISTER_RAX && + instr->operands[ 1 ].mem.scale == 8 && + instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + ( instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX || + instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RCX ); } ); // check to see if we found the fetch instruction and if the next instruction // is not the end of the vector... - if ( handler_fetch == vm_entry.end() || ++handler_fetch == vm_entry.end() || + if ( handler_fetch == vm_entry.end() || // must be RCX or RDX... else something went wrong... - ( rcx_or_rdx != ZYDIS_REGISTER_RCX && rcx_or_rdx != ZYDIS_REGISTER_RDX ) ) + ( handler_fetch->instr.operands[ 0 ].reg.value != ZYDIS_REGISTER_RCX && + handler_fetch->instr.operands[ 0 ].reg.value != ZYDIS_REGISTER_RDX ) ) return false; // find the next instruction that writes to RCX or RDX... // the register is determined by the vm handler fetch above... auto handler_transform = std::find_if( handler_fetch, vm_entry.end(), [ & ]( const zydis_instr_t &instr_data ) -> bool { - if ( instr_data.instr.operands[ 0 ].reg.value == rcx_or_rdx && - instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE ) - return true; - return false; + return vm::transform::valid( instr_data.instr.mnemonic ) && + instr_data.instr.operands[ 0 ].reg.value == + handler_fetch->instr.operands[ 0 ].reg.value && + instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE; } ); if ( handler_transform == vm_entry.end() ) diff --git a/src/vmprofiles/lflags.cpp b/src/vmprofiles/lflags.cpp new file mode 100644 index 0000000..5b84ef6 --- /dev/null +++ b/src/vmprofiles/lflags.cpp @@ -0,0 +1,36 @@ +#include "../../include/vmprofiler.hpp" + +namespace vm +{ + namespace handler + { + namespace profile + { + vm::handler::profile_t lrflags = { + // PUSH [RBP] + // ADD RBP, 0x8 + // POPFQ + "LRFLAGS", + LRFLAGS, + NULL, + { { // PUSH [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_PUSH && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // ADD RBP, 0x8 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x8; + }, + // POPFQ + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POPFQ; + } } } }; + } + } // namespace handler +} // namespace vm \ No newline at end of file diff --git a/src/vmprofiles/nand.cpp b/src/vmprofiles/nand.cpp index fcbf681..0fbcec0 100644 --- a/src/vmprofiles/nand.cpp +++ b/src/vmprofiles/nand.cpp @@ -75,14 +75,66 @@ namespace vm } } } }; vm::handler::profile_t nanddw = { + // NOT QWORD PTR [RBP] + // MOV EAX, [RBP] + // SUB RBP, 0x4 + // AND [RBP+0x8], EAX + // PUSHFQ + // POP [RBP] + "NANDDW", + NANDDW, + NULL, + { { // NOT QWORD PTR [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_NOT && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].size == 64 && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // MOV EAX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // SUB RBP, 0x4 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x4; + }, + // AND [RBP+0x8], EAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_AND && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 0 ].mem.disp.value == 0x8 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; + }, + // PUSHFQ + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; + }, + // POP [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; + + vm::handler::profile_t nandw = { // NOT DWORD PTR [RBP] // MOV AX, [RBP] // SUB RBP, 0x6 // AND [RBP+0x8], AX // PUSHFQ // POP [RBP] - "NANDDW", - NANDDW, + "NANDW", + NANDW, NULL, { { // NOT DWORD PTR [RBP] []( const zydis_decoded_instr_t &instr ) -> bool { diff --git a/src/vmutils.cpp b/src/vmutils.cpp index cb8d53f..147b5f4 100644 --- a/src/vmutils.cpp +++ b/src/vmutils.cpp @@ -24,7 +24,6 @@ namespace vm ZydisFormatter formatter; ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL ); ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), 0u ); - puts( buffer ); } @@ -38,7 +37,6 @@ namespace vm { std::printf( "> 0x%p ", addr ); ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); - puts( buffer ); } }