From 786ecb2f810e73a616ca31aab586b299549164d8 Mon Sep 17 00:00:00 2001 From: John Doe Date: Tue, 28 Dec 2021 14:17:54 -0800 Subject: [PATCH] porting the project to cmkr... --- .clang-format | 17 +- .gitignore | 2 + CMakeLists.txt | 90 +++++++ README.md | 6 +- cmake.toml | 12 + cmkr.cmake | 162 ++++++++++++ dependencies/CMakeLists.txt | 54 ++++ dependencies/cmake.toml | 9 + dependencies/vmprofiler | 2 +- dependencies/xtils | 2 +- include/compiler.hpp | 131 ++++++++++ {src => include}/gen_code.hpp | 255 ++++++++++--------- src/parser.h => include/parser.hpp | 0 src/compiler.cpp | 385 +++++++++++++++-------------- src/compiler.h | 130 ---------- src/main.cpp | 245 +++++++++--------- src/parser.cpp | 43 ++-- vmassembler.sln | 266 -------------------- 18 files changed, 944 insertions(+), 867 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 cmake.toml create mode 100644 cmkr.cmake create mode 100644 dependencies/CMakeLists.txt create mode 100644 dependencies/cmake.toml create mode 100644 include/compiler.hpp rename {src => include}/gen_code.hpp (64%) rename src/parser.h => include/parser.hpp (100%) delete mode 100644 src/compiler.h delete mode 100644 vmassembler.sln diff --git a/.clang-format b/.clang-format index 8063c5e..e90a94d 100644 --- a/.clang-format +++ b/.clang-format @@ -1,18 +1,5 @@ --- -BasedOnStyle: Microsoft -AlignAfterOpenBracket: Align -AllowAllArgumentsOnNextLine: 'true' -AllowAllParametersOfDeclarationOnNextLine: 'true' -AllowShortIfStatementsOnASingleLine: Never -BreakBeforeBraces: Allman -IndentWidth: '4' -Language: Cpp -NamespaceIndentation: All -SpacesInAngles: 'true' -SpacesInCStyleCastParentheses: 'true' -SpacesInContainerLiterals: 'true' -SpacesInParentheses: 'true' -SpacesInSquareBrackets: 'true' -UseTab: Never +BasedOnStyle: Chromium ... + diff --git a/.gitignore b/.gitignore index 72de34f..a68af18 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ *.user *.userosscache *.sln.docstates +*.exe # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs @@ -17,6 +18,7 @@ mono_crash.* # Build results +build/ [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..cc4cad0 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,90 @@ +# This file is automatically generated from cmake.toml - DO NOT EDIT +# See https://github.com/build-cpp/cmkr for more information + +cmake_minimum_required(VERSION 3.15) + +# Regenerate CMakeLists.txt automatically in the root project +set(CMKR_ROOT_PROJECT OFF) +if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(CMKR_ROOT_PROJECT ON) + + # Bootstrap cmkr + include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT) + if(CMKR_INCLUDE_RESULT) + cmkr() + endif() + + # Enable folder support + set_property(GLOBAL PROPERTY USE_FOLDERS ON) +endif() + +# Create a configure-time dependency on cmake.toml to improve IDE support +if(CMKR_ROOT_PROJECT) + configure_file(cmake.toml cmake.toml COPYONLY) +endif() + +project(vmassembler) + +# dependencies +set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER}) +if(CMAKE_FOLDER) + set(CMAKE_FOLDER "${CMAKE_FOLDER}/dependencies") +else() + set(CMAKE_FOLDER dependencies) +endif() +add_subdirectory(dependencies) +set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER}) + +# Target vmassembler +set(CMKR_TARGET vmassembler) +set(vmassembler_SOURCES "") + +list(APPEND vmassembler_SOURCES + "src/compiler.cpp" + "src/main.cpp" + "src/parser.cpp" + "include/compiler.hpp" + "include/gen_code.hpp" + "include/parser.hpp" +) + +list(APPEND vmassembler_SOURCES + cmake.toml +) + +set(CMKR_SOURCES ${vmassembler_SOURCES}) +add_executable(vmassembler) + +if(vmassembler_SOURCES) + target_sources(vmassembler PRIVATE ${vmassembler_SOURCES}) +endif() + +get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT) +if(NOT CMKR_VS_STARTUP_PROJECT) + set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT vmassembler) +endif() + +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${vmassembler_SOURCES}) + +target_compile_definitions(vmassembler PRIVATE + NOMINMAX +) + +target_compile_features(vmassembler PRIVATE + cxx_std_20 +) + +target_include_directories(vmassembler PRIVATE + include +) + +target_link_libraries(vmassembler PRIVATE + vmprofiler + xtils + cli-parser + linux-pe +) + +unset(CMKR_TARGET) +unset(CMKR_SOURCES) + diff --git a/README.md b/README.md index 5f6560c..40bcbcd 100644 --- a/README.md +++ b/README.md @@ -145,8 +145,8 @@ int main() { // note, the header file generates an enum call "calls", inside of this enum will be an entry with the same name as your label! // note, the second template param is the return type... - const auto hello = vm::call< vm::calls::get_hello, vm::u64 >(); - const auto world = vm::call< vm::calls::get_world, vm::u64 >(); - std::printf( "> %s %s\n", ( char * )&hello, (char*)&world ); + const auto hello = vm::call< vm::calls::get_hello, vm::u64 >(); + const auto world = vm::call< vm::calls::get_world, vm::u64 >(); + std::printf( "> %s %s\n", ( char * )&hello, (char*)&world ); } ``` \ No newline at end of file diff --git a/cmake.toml b/cmake.toml new file mode 100644 index 0000000..7b1428e --- /dev/null +++ b/cmake.toml @@ -0,0 +1,12 @@ +[project] +name = "vmassembler" + +[subdir.dependencies] + +[target.vmassembler] +type = "executable" +compile-features = ["cxx_std_20"] +sources = ["src/**.cpp", "include/**.hpp"] +include-directories = ["include"] +link-libraries = ["vmprofiler", "xtils", "cli-parser", "linux-pe"] +compile-definitions = ["NOMINMAX"] \ No newline at end of file diff --git a/cmkr.cmake b/cmkr.cmake new file mode 100644 index 0000000..cc90624 --- /dev/null +++ b/cmkr.cmake @@ -0,0 +1,162 @@ +include_guard() + +# Change these defaults to point to your infrastructure if desired +set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE) +set(CMKR_TAG "archive_264e4ace" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE) + +# Set these from the command line to customize for development/debugging purposes +set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable") +set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation") + +# Disable cmkr if generation is disabled +if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION) + message(STATUS "[cmkr] Skipping automatic cmkr generation") + macro(cmkr) + endmacro() + return() +endif() + +# Disable cmkr if no cmake.toml file is found +if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") + message(AUTHOR_WARNING "[cmkr] Not found: ${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") + macro(cmkr) + endmacro() + return() +endif() + +# Convert a Windows native path to CMake path +if(CMKR_EXECUTABLE MATCHES "\\\\") + string(REPLACE "\\" "/" CMKR_EXECUTABLE_CMAKE "${CMKR_EXECUTABLE}") + set(CMKR_EXECUTABLE "${CMKR_EXECUTABLE_CMAKE}" CACHE FILEPATH "" FORCE) + unset(CMKR_EXECUTABLE_CMAKE) +endif() + +# Helper macro to execute a process (COMMAND_ERROR_IS_FATAL ANY is 3.19 and higher) +function(cmkr_exec) + execute_process(COMMAND ${ARGV} RESULT_VARIABLE CMKR_EXEC_RESULT) + if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "cmkr_exec(${ARGV}) failed (exit code ${CMKR_EXEC_RESULT})") + endif() +endfunction() + +# Windows-specific hack (CMAKE_EXECUTABLE_PREFIX is not set at the moment) +if(WIN32) + set(CMKR_EXECUTABLE_NAME "cmkr.exe") +else() + set(CMKR_EXECUTABLE_NAME "cmkr") +endif() + +# Use cached cmkr if found +set(CMKR_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_${CMKR_TAG}") +set(CMKR_CACHED_EXECUTABLE "${CMKR_DIRECTORY}/bin/${CMKR_EXECUTABLE_NAME}") + +if(NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE AND CMKR_EXECUTABLE MATCHES "^${CMAKE_CURRENT_BINARY_DIR}/_cmkr") + message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") + unset(CMKR_EXECUTABLE CACHE) +endif() + +if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}") + message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'") +elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE) + message(FATAL_ERROR "[cmkr] '${CMKR_EXECUTABLE}' not found") +else() + set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) + message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'") + + message(STATUS "[cmkr] Fetching cmkr...") + if(EXISTS "${CMKR_DIRECTORY}") + cmkr_exec("${CMAKE_COMMAND}" -E rm -rf "${CMKR_DIRECTORY}") + endif() + find_package(Git QUIET REQUIRED) + cmkr_exec("${GIT_EXECUTABLE}" + clone + --config advice.detachedHead=false + --branch ${CMKR_TAG} + --depth 1 + ${CMKR_REPO} + "${CMKR_DIRECTORY}" + ) + message(STATUS "[cmkr] Building cmkr...") + cmkr_exec("${CMAKE_COMMAND}" + --no-warn-unused-cli + "${CMKR_DIRECTORY}" + "-B${CMKR_DIRECTORY}/build" + "-DCMAKE_BUILD_TYPE=Release" + "-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}" + "-DCMKR_GENERATE_DOCUMENTATION=OFF" + ) + cmkr_exec("${CMAKE_COMMAND}" + --build "${CMKR_DIRECTORY}/build" + --config Release + --parallel + ) + cmkr_exec("${CMAKE_COMMAND}" + --install "${CMKR_DIRECTORY}/build" + --config Release + --prefix "${CMKR_DIRECTORY}" + --component cmkr + ) + if(NOT EXISTS ${CMKR_EXECUTABLE}) + message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'") + endif() + cmkr_exec("${CMKR_EXECUTABLE}" version) + message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}") +endif() +execute_process(COMMAND "${CMKR_EXECUTABLE}" version + RESULT_VARIABLE CMKR_EXEC_RESULT +) +if(NOT CMKR_EXEC_RESULT EQUAL 0) + message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding") +endif() + +# This is the macro that contains black magic +macro(cmkr) + # When this macro is called from the generated file, fake some internal CMake variables + get_source_file_property(CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" CMKR_CURRENT_LIST_FILE) + if(CMKR_CURRENT_LIST_FILE) + set(CMAKE_CURRENT_LIST_FILE "${CMKR_CURRENT_LIST_FILE}") + get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) + endif() + + # File-based include guard (include_guard is not documented to work) + get_source_file_property(CMKR_INCLUDE_GUARD "${CMAKE_CURRENT_LIST_FILE}" CMKR_INCLUDE_GUARD) + if(NOT CMKR_INCLUDE_GUARD) + set_source_files_properties("${CMAKE_CURRENT_LIST_FILE}" PROPERTIES CMKR_INCLUDE_GUARD TRUE) + + file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_PRE) + + # Generate CMakeLists.txt + cmkr_exec("${CMKR_EXECUTABLE}" gen + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + ) + + file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_POST) + + # Delete the temporary file if it was left for some reason + set(CMKR_TEMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CMakerLists.txt") + if(EXISTS "${CMKR_TEMP_FILE}") + file(REMOVE "${CMKR_TEMP_FILE}") + endif() + + if(NOT CMKR_LIST_FILE_SHA256_PRE STREQUAL CMKR_LIST_FILE_SHA256_POST) + # Copy the now-generated CMakeLists.txt to CMakerLists.txt + # This is done because you cannot include() a file you are currently in + configure_file(CMakeLists.txt "${CMKR_TEMP_FILE}" COPYONLY) + + # Add the macro required for the hack at the start of the cmkr macro + set_source_files_properties("${CMKR_TEMP_FILE}" PROPERTIES + CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" + ) + + # 'Execute' the newly-generated CMakeLists.txt + include("${CMKR_TEMP_FILE}") + + # Delete the generated file + file(REMOVE "${CMKR_TEMP_FILE}") + + # Do not execute the rest of the original CMakeLists.txt + return() + endif() + # Resume executing the unmodified CMakeLists.txt + endif() +endmacro() diff --git a/dependencies/CMakeLists.txt b/dependencies/CMakeLists.txt new file mode 100644 index 0000000..644c422 --- /dev/null +++ b/dependencies/CMakeLists.txt @@ -0,0 +1,54 @@ +# This file is automatically generated from cmake.toml - DO NOT EDIT +# See https://github.com/build-cpp/cmkr for more information + +# Create a configure-time dependency on cmake.toml to improve IDE support +if(CMKR_ROOT_PROJECT) + configure_file(cmake.toml cmake.toml COPYONLY) +endif() + +# vmprofiler +set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER}) +if(CMAKE_FOLDER) + set(CMAKE_FOLDER "${CMAKE_FOLDER}/vmprofiler") +else() + set(CMAKE_FOLDER vmprofiler) +endif() +add_subdirectory(vmprofiler) +set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER}) + +# Target cli-parser +set(CMKR_TARGET cli-parser) +set(cli-parser_SOURCES "") + +set(CMKR_SOURCES ${cli-parser_SOURCES}) +add_library(cli-parser INTERFACE) + +if(cli-parser_SOURCES) + target_sources(cli-parser INTERFACE ${cli-parser_SOURCES}) +endif() + +target_include_directories(cli-parser INTERFACE + cli-parser +) + +unset(CMKR_TARGET) +unset(CMKR_SOURCES) + +# Target xtils +set(CMKR_TARGET xtils) +set(xtils_SOURCES "") + +set(CMKR_SOURCES ${xtils_SOURCES}) +add_library(xtils INTERFACE) + +if(xtils_SOURCES) + target_sources(xtils INTERFACE ${xtils_SOURCES}) +endif() + +target_include_directories(xtils INTERFACE + xtils +) + +unset(CMKR_TARGET) +unset(CMKR_SOURCES) + diff --git a/dependencies/cmake.toml b/dependencies/cmake.toml new file mode 100644 index 0000000..1bceb53 --- /dev/null +++ b/dependencies/cmake.toml @@ -0,0 +1,9 @@ +[subdir.vmprofiler] + +[target.cli-parser] +type = "interface" +include-directories = ["cli-parser"] + +[target.xtils] +type = "interface" +include-directories = ["xtils"] \ No newline at end of file diff --git a/dependencies/vmprofiler b/dependencies/vmprofiler index 0f6ba9b..14cc72c 160000 --- a/dependencies/vmprofiler +++ b/dependencies/vmprofiler @@ -1 +1 @@ -Subproject commit 0f6ba9bad30d67f25f01b6c1e872077efdff61d4 +Subproject commit 14cc72c0ff121d13f2ba26be34d1e99492aad296 diff --git a/dependencies/xtils b/dependencies/xtils index 7c32517..db7526d 160000 --- a/dependencies/xtils +++ b/dependencies/xtils @@ -1 +1 @@ -Subproject commit 7c32517322c29a866cbb1e67fb9051efa2e05553 +Subproject commit db7526d989bdfecb6fac2079929efce94cead52c diff --git a/include/compiler.hpp b/include/compiler.hpp new file mode 100644 index 0000000..3bef9e6 --- /dev/null +++ b/include/compiler.hpp @@ -0,0 +1,131 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace vm { +/// +/// struct containing encoded data for a given virtual instruction... +/// +struct vinstr_data { + /// + /// vm handler index also known as the opcode... + /// + std::uint8_t vm_handler; + + /// + /// this field contains the second operand if any... + /// + std::uint64_t operand; + + /// + /// size in bits of the second operand if any... zero if none... + /// + std::uint8_t imm_size; +}; + +/// +/// struct containing all information for a label... +/// +struct vlabel_data { + /// + /// name of the label... + /// + std::string label_name; + + /// + /// vector of encoded virtual instructions... + /// + std::vector vinstrs; +}; + +/// +/// struct containing compiled virtual instructions (encoded and encrypted) for +/// a given label... +/// +struct compiled_label_data { + /// + /// label name... + /// + std::string label_name; + + /// + /// relative virtual address from vm_entry to the virtual instructions... + /// + std::uintptr_t alloc_rva; + + /// + /// encrypted relative virtual address from vm_entry to virtual + /// instructions... + /// + std::uintptr_t enc_alloc_rva; + + /// + /// vector of bytes containing the raw, encrypted virtual instructions... + /// + std::vector vinstrs; +}; + +/// +/// class containing member functions used to encode and encrypted virtual +/// instructions... +/// +class compiler_t { + public: + /// + /// default constructor + /// + /// pointer to a vm context object which has already been + /// init... + explicit compiler_t(vm::ctx_t* vmctx); + + /// + /// encode virtual instructions from parser::virt_labels + /// + /// returns a vector of labels containing encoded virtual + /// instructions + std::vector* encode(); + + /// + /// encrypt virtual instructions from parser::virt_labels + /// + /// returns a vector of compiled labels containing encoded and + /// encrypted virtual instructions... + std::vector encrypt(); + + private: + /// + /// encrypt virtual instructions rva... read more here... + /// + /// relative virtual address to encrypted virtual + /// instructions... + std::uint64_t encrypt_rva(std::uint64_t rva); + + /// + /// pointer to the vmctx passed in by the constructor... + /// + vm::ctx_t* vmctx; + + /// + /// transformations used to decrypt the opcode operand extracted from + /// calc_jmp... you can read more here... + /// + transform::map_t calc_jmp_transforms; + + /// + /// vector of encoded labels... + /// + std::vector virt_labels; + + /// + /// vector of decoded zydis instructions containing the native instructions to + /// encrypt the virtual instruction rva which will be pushed onto the stack + /// prior to jmping to vm entry... + /// + std::vector encrypt_vinstrs_rva; +}; +} // namespace vm \ No newline at end of file diff --git a/src/gen_code.hpp b/include/gen_code.hpp similarity index 64% rename from src/gen_code.hpp rename to include/gen_code.hpp index d483234..5f5a117 100644 --- a/src/gen_code.hpp +++ b/include/gen_code.hpp @@ -1,52 +1,55 @@ #pragma once +#include #include #include #include -#include "compiler.h" - -namespace gen -{ - /// - /// function pasted from https://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprintf - /// - /// - /// - /// - /// - template < typename... Args > std::string string_format( const std::string &format, Args... args ) - { - int size_s = std::snprintf( nullptr, 0, format.c_str(), args... ) + 1; - auto size = static_cast< size_t >( size_s ); - auto buf = std::make_unique< char[] >( size ); - std::snprintf( buf.get(), size, format.c_str(), args... ); - return std::string( buf.get(), buf.get() + size - 1 ); - } - - /// - /// generates c++ header file which MUST BE COMPILED USING CLANG BECAUSE MSVC CANT HANDLE HUGE STATIC INITS (6/13/2021).... - /// - /// vector of compiled labels... - /// path to the image on disk... - /// - /// - inline std::string code( std::vector< vm::compiled_label_data > &labels, std::string image_path, vm::ctx_t& vmctx ) - { - std::string result, raw_file_array; - std::vector< std::uint8_t > raw_file; - xtils::um_t::get_instance()->open_binary_file( image_path, raw_file ); - - for ( auto idx = 0u; idx < raw_file.size(); ++idx ) - raw_file_array.append( string_format( "0x%x, ", raw_file[ idx ] ) ); - - result.append( "#pragma once\n" - "#pragma section( \".xmp2\" )\n" - "#pragma comment( linker, \"/section:.xmp2,RWE\" ) \n\n" ); - - result.append( "namespace vm\n" - "{\n" ); - - result.append( R"( using u8 = unsigned char; +namespace gen { +/// +/// function pasted from +/// https://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprintf +/// +/// +/// +/// +/// +template +std::string string_format(const std::string& format, Args... args) { + int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; + auto size = static_cast(size_s); + auto buf = std::make_unique(size); + std::snprintf(buf.get(), size, format.c_str(), args...); + return std::string(buf.get(), buf.get() + size - 1); +} + +/// +/// generates c++ header file which MUST BE COMPILED USING CLANG BECAUSE MSVC +/// CANT HANDLE HUGE STATIC INITS (6/13/2021).... +/// +/// vector of compiled labels... +/// path to the image on disk... +/// +/// +inline std::string code(std::vector& labels, + std::string image_path, + vm::ctx_t& vmctx) { + std::string result, raw_file_array; + std::vector raw_file; + xtils::um_t::get_instance()->open_binary_file(image_path, raw_file); + + for (auto idx = 0u; idx < raw_file.size(); ++idx) + raw_file_array.append(string_format("0x%x, ", raw_file[idx])); + + result.append( + "#pragma once\n" + "#pragma section( \".xmp2\" )\n" + "#pragma comment( linker, \"/section:.xmp2,RWE\" ) \n\n"); + + result.append( + "namespace vm\n" + "{\n"); + + result.append(R"( using u8 = unsigned char; using s8 = signed char; using u16 = unsigned short; @@ -169,78 +172,84 @@ namespace gen { unsigned int VirtualAddress; unsigned int SizeOfBlock; - } IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION;)" ); - - result.append( "\n\n\ttemplate < class T, class U > struct _pair_t\n" - "\t{\n" - "\t\tT first;\n" - "\t\tU second;\n" - "\t};\n\n" ); - - result.append( string_format( "\tconstexpr auto entry_rva = 0x%x;\n\n", vmctx.vm_entry_rva ) ); - - result.append( "\tenum class calls : u32\n" - "\t{\n" ); - - for ( auto idx = 0u; idx < labels.size(); ++idx ) - result.append( string_format( "\t\t%s = 0x%x,\n", labels[ idx ].label_name, labels[ idx ].enc_alloc_rva ) ); - - result.append( "\t};\n\n" ); - result.append( string_format( "\tinline _pair_t< u8, calls > call_map[%d] = \n" - "\t{\n", - labels.size() ) ); - - for ( auto idx = 0u; idx < labels.size(); ++idx ) - result.append( string_format( "\t\t{ %d, calls::%s },\n", idx, labels[ idx ].label_name.c_str() ) ); - - result.append( "\t};\n\n" ); - result.append( string_format( "\t__declspec(align(1)) struct _gen_data\n" - "\t{\n" - "\t\tu8 bin[%d] =\n" - "\t\t{\n" - "\t\t\t%s\n", - raw_file.size(), raw_file_array.c_str() ) ); - - result.append( "\t\t};\n\n" ); - result.append( string_format( "\t\tu8 map_area[0x%x];\n\n", vmctx.image_size ) ); - - for ( auto &label : labels ) - { - result.append( - string_format( "\t\tu8 __%s_vinstrs[%d] =\n", label.label_name.c_str(), label.vinstrs.size() ) ); - result.append( "\t\t{\n\t\t\t" ); - for ( auto &byte : label.vinstrs ) - result.append( string_format( "0x%x, ", byte ) ); - result.append( "\n\t\t};\n\n" ); - } - - result.append( string_format( "\t\tu8 __vmcall_shell_code[%d][15] =\n" - "\t\t{\n", - labels.size() ) ); - - for ( auto idx = 0u; idx < labels.size(); ++idx ) - { - std::string jmp_code; - - // two push instructions... - for ( auto i = 0u; i < 2; ++i ) - { - jmp_code.append( "0x68, " ); // push opcode... - - for ( auto _idx = 0u; _idx < 4; ++_idx ) - jmp_code.append( "0x0, " ); - } + } IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION;)"); + + result.append( + "\n\n\ttemplate < class T, class U > struct _pair_t\n" + "\t{\n" + "\t\tT first;\n" + "\t\tU second;\n" + "\t};\n\n"); + + result.append(string_format("\tconstexpr auto entry_rva = 0x%x;\n\n", + vmctx.vm_entry_rva)); + + result.append( + "\tenum class calls : u32\n" + "\t{\n"); + + for (auto idx = 0u; idx < labels.size(); ++idx) + result.append(string_format("\t\t%s = 0x%x,\n", labels[idx].label_name, + labels[idx].enc_alloc_rva)); + + result.append("\t};\n\n"); + result.append( + string_format("\tinline _pair_t< u8, calls > call_map[%d] = \n" + "\t{\n", + labels.size())); + + for (auto idx = 0u; idx < labels.size(); ++idx) + result.append(string_format("\t\t{ %d, calls::%s },\n", idx, + labels[idx].label_name.c_str())); + + result.append("\t};\n\n"); + result.append( + string_format("\t__declspec(align(1)) struct _gen_data\n" + "\t{\n" + "\t\tu8 bin[%d] =\n" + "\t\t{\n" + "\t\t\t%s\n", + raw_file.size(), raw_file_array.c_str())); + + result.append("\t\t};\n\n"); + result.append(string_format("\t\tu8 map_area[0x%x];\n\n", vmctx.image_size)); + + for (auto& label : labels) { + result.append(string_format("\t\tu8 __%s_vinstrs[%d] =\n", + label.label_name.c_str(), + label.vinstrs.size())); + result.append("\t\t{\n\t\t\t"); + for (auto& byte : label.vinstrs) + result.append(string_format("0x%x, ", byte)); + result.append("\n\t\t};\n\n"); + } + + result.append( + string_format("\t\tu8 __vmcall_shell_code[%d][15] =\n" + "\t\t{\n", + labels.size())); + + for (auto idx = 0u; idx < labels.size(); ++idx) { + std::string jmp_code; + + // two push instructions... + for (auto i = 0u; i < 2; ++i) { + jmp_code.append("0x68, "); // push opcode... + + for (auto _idx = 0u; _idx < 4; ++_idx) + jmp_code.append("0x0, "); + } - // one jmp instruction... - jmp_code.append( "0xE9, " ); - for ( auto i = 0u; i < 4; ++i ) - jmp_code.append( "0x0, " ); + // one jmp instruction... + jmp_code.append("0xE9, "); + for (auto i = 0u; i < 4; ++i) + jmp_code.append("0x0, "); - result.append( string_format( "\t\t\t{ %s },\n", jmp_code.c_str() ) ); - } + result.append(string_format("\t\t\t{ %s },\n", jmp_code.c_str())); + } - result.append( "\t\t};\n\n" ); - result.append( R"( bool init() + result.append("\t\t};\n\n"); + result.append(R"( bool init() { static const auto _memcpy = []( void *dest, const void *src, size_t len ) -> void * { char *d = ( char * )dest; @@ -324,12 +333,14 @@ namespace gen } return true; // only a bool so i can use static/call init only once... - })" ); + })"); - result.append( "\n\t};\n\n" ); - result.append( "\t__declspec(allocate(\".xmp2\")) inline _gen_data gen_data;\n\n" ); + result.append("\n\t};\n\n"); + result.append( + "\t__declspec(allocate(\".xmp2\")) inline _gen_data gen_data;\n\n"); - result.append( R"( template < calls e_call, class T, class ... Ts > auto call(const Ts... args) -> T + result.append( + R"( template < calls e_call, class T, class ... Ts > auto call(const Ts... args) -> T { static auto __init_result = gen_data.init(); @@ -339,9 +350,9 @@ namespace gen vmcall = reinterpret_cast< __vmcall_t >( &gen_data.__vmcall_shell_code[ idx ] ); return reinterpret_cast< T >( vmcall( args... ) ); - })" ); + })"); - result.append( "\n}" ); - return result; - } -} // namespace gen \ No newline at end of file + result.append("\n}"); + return result; +} +} // namespace gen \ No newline at end of file diff --git a/src/parser.h b/include/parser.hpp similarity index 100% rename from src/parser.h rename to include/parser.hpp diff --git a/src/compiler.cpp b/src/compiler.cpp index 799f6ab..9407cf5 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1,194 +1,211 @@ -#include "compiler.h" - -namespace vm -{ - compiler_t::compiler_t( vm::ctx_t *vmctx ) : vmctx( vmctx ) - { - if ( !parse_t::get_instance()->for_each( [ & ]( _vlabel_meta *label_data ) -> bool { - std::printf( "> checking label %s for invalid instructions... number of instructions = %d\n", - label_data->label_name.c_str(), label_data->vinstrs.size() ); - - const auto result = std::find_if( - label_data->vinstrs.begin(), label_data->vinstrs.end(), - [ & ]( const _vinstr_meta &vinstr ) -> bool { - std::printf( "> vinstr name = %s, has imm = %d, imm = 0x%p\n", vinstr.name.c_str(), - vinstr.has_imm, vinstr.imm ); - - for ( auto &vm_handler : vmctx->vm_handlers ) - if ( vm_handler.profile && vm_handler.profile->name == vinstr.name ) - return false; - - std::printf( "[!] this vm protected file does not have the vm handler for: %s...\n", - vinstr.name.c_str() ); - - return true; - } ); - - return result == label_data->vinstrs.end(); - } ) ) - { - std::printf( "[!] binary does not have the required vm handlers...\n" ); - exit( -1 ); - } - - if ( !vm::handler::get_operand_transforms( vmctx->calc_jmp, calc_jmp_transforms ) ) - { - std::printf( "[!] failed to extract calc_jmp transformations...\n" ); - exit( -1 ); - } - - if ( !vm::instrs::get_rva_decrypt( vmctx->vm_entry, encrypt_vinstrs_rva ) ) - { - std::printf( "[!] failed to extract virtual instruction rva decryption instructions...\n" ); - exit( -1 ); - } - - if ( !vm::transform::inverse_transforms( encrypt_vinstrs_rva ) ) - { - std::printf( "[!] failed to inverse virtual instruction rva decrypt instructions...\n" ); - exit( -1 ); +#include + +namespace vm { +compiler_t::compiler_t(vm::ctx_t* vmctx) : vmctx(vmctx) { + if (!parse_t::get_instance()->for_each([&](_vlabel_meta* label_data) -> bool { + std::printf( + "> checking label %s for invalid instructions... number of " + "instructions = %d\n", + label_data->label_name.c_str(), label_data->vinstrs.size()); + + const auto result = std::find_if( + label_data->vinstrs.begin(), label_data->vinstrs.end(), + [&](const _vinstr_meta& vinstr) -> bool { + std::printf("> vinstr name = %s, has imm = %d, imm = 0x%p\n", + vinstr.name.c_str(), vinstr.has_imm, vinstr.imm); + + for (auto& vm_handler : vmctx->vm_handlers) + if (vm_handler.profile && + vm_handler.profile->name == vinstr.name) + return false; + + std::printf( + "[!] this vm protected file does not have the vm handler " + "for: %s...\n", + vinstr.name.c_str()); + + return true; + }); + + return result == label_data->vinstrs.end(); + })) { + std::printf("[!] binary does not have the required vm handlers...\n"); + exit(-1); + } + + if (!vm::handler::get_operand_transforms(vmctx->calc_jmp, + calc_jmp_transforms)) { + std::printf("[!] failed to extract calc_jmp transformations...\n"); + exit(-1); + } + + if (!vm::instrs::get_rva_decrypt(vmctx->vm_entry, encrypt_vinstrs_rva)) { + std::printf( + "[!] failed to extract virtual instruction rva decryption " + "instructions...\n"); + exit(-1); + } + + if (!vm::transform::inverse_transforms(encrypt_vinstrs_rva)) { + std::printf( + "[!] failed to inverse virtual instruction rva decrypt " + "instructions...\n"); + exit(-1); + } +} + +std::vector* compiler_t::encode() { + parse_t::get_instance()->for_each([&](_vlabel_meta* label_data) -> bool { + virt_labels.push_back({label_data->label_name}); + for (const auto& vinstr : label_data->vinstrs) { + for (auto idx = 0u; idx < 256; ++idx) { + const auto& vm_handler = vmctx->vm_handlers[idx]; + if (vm_handler.profile && + !vinstr.name.compare(vm_handler.profile->name)) { + virt_labels.back().vinstrs.push_back( + {(std::uint8_t)idx, vinstr.imm, vm_handler.profile->imm_size}); + break; } + } } - - std::vector< vlabel_data > *compiler_t::encode() - { - parse_t::get_instance()->for_each( [ & ]( _vlabel_meta *label_data ) -> bool { - virt_labels.push_back( { label_data->label_name } ); - for ( const auto &vinstr : label_data->vinstrs ) - { - for ( auto idx = 0u; idx < 256; ++idx ) + return true; + }); + + return &virt_labels; +} + +std::vector compiler_t::encrypt() { + std::vector result; + const auto end_of_module = vmctx->image_size + vmctx->image_base; + + // decryption key starts off as the image + // base address of the virtual instructions... + std::uintptr_t decrypt_key = end_of_module, start_addr; + if (vmctx->exec_type == vmp2::exec_type_t::backward) + std::for_each( + virt_labels.begin()->vinstrs.begin(), + virt_labels.begin()->vinstrs.end(), [&](const vinstr_data& vinstr) { + (++decrypt_key) += vinstr.imm_size ? vinstr.imm_size / 8 : 0; + }); + + const auto opcode_fetch = std::find_if( + vmctx->calc_jmp.begin(), vmctx->calc_jmp.end(), + [](const zydis_instr_t& instr_data) -> bool { + // mov/movsx/movzx rax/eax/ax/al, [rsi] + return instr_data.instr.operand_count > 1 && + (instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX) && + instr_data.instr.operands[0].type == + ZYDIS_OPERAND_TYPE_REGISTER && + util::reg::to64(instr_data.instr.operands[0].reg.value) == + ZYDIS_REGISTER_RAX && + instr_data.instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI; + }); + + if (opcode_fetch == vmctx->calc_jmp.end()) { + std::printf( + "> critical error trying to find opcode fetch inside of " + "compiler_t::encrypt...\n"); + exit(0); + } + + start_addr = decrypt_key - 1; // make it zero based... + std::for_each( + virt_labels.begin(), virt_labels.end(), [&](vm::vlabel_data& label) { + // sometimes there is a mov al, [rsi-1]... we want that disp... + if (opcode_fetch->instr.operands[1].mem.disp.has_displacement) + start_addr += + std::abs(opcode_fetch->instr.operands[1].mem.disp.value); + + decrypt_key = start_addr; + result.push_back({label.label_name, start_addr}); + + if (vmctx->exec_type == vmp2::exec_type_t::forward) { + std::for_each( + label.vinstrs.begin(), label.vinstrs.end(), + [&](vm::vinstr_data& vinstr) { + std::uint8_t opcode = vinstr.vm_handler; + std::uint64_t operand = 0u; + + // encrypt opcode... + std::tie(opcode, decrypt_key) = vm::instrs::encrypt_operand( + calc_jmp_transforms, vinstr.vm_handler, decrypt_key); + + // if there is an operand then we will encrypt that as well.. + if (vmctx->vm_handlers[vinstr.vm_handler].imm_size) { + auto& vm_handler_transforms = + vmctx->vm_handlers[vinstr.vm_handler].transforms; + std::tie(operand, decrypt_key) = vm::instrs::encrypt_operand( + vm_handler_transforms, vinstr.operand, decrypt_key); + } else // else just push back the opcode... { - const auto &vm_handler = vmctx->vm_handlers[ idx ]; - if ( vm_handler.profile && !vinstr.name.compare( vm_handler.profile->name ) ) - { - virt_labels.back().vinstrs.push_back( - { ( std::uint8_t )idx, vinstr.imm, vm_handler.profile->imm_size } ); - break; - } + result.back().vinstrs.push_back(opcode); + return; // finished here... } - } - return true; - } ); - return &virt_labels; - } + result.back().vinstrs.push_back(opcode); + for (auto idx = 0u; + idx < vmctx->vm_handlers[vinstr.vm_handler].imm_size / 8; + ++idx) + result.back().vinstrs.push_back( + reinterpret_cast(&vinstr.operand)[idx]); + }); + } else { + std::for_each( + label.vinstrs.begin(), label.vinstrs.end(), + [&](vm::vinstr_data& vinstr) { + std::uint8_t opcode = vinstr.vm_handler; + std::uint64_t operand = 0u; + + // encrypt opcode... + std::tie(opcode, decrypt_key) = vm::instrs::encrypt_operand( + calc_jmp_transforms, vinstr.vm_handler, decrypt_key); + + // if there is an operand then we will encrypt that as well.. + if (vmctx->vm_handlers[vinstr.vm_handler].imm_size) { + auto& vm_handler_transforms = + vmctx->vm_handlers[vinstr.vm_handler].transforms; + std::tie(operand, decrypt_key) = vm::instrs::encrypt_operand( + vm_handler_transforms, vinstr.operand, decrypt_key); + } else // else just push back the opcode... + { + result.back().vinstrs.insert(result.back().vinstrs.begin(), 1, + opcode); + return; // finished here... + } - std::vector< compiled_label_data > compiler_t::encrypt() - { - std::vector< compiled_label_data > result; - const auto end_of_module = vmctx->image_size + vmctx->image_base; - - // decryption key starts off as the image - // base address of the virtual instructions... - std::uintptr_t decrypt_key = end_of_module, start_addr; - if ( vmctx->exec_type == vmp2::exec_type_t::backward ) - std::for_each( virt_labels.begin()->vinstrs.begin(), virt_labels.begin()->vinstrs.end(), - [ & ]( const vinstr_data &vinstr ) { - ( ++decrypt_key ) += vinstr.imm_size ? vinstr.imm_size / 8 : 0; - } ); - - const auto opcode_fetch = std::find_if( - vmctx->calc_jmp.begin(), vmctx->calc_jmp.end(), []( const zydis_instr_t &instr_data ) -> bool { - // mov/movsx/movzx rax/eax/ax/al, [rsi] - return instr_data.instr.operand_count > 1 && - ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && - instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && - instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; - } ); - - if ( opcode_fetch == vmctx->calc_jmp.end() ) - { - std::printf( "> critical error trying to find opcode fetch inside of compiler_t::encrypt...\n" ); - exit( 0 ); + // operand goes first, then opcode when vip advances + // backwards... + std::vector _temp; + for (auto idx = 0u; + idx < vmctx->vm_handlers[vinstr.vm_handler].imm_size / 8; + ++idx) + _temp.push_back( + reinterpret_cast(&operand)[idx]); + + result.back().vinstrs.insert(result.back().vinstrs.begin(), + _temp.begin(), _temp.end()); + result.back().vinstrs.insert( + result.back().vinstrs.begin() + _temp.size(), opcode); + }); } - start_addr = decrypt_key - 1; // make it zero based... - std::for_each( virt_labels.begin(), virt_labels.end(), [ & ]( vm::vlabel_data &label ) { - // sometimes there is a mov al, [rsi-1]... we want that disp... - if ( opcode_fetch->instr.operands[ 1 ].mem.disp.has_displacement ) - start_addr += std::abs( opcode_fetch->instr.operands[ 1 ].mem.disp.value ); - - decrypt_key = start_addr; - result.push_back( { label.label_name, start_addr } ); - - if ( vmctx->exec_type == vmp2::exec_type_t::forward ) - { - std::for_each( label.vinstrs.begin(), label.vinstrs.end(), [ & ]( vm::vinstr_data &vinstr ) { - std::uint8_t opcode = vinstr.vm_handler; - std::uint64_t operand = 0u; - - // encrypt opcode... - std::tie( opcode, decrypt_key ) = - vm::instrs::encrypt_operand( calc_jmp_transforms, vinstr.vm_handler, decrypt_key ); - - // if there is an operand then we will encrypt that as well.. - if ( vmctx->vm_handlers[ vinstr.vm_handler ].imm_size ) - { - auto &vm_handler_transforms = vmctx->vm_handlers[ vinstr.vm_handler ].transforms; - std::tie( operand, decrypt_key ) = - vm::instrs::encrypt_operand( vm_handler_transforms, vinstr.operand, decrypt_key ); - } - else // else just push back the opcode... - { - result.back().vinstrs.push_back( opcode ); - return; // finished here... - } - - result.back().vinstrs.push_back( opcode ); - for ( auto idx = 0u; idx < vmctx->vm_handlers[ vinstr.vm_handler ].imm_size / 8; ++idx ) - result.back().vinstrs.push_back( reinterpret_cast< std::uint8_t * >( &vinstr.operand )[ idx ] ); - } ); - } - else - { - std::for_each( label.vinstrs.begin(), label.vinstrs.end(), [ & ]( vm::vinstr_data &vinstr ) { - std::uint8_t opcode = vinstr.vm_handler; - std::uint64_t operand = 0u; - - // encrypt opcode... - std::tie( opcode, decrypt_key ) = - vm::instrs::encrypt_operand( calc_jmp_transforms, vinstr.vm_handler, decrypt_key ); - - // if there is an operand then we will encrypt that as well.. - if ( vmctx->vm_handlers[ vinstr.vm_handler ].imm_size ) - { - auto &vm_handler_transforms = vmctx->vm_handlers[ vinstr.vm_handler ].transforms; - std::tie( operand, decrypt_key ) = - vm::instrs::encrypt_operand( vm_handler_transforms, vinstr.operand, decrypt_key ); - } - else // else just push back the opcode... - { - result.back().vinstrs.insert( result.back().vinstrs.begin(), 1, opcode ); - return; // finished here... - } - - // operand goes first, then opcode when vip advances backwards... - std::vector< std::uint8_t > _temp; - for ( auto idx = 0u; idx < vmctx->vm_handlers[ vinstr.vm_handler ].imm_size / 8; ++idx ) - _temp.push_back( reinterpret_cast< std::uint8_t * >( &operand )[ idx ] ); - - result.back().vinstrs.insert( result.back().vinstrs.begin(), _temp.begin(), _temp.end() ); - result.back().vinstrs.insert( result.back().vinstrs.begin() + _temp.size(), opcode ); - } ); - } - - result.back().enc_alloc_rva = encrypt_rva( start_addr ); - start_addr += result.back().vinstrs.size() - 1; // make it zero based... - } ); - - return result; - } + result.back().enc_alloc_rva = encrypt_rva(start_addr); + start_addr += + result.back().vinstrs.size() - 1; // make it zero based... + }); - std::uint64_t compiler_t::encrypt_rva( std::uint64_t rva ) - { - for ( auto &instr : encrypt_vinstrs_rva ) - rva = vm::transform::apply( instr.operands[ 0 ].size, instr.mnemonic, rva, - transform::has_imm( &instr ) ? instr.operands[ 1 ].imm.value.u : 0 ); + return result; +} - return rva; - } -} // namespace vm \ No newline at end of file +std::uint64_t compiler_t::encrypt_rva(std::uint64_t rva) { + for (auto& instr : encrypt_vinstrs_rva) + rva = vm::transform::apply( + instr.operands[0].size, instr.mnemonic, rva, + transform::has_imm(&instr) ? instr.operands[1].imm.value.u : 0); + + return rva; +} +} // namespace vm \ No newline at end of file diff --git a/src/compiler.h b/src/compiler.h deleted file mode 100644 index 96867a4..0000000 --- a/src/compiler.h +++ /dev/null @@ -1,130 +0,0 @@ -#pragma once -#include -#include -#include -#include - -#include "parser.h" - -namespace vm -{ - /// - /// struct containing encoded data for a given virtual instruction... - /// - struct vinstr_data - { - /// - /// vm handler index also known as the opcode... - /// - std::uint8_t vm_handler; - - /// - /// this field contains the second operand if any... - /// - std::uint64_t operand; - - /// - /// size in bits of the second operand if any... zero if none... - /// - std::uint8_t imm_size; - }; - - /// - /// struct containing all information for a label... - /// - struct vlabel_data - { - /// - /// name of the label... - /// - std::string label_name; - - /// - /// vector of encoded virtual instructions... - /// - std::vector< vinstr_data > vinstrs; - }; - - /// - /// struct containing compiled virtual instructions (encoded and encrypted) for a given label... - /// - struct compiled_label_data - { - /// - /// label name... - /// - std::string label_name; - - /// - /// relative virtual address from vm_entry to the virtual instructions... - /// - std::uintptr_t alloc_rva; - - /// - /// encrypted relative virtual address from vm_entry to virtual instructions... - /// - std::uintptr_t enc_alloc_rva; - - /// - /// vector of bytes containing the raw, encrypted virtual instructions... - /// - std::vector< std::uint8_t > vinstrs; - }; - - /// - /// class containing member functions used to encode and encrypted virtual instructions... - /// - class compiler_t - { - public: - /// - /// default constructor - /// - /// pointer to a vm context object which has already been init... - explicit compiler_t( vm::ctx_t *vmctx ); - - /// - /// encode virtual instructions from parser::virt_labels - /// - /// returns a vector of labels containing encoded virtual instructions - std::vector< vlabel_data > *encode(); - - /// - /// encrypt virtual instructions from parser::virt_labels - /// - /// returns a vector of compiled labels containing encoded and encrypted virtual - /// instructions... - std::vector< compiled_label_data > encrypt(); - - private: - /// - /// encrypt virtual instructions rva... read more - /// here... - /// - /// relative virtual address to encrypted virtual instructions... - /// - std::uint64_t encrypt_rva( std::uint64_t rva ); - - /// - /// pointer to the vmctx passed in by the constructor... - /// - vm::ctx_t *vmctx; - - /// - /// transformations used to decrypt the opcode operand extracted from calc_jmp... - /// you can read more here... - /// - transform::map_t calc_jmp_transforms; - - /// - /// vector of encoded labels... - /// - std::vector< vlabel_data > virt_labels; - - /// - /// vector of decoded zydis instructions containing the native instructions to encrypt the virtual instruction - /// rva which will be pushed onto the stack prior to jmping to vm entry... - /// - std::vector< zydis_decoded_instr_t > encrypt_vinstrs_rva; - }; -} // namespace vm \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index cf8731d..df18dbc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,138 +6,143 @@ #include #include -#include "compiler.h" -#include "parser.h" -#include "parser.tab.h" -#include "vmprofiler.hpp" -#include "gen_code.hpp" - -extern FILE *yyin; -extern "C" int yywrap() -{ - return 1; +#include +#include +#include +#include +#include + +extern FILE* yyin; +extern "C" int yywrap() { + return 1; } -void yyerror( char *msg ) -{ - std::printf( "[!] parsing failure: %s\n", msg ); +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().names( { "--out", "--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; +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() + .names({"--out", "--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("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( + LoadLibraryExA(argp.get("vmpbin").c_str(), NULL, + DONT_RESOLVE_DLL_REFERENCES)); + + const auto vm_entry_rva = + std::strtoull(argp.get("vmentry").c_str(), nullptr, 16); + const auto image_base = xtils::um_t::get_instance()->image_base( + argp.get("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; + } + + std::printf("> flattened and deobfuscated vm entry...\n"); + vm::util::print(vmctx.vm_entry); + std::printf("> extracted calc jmp from vm entry...\n"); + vm::util::print(vmctx.calc_jmp); + + 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); } + } - // - // 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... - // + // + // encrypt virtual instructions... + // - const auto module_base = reinterpret_cast< std::uintptr_t >( - LoadLibraryExA( argp.get< std::string >( "vmpbin" ).c_str(), NULL, DONT_RESOLVE_DLL_REFERENCES ) ); + auto compiled_labels = compiler.encrypt(); + std::printf("[+] finished encrypting... encrypted labels below...\n"); - 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 ); + for (const auto& label : compiled_labels) { + std::printf("> %s must be allocated at = 0x%p, encrypted rva = 0x%p\n", + label.label_name.c_str(), label.alloc_rva, label.enc_alloc_rva); - if ( !vmctx.init() ) + std::printf("> "); { - 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; - } - - std::printf( "> flattened and deobfuscated vm entry...\n" ); - vm::util::print( vmctx.vm_entry ); - std::printf( "> extracted calc jmp from vm entry...\n" ); - vm::util::print( vmctx.calc_jmp ); - - 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, encrypted rva = 0x%p\n", label.label_name.c_str(), - label.alloc_rva, label.enc_alloc_rva ); - - std::printf( "> " ); - { - for ( auto byte : label.vinstrs ) - std::printf( "0x%x ", byte ); + for (auto byte : label.vinstrs) + std::printf("0x%x ", byte); - std::printf( "\n" ); - } + std::printf("\n"); } + } - const auto cpp_result = gen::code( compiled_labels, argp.get< std::string >( "vmpbin" ), vmctx ); - std::ofstream output( argp.get< std::string >( "out" ) ); - output.write( cpp_result.data(), cpp_result.size() ); - output.close(); + const auto cpp_result = + gen::code(compiled_labels, argp.get("vmpbin"), vmctx); + std::ofstream output(argp.get("out")); + output.write(cpp_result.data(), cpp_result.size()); + output.close(); - std::printf( "> generated header file...\n" ); + std::printf("> generated header file...\n"); } \ No newline at end of file diff --git a/src/parser.cpp b/src/parser.cpp index 78747ec..8e1e41e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1,37 +1,30 @@ -#include "parser.h" +#include -parse_t::parse_t() -{ -} +parse_t::parse_t() {} -auto parse_t::get_instance() -> parse_t * -{ - static parse_t obj; - return &obj; +auto parse_t::get_instance() -> parse_t* { + static parse_t obj; + return &obj; } -void parse_t::add_label( std::string label_name ) -{ - // remove ":" from the end of the label name... - label_name.erase( label_name.end() - 1 ); - virt_labels.push_back( { label_name } ); +void parse_t::add_label(std::string label_name) { + // remove ":" from the end of the label name... + label_name.erase(label_name.end() - 1); + virt_labels.push_back({label_name}); } -void parse_t::add_vinstr( std::string vinstr_name ) -{ - virt_labels.back().vinstrs.push_back( { vinstr_name, false, 0u } ); +void parse_t::add_vinstr(std::string vinstr_name) { + virt_labels.back().vinstrs.push_back({vinstr_name, false, 0u}); } -void parse_t::add_vinstr( std::string vinstr_name, std::uintptr_t imm_val ) -{ - virt_labels.back().vinstrs.push_back( { vinstr_name, true, imm_val } ); +void parse_t::add_vinstr(std::string vinstr_name, std::uintptr_t imm_val) { + virt_labels.back().vinstrs.push_back({vinstr_name, true, imm_val}); } -bool parse_t::for_each( callback_t callback ) -{ - for ( auto &entry : virt_labels ) - if ( !callback( &entry ) ) - return false; +bool parse_t::for_each(callback_t callback) { + for (auto& entry : virt_labels) + if (!callback(&entry)) + return false; - return true; + return true; } \ No newline at end of file diff --git a/vmassembler.sln b/vmassembler.sln deleted file mode 100644 index 23f78af..0000000 --- a/vmassembler.sln +++ /dev/null @@ -1,266 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30907.101 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmassembler", "src\vmassembler.vcxproj", "{6AC977FF-BD53-4A74-8452-69B3500924E8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Zydis", "dependencies\vmprofiler\dependencies\zydis\msvc\zydis\Zydis.vcxproj", "{88A23124-5640-35A0-B890-311D7A67A7D2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmprofiler", "dependencies\vmprofiler\vmprofiler.vcxproj", "{D0B6092A-9944-4F24-9486-4B7DAE372619}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo", "demo\demo.vcxproj", "{1DC5C971-7D10-488D-A4BF-8702FA804559}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dependencies", "dependencies", "{78C20558-6361-4C90-BE9E-273885FFA6C5}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - DBG|x64 = DBG|x64 - DBG|x86 = DBG|x86 - Debug Kernel|x64 = Debug Kernel|x64 - Debug Kernel|x86 = Debug Kernel|x86 - Debug MD DLL|x64 = Debug MD DLL|x64 - Debug MD DLL|x86 = Debug MD DLL|x86 - Debug MD|x64 = Debug MD|x64 - Debug MD|x86 = Debug MD|x86 - Debug MT DLL|x64 = Debug MT DLL|x64 - Debug MT DLL|x86 = Debug MT DLL|x86 - Debug MT|x64 = Debug MT|x64 - Debug MT|x86 = Debug MT|x86 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release Kernel|x64 = Release Kernel|x64 - Release Kernel|x86 = Release Kernel|x86 - Release MD DLL|x64 = Release MD DLL|x64 - Release MD DLL|x86 = Release MD DLL|x86 - Release MD|x64 = Release MD|x64 - Release MD|x86 = Release MD|x86 - Release MT DLL|x64 = Release MT DLL|x64 - Release MT DLL|x86 = Release MT DLL|x86 - Release MT|x64 = Release MT|x64 - Release MT|x86 = Release MT|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6AC977FF-BD53-4A74-8452-69B3500924E8}.DBG|x64.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.DBG|x64.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.DBG|x86.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.DBG|x86.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug Kernel|x64.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug Kernel|x64.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug Kernel|x86.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug Kernel|x86.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MD DLL|x64.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MD DLL|x64.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MD DLL|x86.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MD DLL|x86.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MD|x64.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MD|x64.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MD|x86.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MD|x86.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MT DLL|x64.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MT DLL|x64.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MT DLL|x86.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MT DLL|x86.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MT|x64.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MT|x64.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MT|x86.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug MT|x86.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug|x64.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug|x64.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug|x86.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Debug|x86.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release Kernel|x64.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release Kernel|x64.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release Kernel|x86.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release Kernel|x86.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MD DLL|x64.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MD DLL|x64.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MD DLL|x86.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MD DLL|x86.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MD|x64.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MD|x64.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MD|x86.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MD|x86.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MT DLL|x64.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MT DLL|x64.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MT DLL|x86.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MT DLL|x86.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MT|x64.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MT|x64.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MT|x86.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release MT|x86.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release|x64.ActiveCfg = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release|x64.Build.0 = Release|x64 - {6AC977FF-BD53-4A74-8452-69B3500924E8}.Release|x86.ActiveCfg = Release|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.DBG|x64.ActiveCfg = Debug MT|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.DBG|x64.Build.0 = Debug MT|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.DBG|x86.ActiveCfg = Debug MT|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.DBG|x86.Build.0 = Debug MT|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug Kernel|x64.ActiveCfg = Debug Kernel|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug Kernel|x64.Build.0 = Debug Kernel|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug Kernel|x64.Deploy.0 = Debug Kernel|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug Kernel|x86.ActiveCfg = Debug Kernel|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug Kernel|x86.Build.0 = Debug Kernel|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug Kernel|x86.Deploy.0 = Debug Kernel|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MD DLL|x64.ActiveCfg = Debug MD DLL|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MD DLL|x64.Build.0 = Debug MD DLL|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MD DLL|x86.ActiveCfg = Debug MD DLL|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MD DLL|x86.Build.0 = Debug MD DLL|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MD|x64.ActiveCfg = Debug MD|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MD|x64.Build.0 = Debug MD|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MD|x86.ActiveCfg = Debug MD|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MD|x86.Build.0 = Debug MD|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MT DLL|x64.ActiveCfg = Debug MT DLL|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MT DLL|x64.Build.0 = Debug MT DLL|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MT DLL|x86.ActiveCfg = Debug MT DLL|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MT DLL|x86.Build.0 = Debug MT DLL|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MT|x64.ActiveCfg = Debug MT|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MT|x64.Build.0 = Debug MT|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MT|x86.ActiveCfg = Debug MT|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug MT|x86.Build.0 = Debug MT|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug|x64.ActiveCfg = Debug MD DLL|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug|x64.Build.0 = Debug MD DLL|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug|x86.ActiveCfg = Debug MD DLL|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug|x86.Build.0 = Debug MD DLL|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release Kernel|x64.ActiveCfg = Release Kernel|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release Kernel|x64.Build.0 = Release Kernel|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release Kernel|x64.Deploy.0 = Release Kernel|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release Kernel|x86.ActiveCfg = Release Kernel|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release Kernel|x86.Build.0 = Release Kernel|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release Kernel|x86.Deploy.0 = Release Kernel|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MD DLL|x64.ActiveCfg = Release MD DLL|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MD DLL|x64.Build.0 = Release MD DLL|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MD DLL|x86.ActiveCfg = Release MD DLL|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MD DLL|x86.Build.0 = Release MD DLL|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MD|x64.ActiveCfg = Release MD|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MD|x64.Build.0 = Release MD|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MD|x86.ActiveCfg = Release MD|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MD|x86.Build.0 = Release MD|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MT DLL|x64.ActiveCfg = Release MT DLL|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MT DLL|x64.Build.0 = Release MT DLL|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MT DLL|x86.ActiveCfg = Release MT DLL|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MT DLL|x86.Build.0 = Release MT DLL|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MT|x64.ActiveCfg = Release MT|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MT|x64.Build.0 = Release MT|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MT|x86.ActiveCfg = Release MT|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release MT|x86.Build.0 = Release MT|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release|x64.ActiveCfg = Release MT|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release|x64.Build.0 = Release MT|x64 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release|x86.ActiveCfg = Release MT DLL|Win32 - {88A23124-5640-35A0-B890-311D7A67A7D2}.Release|x86.Build.0 = Release MT DLL|Win32 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.DBG|x64.ActiveCfg = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.DBG|x64.Build.0 = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.DBG|x86.ActiveCfg = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug Kernel|x64.ActiveCfg = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug Kernel|x64.Build.0 = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug Kernel|x86.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug Kernel|x86.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD DLL|x64.ActiveCfg = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD DLL|x64.Build.0 = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD DLL|x86.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD DLL|x86.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD|x64.ActiveCfg = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD|x64.Build.0 = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD|x86.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD|x86.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT DLL|x64.ActiveCfg = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT DLL|x64.Build.0 = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT DLL|x86.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT DLL|x86.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT|x64.ActiveCfg = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT|x64.Build.0 = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT|x86.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT|x86.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug|x64.ActiveCfg = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug|x64.Build.0 = DBG|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug|x86.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug|x86.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release Kernel|x64.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release Kernel|x64.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release Kernel|x86.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release Kernel|x86.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MD DLL|x64.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MD DLL|x64.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MD DLL|x86.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MD DLL|x86.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MD|x64.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MD|x64.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MD|x86.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MD|x86.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MT DLL|x64.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MT DLL|x64.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MT DLL|x86.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MT DLL|x86.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MT|x64.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MT|x64.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MT|x86.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MT|x86.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release|x64.ActiveCfg = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release|x64.Build.0 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Release|x86.ActiveCfg = Release|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.DBG|x64.ActiveCfg = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.DBG|x64.Build.0 = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.DBG|x86.ActiveCfg = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.DBG|x86.Build.0 = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug Kernel|x64.ActiveCfg = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug Kernel|x64.Build.0 = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug Kernel|x86.ActiveCfg = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug Kernel|x86.Build.0 = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MD DLL|x64.ActiveCfg = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MD DLL|x64.Build.0 = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MD DLL|x86.ActiveCfg = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MD DLL|x86.Build.0 = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MD|x64.ActiveCfg = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MD|x64.Build.0 = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MD|x86.ActiveCfg = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MD|x86.Build.0 = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MT DLL|x64.ActiveCfg = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MT DLL|x64.Build.0 = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MT DLL|x86.ActiveCfg = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MT DLL|x86.Build.0 = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MT|x64.ActiveCfg = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MT|x64.Build.0 = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MT|x86.ActiveCfg = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug MT|x86.Build.0 = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug|x64.ActiveCfg = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug|x64.Build.0 = Debug|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug|x86.ActiveCfg = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Debug|x86.Build.0 = Debug|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release Kernel|x64.ActiveCfg = Release|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release Kernel|x64.Build.0 = Release|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release Kernel|x86.ActiveCfg = Release|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release Kernel|x86.Build.0 = Release|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MD DLL|x64.ActiveCfg = Release|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MD DLL|x64.Build.0 = Release|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MD DLL|x86.ActiveCfg = Release|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MD DLL|x86.Build.0 = Release|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MD|x64.ActiveCfg = Release|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MD|x64.Build.0 = Release|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MD|x86.ActiveCfg = Release|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MD|x86.Build.0 = Release|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MT DLL|x64.ActiveCfg = Release|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MT DLL|x64.Build.0 = Release|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MT DLL|x86.ActiveCfg = Release|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MT DLL|x86.Build.0 = Release|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MT|x64.ActiveCfg = Release|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MT|x64.Build.0 = Release|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MT|x86.ActiveCfg = Release|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release MT|x86.Build.0 = Release|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release|x64.ActiveCfg = Release|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release|x64.Build.0 = Release|x64 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release|x86.ActiveCfg = Release|Win32 - {1DC5C971-7D10-488D-A4BF-8702FA804559}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {88A23124-5640-35A0-B890-311D7A67A7D2} = {78C20558-6361-4C90-BE9E-273885FFA6C5} - {D0B6092A-9944-4F24-9486-4B7DAE372619} = {78C20558-6361-4C90-BE9E-273885FFA6C5} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {BDC537F0-DE8E-4744-A03B-BD9FD0B98C60} - EndGlobalSection -EndGlobal