diff --git a/include/vm_lifters.hpp b/include/vm_lifters.hpp index e2d4bb7..f6dc366 100644 --- a/include/vm_lifters.hpp +++ b/include/vm_lifters.hpp @@ -24,16 +24,25 @@ namespace vmp2::lifters extern lifter_callback_t lconstq; extern lifter_callback_t lconstdwsxq; + extern lifter_callback_t lconstwsxq; extern lifter_callback_t pushvsp; + extern lifter_callback_t addq; + extern lifter_callback_t adddw; + extern lifter_callback_t addw; + extern lifter_callback_t sregq; extern lifter_callback_t lregq; + extern lifter_callback_t readq; + inline std::map< vm::handler::mnemonic_t, lifter_callback_t * > lifters = { - { vm::handler::LCONSTQ, &lconstq }, { vm::handler::LCONSTDWSXQ, &lconstdwsxq }, - { vm::handler::ADDQ, &addq }, { vm::handler::PUSHVSP, &pushvsp }, - { vm::handler::SREGQ, &sregq }, { vm::handler::LREGQ, &lregq } }; + { vm::handler::LCONSTQ, &lconstq }, { vm::handler::LCONSTDWSXQ, &lconstdwsxq }, + { vm::handler::LCONSTWSXQ, &lconstwsxq }, { vm::handler::ADDQ, &addq }, + { vm::handler::ADDDW, &adddw }, { vm::handler::ADDW, &addw }, + { vm::handler::PUSHVSP, &pushvsp }, { vm::handler::SREGQ, &sregq }, + { vm::handler::LREGQ, &lregq }, { vm::handler::READQ, &readq } }; inline bool lift( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block, const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) diff --git a/include/vmp_rtn.hpp b/include/vmp_rtn.hpp index 40fdd00..c794615 100644 --- a/include/vmp_rtn.hpp +++ b/include/vmp_rtn.hpp @@ -30,7 +30,7 @@ namespace vm std::uintptr_t rtn_begin; llvm::Function *llvm_fptr; std::shared_ptr< llvm::IRBuilder<> > ir_builder; - llvm::AllocaInst *virtual_stack, *stack_ptr; + llvm::AllocaInst *virtual_stack, *stack_ptr, *flags; std::map< ZydisRegister, llvm::GlobalVariable * > native_registers; std::vector< llvm::AllocaInst * > virtual_registers; diff --git a/src/lifters/add.cpp b/src/lifters/add.cpp index e8e668d..945778c 100644 --- a/src/lifters/add.cpp +++ b/src/lifters/add.cpp @@ -7,11 +7,44 @@ namespace vmp2::lifters auto t1 = rtn->pop( 8 ); auto t2 = rtn->pop( 8 ); auto t3 = ir_builder->CreateAdd( t1, t2 ); - - rtn->push( 8, t1 ); rtn->push( 8, t3 ); // TODO: compute and update RFLAGS... - rtn->push( 8, rtn->load_value( 8, rtn->native_registers[ ZYDIS_REGISTER_RFLAGS ] ) ); + // do the updating here on rtn->flags before we push it... + // + // + + rtn->push( 8, rtn->load_value( 8, rtn->flags ) ); + }; + + lifter_callback_t adddw = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block, + const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { + auto t1 = rtn->pop( 4 ); + auto t2 = rtn->pop( 4 ); + auto t3 = ir_builder->CreateAdd( t1, t2 ); + rtn->push( 4, t3 ); + + // TODO: compute and update RFLAGS... + // do the updating here on rtn->flags before we push it... + // + // + + rtn->push( 8, rtn->load_value( 8, rtn->flags ) ); + }; + + lifter_callback_t addw = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block, + const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { + auto t1 = rtn->pop( 2 ); + auto t2 = rtn->pop( 2 ); + auto t3 = ir_builder->CreateAdd( t1, t2 ); + rtn->push( 2, t3 ); + + // TODO: compute and update RFLAGS... + // do the updating here on rtn->flags before we push it... + // + // + + rtn->push( 8, rtn->load_value( 8, rtn->flags ) ); }; -} \ No newline at end of file + +} // namespace vmp2::lifters \ No newline at end of file diff --git a/src/lifters/lconst.cpp b/src/lifters/lconst.cpp index 0de0f38..55cfbc7 100644 --- a/src/lifters/lconst.cpp +++ b/src/lifters/lconst.cpp @@ -11,4 +11,9 @@ namespace vmp2::lifters const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { rtn->push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), vinstr.operand.imm.u ) ); }; + + lifter_callback_t lconstwsxq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block, + const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { + rtn->push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), vinstr.operand.imm.u ) ); + }; } // namespace vmp2::lifters \ No newline at end of file diff --git a/src/lifters/read.cpp b/src/lifters/read.cpp index e69de29..1fd2b8a 100644 --- a/src/lifters/read.cpp +++ b/src/lifters/read.cpp @@ -0,0 +1,12 @@ +#include + +namespace vmp2::lifters +{ + lifter_callback_t readq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block, + const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { + auto t1 = rtn->pop( 8 ); + auto t2 = ir_builder->CreateIntToPtr( t1, llvm::PointerType::get( ir_builder->getInt64Ty(), 0ull ) ); + auto t3 = ir_builder->CreateLoad( ir_builder->getInt64Ty(), t2 ); + rtn->push( 8, t3 ); + }; +} \ No newline at end of file diff --git a/src/lifters/sreg.cpp b/src/lifters/sreg.cpp index 52322b4..3125176 100644 --- a/src/lifters/sreg.cpp +++ b/src/lifters/sreg.cpp @@ -9,6 +9,6 @@ namespace vmp2::lifters const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { auto t1 = rtn->pop( 8 ); auto vreg = rtn->virtual_registers[ vinstr.operand.imm.u ? vinstr.operand.imm.u / 8 : 0 ]; - ir_builder->CreateStore( t1, vreg ); + ir_builder->CreateStore( t1, vreg )->setAlignment( llvm::Align( 8 ) ); }; } // namespace vmp2::lifters \ No newline at end of file diff --git a/src/vmp_rtn.cpp b/src/vmp_rtn.cpp index dd1606b..0543411 100644 --- a/src/vmp_rtn.cpp +++ b/src/vmp_rtn.cpp @@ -111,6 +111,7 @@ namespace vm llvm_module->getOrInsertGlobal( "rflags", ir_builder->getInt64Ty() ); native_registers[ ZYDIS_REGISTER_RFLAGS ] = llvm_module->getGlobalVariable( "rflags" ); + flags = ir_builder->CreateAlloca( ir_builder->getInt64Ty(), nullptr, "flags" ); } void vmp_rtn_t::create_virtual_registers( void ) @@ -147,11 +148,11 @@ namespace vm void vmp_rtn_t::push( std::uint8_t byte_size, llvm::Value *input_value ) { // Load the current stack index into a temporary variable - auto current_stack_index = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), stack_ptr, false ); + auto current_stack_index = ir_builder->CreateLoad( ir_builder->getInt64Ty(), stack_ptr, false ); // Subtract the input value size from the current stack index - auto new_stack_index = ir_builder->CreateSub( - current_stack_index, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), byte_size ) ); + auto new_stack_index = + ir_builder->CreateSub( current_stack_index, llvm::ConstantInt::get( ir_builder->getInt64Ty(), byte_size ) ); // Store the newly calculated stack index into VSP ir_builder->CreateStore( new_stack_index, stack_ptr ); @@ -178,67 +179,56 @@ namespace vm llvm::Value *vmp_rtn_t::pop( std::uint8_t byte_size ) { - // Load the current stack index into a temporary variable - auto current_stack_index = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), stack_ptr, false ); + llvm::Value *output_value = nullptr; + auto current_spi = ir_builder->CreateLoad( ir_builder->getInt64Ty(), stack_ptr, false ); - // Get a pointer to the top byte of the stack llvm::Value *i64_zero = llvm::ConstantInt::get( *llvm_ctx, llvm::APInt( 64, 0 ) ); - llvm::Value *indices[ 2 ] = { i64_zero, current_stack_index }; - auto stack_ptr = ir_builder->CreateInBoundsGEP( virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) ); + llvm::Value *indices[ 2 ] = { i64_zero, current_spi }; + auto top_stack = ir_builder->CreateInBoundsGEP( virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) ); - // Read the value at the top of the stack - llvm::Value *output_value = nullptr; - - if ( byte_size == 1 ) - { - output_value = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 8 ), stack_ptr ); - } - else + if ( byte_size > 1 ) { - // Cast the current stack pointer so the stack item width matches the width of the output value auto casted_ptr = ir_builder->CreatePointerCast( - stack_ptr, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), 0 ) ); + top_stack, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), 0 ) ); output_value = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), casted_ptr ); } + else + output_value = ir_builder->CreateLoad( ir_builder->getInt8Ty(), top_stack ); - // Subtract the input value size from the current stack index auto new_stack_index = ir_builder->CreateAdd( - current_stack_index, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), byte_size ) ); + current_spi, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), byte_size ) ); - // Store the newly calculated stack index into VSP - ir_builder->CreateStore( new_stack_index, this->stack_ptr ); + ir_builder->CreateStore( new_stack_index, stack_ptr ); return output_value; } llvm::Value *vmp_rtn_t::peek( std::uint8_t byte_size, std::uint8_t byte_offset ) { - // Load the current stack index into a temporary variable - auto current_stack_index = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), stack_ptr, false ); + auto current_spi = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), stack_ptr, false ); if ( byte_offset ) { auto t1 = ir_builder->CreateAdd( - current_stack_index, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), byte_offset ) ); + current_spi, llvm::ConstantInt::get( llvm::IntegerType::get( *llvm_ctx, 64 ), byte_offset ) ); - current_stack_index = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), t1, false ); + current_spi = ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, 64 ), t1, false ); } - // Get a pointer to the top byte of the stack + byte_offset (if any) llvm::Value *i64_zero = llvm::ConstantInt::get( *llvm_ctx, llvm::APInt( 64, 0 ) ); - llvm::Value *indices[ 2 ] = { i64_zero, current_stack_index }; - auto stack_ptr = ir_builder->CreateInBoundsGEP( virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) ); + llvm::Value *indices[ 2 ] = { i64_zero, current_spi }; + auto top_stack = ir_builder->CreateInBoundsGEP( virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) ); - if ( byte_size != 1 ) + if ( byte_size > 1 ) { auto casted_ptr = ir_builder->CreatePointerCast( - stack_ptr, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), 0 ) ); + top_stack, llvm::PointerType::get( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), 0 ) ); return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), casted_ptr ); } else { - return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), stack_ptr ); + return ir_builder->CreateLoad( llvm::IntegerType::get( *llvm_ctx, byte_size * 8 ), top_stack ); } }