#include #include #include #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" using namespace llvm; int main( int argc, const char *argv[] ) { argparse::argument_parser_t parser( "vmdevirt", "virtual instruction pseudo code generator" ); parser.add_argument().name( "--vmp2file" ).required( true ).description( "path to .vmp2 file..." ); parser.enable_help(); auto err = parser.parse( argc, argv ); if ( err ) { std::cout << err << std::endl; return -1; } if ( parser.exists( "help" ) ) { parser.print_help(); return 0; } std::vector< std::uint8_t > vmp2file; const auto umtils = xtils::um_t::get_instance(); if ( !umtils->open_binary_file( parser.get< std::string >( "vmp2file" ), vmp2file ) ) { std::printf( "[!] failed to open vmp2 file...\n" ); return -1; } const auto file_header = reinterpret_cast< vmp2::v3::file_header * >( vmp2file.data() ); if ( file_header->version != vmp2::version_t::v3 ) { std::printf( "[!] invalid vmp2 file version... this build uses v3...\n" ); return -1; } auto first_block = reinterpret_cast< vmp2::v3::code_block_t * >( reinterpret_cast< std::uintptr_t >( file_header ) + file_header->code_block_offset ); 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 ) { 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 ) ); } 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() ); }