diff --git a/CMakeLists.txt b/CMakeLists.txt index 4855cec..4c0445e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,16 @@ set(CMKR_TARGET vmdevirt) set(vmdevirt_SOURCES "") list(APPEND vmdevirt_SOURCES + "src/lifters/lconst.cpp" + "src/lifters/lreg.cpp" + "src/lifters/sreg.cpp" "src/main.cpp" + "src/vmp_rtn.cpp" + "src/lifters/lconst.cpp" + "src/lifters/lreg.cpp" + "src/lifters/sreg.cpp" + "include/vm_lifters.hpp" + "include/vmp_rtn.hpp" ) list(APPEND vmdevirt_SOURCES diff --git a/cmake.toml b/cmake.toml index 1be73bc..24efd64 100644 --- a/cmake.toml +++ b/cmake.toml @@ -7,6 +7,7 @@ type = "executable" sources = [ "src/**.cpp", + "src/lifters/**.cpp", "include/**.hpp", ] include-directories = [ diff --git a/cmkr.exe b/cmkr.exe new file mode 100644 index 0000000..745e219 Binary files /dev/null and b/cmkr.exe differ diff --git a/include/vm_lifters.hpp b/include/vm_lifters.hpp new file mode 100644 index 0000000..e69de29 diff --git a/include/vmp_rtn.hpp b/include/vmp_rtn.hpp new file mode 100644 index 0000000..fa46aef --- /dev/null +++ b/include/vmp_rtn.hpp @@ -0,0 +1,38 @@ +#pragma once +#include + +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IRPrintingPasses.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" + +namespace vm +{ + class vmp_rtn_t + { + public: + explicit vmp_rtn_t( llvm::LLVMContext *llvm_ctx, llvm::Module *llvm_module, std::uintptr_t rtn_begin, + std::vector< vm::instrs::code_block_t > vmp2_code_blocks ); + + llvm::Function *lift( void ); + + private: + llvm::LLVMContext *llvm_ctx; + llvm::Module *llvm_module; + + std::uintptr_t rtn_begin; + std::shared_ptr< llvm::Function > llvm_fptr; + std::shared_ptr< llvm::IRBuilder<> > ir_builder; + std::vector< std::shared_ptr< llvm::BasicBlock > > llvm_code_blocks; + std::vector< vm::instrs::code_block_t > vmp2_code_blocks; + }; +} // namespace vm \ No newline at end of file diff --git a/src/lifters/lconst.cpp b/src/lifters/lconst.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/lifters/lreg.cpp b/src/lifters/lreg.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/lifters/sreg.cpp b/src/lifters/sreg.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/main.cpp b/src/main.cpp index 56f637b..dcb2e34 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -59,34 +60,23 @@ int main( int argc, const char *argv[] ) auto first_block = reinterpret_cast< vmp2::v3::code_block_t * >( reinterpret_cast< std::uintptr_t >( file_header ) + file_header->code_block_offset ); + std::vector< vm::instrs::code_block_t > vmp_code_blocks; + // convert code blocks back to vm::instrs::code_block_t form... for ( auto [ code_block, code_block_num ] = std::tuple{ first_block, 0u }; code_block_num < file_header->code_block_count; code_block = reinterpret_cast< vmp2::v3::code_block_t * >( reinterpret_cast< std::uintptr_t >( code_block ) + code_block->next_block_offset ), ++code_block_num ) { + vm::instrs::code_block_t _code_block{ code_block->vip_begin, code_block->jcc }; + std::for_each( code_block->vinstr, code_block->vinstr + code_block->vinstr_count, + [ & ]( const vm::instrs::virt_instr_t &vinstr ) { _code_block.vinstrs.push_back( vinstr ); } ); - std::printf( "[code block #%d] begin = 0x%p, virtual instruction count = %d\n", code_block_num, - ABS_TO_IMG( code_block->vip_begin, file_header->module_base, file_header->image_base ), - code_block->vinstr_count ); - - if ( code_block->jcc.has_jcc ) - std::printf( - "\tcode block branches to 0x%p and 0x%p\n", - ABS_TO_IMG( code_block->jcc.block_addr[ 0 ], file_header->module_base, file_header->image_base ), - ABS_TO_IMG( code_block->jcc.block_addr[ 1 ], file_header->module_base, file_header->image_base ) ); + vmp_code_blocks.push_back( _code_block ); } LLVMContext llvm_ctx; Module llvm_module( "VMProtect 2 Static Devirtualizer", llvm_ctx ); - IRBuilder<> ir_builder( llvm_ctx ); - - FunctionType *FT = FunctionType::get( Type::getVoidTy( llvm_ctx ), false ); - Function *F = Function::Create( FT, Function::ExternalLinkage, "test_func", llvm_module ); - F->setCallingConv( CallingConv::C ); - auto basic_block = BasicBlock::Create( llvm_ctx, "test", F ); - ir_builder.SetInsertPoint( basic_block ); - ir_builder.CreateRetVoid(); - basic_block->print( outs() ); + vm::vmp_rtn_t vmp_rtn( &llvm_ctx, &llvm_module, first_block->vip_begin, vmp_code_blocks ); } \ No newline at end of file diff --git a/src/vmp_rtn.cpp b/src/vmp_rtn.cpp new file mode 100644 index 0000000..5f49f6b --- /dev/null +++ b/src/vmp_rtn.cpp @@ -0,0 +1,28 @@ +#include + +namespace vm +{ + vmp_rtn_t::vmp_rtn_t( llvm::LLVMContext *llvm_ctx, llvm::Module *llvm_module, std::uintptr_t rtn_begin, + std::vector< vm::instrs::code_block_t > vmp2_code_blocks ) + : llvm_ctx( llvm_ctx ), llvm_module( llvm_module ), rtn_begin( rtn_begin ), vmp2_code_blocks( vmp2_code_blocks ) + { + // function has no arguments and returns void... maybe change this in the future as i learn + // more and more LLVM... + auto func_ty = llvm::FunctionType::get( llvm::Type::getVoidTy( *llvm_ctx ), false ); + + // convert the rtn_begin address to a hex string and prepend "rtn_" to it... + std::stringstream rtn_name; + rtn_name << "rtn_" << std::hex << rtn_begin; + const llvm::Twine rtn_twine( rtn_name.str() ); + + llvm_fptr = std::shared_ptr< llvm::Function >( llvm::Function::Create( + func_ty, llvm::GlobalValue::LinkageTypes::ExternalLinkage, rtn_twine, *llvm_module ) ); + + ir_builder = std::make_shared< llvm::IRBuilder<> >( *llvm_ctx ); + } + + llvm::Function *vmp_rtn_t::lift( void ) + { + return {}; + } +} // namespace vm \ No newline at end of file