diff --git a/CMakeLists.txt b/CMakeLists.txt index 1196e8c..34c833c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,7 @@ list(APPEND vmdevirt_SOURCES "src/lifters/nand.cpp" "src/lifters/popvsp.cpp" "src/lifters/pushvsp.cpp" + "src/lifters/rdtsc.cpp" "src/lifters/read.cpp" "src/lifters/readcr3.cpp" "src/lifters/readcr8.cpp" diff --git a/include/vm_lifters.hpp b/include/vm_lifters.hpp index 94e87ec..5ce6e32 100644 --- a/include/vm_lifters.hpp +++ b/include/vm_lifters.hpp @@ -42,7 +42,7 @@ namespace vm static lifter_callback_t readq, readdw, readw, readb; static lifter_callback_t nandq, nanddw, nandw, nandb; static lifter_callback_t shrq, shrdw, shrw, shrb; - static lifter_callback_t shlq, shldw; + static lifter_callback_t shlq, shldw, shlb; static lifter_callback_t shldq, shlddw; static lifter_callback_t shrdq, shrddw; static lifter_callback_t jmp; @@ -51,8 +51,9 @@ namespace vm static lifter_callback_t readcr8; static lifter_callback_t readcr3; static lifter_callback_t writecr3; + static lifter_callback_t rdtsc; static lifter_callback_t readgsq; - static lifter_callback_t divdw; + static lifter_callback_t divq, divdw; static lifter_callback_t idivdw; std::map< vm::handler::mnemonic_t, lifter_callback_t * > lifters = { { vm::handler::LCONSTQ, &lconstq }, @@ -64,6 +65,7 @@ namespace vm { vm::handler::LCONSTBSXQ, &lconstbsxq }, { vm::handler::LCONSTWSXDW, &lconstwsxdw }, { vm::handler::LCONSTBSXDW, &lconstbsxdw }, + { vm::handler::DIVQ, &divq }, { vm::handler::DIVDW, &divdw }, { vm::handler::IDIVDW, &idivdw }, { vm::handler::ADDQ, &addq }, @@ -76,6 +78,7 @@ namespace vm { vm::handler::SHRB, &shrb }, { vm::handler::SHLQ, &shlq }, { vm::handler::SHLDW, &shldw }, + { vm::handler::SHLB, &shlb }, { vm::handler::SHLDQ, &shldq }, { vm::handler::SHLDDW, &shlddw }, { vm::handler::SHRDQ, &shrdq }, @@ -109,6 +112,7 @@ namespace vm { vm::handler::READCR8, &readcr8 }, { vm::handler::READCR3, &readcr3 }, { vm::handler::WRITECR3, &writecr3 }, + { vm::handler::RDTSC, &rdtsc }, { vm::handler::READGSQ, &readgsq }, { vm::handler::JMP, &jmp }, { vm::handler::VMEXIT, &vmexit } }; diff --git a/src/devirt_t.cpp b/src/devirt_t.cpp index 478f3e5..5e1dad3 100644 --- a/src/devirt_t.cpp +++ b/src/devirt_t.cpp @@ -115,6 +115,9 @@ namespace vm for ( auto idx = 0u; idx < vmp_rtn->vmp2_code_blocks.size(); ++idx ) { + if ( vmp_rtn->vmp2_code_blocks[ idx ].vinstrs.size() < 35 ) + continue; + ir_builder->SetInsertPoint( vmp_rtn->llvm_code_blocks[ idx ].second ); for ( auto &vinstr : vmp_rtn->vmp2_code_blocks[ idx ].vinstrs ) { diff --git a/src/lifters/div.cpp b/src/lifters/div.cpp index 72cf65f..f13e8e0 100644 --- a/src/lifters/div.cpp +++ b/src/lifters/div.cpp @@ -2,6 +2,21 @@ namespace vm { + lifters_t::lifter_callback_t lifters_t::divq = + [ & ]( 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( 8 ); + auto t2 = rtn->pop( 8 ); + auto t3 = rtn->pop( 8 ); + ir_builder->CreateUDiv( t2, t3 ); + rtn->push( 8, t1 ); + rtn->push( 8, t2 ); + + auto &vmp_rtn = rtn->vmp_rtns.back(); + // TODO: compute flags... + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; + lifters_t::lifter_callback_t lifters_t::divdw = [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { @@ -16,4 +31,4 @@ namespace vm // TODO: compute flags... rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); }; -} \ No newline at end of file +} // namespace vm \ No newline at end of file diff --git a/src/lifters/jmp.cpp b/src/lifters/jmp.cpp index ba9325e..385bbb0 100644 --- a/src/lifters/jmp.cpp +++ b/src/lifters/jmp.cpp @@ -5,8 +5,8 @@ namespace vm lifters_t::lifter_callback_t lifters_t::jmp = [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { - assert( vm_code_block.jcc.has_jcc, "[!] fatal error in vmemu... virtual block ending with jmp marked as" - " has_jcc = false... debug time!\n" ); + if ( !vm_code_block.jcc.has_jcc ) + return; auto &vmp_rtn = rtn->vmp_rtns.back(); switch ( vm_code_block.jcc.type ) diff --git a/src/lifters/rdtsc.cpp b/src/lifters/rdtsc.cpp new file mode 100644 index 0000000..c456ff5 --- /dev/null +++ b/src/lifters/rdtsc.cpp @@ -0,0 +1,32 @@ +#include + +namespace vm +{ + lifters_t::lifter_callback_t lifters_t::rdtsc = + [ & ]( 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 *rdtsc_intrin = nullptr; + if ( !( rdtsc_intrin = rtn->llvm_module->getFunction( "rdtsc" ) ) ) + { + rdtsc_intrin = llvm::Function::Create( + llvm::FunctionType::get( ir_builder->getVoidTy(), + { llvm::PointerType::get( ir_builder->getInt8Ty(), 0ull ) }, false ), + llvm::GlobalValue::LinkageTypes::ExternalLinkage, "rdtsc", *rtn->llvm_module ); + + auto entry_block = llvm::BasicBlock::Create( ir_builder->getContext(), "", rdtsc_intrin ); + auto ib = ir_builder->GetInsertBlock(); + ir_builder->SetInsertPoint( entry_block ); + + std::string asm_str( "rdtsc; sub rbp, 0x08; mov [rcx], edx; mov [rcx+0x04], eax; 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 &vmp_rtn = rtn->vmp_rtns.back(); + ir_builder->CreateCall( rdtsc_intrin, { vmp_rtn->stack } ); + }; +} \ No newline at end of file diff --git a/src/lifters/shl.cpp b/src/lifters/shl.cpp index fa34a94..d2c6ecd 100644 --- a/src/lifters/shl.cpp +++ b/src/lifters/shl.cpp @@ -31,4 +31,20 @@ namespace vm rtn->push( 4, t4 ); rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); }; + + lifters_t::lifter_callback_t lifters_t::shlb = + [ & ]( 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( 2 ); + auto t2 = rtn->pop( 2 ); + auto t3 = ir_builder->CreateIntCast( t1, ir_builder->getInt8Ty(), false ); + auto t4 = ir_builder->CreateIntCast( t2, ir_builder->getInt8Ty(), false ); + auto t5 = ir_builder->CreateShl( t3, t4 ); + + auto &vmp_rtn = rtn->vmp_rtns.back(); + // TODO: update rflags... + + rtn->push( 2, ir_builder->CreateIntCast( t5, ir_builder->getInt16Ty(), false ) ); + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; } // namespace vm \ No newline at end of file