#include #include #include #include #include #include #include #include "compiler.h" #include "parser.h" #include "parser.tab.h" #include "vmasm.hpp" extern FILE *yyin; extern "C" int yywrap() { return 1; } void yyerror( char *msg ) { std::printf( "[!] parsing failure: %s\n", msg ); } int __cdecl main( int argc, const char *argv[] ) { argparse::argument_parser_t argp( "vmassembler", "virtual instruction assembler" ); argp.add_argument() .names( { "--input", "--in" } ) .description( "path to a vasm file to be assembled..." ) .required( true ); argp.add_argument().names( { "--vmpbin", "--bin" } ).description( "path to protected binary..." ).required( true ); argp.add_argument().names( { "--vmentry", "--entry" } ).description( "rva to vm entry..." ).required( true ); argp.add_argument().name( { "--output" } ).description( "output file name and path..." ).required( true ); argp.enable_help(); auto err = argp.parse( argc, argv ); if ( err ) { std::cout << err << std::endl; return -1; } if ( argp.exists( "help" ) ) { argp.print_help(); return 0; } // // set yyin to the vasm file... // if ( ( yyin = fopen( argp.get< std::string >( "input" ).c_str(), "r" ) ) == nullptr ) { std::printf( "[!] failed to open vasm file...\n" ); return -1; } // // parse vasm file for all of the instructions... // yyparse(); std::printf( "[+] finished parsing vasm file...\n" ); // // init vm variables... // const auto module_base = reinterpret_cast< std::uintptr_t >( LoadLibraryExA( argp.get< std::string >( "vmpbin" ).c_str(), NULL, DONT_RESOLVE_DLL_REFERENCES ) ); const auto vm_entry_rva = std::strtoull( argp.get< std::string >( "vmentry" ).c_str(), nullptr, 16 ); const auto image_base = xtils::um_t::get_instance()->image_base( argp.get< std::string >( "vmpbin" ).c_str() ); const auto image_size = NT_HEADER( module_base )->OptionalHeader.SizeOfImage; vm::ctx_t vmctx( module_base, image_base, image_size, vm_entry_rva ); if ( !vmctx.init() ) { std::printf( "> failed to init vmctx... make sure all arguments are valid\n" "and that the binary you are providing is unpacked and protected\n" "by VMProtect 2...\n" ); return -1; } vm::compiler_t compiler( &vmctx ); // // encode virtual instructions... // auto virt_labels = compiler.encode(); std::printf( "[+] finished encoding... encoded instructions below...\n" ); for ( auto &label : *virt_labels ) { for ( const auto &vinstr : label.vinstrs ) { if ( vinstr.imm_size ) std::printf( "> 0x%x - 0x%x\n", vinstr.vm_handler, vinstr.operand ); else std::printf( "> 0x%x\n", vinstr.vm_handler ); } } // // encrypt virtual instructions... // auto compiled_labels = compiler.encrypt(); std::printf( "[+] finished encrypting... encrypted labels below...\n" ); for ( const auto &label : compiled_labels ) { std::printf( "> %s must be allocated at = 0x%p\n", label.label_name.c_str(), label.alloc_rva ); std::printf( "> " ); { auto idx = 0u; for ( auto byte : label.vinstrs ) { std::printf( "0x%x ", byte ); if ( ++idx == 10 ) { std::printf( "\n" ); idx = 0u; } } } } std::printf( "\n" ); }