diff --git a/CMakeLists.txt b/CMakeLists.txt index ac51295..34c833c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,8 @@ 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" "src/lifters/lflags.cpp" @@ -52,13 +54,20 @@ 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" + "src/lifters/readgs.cpp" "src/lifters/sflags.cpp" "src/lifters/shl.cpp" + "src/lifters/shld.cpp" "src/lifters/shr.cpp" + "src/lifters/shrd.cpp" "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/dependencies/vmprofiler b/dependencies/vmprofiler index 7b1f815..1b6875d 160000 --- a/dependencies/vmprofiler +++ b/dependencies/vmprofiler @@ -1 +1 @@ -Subproject commit 7b1f815a73096ac33f41133b63d991019622de49 +Subproject commit 1b6875d18825529907289bc87990fed5d99e7f96 diff --git a/include/vm_lifters.hpp b/include/vm_lifters.hpp index cb6dc90..5ce6e32 100644 --- a/include/vm_lifters.hpp +++ b/include/vm_lifters.hpp @@ -29,48 +29,91 @@ namespace vm const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) >; static lifter_callback_t lconstq, lconstdwsxq, lconstwsxq, lconstbzxw, lconstbsxq, lconstwsxdw, lconstdw, - lconstbsxdw; + lconstw, lconstbsxdw; - static lifter_callback_t addq, adddw, addw; - static lifter_callback_t sregq, sregdw, sregb; + static lifter_callback_t addq, adddw, addw, addb; + static lifter_callback_t sregq, sregdw, sregw, sregb; static lifter_callback_t lregq, lregdw; - - static lifter_callback_t pushvsp; + static lifter_callback_t imulq, imuldw; + static lifter_callback_t mulq, muldw; + static lifter_callback_t pushvspq, pushvspdw; static lifter_callback_t popvsp; - static lifter_callback_t writeq; - static lifter_callback_t readq, readdw; - static lifter_callback_t nandq, nanddw, nandb; - static lifter_callback_t shrq; + static lifter_callback_t writeq, writedw, writew, writeb; + 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, shlb; + static lifter_callback_t shldq, shlddw; + 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 rdtsc; + static lifter_callback_t readgsq; + 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 }, { vm::handler::LCONSTDW, &lconstdw }, + { vm::handler::LCONSTW, &lconstw }, { vm::handler::LCONSTDWSXQ, &lconstdwsxq }, { vm::handler::LCONSTWSXQ, &lconstwsxq }, { vm::handler::LCONSTBZXW, &lconstbzxw }, { 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 }, { vm::handler::ADDDW, &adddw }, { vm::handler::ADDW, &addw }, + { vm::handler::ADDB, &addb }, { vm::handler::SHRQ, &shrq }, - { vm::handler::PUSHVSP, &pushvsp }, - { vm::handler::POPVSP, &popvsp }, + { vm::handler::SHRDW, &shrdw }, + { vm::handler::SHRW, &shrw }, + { 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 }, + { vm::handler::SHRDDW, &shrddw }, + { vm::handler::IMULQ, &imulq }, + { vm::handler::IMULDW, &imuldw }, + { vm::handler::MULQ, &mulq }, + { vm::handler::MULDW, &muldw }, + { vm::handler::PUSHVSPQ, &pushvspq }, + { vm::handler::PUSHVSPDW, &pushvspdw }, + { vm::handler::POPVSPQ, &popvsp }, { vm::handler::SREGQ, &sregq }, { vm::handler::SREGDW, &sregdw }, + { vm::handler::SREGW, &sregw }, { vm::handler::SREGB, &sregb }, { vm::handler::LREGQ, &lregq }, { vm::handler::LREGDW, &lregdw }, { vm::handler::READQ, &readq }, { vm::handler::READDW, &readdw }, + { vm::handler::READW, &readw }, + { vm::handler::READB, &readb }, { vm::handler::WRITEQ, &writeq }, + { vm::handler::WRITEDW, &writedw }, + { vm::handler::WRITEW, &writew }, + { vm::handler::WRITEB, &writeb }, { vm::handler::NANDQ, &nandq }, { vm::handler::NANDDW, &nanddw }, + { vm::handler::NANDW, &nandw }, { vm::handler::NANDB, &nandb }, { vm::handler::LFLAGSQ, &lflagsq }, + { 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 } }; @@ -96,4 +139,4 @@ namespace vm return true; } }; -} // namespace vm +} // namespace vm \ No newline at end of file diff --git a/src/devirt_t.cpp b/src/devirt_t.cpp index 478f3e5..75805e6 100644 --- a/src/devirt_t.cpp +++ b/src/devirt_t.cpp @@ -85,6 +85,19 @@ namespace vm bool devirt_t::compile( std::vector< std::uint8_t > &obj ) { + llvm::legacy::FunctionPassManager pass_mgr( llvm_module ); + pass_mgr.add( llvm::createPromoteMemoryToRegisterPass() ); + pass_mgr.add( llvm::createNewGVNPass() ); + pass_mgr.add( llvm::createReassociatePass() ); + pass_mgr.add( llvm::createDeadCodeEliminationPass() ); + pass_mgr.add( llvm::createInstructionCombiningPass() ); + + for ( auto vmp_rtn : vmp_rtns ) + { + pass_mgr.run( *vmp_rtn->llvm_fptr ); + std::printf( "> opt rtn_0x%p\n", vmp_rtn->rtn_begin ); + } + llvm::TargetOptions opt; llvm::SmallVector< char, 128 > buff; llvm::raw_svector_ostream dest( buff ); @@ -116,6 +129,12 @@ namespace vm for ( auto idx = 0u; idx < vmp_rtn->vmp2_code_blocks.size(); ++idx ) { ir_builder->SetInsertPoint( vmp_rtn->llvm_code_blocks[ idx ].second ); + if ( vmp_rtn->vmp2_code_blocks[ idx ].vinstrs.size() < 35 ) + { + ir_builder->CreateRetVoid(); + continue; + } + for ( auto &vinstr : vmp_rtn->vmp2_code_blocks[ idx ].vinstrs ) { if ( !lifters->lift( this, vmp_rtn->vmp2_code_blocks[ idx ], vinstr, ir_builder.get() ) ) diff --git a/src/devirt_utils.cpp b/src/devirt_utils.cpp index ff8d310..255d97f 100644 --- a/src/devirt_utils.cpp +++ b/src/devirt_utils.cpp @@ -193,30 +193,6 @@ namespace devirt } } ); - auto resize_cnt = new_relocs.size() * ( sizeof( win::reloc_entry_t ) + sizeof( win::reloc_block_t ) ); - map_buff.resize( map_img->get_nt_headers()->optional_header.size_image += resize_cnt ); - - map_img = reinterpret_cast< win::image_t<> * >( map_buff.data() ); - auto basereloc_dir = map_img->get_directory( win::directory_id::directory_entry_basereloc ); - auto reloc_dir = reinterpret_cast< win::reloc_directory_t * >( basereloc_dir->rva + map_buff.data() ); - - basereloc_dir->size += resize_cnt; - for ( const auto &[ reloc_rva, reloc_offset ] : new_relocs ) - { - win::reloc_block_t *reloc_block = &reloc_dir->first_block; - while ( reloc_block->base_rva && reloc_block->size_block ) - reloc_block = reloc_block->next(); - - reloc_block->base_rva = reloc_rva; - reloc_block->size_block = sizeof( win::reloc_entry_t ) + sizeof uint64_t; - - reloc_block->next()->base_rva = 0ull; - reloc_block->next()->size_block = 0ull; - - reloc_block->entries[ 0 ].type = win::reloc_type_id::rel_based_dir64; - reloc_block->entries[ 0 ].offset = reloc_offset; - } - // replace bin vector with map_buff vector... bin.clear(); bin.insert( bin.begin(), map_buff.begin(), map_buff.end() ); diff --git a/src/lifters/add.cpp b/src/lifters/add.cpp index 9060c1d..0da5cd3 100644 --- a/src/lifters/add.cpp +++ b/src/lifters/add.cpp @@ -29,15 +29,15 @@ namespace vm auto pf = llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), 0 ); // TODO make clean PF bit computation... - auto flags_calc = rtn->flags( - cf, pf, llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), 0 ), zf, sf, of ); + auto flags_calc = + rtn->flags( cf, pf, llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), 0 ), zf, sf, of ); return flags_calc; } lifters_t::lifter_callback_t lifters_t::addq = - [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, - const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { + [ & ]( 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 = ir_builder->CreateAdd( t1, t2 ); @@ -50,8 +50,8 @@ namespace vm }; lifters_t::lifter_callback_t lifters_t::adddw = - [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, - const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { + [ & ]( 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 = ir_builder->CreateAdd( t1, t2 ); @@ -64,8 +64,8 @@ namespace vm }; lifters_t::lifter_callback_t lifters_t::addw = - [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, - const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { + [ & ]( 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->CreateAdd( t1, t2 ); @@ -77,4 +77,22 @@ namespace vm rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); }; + lifters_t::lifter_callback_t lifters_t::addb = + [ & ]( 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->CreateAdd( t3, t4 ); + rtn->push( 2, ir_builder->CreateIntCast( t5, ir_builder->getInt16Ty(), false ) ); + + auto &vmp_rtn = rtn->vmp_rtns.back(); + auto flags = lifters_t::add_flags( rtn, 1, t3, t4 ); + ir_builder->CreateStore( flags, vmp_rtn->flags ); + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; + } // namespace vm \ No newline at end of file diff --git a/src/lifters/div.cpp b/src/lifters/div.cpp index e69de29..f13e8e0 100644 --- a/src/lifters/div.cpp +++ b/src/lifters/div.cpp @@ -0,0 +1,34 @@ +#include + +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 ) { + auto t1 = rtn->pop( 4 ); + auto t2 = rtn->pop( 4 ); + auto t3 = rtn->pop( 4 ); + ir_builder->CreateUDiv( t2, t3 ); + 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 ) ); + }; +} // namespace vm \ No newline at end of file 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/imul.cpp b/src/lifters/imul.cpp new file mode 100644 index 0000000..506f54e --- /dev/null +++ b/src/lifters/imul.cpp @@ -0,0 +1,45 @@ +#include + +// https://lists.llvm.org/pipermail/llvm-dev/2014-July/074685.html +// credit to James Courtier-Dutton for asking this question in 2014... +namespace vm +{ + lifters_t::lifter_callback_t lifters_t::imulq = + [ & ]( 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 ); + + // TODO: this is wrong... still need to do some more research into this... + auto t3 = ir_builder->CreateMul( t1, t2 ); + auto t4 = ir_builder->CreateAShr( t3, llvm::APInt( 64, 32 ) ); + auto t5 = ir_builder->CreateAnd( t3, 0xFFFFFFFF00000000 ); + rtn->push( 8, t4 ); + rtn->push( 8, t5 ); + + // TODO: compute flags for IMULQ + auto &vmp_rtn = rtn->vmp_rtns.back(); + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; + + lifters_t::lifter_callback_t lifters_t::imuldw = + [ & ]( 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 = ir_builder->CreateIntCast( t1, ir_builder->getInt64Ty(), false ); + auto t4 = ir_builder->CreateIntCast( t2, ir_builder->getInt64Ty(), false ); + + auto t5 = ir_builder->CreateMul( t3, t4 ); + auto t6 = ir_builder->CreateAShr( t5, llvm::APInt( 64, 32 ) ); + auto t7 = ir_builder->CreateAnd( t5, 0xFFFFFFFF00000000 ); + + rtn->push( 8, t6 ); + rtn->push( 8, t7 ); + + // TODO: compute flags for IMULQ + auto &vmp_rtn = rtn->vmp_rtns.back(); + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; +} // namespace vm \ No newline at end of file diff --git a/src/lifters/jmp.cpp b/src/lifters/jmp.cpp index 43464ad..d23f62b 100644 --- a/src/lifters/jmp.cpp +++ b/src/lifters/jmp.cpp @@ -5,11 +5,16 @@ 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 ) + { + ir_builder->CreateRetVoid(); + return; + } auto &vmp_rtn = rtn->vmp_rtns.back(); - if ( vm_code_block.jcc.type == vm::instrs::jcc_type::branching ) + switch ( vm_code_block.jcc.type ) + { + case vm::instrs::jcc_type::branching: { auto rva = rtn->pop( 8 ); auto b1 = vm_code_block.jcc.block_addr[ 0 ] & std::numeric_limits< std::uint32_t >::max(); @@ -38,8 +43,9 @@ namespace vm "[!] fatal error... unable to locate basic block for branching...\n" ); ir_builder->CreateCondBr( cmp, bb1->second, bb2->second ); + break; } - else + case vm::instrs::jcc_type::absolute: { auto rva = rtn->pop( 8 ); auto bb_data = @@ -52,6 +58,15 @@ namespace vm "[!] fatal error... unable to locate basic block...\n" ); ir_builder->CreateBr( bb_data->second ); + break; + } + case vm::instrs::jcc_type::switch_case: + { + // TODO: add switch case support here... + break; + } + default: + break; } }; -} \ No newline at end of file +} // namespace vm \ No newline at end of file diff --git a/src/lifters/lconst.cpp b/src/lifters/lconst.cpp index 1e7d32e..4d5e81e 100644 --- a/src/lifters/lconst.cpp +++ b/src/lifters/lconst.cpp @@ -32,6 +32,12 @@ namespace vm rtn->push( 4, llvm::ConstantInt::get( ir_builder->getInt32Ty(), vinstr.operand.imm.u ) ); }; + lifters_t::lifter_callback_t lifters_t::lconstw = + [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, const vm::instrs::virt_instr_t &vinstr, + llvm::IRBuilder<> *ir_builder ) { + rtn->push( 2, llvm::ConstantInt::get( ir_builder->getInt16Ty(), vinstr.operand.imm.u ) ); + }; + lifters_t::lifter_callback_t lifters_t::lconstwsxdw = [ & ]( vm::devirt_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/src/lifters/mul.cpp b/src/lifters/mul.cpp index e69de29..a47789f 100644 --- a/src/lifters/mul.cpp +++ b/src/lifters/mul.cpp @@ -0,0 +1,40 @@ +#include + +namespace vm +{ + lifters_t::lifter_callback_t lifters_t::mulq = + [ & ]( 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 ); + + // TODO: this is wrong... still need to do some more research into this... + auto t3 = ir_builder->CreateMul( t1, t2 ); + auto t4 = ir_builder->CreateAShr( t3, llvm::APInt( 64, 32 ) ); + auto t5 = ir_builder->CreateAnd( t3, 0xFFFFFFFF00000000 ); + rtn->push( 8, t4 ); + rtn->push( 8, t5 ); + + // TODO: compute flags for IMULQ + auto &vmp_rtn = rtn->vmp_rtns.back(); + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; + + lifters_t::lifter_callback_t lifters_t::muldw = + [ & ]( 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... still need to do some more research into this... + auto t3 = ir_builder->CreateMul( t1, t2 ); + auto t4 = ir_builder->CreateAShr( t3, llvm::APInt( 32, 16 ) ); + auto t5 = ir_builder->CreateAnd( t3, 0xFFFF0000 ); + rtn->push( 4, t4 ); + rtn->push( 4, t5 ); + + // TODO: compute flags for IMULQ + auto &vmp_rtn = rtn->vmp_rtns.back(); + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; +} \ No newline at end of file diff --git a/src/lifters/nand.cpp b/src/lifters/nand.cpp index 58d1a6f..5640872 100644 --- a/src/lifters/nand.cpp +++ b/src/lifters/nand.cpp @@ -51,6 +51,24 @@ namespace vm rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); }; + lifters_t::lifter_callback_t lifters_t::nandw = + [ & ]( 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 t1_not = ir_builder->CreateNot( t1 ); + auto t2_not = ir_builder->CreateNot( t2 ); + + auto t3 = ir_builder->CreateAnd( { t1_not, t2_not } ); + rtn->push( 2, t3 ); + + auto &vmp_rtn = rtn->vmp_rtns.back(); + auto flags = and_flags( rtn, 2, t3 ); + ir_builder->CreateStore( flags, vmp_rtn->flags ); + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; + lifters_t::lifter_callback_t lifters_t::nandb = [ & ]( vm::devirt_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/src/lifters/pushvsp.cpp b/src/lifters/pushvsp.cpp index 0b91ba8..0e50fb4 100644 --- a/src/lifters/pushvsp.cpp +++ b/src/lifters/pushvsp.cpp @@ -2,7 +2,7 @@ namespace vm { - lifters_t::lifter_callback_t lifters_t::pushvsp = + lifters_t::lifter_callback_t lifters_t::pushvspq = [ & ]( 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 &vmp_rtn = rtn->vmp_rtns.back(); @@ -10,4 +10,13 @@ namespace vm auto stack_ptr = ir_builder->CreatePtrToInt( stack, ir_builder->getInt64Ty() ); rtn->push( 8, stack_ptr ); }; -} \ No newline at end of file + + lifters_t::lifter_callback_t lifters_t::pushvspdw = + [ & ]( 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 &vmp_rtn = rtn->vmp_rtns.back(); + auto stack = ir_builder->CreateLoad( vmp_rtn->stack ); + auto stack_ptr = ir_builder->CreatePtrToInt( stack, ir_builder->getInt32Ty() ); + rtn->push( 4, stack_ptr ); + }; +} // namespace vm \ No newline at end of file diff --git a/src/lifters/rdtsc.cpp b/src/lifters/rdtsc.cpp new file mode 100644 index 0000000..4f9b660 --- /dev/null +++ b/src/lifters/rdtsc.cpp @@ -0,0 +1,28 @@ +#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(), 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 ); + + // TODO: put RDTSC code here... + + ir_builder->CreateRetVoid(); + ir_builder->SetInsertPoint( ib ); + } + + auto &vmp_rtn = rtn->vmp_rtns.back(); + ir_builder->CreateCall( rdtsc_intrin ); + }; +} \ No newline at end of file diff --git a/src/lifters/read.cpp b/src/lifters/read.cpp index b92f53d..6bf602a 100644 --- a/src/lifters/read.cpp +++ b/src/lifters/read.cpp @@ -3,8 +3,8 @@ namespace vm { lifters_t::lifter_callback_t lifters_t::readq = - [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, - const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { + [ & ]( 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 = ir_builder->CreateIntToPtr( t1, llvm::PointerType::get( ir_builder->getInt64Ty(), 0ull ) ); auto t3 = ir_builder->CreateLoad( ir_builder->getInt64Ty(), t2 ); @@ -12,11 +12,30 @@ namespace vm }; lifters_t::lifter_callback_t lifters_t::readdw = - [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, - const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { + [ & ]( 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 = ir_builder->CreateIntToPtr( t1, llvm::PointerType::get( ir_builder->getInt32Ty(), 0ull ) ); auto t3 = ir_builder->CreateLoad( ir_builder->getInt32Ty(), t2 ); rtn->push( 4, t3 ); }; + + lifters_t::lifter_callback_t lifters_t::readw = + [ & ]( 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 = ir_builder->CreateIntToPtr( t1, llvm::PointerType::get( ir_builder->getInt16Ty(), 0ull ) ); + auto t3 = ir_builder->CreateLoad( ir_builder->getInt16Ty(), t2 ); + rtn->push( 2, t3 ); + }; + + lifters_t::lifter_callback_t lifters_t::readb = + [ & ]( 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 = ir_builder->CreateIntToPtr( t1, llvm::PointerType::get( ir_builder->getInt8Ty(), 0ull ) ); + auto t3 = ir_builder->CreateLoad( ir_builder->getInt8Ty(), t2 ); + auto t4 = ir_builder->CreateIntCast( t3, ir_builder->getInt16Ty(), false ); + rtn->push( 2, t4 ); + }; } // namespace vm \ 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/readcr8.cpp b/src/lifters/readcr8.cpp new file mode 100644 index 0000000..ac82132 --- /dev/null +++ b/src/lifters/readcr8.cpp @@ -0,0 +1,30 @@ +#include + +namespace vm +{ + lifters_t::lifter_callback_t lifters_t::readcr8 = + [ & ]( 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 *readcr8_intrin = nullptr; + if ( !( readcr8_intrin = rtn->llvm_module->getFunction( "readcr8" ) ) ) + { + readcr8_intrin = llvm::Function::Create( llvm::FunctionType::get( ir_builder->getInt64Ty(), false ), + llvm::GlobalValue::LinkageTypes::ExternalLinkage, "readcr8", + *rtn->llvm_module ); + + auto entry_block = llvm::BasicBlock::Create( ir_builder->getContext(), "", readcr8_intrin ); + auto ib = ir_builder->GetInsertBlock(); + ir_builder->SetInsertPoint( entry_block ); + + std::string asm_str( "mov rax, cr8; 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( readcr8_intrin ); + rtn->push( 8, t1 ); + }; +} \ No newline at end of file diff --git a/src/lifters/readgs.cpp b/src/lifters/readgs.cpp new file mode 100644 index 0000000..ada1ea5 --- /dev/null +++ b/src/lifters/readgs.cpp @@ -0,0 +1,32 @@ +#include + +namespace vm +{ + lifters_t::lifter_callback_t lifters_t::readgsq = + [ & ]( 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 *readgs_intrin = nullptr; + if ( !( readgs_intrin = rtn->llvm_module->getFunction( "readgs" ) ) ) + { + readgs_intrin = llvm::Function::Create( + llvm::FunctionType::get( ir_builder->getInt64Ty(), { ir_builder->getInt64Ty() }, false ), + llvm::GlobalValue::LinkageTypes::ExternalLinkage, "readgs", *rtn->llvm_module ); + + auto entry_block = llvm::BasicBlock::Create( ir_builder->getContext(), "", readgs_intrin ); + auto ib = ir_builder->GetInsertBlock(); + ir_builder->SetInsertPoint( entry_block ); + + std::string asm_str( "mov rax, gs:[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->CreateRet( llvm::ConstantInt::get( *rtn->llvm_ctx, llvm::APInt( 64, 0 ) ) ); + ir_builder->SetInsertPoint( ib ); + } + + auto t1 = rtn->pop( 8 ); + auto t2 = ir_builder->CreateCall( readgs_intrin, { t1 } ); + rtn->push( 8, t2 ); + }; +} // namespace vm \ No newline at end of file diff --git a/src/lifters/shl.cpp b/src/lifters/shl.cpp index e69de29..d2c6ecd 100644 --- a/src/lifters/shl.cpp +++ b/src/lifters/shl.cpp @@ -0,0 +1,50 @@ +#include + +namespace vm +{ + lifters_t::lifter_callback_t lifters_t::shlq = + [ & ]( 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( 2 ); + auto t3 = ir_builder->CreateIntCast( t2, llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), false ); + auto t4 = ir_builder->CreateShl( t1, t3 ); + + auto &vmp_rtn = rtn->vmp_rtns.back(); + // TODO: update rflags... + + rtn->push( 8, t4 ); + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; + + lifters_t::lifter_callback_t lifters_t::shldw = + [ & ]( 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( 2 ); + auto t3 = ir_builder->CreateIntCast( t2, llvm::IntegerType::get( *rtn->llvm_ctx, 32 ), false ); + auto t4 = ir_builder->CreateShl( t1, t3 ); + + auto &vmp_rtn = rtn->vmp_rtns.back(); + // TODO: update rflags... + + 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 diff --git a/src/lifters/shld.cpp b/src/lifters/shld.cpp new file mode 100644 index 0000000..ca14358 --- /dev/null +++ b/src/lifters/shld.cpp @@ -0,0 +1,38 @@ +#include + +namespace vm +{ + lifters_t::lifter_callback_t lifters_t::shldq = + [ & ]( 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( 2 ); + + // TODO: this is wrong - replace with more logic! + auto t4 = ir_builder->CreateShl( t1, ir_builder->CreateIntCast( t3, ir_builder->getInt64Ty(), false ) ); + + rtn->push( 8, t4 ); + auto &vmp_rtn = rtn->vmp_rtns.back(); + + // TODO: update rflags... + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; + + lifters_t::lifter_callback_t lifters_t::shlddw = + [ & ]( 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->CreateShl( 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/shr.cpp b/src/lifters/shr.cpp index 03a74f6..50c3874 100644 --- a/src/lifters/shr.cpp +++ b/src/lifters/shr.cpp @@ -2,7 +2,6 @@ namespace vm { - // our undefined behavior is that we don't model cases where the shift count is zero... llvm::Value *lifters_t::shr_flags( vm::devirt_t *rtn, std::uint8_t byte_size, llvm::Value *lhs, llvm::Value *rhs, llvm::Value *result ) { @@ -10,19 +9,18 @@ namespace vm auto msb = rtn->ir_builder->CreateLShr( lhs, ( byte_size * 8 ) - 1 ); auto cf = rtn->ir_builder->CreateZExt( msb, llvm::IntegerType::get( *rtn->llvm_ctx, 64 ) ); - auto of = - rtn->sf( byte_size, lhs ); // we reuse the compute_sf helper since the flag expression is the same + auto of = rtn->sf( byte_size, lhs ); auto sf = rtn->sf( byte_size, result ); auto zf = rtn->zf( byte_size, result ); auto pf = llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), 0 ); - return rtn->flags( cf, pf, llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), 0 ), - zf, sf, of ); + return rtn->flags( cf, pf, llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), 0 ), zf, sf, + of ); } lifters_t::lifter_callback_t lifters_t::shrq = - [ & ]( vm::devirt_t *rtn, const vm::instrs::code_block_t &vm_code_block, - const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) { + [ & ]( 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( 2 ); auto t3 = ir_builder->CreateIntCast( t2, llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), false ); @@ -34,4 +32,49 @@ namespace vm rtn->push( 8, t4 ); rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); }; + + lifters_t::lifter_callback_t lifters_t::shrdw = + [ & ]( 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( 2 ); + auto t3 = ir_builder->CreateIntCast( t2, llvm::IntegerType::get( *rtn->llvm_ctx, 32 ), false ); + auto t4 = ir_builder->CreateLShr( t1, t3 ); + + auto &vmp_rtn = rtn->vmp_rtns.back(); + auto flags = lifters_t::shr_flags( rtn, 4, t1, t3, t4 ); + ir_builder->CreateStore( flags, vmp_rtn->flags ); + rtn->push( 4, t4 ); + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; + + lifters_t::lifter_callback_t lifters_t::shrw = + [ & ]( 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->CreateLShr( t1, t2 ); + + auto &vmp_rtn = rtn->vmp_rtns.back(); + auto flags = lifters_t::shr_flags( rtn, 2, t1, t2, t3 ); + ir_builder->CreateStore( flags, vmp_rtn->flags ); + rtn->push( 2, t3 ); + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; + + lifters_t::lifter_callback_t lifters_t::shrb = + [ & ]( 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->CreateLShr( t3, t4 ); + + auto &vmp_rtn = rtn->vmp_rtns.back(); + auto flags = lifters_t::shr_flags( rtn, 1, t3, t4, t5 ); + ir_builder->CreateStore( flags, vmp_rtn->flags ); + 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 diff --git a/src/lifters/shrd.cpp b/src/lifters/shrd.cpp new file mode 100644 index 0000000..36f88d6 --- /dev/null +++ b/src/lifters/shrd.cpp @@ -0,0 +1,38 @@ +#include + +namespace vm +{ + lifters_t::lifter_callback_t lifters_t::shrdq = + [ & ]( 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( 2 ); + + // TODO: this is wrong - replace with more logic! + auto t4 = ir_builder->CreateLShr( t1, ir_builder->CreateIntCast( t3, ir_builder->getInt64Ty(), false ) ); + + rtn->push( 8, t4 ); + auto &vmp_rtn = rtn->vmp_rtns.back(); + + // TODO: update rflags... + rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); + }; + + 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/sreg.cpp b/src/lifters/sreg.cpp index 97e6c9e..46e1502 100644 --- a/src/lifters/sreg.cpp +++ b/src/lifters/sreg.cpp @@ -20,6 +20,17 @@ namespace vm ir_builder->CreateStore( ir_builder->CreateIntCast( t1, ir_builder->getInt64Ty(), false ), vreg ); }; + lifters_t::lifter_callback_t lifters_t::sregw = + [ & ]( 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 &vmp_rtn = rtn->vmp_rtns.back(); + auto vreg = vmp_rtn->virtual_registers[ vinstr.operand.imm.u ? vinstr.operand.imm.u / 8 : 0 ]; + ir_builder->CreateStore( + ir_builder->CreateIntCast( t1, ir_builder->getInt16Ty(), false ), + ir_builder->CreatePointerCast( vreg, llvm::PointerType::get( ir_builder->getInt16Ty(), 0ull ) ) ); + }; + lifters_t::lifter_callback_t lifters_t::sregb = [ & ]( vm::devirt_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/src/lifters/write.cpp b/src/lifters/write.cpp index d2e00f7..9097ff8 100644 --- a/src/lifters/write.cpp +++ b/src/lifters/write.cpp @@ -10,4 +10,32 @@ namespace vm auto t3 = ir_builder->CreateIntToPtr( t1, llvm::PointerType::get( ir_builder->getInt64Ty(), 0ull ) ); ir_builder->CreateStore( t2, t3 ); }; + + lifters_t::lifter_callback_t lifters_t::writedw = + [ & ]( 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( 4 ); + auto t3 = ir_builder->CreateIntToPtr( t1, llvm::PointerType::get( ir_builder->getInt32Ty(), 0ull ) ); + ir_builder->CreateStore( t2, t3 ); + }; + + lifters_t::lifter_callback_t lifters_t::writew = + [ & ]( 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( 2 ); + auto t3 = ir_builder->CreateIntToPtr( t1, llvm::PointerType::get( ir_builder->getInt16Ty(), 0ull ) ); + ir_builder->CreateStore( t2, t3 ); + }; + + lifters_t::lifter_callback_t lifters_t::writeb = + [ & ]( 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( 2 ); + auto t3 = ir_builder->CreateIntToPtr( t1, llvm::PointerType::get( ir_builder->getInt8Ty(), 0ull ) ); + auto t4 = ir_builder->CreateIntCast( t2, ir_builder->getInt8Ty(), false ); + ir_builder->CreateStore( t4, t3 ); + }; } // 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 diff --git a/src/main.cpp b/src/main.cpp index 89f8f81..60f0e3c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,6 +60,9 @@ int main( int argc, const char *argv[] ) for ( auto &[ vm_enter_offset, vmp2_code_blocks ] : virt_rtns ) { + if ( vmp2_code_blocks.empty() ) + continue; + if ( !vmp_devirt.lift( vm_enter_offset + file_header->image_base, vmp2_code_blocks ) ) { std::printf( "[!] failed to lift rtn_0x%p, please review the console...\n", @@ -67,6 +70,8 @@ int main( int argc, const char *argv[] ) return -1; } + + std::printf( "> lifted rtn_0x%p\n", vm_enter_offset + file_header->image_base ); } llvm::LLVMInitializeX86TargetInfo();