|
|
@ -5,25 +5,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
namespace vm
|
|
|
|
namespace vm
|
|
|
|
{
|
|
|
|
{
|
|
|
|
namespace calc_jmp
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
bool get( const zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::optional< vmp2::exec_type_t > get_advancement( const zydis_routine_t &calc_jmp );
|
|
|
|
|
|
|
|
} // namespace calc_jmp
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace instrs
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// decrypt transformations for encrypted virtual instruction rva...
|
|
|
|
|
|
|
|
bool get_rva_decrypt( const zydis_routine_t &vm_entry, std::vector< zydis_decoded_instr_t > &transform_instrs );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::pair< std::uint64_t, std::uint64_t > decrypt_operand( transform::map_t &transforms, std::uint64_t operand,
|
|
|
|
|
|
|
|
std::uint64_t rolling_key );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::pair< std::uint64_t, std::uint64_t > encrypt_operand( transform::map_t &transforms, std::uint64_t operand,
|
|
|
|
|
|
|
|
std::uint64_t rolling_key );
|
|
|
|
|
|
|
|
} // namespace instrs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace handler
|
|
|
|
namespace handler
|
|
|
|
{
|
|
|
|
{
|
|
|
|
using instr_callback_t = bool ( * )( const zydis_decoded_instr_t &instr );
|
|
|
|
using instr_callback_t = bool ( * )( const zydis_decoded_instr_t &instr );
|
|
|
@ -187,4 +168,89 @@ namespace vm
|
|
|
|
&lrflags, &vmexit, &call };
|
|
|
|
&lrflags, &vmexit, &call };
|
|
|
|
} // namespace profile
|
|
|
|
} // namespace profile
|
|
|
|
} // namespace handler
|
|
|
|
} // namespace handler
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ctx_t
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
explicit ctx_t( std::uintptr_t module_base, std::uintptr_t image_base, std::uint32_t vm_entry_rva );
|
|
|
|
|
|
|
|
ctx_t( std::vector< vm::handler::handler_t > &vm_handlers, zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp,
|
|
|
|
|
|
|
|
vmp2::exec_type_t exec_type );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vmp2::exec_type_t exec_type;
|
|
|
|
|
|
|
|
zydis_routine_t vm_entry, calc_jmp;
|
|
|
|
|
|
|
|
std::vector< vm::handler::handler_t > vm_handlers;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace instrs
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct virt_instr_t
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
vm::handler::mnemonic_t mnemonic_t;
|
|
|
|
|
|
|
|
std::uint8_t opcode; // aka vm handler idx...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// can be used to look at values on the stack...
|
|
|
|
|
|
|
|
vmp2::v2::entry_t trace_data;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
bool has_imm;
|
|
|
|
|
|
|
|
struct
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::uint8_t imm_size; // size in bits...
|
|
|
|
|
|
|
|
union
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::int64_t s;
|
|
|
|
|
|
|
|
std::uint64_t u;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
} imm;
|
|
|
|
|
|
|
|
} operand;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum class jcc_type
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
none,
|
|
|
|
|
|
|
|
branching,
|
|
|
|
|
|
|
|
absolute
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct code_block_t
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
bool has_jcc;
|
|
|
|
|
|
|
|
jcc_type type;
|
|
|
|
|
|
|
|
std::uint32_t block_rva[ 2 ];
|
|
|
|
|
|
|
|
} jcc;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::uint32_t code_block_rva;
|
|
|
|
|
|
|
|
std::vector< virt_instr_t > vinstrs;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// decrypt transformations for encrypted virtual instruction rva...
|
|
|
|
|
|
|
|
bool get_rva_decrypt( const zydis_routine_t &vm_entry, std::vector< zydis_decoded_instr_t > &transform_instrs );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::pair< std::uint64_t, std::uint64_t > decrypt_operand( transform::map_t &transforms, std::uint64_t operand,
|
|
|
|
|
|
|
|
std::uint64_t rolling_key );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::pair< std::uint64_t, std::uint64_t > encrypt_operand( transform::map_t &transforms, std::uint64_t operand,
|
|
|
|
|
|
|
|
std::uint64_t rolling_key );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::optional< virt_instr_t > get( vm::ctx_t &ctx, vmp2::v2::entry_t &entry );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// gets the second operand (imm) given vip and vm::ctx_t...
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <param name="ctx">vm context</param>
|
|
|
|
|
|
|
|
/// <param name="imm_size">immediate value size in bits...</param>
|
|
|
|
|
|
|
|
/// <param name="vip">virtual instruction pointer, linear virtual address...</param>
|
|
|
|
|
|
|
|
/// <returns>returns immediate value if imm_size is not 0...</returns>
|
|
|
|
|
|
|
|
std::optional< std::uint64_t > get_imm( vm::ctx_t &ctx, std::uint8_t imm_size, std::uintptr_t vip );
|
|
|
|
|
|
|
|
} // namespace instrs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace calc_jmp
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
bool get( const zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::optional< vmp2::exec_type_t > get_advancement( const zydis_routine_t &calc_jmp );
|
|
|
|
|
|
|
|
} // namespace calc_jmp
|
|
|
|
} // namespace vm
|
|
|
|
} // namespace vm
|