diff --git a/CMakeLists.txt b/CMakeLists.txt index ddd557c..8216de0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ list(APPEND vmdevirt_SOURCES "src/lifters/pushvsp.cpp" "src/lifters/read.cpp" "src/lifters/readcr8.cpp" + "src/lifters/readgs.cpp" "src/lifters/sflags.cpp" "src/lifters/shl.cpp" "src/lifters/shr.cpp" diff --git a/include/vm_lifters.hpp b/include/vm_lifters.hpp index 9b81957..e829453 100644 --- a/include/vm_lifters.hpp +++ b/include/vm_lifters.hpp @@ -31,21 +31,22 @@ namespace vm static lifter_callback_t lconstq, lconstdwsxq, lconstwsxq, lconstbzxw, lconstbsxq, lconstwsxdw, lconstdw, lconstbsxdw; - static lifter_callback_t addq, adddw, addw; + static lifter_callback_t addq, adddw, addw, addb; static lifter_callback_t sregq, sregdw, sregb; static lifter_callback_t lregq, lregdw; - static lifter_callback_t imulq; + static lifter_callback_t imulq, imuldw; static lifter_callback_t pushvsp; static lifter_callback_t popvsp; - static lifter_callback_t writeq, writedw; + static lifter_callback_t writeq, writedw, writeb; static lifter_callback_t readq, readdw, readw, readb; - static lifter_callback_t nandq, nanddw, nandb; + static lifter_callback_t nandq, nanddw, nandw, nandb; static lifter_callback_t shrq, shrdw; static lifter_callback_t shlq; static lifter_callback_t jmp; static lifter_callback_t lflagsq; static lifter_callback_t vmexit; static lifter_callback_t readcr8; + static lifter_callback_t readgsq; std::map< vm::handler::mnemonic_t, lifter_callback_t * > lifters = { { vm::handler::LCONSTQ, &lconstq }, { vm::handler::LCONSTDW, &lconstdw }, @@ -58,10 +59,12 @@ namespace vm { vm::handler::ADDQ, &addq }, { vm::handler::ADDDW, &adddw }, { vm::handler::ADDW, &addw }, + { vm::handler::ADDB, &addb }, { vm::handler::SHRQ, &shrq }, { vm::handler::SHRDW, &shrdw }, { vm::handler::SHLQ, &shlq }, { vm::handler::IMULQ, &imulq }, + { vm::handler::IMULDW, &imuldw }, { vm::handler::PUSHVSPQ, &pushvsp }, { vm::handler::POPVSPQ, &popvsp }, { vm::handler::SREGQ, &sregq }, @@ -75,11 +78,14 @@ namespace vm { vm::handler::READB, &readb }, { vm::handler::WRITEQ, &writeq }, { vm::handler::WRITEDW, &writedw }, + { 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::READGSQ, &readgsq }, { vm::handler::JMP, &jmp }, { vm::handler::VMEXIT, &vmexit } }; 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/imul.cpp b/src/lifters/imul.cpp index ec13813..74d60c2 100644 --- a/src/lifters/imul.cpp +++ b/src/lifters/imul.cpp @@ -19,4 +19,25 @@ namespace vm auto &vmp_rtn = rtn->vmp_rtns.back(); rtn->push( 8, rtn->load_value( 8, vmp_rtn->flags ) ); }; -} \ No newline at end of file + + 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/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/readcr8.cpp b/src/lifters/readcr8.cpp index a69063b..ac82132 100644 --- a/src/lifters/readcr8.cpp +++ b/src/lifters/readcr8.cpp @@ -9,15 +9,19 @@ namespace vm if ( !( readcr8_intrin = rtn->llvm_module->getFunction( "readcr8" ) ) ) { readcr8_intrin = llvm::Function::Create( llvm::FunctionType::get( ir_builder->getInt64Ty(), false ), - llvm::GlobalValue::LinkageTypes::ExternalLinkage ); + 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 ); - auto intrin = llvm::InlineAsm::get( llvm::FunctionType::get( ir_builder->getVoidTy(), false ), - "mov rax, cr8; ret", "", false, false, llvm::InlineAsm::AD_Intel ); + + 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->CreateRetVoid(); // TODO: dont return VOID here... + ir_builder->CreateRet( llvm::ConstantInt::get( *rtn->llvm_ctx, llvm::APInt( 64, 0 ) ) ); ir_builder->SetInsertPoint( ib ); } auto t1 = ir_builder->CreateCall( readcr8_intrin ); 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/write.cpp b/src/lifters/write.cpp index 037b878..89e61de 100644 --- a/src/lifters/write.cpp +++ b/src/lifters/write.cpp @@ -19,4 +19,14 @@ namespace vm 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::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