diff --git a/CMakeLists.txt b/CMakeLists.txt index 40cb428..1196e8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,7 @@ list(APPEND vmdevirt_SOURCES "src/devirt_utils.cpp" "src/lifters/add.cpp" "src/lifters/div.cpp" + "src/lifters/idiv.cpp" "src/lifters/imul.cpp" "src/lifters/jmp.cpp" "src/lifters/lconst.cpp" @@ -54,6 +55,7 @@ list(APPEND vmdevirt_SOURCES "src/lifters/popvsp.cpp" "src/lifters/pushvsp.cpp" "src/lifters/read.cpp" + "src/lifters/readcr3.cpp" "src/lifters/readcr8.cpp" "src/lifters/readgs.cpp" "src/lifters/sflags.cpp" @@ -64,6 +66,7 @@ list(APPEND vmdevirt_SOURCES "src/lifters/sreg.cpp" "src/lifters/vmexit.cpp" "src/lifters/write.cpp" + "src/lifters/writecr3.cpp" "src/main.cpp" "src/vmp_rtn_t.cpp" "include/devirt_t.hpp" diff --git a/include/vm_lifters.hpp b/include/vm_lifters.hpp index 835d2e1..c7d07d3 100644 --- a/include/vm_lifters.hpp +++ b/include/vm_lifters.hpp @@ -44,13 +44,16 @@ namespace vm static lifter_callback_t shrq, shrdw, shrw; static lifter_callback_t shlq, shldw; static lifter_callback_t shlddw; - static lifter_callback_t shrdq; + static lifter_callback_t shrdq, shrddw; static lifter_callback_t jmp; static lifter_callback_t lflagsq; static lifter_callback_t vmexit; static lifter_callback_t readcr8; + static lifter_callback_t readcr3; + static lifter_callback_t writecr3; static lifter_callback_t readgsq; static lifter_callback_t divdw; + static lifter_callback_t idivdw; std::map< vm::handler::mnemonic_t, lifter_callback_t * > lifters = { { vm::handler::LCONSTQ, &lconstq }, { vm::handler::LCONSTDW, &lconstdw }, @@ -62,6 +65,7 @@ namespace vm { vm::handler::LCONSTWSXDW, &lconstwsxdw }, { vm::handler::LCONSTBSXDW, &lconstbsxdw }, { vm::handler::DIVDW, &divdw }, + { vm::handler::IDIVDW, &idivdw }, { vm::handler::ADDQ, &addq }, { vm::handler::ADDDW, &adddw }, { vm::handler::ADDW, &addw }, @@ -73,6 +77,7 @@ namespace vm { vm::handler::SHLDW, &shldw }, { vm::handler::SHLDDW, &shlddw }, { vm::handler::SHRDQ, &shrdq }, + { vm::handler::SHRDDW, &shrddw }, { vm::handler::IMULQ, &imulq }, { vm::handler::IMULDW, &imuldw }, { vm::handler::MULQ, &mulq }, @@ -98,6 +103,8 @@ namespace vm { vm::handler::NANDB, &nandb }, { vm::handler::LFLAGSQ, &lflagsq }, { vm::handler::READCR8, &readcr8 }, + { vm::handler::READCR3, &readcr3 }, + { vm::handler::WRITECR3, &writecr3 }, { vm::handler::READGSQ, &readgsq }, { vm::handler::JMP, &jmp }, { vm::handler::VMEXIT, &vmexit } }; diff --git a/src/lifters/idiv.cpp b/src/lifters/idiv.cpp new file mode 100644 index 0000000..ff00c8c --- /dev/null +++ b/src/lifters/idiv.cpp @@ -0,0 +1,20 @@ +#include + +namespace vm +{ + lifters_t::lifter_callback_t lifters_t::idivdw = + [ & ]( vm::devirt_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 ); + + // TODO: this is wrong... + ir_builder->CreateUDiv( t1, t2 ); + rtn->push( 4, t1 ); + rtn->push( 4, t2 ); + + auto &vmp_rtn = rtn->vmp_rtns.back(); + // TODO: compute flags... + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; +} \ No newline at end of file diff --git a/src/lifters/readcr3.cpp b/src/lifters/readcr3.cpp new file mode 100644 index 0000000..15ec784 --- /dev/null +++ b/src/lifters/readcr3.cpp @@ -0,0 +1,30 @@ +#include + +namespace vm +{ + lifters_t::lifter_callback_t lifters_t::readcr3 = + [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, const vm::instrs::virt_instr_t &vinstr, + llvm::IRBuilder<> *ir_builder ) { + llvm::Function *readcr3_intrin = nullptr; + if ( !( readcr3_intrin = rtn->llvm_module->getFunction( "readcr3" ) ) ) + { + readcr3_intrin = llvm::Function::Create( llvm::FunctionType::get( ir_builder->getInt64Ty(), false ), + llvm::GlobalValue::LinkageTypes::ExternalLinkage, "readcr3", + *rtn->llvm_module ); + + auto entry_block = llvm::BasicBlock::Create( ir_builder->getContext(), "", readcr3_intrin ); + auto ib = ir_builder->GetInsertBlock(); + ir_builder->SetInsertPoint( entry_block ); + + std::string asm_str( "mov rax, cr3; ret" ); + auto intrin = llvm::InlineAsm::get( llvm::FunctionType::get( ir_builder->getVoidTy(), false ), asm_str, + "", false, false, llvm::InlineAsm::AD_Intel ); + + ir_builder->CreateCall( intrin ); + ir_builder->CreateRet( llvm::ConstantInt::get( *rtn->llvm_ctx, llvm::APInt( 64, 0 ) ) ); + ir_builder->SetInsertPoint( ib ); + } + auto t1 = ir_builder->CreateCall( readcr3_intrin ); + rtn->push( 8, t1 ); + }; +} \ No newline at end of file diff --git a/src/lifters/shrd.cpp b/src/lifters/shrd.cpp index 758ee04..36f88d6 100644 --- a/src/lifters/shrd.cpp +++ b/src/lifters/shrd.cpp @@ -18,4 +18,21 @@ namespace vm // TODO: update rflags... rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); }; -} \ No newline at end of file + + lifters_t::lifter_callback_t lifters_t::shrddw = + [ & ]( vm::devirt_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 = rtn->pop( 2 ); + + // TODO: this is wrong - replace with more logic! + auto t4 = ir_builder->CreateLShr( t1, ir_builder->CreateIntCast( t3, ir_builder->getInt32Ty(), false ) ); + + rtn->push( 4, t4 ); + auto &vmp_rtn = rtn->vmp_rtns.back(); + + // TODO: update rflags... + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; +} // namespace vm \ No newline at end of file diff --git a/src/lifters/writecr3.cpp b/src/lifters/writecr3.cpp new file mode 100644 index 0000000..4568e08 --- /dev/null +++ b/src/lifters/writecr3.cpp @@ -0,0 +1,31 @@ +#include + +namespace vm +{ + lifters_t::lifter_callback_t lifters_t::writecr3 = + [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, const vm::instrs::virt_instr_t &vinstr, + llvm::IRBuilder<> *ir_builder ) { + llvm::Function *writecr3_intrin = nullptr; + if ( !( writecr3_intrin = rtn->llvm_module->getFunction( "writecr3" ) ) ) + { + writecr3_intrin = llvm::Function::Create( + llvm::FunctionType::get( ir_builder->getVoidTy(), { ir_builder->getInt64Ty() }, false ), + llvm::GlobalValue::LinkageTypes::ExternalLinkage, "writecr3", *rtn->llvm_module ); + + auto entry_block = llvm::BasicBlock::Create( ir_builder->getContext(), "", writecr3_intrin ); + auto ib = ir_builder->GetInsertBlock(); + ir_builder->SetInsertPoint( entry_block ); + + std::string asm_str( "mov cr3, rcx; ret" ); + auto intrin = llvm::InlineAsm::get( + llvm::FunctionType::get( ir_builder->getVoidTy(), false ), asm_str, + "", false, false, llvm::InlineAsm::AD_Intel ); + + ir_builder->CreateCall( intrin ); + ir_builder->CreateRetVoid(); + ir_builder->SetInsertPoint( ib ); + } + auto t1 = rtn->pop( 8 ); + ir_builder->CreateCall( writecr3_intrin, { t1 } ); + }; +} \ No newline at end of file