porting the project to cmkr...

merge-requests/3/head
John Doe 3 years ago
parent a9c482fb13
commit 786ecb2f81

@ -1,18 +1,5 @@
--- ---
BasedOnStyle: Microsoft BasedOnStyle: Chromium
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
... ...

2
.gitignore vendored

@ -9,6 +9,7 @@
*.user *.user
*.userosscache *.userosscache
*.sln.docstates *.sln.docstates
*.exe
# User-specific files (MonoDevelop/Xamarin Studio) # User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs *.userprefs
@ -17,6 +18,7 @@
mono_crash.* mono_crash.*
# Build results # Build results
build/
[Dd]ebug/ [Dd]ebug/
[Dd]ebugPublic/ [Dd]ebugPublic/
[Rr]elease/ [Rr]elease/

@ -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)

@ -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"]

@ -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()

@ -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)

@ -0,0 +1,9 @@
[subdir.vmprofiler]
[target.cli-parser]
type = "interface"
include-directories = ["cli-parser"]
[target.xtils]
type = "interface"
include-directories = ["xtils"]

@ -1 +1 @@
Subproject commit 0f6ba9bad30d67f25f01b6c1e872077efdff61d4 Subproject commit 14cc72c0ff121d13f2ba26be34d1e99492aad296

@ -1 +1 @@
Subproject commit 7c32517322c29a866cbb1e67fb9051efa2e05553 Subproject commit db7526d989bdfecb6fac2079929efce94cead52c

@ -0,0 +1,131 @@
#pragma once
#include <Windows.h>
#include <algorithm>
#include <vmprofiler.hpp>
#include <xtils.hpp>
#include <parser.hpp>
namespace vm {
/// <summary>
/// struct containing encoded data for a given virtual instruction...
/// </summary>
struct vinstr_data {
/// <summary>
/// vm handler index also known as the opcode...
/// </summary>
std::uint8_t vm_handler;
/// <summary>
/// this field contains the second operand if any...
/// </summary>
std::uint64_t operand;
/// <summary>
/// size in bits of the second operand if any... zero if none...
/// </summary>
std::uint8_t imm_size;
};
/// <summary>
/// struct containing all information for a label...
/// </summary>
struct vlabel_data {
/// <summary>
/// name of the label...
/// </summary>
std::string label_name;
/// <summary>
/// vector of encoded virtual instructions...
/// </summary>
std::vector<vinstr_data> vinstrs;
};
/// <summary>
/// struct containing compiled virtual instructions (encoded and encrypted) for
/// a given label...
/// </summary>
struct compiled_label_data {
/// <summary>
/// label name...
/// </summary>
std::string label_name;
/// <summary>
/// relative virtual address from vm_entry to the virtual instructions...
/// </summary>
std::uintptr_t alloc_rva;
/// <summary>
/// encrypted relative virtual address from vm_entry to virtual
/// instructions...
/// </summary>
std::uintptr_t enc_alloc_rva;
/// <summary>
/// vector of bytes containing the raw, encrypted virtual instructions...
/// </summary>
std::vector<std::uint8_t> vinstrs;
};
/// <summary>
/// class containing member functions used to encode and encrypted virtual
/// instructions...
/// </summary>
class compiler_t {
public:
/// <summary>
/// default constructor
/// </summary>
/// <param name="vmctx">pointer to a vm context object which has already been
/// init...</param>
explicit compiler_t(vm::ctx_t* vmctx);
/// <summary>
/// encode virtual instructions from parser::virt_labels
/// </summary>
/// <returns>returns a vector of labels containing encoded virtual
/// instructions</returns>
std::vector<vlabel_data>* encode();
/// <summary>
/// encrypt virtual instructions from parser::virt_labels
/// </summary>
/// <returns>returns a vector of compiled labels containing encoded and
/// encrypted virtual instructions...</returns>
std::vector<compiled_label_data> encrypt();
private:
/// <summary>
/// encrypt virtual instructions rva... <a
/// href="https://back.engineering/17/05/2021/#vm_entry">read more here...</a>
/// </summary>
/// <param name="rva">relative virtual address to encrypted virtual
/// instructions...</param> <returns></returns>
std::uint64_t encrypt_rva(std::uint64_t rva);
/// <summary>
/// pointer to the vmctx passed in by the constructor...
/// </summary>
vm::ctx_t* vmctx;
/// <summary>
/// transformations used to decrypt the opcode operand extracted from
/// calc_jmp... you can read more <a
/// href="https://back.engineering/17/05/2021/#calc_jmp">here...</a>
/// </summary>
transform::map_t calc_jmp_transforms;
/// <summary>
/// vector of encoded labels...
/// </summary>
std::vector<vlabel_data> virt_labels;
/// <summary>
/// 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...
/// </summary>
std::vector<zydis_decoded_instr_t> encrypt_vinstrs_rva;
};
} // namespace vm

@ -1,52 +1,55 @@
#pragma once #pragma once
#include <compiler.hpp>
#include <fstream> #include <fstream>
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
#include <xtils.hpp> #include <xtils.hpp>
#include "compiler.h" namespace gen {
/// <summary>
namespace gen /// function pasted from
{ /// https://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprintf
/// <summary> /// </summary>
/// function pasted from https://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprintf /// <typeparam name="...Args"></typeparam>
/// </summary> /// <param name="format"></param>
/// <typeparam name="...Args"></typeparam> /// <param name="...args"></param>
/// <param name="format"></param> /// <returns></returns>
/// <param name="...args"></param> template <typename... Args>
/// <returns></returns> std::string string_format(const std::string& format, Args... args) {
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);
int size_s = std::snprintf( nullptr, 0, format.c_str(), args... ) + 1; auto buf = std::make_unique<char[]>(size);
auto size = static_cast< size_t >( size_s ); std::snprintf(buf.get(), size, format.c_str(), args...);
auto buf = std::make_unique< char[] >( size ); return std::string(buf.get(), buf.get() + size - 1);
std::snprintf( buf.get(), size, format.c_str(), args... ); }
return std::string( buf.get(), buf.get() + size - 1 );
} /// <summary>
/// generates c++ header file which MUST BE COMPILED USING CLANG BECAUSE MSVC
/// <summary> /// CANT HANDLE HUGE STATIC INITS (6/13/2021)....
/// generates c++ header file which MUST BE COMPILED USING CLANG BECAUSE MSVC CANT HANDLE HUGE STATIC INITS (6/13/2021).... /// </summary>
/// </summary> /// <param name="labels">vector of compiled labels...</param>
/// <param name="labels">vector of compiled labels...</param> /// <param name="image_path">path to the image on disk...</param>
/// <param name="image_path">path to the image on disk...</param> /// <param name="vmctx"></param>
/// <param name="vmctx"></param> /// <returns></returns>
/// <returns></returns> inline std::string code(std::vector<vm::compiled_label_data>& labels,
inline std::string code( std::vector< vm::compiled_label_data > &labels, std::string image_path, vm::ctx_t& vmctx ) std::string image_path,
{ vm::ctx_t& vmctx) {
std::string result, raw_file_array; std::string result, raw_file_array;
std::vector< std::uint8_t > raw_file; std::vector<std::uint8_t> raw_file;
xtils::um_t::get_instance()->open_binary_file( image_path, raw_file ); xtils::um_t::get_instance()->open_binary_file(image_path, raw_file);
for ( auto idx = 0u; idx < raw_file.size(); ++idx ) for (auto idx = 0u; idx < raw_file.size(); ++idx)
raw_file_array.append( string_format( "0x%x, ", raw_file[ idx ] ) ); raw_file_array.append(string_format("0x%x, ", raw_file[idx]));
result.append( "#pragma once\n" result.append(
"#pragma once\n"
"#pragma section( \".xmp2\" )\n" "#pragma section( \".xmp2\" )\n"
"#pragma comment( linker, \"/section:.xmp2,RWE\" ) \n\n" ); "#pragma comment( linker, \"/section:.xmp2,RWE\" ) \n\n");
result.append( "namespace vm\n" result.append(
"{\n" ); "namespace vm\n"
"{\n");
result.append( R"( using u8 = unsigned char; result.append(R"( using u8 = unsigned char;
using s8 = signed char; using s8 = signed char;
using u16 = unsigned short; using u16 = unsigned short;
@ -169,78 +172,84 @@ namespace gen
{ {
unsigned int VirtualAddress; unsigned int VirtualAddress;
unsigned int SizeOfBlock; unsigned int SizeOfBlock;
} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION;)" ); } IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION;)");
result.append( "\n\n\ttemplate < class T, class U > struct _pair_t\n" result.append(
"\n\n\ttemplate < class T, class U > struct _pair_t\n"
"\t{\n" "\t{\n"
"\t\tT first;\n" "\t\tT first;\n"
"\t\tU second;\n" "\t\tU second;\n"
"\t};\n\n" ); "\t};\n\n");
result.append( string_format( "\tconstexpr auto entry_rva = 0x%x;\n\n", vmctx.vm_entry_rva ) ); result.append(string_format("\tconstexpr auto entry_rva = 0x%x;\n\n",
vmctx.vm_entry_rva));
result.append( "\tenum class calls : u32\n" result.append(
"\t{\n" ); "\tenum class calls : u32\n"
"\t{\n");
for ( auto idx = 0u; idx < labels.size(); ++idx ) 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(string_format("\t\t%s = 0x%x,\n", labels[idx].label_name,
labels[idx].enc_alloc_rva));
result.append( "\t};\n\n" ); result.append("\t};\n\n");
result.append( string_format( "\tinline _pair_t< u8, calls > call_map[%d] = \n" result.append(
string_format("\tinline _pair_t< u8, calls > call_map[%d] = \n"
"\t{\n", "\t{\n",
labels.size() ) ); labels.size()));
for ( auto idx = 0u; idx < labels.size(); ++idx ) 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(string_format("\t\t{ %d, calls::%s },\n", idx,
labels[idx].label_name.c_str()));
result.append( "\t};\n\n" ); result.append("\t};\n\n");
result.append( string_format( "\t__declspec(align(1)) struct _gen_data\n" result.append(
string_format("\t__declspec(align(1)) struct _gen_data\n"
"\t{\n" "\t{\n"
"\t\tu8 bin[%d] =\n" "\t\tu8 bin[%d] =\n"
"\t\t{\n" "\t\t{\n"
"\t\t\t%s\n", "\t\t\t%s\n",
raw_file.size(), raw_file_array.c_str() ) ); raw_file.size(), raw_file_array.c_str()));
result.append( "\t\t};\n\n" ); result.append("\t\t};\n\n");
result.append( string_format( "\t\tu8 map_area[0x%x];\n\n", vmctx.image_size ) ); result.append(string_format("\t\tu8 map_area[0x%x];\n\n", vmctx.image_size));
for ( auto &label : labels ) for (auto& label : labels) {
{ result.append(string_format("\t\tu8 __%s_vinstrs[%d] =\n",
result.append( label.label_name.c_str(),
string_format( "\t\tu8 __%s_vinstrs[%d] =\n", label.label_name.c_str(), label.vinstrs.size() ) ); label.vinstrs.size()));
result.append( "\t\t{\n\t\t\t" ); result.append("\t\t{\n\t\t\t");
for ( auto &byte : label.vinstrs ) for (auto& byte : label.vinstrs)
result.append( string_format( "0x%x, ", byte ) ); result.append(string_format("0x%x, ", byte));
result.append( "\n\t\t};\n\n" ); result.append("\n\t\t};\n\n");
} }
result.append( string_format( "\t\tu8 __vmcall_shell_code[%d][15] =\n" result.append(
string_format("\t\tu8 __vmcall_shell_code[%d][15] =\n"
"\t\t{\n", "\t\t{\n",
labels.size() ) ); labels.size()));
for ( auto idx = 0u; idx < labels.size(); ++idx ) for (auto idx = 0u; idx < labels.size(); ++idx) {
{
std::string jmp_code; std::string jmp_code;
// two push instructions... // two push instructions...
for ( auto i = 0u; i < 2; ++i ) for (auto i = 0u; i < 2; ++i) {
{ jmp_code.append("0x68, "); // push opcode...
jmp_code.append( "0x68, " ); // push opcode...
for ( auto _idx = 0u; _idx < 4; ++_idx ) for (auto _idx = 0u; _idx < 4; ++_idx)
jmp_code.append( "0x0, " ); jmp_code.append("0x0, ");
} }
// one jmp instruction... // one jmp instruction...
jmp_code.append( "0xE9, " ); jmp_code.append("0xE9, ");
for ( auto i = 0u; i < 4; ++i ) for (auto i = 0u; i < 4; ++i)
jmp_code.append( "0x0, " ); 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("\t\t};\n\n");
result.append( R"( bool init() result.append(R"( bool init()
{ {
static const auto _memcpy = []( void *dest, const void *src, size_t len ) -> void * { static const auto _memcpy = []( void *dest, const void *src, size_t len ) -> void * {
char *d = ( char * )dest; char *d = ( char * )dest;
@ -324,12 +333,14 @@ namespace gen
} }
return true; // only a bool so i can use static/call init only once... return true; // only a bool so i can use static/call init only once...
})" ); })");
result.append( "\n\t};\n\n" ); result.append("\n\t};\n\n");
result.append( "\t__declspec(allocate(\".xmp2\")) inline _gen_data gen_data;\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(); static auto __init_result = gen_data.init();
@ -339,9 +350,9 @@ namespace gen
vmcall = reinterpret_cast< __vmcall_t >( &gen_data.__vmcall_shell_code[ idx ] ); vmcall = reinterpret_cast< __vmcall_t >( &gen_data.__vmcall_shell_code[ idx ] );
return reinterpret_cast< T >( vmcall( args... ) ); return reinterpret_cast< T >( vmcall( args... ) );
})" ); })");
result.append( "\n}" ); result.append("\n}");
return result; return result;
} }
} // namespace gen } // namespace gen

@ -1,194 +1,211 @@
#include "compiler.h" #include <compiler.hpp>
namespace vm namespace vm {
{ compiler_t::compiler_t(vm::ctx_t* vmctx) : vmctx(vmctx) {
compiler_t::compiler_t( vm::ctx_t *vmctx ) : vmctx( vmctx ) if (!parse_t::get_instance()->for_each([&](_vlabel_meta* label_data) -> bool {
{ std::printf(
if ( !parse_t::get_instance()->for_each( [ & ]( _vlabel_meta *label_data ) -> bool { "> checking label %s for invalid instructions... number of "
std::printf( "> checking label %s for invalid instructions... number of instructions = %d\n", "instructions = %d\n",
label_data->label_name.c_str(), label_data->vinstrs.size() ); label_data->label_name.c_str(), label_data->vinstrs.size());
const auto result = std::find_if( const auto result = std::find_if(
label_data->vinstrs.begin(), label_data->vinstrs.end(), label_data->vinstrs.begin(), label_data->vinstrs.end(),
[ & ]( const _vinstr_meta &vinstr ) -> bool { [&](const _vinstr_meta& vinstr) -> bool {
std::printf( "> vinstr name = %s, has imm = %d, imm = 0x%p\n", vinstr.name.c_str(), std::printf("> vinstr name = %s, has imm = %d, imm = 0x%p\n",
vinstr.has_imm, vinstr.imm ); vinstr.name.c_str(), vinstr.has_imm, vinstr.imm);
for ( auto &vm_handler : vmctx->vm_handlers ) for (auto& vm_handler : vmctx->vm_handlers)
if ( vm_handler.profile && vm_handler.profile->name == vinstr.name ) if (vm_handler.profile &&
vm_handler.profile->name == vinstr.name)
return false; return false;
std::printf( "[!] this vm protected file does not have the vm handler for: %s...\n", std::printf(
vinstr.name.c_str() ); "[!] this vm protected file does not have the vm handler "
"for: %s...\n",
vinstr.name.c_str());
return true; return true;
} ); });
return result == label_data->vinstrs.end(); return result == label_data->vinstrs.end();
} ) ) })) {
{ std::printf("[!] binary does not have the required vm handlers...\n");
std::printf( "[!] binary does not have the required vm handlers...\n" ); exit(-1);
exit( -1 );
} }
if ( !vm::handler::get_operand_transforms( vmctx->calc_jmp, calc_jmp_transforms ) ) if (!vm::handler::get_operand_transforms(vmctx->calc_jmp,
{ calc_jmp_transforms)) {
std::printf( "[!] failed to extract calc_jmp transformations...\n" ); std::printf("[!] failed to extract calc_jmp transformations...\n");
exit( -1 ); exit(-1);
} }
if ( !vm::instrs::get_rva_decrypt( vmctx->vm_entry, encrypt_vinstrs_rva ) ) if (!vm::instrs::get_rva_decrypt(vmctx->vm_entry, encrypt_vinstrs_rva)) {
{ std::printf(
std::printf( "[!] failed to extract virtual instruction rva decryption instructions...\n" ); "[!] failed to extract virtual instruction rva decryption "
exit( -1 ); "instructions...\n");
exit(-1);
} }
if ( !vm::transform::inverse_transforms( encrypt_vinstrs_rva ) ) if (!vm::transform::inverse_transforms(encrypt_vinstrs_rva)) {
{ std::printf(
std::printf( "[!] failed to inverse virtual instruction rva decrypt instructions...\n" ); "[!] failed to inverse virtual instruction rva decrypt "
exit( -1 ); "instructions...\n");
} exit(-1);
} }
}
std::vector< vlabel_data > *compiler_t::encode() std::vector<vlabel_data>* compiler_t::encode() {
{ parse_t::get_instance()->for_each([&](_vlabel_meta* label_data) -> bool {
parse_t::get_instance()->for_each( [ & ]( _vlabel_meta *label_data ) -> bool { virt_labels.push_back({label_data->label_name});
virt_labels.push_back( { label_data->label_name } ); for (const auto& vinstr : label_data->vinstrs) {
for ( const auto &vinstr : label_data->vinstrs ) for (auto idx = 0u; idx < 256; ++idx) {
{ const auto& vm_handler = vmctx->vm_handlers[idx];
for ( auto idx = 0u; idx < 256; ++idx ) if (vm_handler.profile &&
{ !vinstr.name.compare(vm_handler.profile->name)) {
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( virt_labels.back().vinstrs.push_back(
{ ( std::uint8_t )idx, vinstr.imm, vm_handler.profile->imm_size } ); {(std::uint8_t)idx, vinstr.imm, vm_handler.profile->imm_size});
break; break;
} }
} }
} }
return true; return true;
} ); });
return &virt_labels; return &virt_labels;
} }
std::vector< compiled_label_data > compiler_t::encrypt() std::vector<compiled_label_data> compiler_t::encrypt() {
{ std::vector<compiled_label_data> result;
std::vector< compiled_label_data > result;
const auto end_of_module = vmctx->image_size + vmctx->image_base; const auto end_of_module = vmctx->image_size + vmctx->image_base;
// decryption key starts off as the image // decryption key starts off as the image
// base address of the virtual instructions... // base address of the virtual instructions...
std::uintptr_t decrypt_key = end_of_module, start_addr; std::uintptr_t decrypt_key = end_of_module, start_addr;
if ( vmctx->exec_type == vmp2::exec_type_t::backward ) if (vmctx->exec_type == vmp2::exec_type_t::backward)
std::for_each( virt_labels.begin()->vinstrs.begin(), virt_labels.begin()->vinstrs.end(), std::for_each(
[ & ]( const vinstr_data &vinstr ) { virt_labels.begin()->vinstrs.begin(),
( ++decrypt_key ) += vinstr.imm_size ? vinstr.imm_size / 8 : 0; 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( const auto opcode_fetch = std::find_if(
vmctx->calc_jmp.begin(), vmctx->calc_jmp.end(), []( const zydis_instr_t &instr_data ) -> bool { vmctx->calc_jmp.begin(), vmctx->calc_jmp.end(),
[](const zydis_instr_t& instr_data) -> bool {
// mov/movsx/movzx rax/eax/ax/al, [rsi] // mov/movsx/movzx rax/eax/ax/al, [rsi]
return instr_data.instr.operand_count > 1 && return instr_data.instr.operand_count > 1 &&
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || (instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX) &&
instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr_data.instr.operands[0].type ==
util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && ZYDIS_OPERAND_TYPE_REGISTER &&
instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && util::reg::to64(instr_data.instr.operands[0].reg.value) ==
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; 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" ); if (opcode_fetch == vmctx->calc_jmp.end()) {
exit( 0 ); 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... start_addr = decrypt_key - 1; // make it zero based...
std::for_each( virt_labels.begin(), virt_labels.end(), [ & ]( vm::vlabel_data &label ) { 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... // sometimes there is a mov al, [rsi-1]... we want that disp...
if ( opcode_fetch->instr.operands[ 1 ].mem.disp.has_displacement ) if (opcode_fetch->instr.operands[1].mem.disp.has_displacement)
start_addr += std::abs( opcode_fetch->instr.operands[ 1 ].mem.disp.value ); start_addr +=
std::abs(opcode_fetch->instr.operands[1].mem.disp.value);
decrypt_key = start_addr; decrypt_key = start_addr;
result.push_back( { label.label_name, start_addr } ); result.push_back({label.label_name, start_addr});
if ( vmctx->exec_type == vmp2::exec_type_t::forward ) if (vmctx->exec_type == vmp2::exec_type_t::forward) {
{ std::for_each(
std::for_each( label.vinstrs.begin(), label.vinstrs.end(), [ & ]( vm::vinstr_data &vinstr ) { label.vinstrs.begin(), label.vinstrs.end(),
[&](vm::vinstr_data& vinstr) {
std::uint8_t opcode = vinstr.vm_handler; std::uint8_t opcode = vinstr.vm_handler;
std::uint64_t operand = 0u; std::uint64_t operand = 0u;
// encrypt opcode... // encrypt opcode...
std::tie( opcode, decrypt_key ) = std::tie(opcode, decrypt_key) = vm::instrs::encrypt_operand(
vm::instrs::encrypt_operand( calc_jmp_transforms, vinstr.vm_handler, decrypt_key ); calc_jmp_transforms, vinstr.vm_handler, decrypt_key);
// if there is an operand then we will encrypt that as well.. // if there is an operand then we will encrypt that as well..
if ( vmctx->vm_handlers[ vinstr.vm_handler ].imm_size ) if (vmctx->vm_handlers[vinstr.vm_handler].imm_size) {
{ auto& vm_handler_transforms =
auto &vm_handler_transforms = vmctx->vm_handlers[ vinstr.vm_handler ].transforms; vmctx->vm_handlers[vinstr.vm_handler].transforms;
std::tie( operand, decrypt_key ) = std::tie(operand, decrypt_key) = vm::instrs::encrypt_operand(
vm::instrs::encrypt_operand( vm_handler_transforms, vinstr.operand, decrypt_key ); vm_handler_transforms, vinstr.operand, decrypt_key);
} } else // else just push back the opcode...
else // else just push back the opcode... {
{ result.back().vinstrs.push_back(opcode);
result.back().vinstrs.push_back( opcode );
return; // finished here... return; // finished here...
} }
result.back().vinstrs.push_back( opcode ); result.back().vinstrs.push_back(opcode);
for ( auto idx = 0u; idx < vmctx->vm_handlers[ vinstr.vm_handler ].imm_size / 8; ++idx ) for (auto idx = 0u;
result.back().vinstrs.push_back( reinterpret_cast< std::uint8_t * >( &vinstr.operand )[ idx ] ); idx < vmctx->vm_handlers[vinstr.vm_handler].imm_size / 8;
} ); ++idx)
} result.back().vinstrs.push_back(
else reinterpret_cast<std::uint8_t*>(&vinstr.operand)[idx]);
{ });
std::for_each( label.vinstrs.begin(), label.vinstrs.end(), [ & ]( vm::vinstr_data &vinstr ) { } else {
std::for_each(
label.vinstrs.begin(), label.vinstrs.end(),
[&](vm::vinstr_data& vinstr) {
std::uint8_t opcode = vinstr.vm_handler; std::uint8_t opcode = vinstr.vm_handler;
std::uint64_t operand = 0u; std::uint64_t operand = 0u;
// encrypt opcode... // encrypt opcode...
std::tie( opcode, decrypt_key ) = std::tie(opcode, decrypt_key) = vm::instrs::encrypt_operand(
vm::instrs::encrypt_operand( calc_jmp_transforms, vinstr.vm_handler, decrypt_key ); calc_jmp_transforms, vinstr.vm_handler, decrypt_key);
// if there is an operand then we will encrypt that as well.. // if there is an operand then we will encrypt that as well..
if ( vmctx->vm_handlers[ vinstr.vm_handler ].imm_size ) if (vmctx->vm_handlers[vinstr.vm_handler].imm_size) {
{ auto& vm_handler_transforms =
auto &vm_handler_transforms = vmctx->vm_handlers[ vinstr.vm_handler ].transforms; vmctx->vm_handlers[vinstr.vm_handler].transforms;
std::tie( operand, decrypt_key ) = std::tie(operand, decrypt_key) = vm::instrs::encrypt_operand(
vm::instrs::encrypt_operand( vm_handler_transforms, vinstr.operand, decrypt_key ); vm_handler_transforms, vinstr.operand, decrypt_key);
} } else // else just push back the opcode...
else // else just push back the opcode... {
{ result.back().vinstrs.insert(result.back().vinstrs.begin(), 1,
result.back().vinstrs.insert( result.back().vinstrs.begin(), 1, opcode ); opcode);
return; // finished here... return; // finished here...
} }
// operand goes first, then opcode when vip advances backwards... // operand goes first, then opcode when vip advances
std::vector< std::uint8_t > _temp; // backwards...
for ( auto idx = 0u; idx < vmctx->vm_handlers[ vinstr.vm_handler ].imm_size / 8; ++idx ) std::vector<std::uint8_t> _temp;
_temp.push_back( reinterpret_cast< std::uint8_t * >( &operand )[ idx ] ); 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(),
result.back().vinstrs.insert( result.back().vinstrs.begin() + _temp.size(), opcode ); _temp.begin(), _temp.end());
} ); result.back().vinstrs.insert(
result.back().vinstrs.begin() + _temp.size(), opcode);
});
} }
result.back().enc_alloc_rva = encrypt_rva( start_addr ); result.back().enc_alloc_rva = encrypt_rva(start_addr);
start_addr += result.back().vinstrs.size() - 1; // make it zero based... start_addr +=
} ); result.back().vinstrs.size() - 1; // make it zero based...
});
return result; return result;
} }
std::uint64_t compiler_t::encrypt_rva( std::uint64_t rva ) std::uint64_t compiler_t::encrypt_rva(std::uint64_t rva) {
{ for (auto& instr : encrypt_vinstrs_rva)
for ( auto &instr : encrypt_vinstrs_rva ) rva = vm::transform::apply(
rva = vm::transform::apply( instr.operands[ 0 ].size, instr.mnemonic, rva, instr.operands[0].size, instr.mnemonic, rva,
transform::has_imm( &instr ) ? instr.operands[ 1 ].imm.value.u : 0 ); transform::has_imm(&instr) ? instr.operands[1].imm.value.u : 0);
return rva; return rva;
} }
} // namespace vm } // namespace vm

@ -1,130 +0,0 @@
#pragma once
#include <Windows.h>
#include <algorithm>
#include <vmprofiler.hpp>
#include <xtils.hpp>
#include "parser.h"
namespace vm
{
/// <summary>
/// struct containing encoded data for a given virtual instruction...
/// </summary>
struct vinstr_data
{
/// <summary>
/// vm handler index also known as the opcode...
/// </summary>
std::uint8_t vm_handler;
/// <summary>
/// this field contains the second operand if any...
/// </summary>
std::uint64_t operand;
/// <summary>
/// size in bits of the second operand if any... zero if none...
/// </summary>
std::uint8_t imm_size;
};
/// <summary>
/// struct containing all information for a label...
/// </summary>
struct vlabel_data
{
/// <summary>
/// name of the label...
/// </summary>
std::string label_name;
/// <summary>
/// vector of encoded virtual instructions...
/// </summary>
std::vector< vinstr_data > vinstrs;
};
/// <summary>
/// struct containing compiled virtual instructions (encoded and encrypted) for a given label...
/// </summary>
struct compiled_label_data
{
/// <summary>
/// label name...
/// </summary>
std::string label_name;
/// <summary>
/// relative virtual address from vm_entry to the virtual instructions...
/// </summary>
std::uintptr_t alloc_rva;
/// <summary>
/// encrypted relative virtual address from vm_entry to virtual instructions...
/// </summary>
std::uintptr_t enc_alloc_rva;
/// <summary>
/// vector of bytes containing the raw, encrypted virtual instructions...
/// </summary>
std::vector< std::uint8_t > vinstrs;
};
/// <summary>
/// class containing member functions used to encode and encrypted virtual instructions...
/// </summary>
class compiler_t
{
public:
/// <summary>
/// default constructor
/// </summary>
/// <param name="vmctx">pointer to a vm context object which has already been init...</param>
explicit compiler_t( vm::ctx_t *vmctx );
/// <summary>
/// encode virtual instructions from parser::virt_labels
/// </summary>
/// <returns>returns a vector of labels containing encoded virtual instructions</returns>
std::vector< vlabel_data > *encode();
/// <summary>
/// encrypt virtual instructions from parser::virt_labels
/// </summary>
/// <returns>returns a vector of compiled labels containing encoded and encrypted virtual
/// instructions...</returns>
std::vector< compiled_label_data > encrypt();
private:
/// <summary>
/// encrypt virtual instructions rva... <a href="https://back.engineering/17/05/2021/#vm_entry">read more
/// here...</a>
/// </summary>
/// <param name="rva">relative virtual address to encrypted virtual instructions...</param>
/// <returns></returns>
std::uint64_t encrypt_rva( std::uint64_t rva );
/// <summary>
/// pointer to the vmctx passed in by the constructor...
/// </summary>
vm::ctx_t *vmctx;
/// <summary>
/// transformations used to decrypt the opcode operand extracted from calc_jmp...
/// you can read more <a href="https://back.engineering/17/05/2021/#calc_jmp">here...</a>
/// </summary>
transform::map_t calc_jmp_transforms;
/// <summary>
/// vector of encoded labels...
/// </summary>
std::vector< vlabel_data > virt_labels;
/// <summary>
/// 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...
/// </summary>
std::vector< zydis_decoded_instr_t > encrypt_vinstrs_rva;
};
} // namespace vm

@ -6,47 +6,52 @@
#include <transform.hpp> #include <transform.hpp>
#include <xtils.hpp> #include <xtils.hpp>
#include "compiler.h" #include <parser.tab.h>
#include "parser.h" #include <compiler.hpp>
#include "parser.tab.h" #include <gen_code.hpp>
#include "vmprofiler.hpp" #include <parser.hpp>
#include "gen_code.hpp" #include <vmprofiler.hpp>
extern FILE *yyin; extern FILE* yyin;
extern "C" int yywrap() extern "C" int yywrap() {
{
return 1; return 1;
} }
void yyerror( char *msg ) void yyerror(char* msg) {
{ std::printf("[!] parsing failure: %s\n", msg);
std::printf( "[!] parsing failure: %s\n", msg );
} }
int __cdecl main( int argc, const char *argv[] ) int __cdecl main(int argc, const char* argv[]) {
{ argparse::argument_parser_t argp("vmassembler",
argparse::argument_parser_t argp( "vmassembler", "virtual instruction assembler" ); "virtual instruction assembler");
argp.add_argument() argp.add_argument()
.names( { "--input", "--in" } ) .names({"--input", "--in"})
.description( "path to a vasm file to be assembled..." ) .description("path to a vasm file to be assembled...")
.required( true ); .required(true);
argp.add_argument().names( { "--vmpbin", "--bin" } ).description( "path to protected binary..." ).required( true ); argp.add_argument()
argp.add_argument().names( { "--vmentry", "--entry" } ).description( "rva to vm entry..." ).required( true ); .names({"--vmpbin", "--bin"})
argp.add_argument().names( { "--out", "--output" } ).description( "output file name and path..." ).required( true ); .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(); argp.enable_help();
auto err = argp.parse( argc, argv ); auto err = argp.parse(argc, argv);
if ( err ) if (err) {
{
std::cout << err << std::endl; std::cout << err << std::endl;
return -1; return -1;
} }
if ( argp.exists( "help" ) ) if (argp.exists("help")) {
{
argp.print_help(); argp.print_help();
return 0; return 0;
} }
@ -55,9 +60,8 @@ int __cdecl main( int argc, const char *argv[] )
// set yyin to the vasm file... // set yyin to the vasm file...
// //
if ( ( yyin = fopen( argp.get< std::string >( "input" ).c_str(), "r" ) ) == nullptr ) if ((yyin = fopen(argp.get<std::string>("input").c_str(), "r")) == nullptr) {
{ std::printf("[!] failed to open vasm file...\n");
std::printf( "[!] failed to open vasm file...\n" );
return -1; return -1;
} }
@ -66,50 +70,51 @@ int __cdecl main( int argc, const char *argv[] )
// //
yyparse(); yyparse();
std::printf( "[+] finished parsing vasm file...\n" ); std::printf("[+] finished parsing vasm file...\n");
// //
// init vm variables... // init vm variables...
// //
const auto module_base = reinterpret_cast< std::uintptr_t >( const auto module_base = reinterpret_cast<std::uintptr_t>(
LoadLibraryExA( argp.get< std::string >( "vmpbin" ).c_str(), NULL, DONT_RESOLVE_DLL_REFERENCES ) ); 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 vm_entry_rva =
const auto image_base = xtils::um_t::get_instance()->image_base( argp.get< std::string >( "vmpbin" ).c_str() ); std::strtoull(argp.get<std::string>("vmentry").c_str(), nullptr, 16);
const auto image_size = NT_HEADER( module_base )->OptionalHeader.SizeOfImage; const auto image_base = xtils::um_t::get_instance()->image_base(
vm::ctx_t vmctx( module_base, image_base, image_size, vm_entry_rva ); 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() ) if (!vmctx.init()) {
{ std::printf(
std::printf( "> failed to init vmctx... make sure all arguments are valid\n" "> failed to init vmctx... make sure all arguments are valid\n"
"and that the binary you are providing is unpacked and protected\n" "and that the binary you are providing is unpacked and protected\n"
"by VMProtect 2...\n" ); "by VMProtect 2...\n");
return -1; return -1;
} }
std::printf( "> flattened and deobfuscated vm entry...\n" ); std::printf("> flattened and deobfuscated vm entry...\n");
vm::util::print( vmctx.vm_entry ); vm::util::print(vmctx.vm_entry);
std::printf( "> extracted calc jmp from vm entry...\n" ); std::printf("> extracted calc jmp from vm entry...\n");
vm::util::print( vmctx.calc_jmp ); vm::util::print(vmctx.calc_jmp);
vm::compiler_t compiler( &vmctx ); vm::compiler_t compiler(&vmctx);
// //
// encode virtual instructions... // encode virtual instructions...
// //
auto virt_labels = compiler.encode(); auto virt_labels = compiler.encode();
std::printf( "[+] finished encoding... encoded instructions below...\n" ); std::printf("[+] finished encoding... encoded instructions below...\n");
for ( auto &label : *virt_labels ) for (auto& label : *virt_labels) {
{ for (const auto& vinstr : label.vinstrs) {
for ( const auto &vinstr : label.vinstrs ) if (vinstr.imm_size)
{ std::printf("> 0x%x - 0x%x\n", vinstr.vm_handler, vinstr.operand);
if ( vinstr.imm_size )
std::printf( "> 0x%x - 0x%x\n", vinstr.vm_handler, vinstr.operand );
else else
std::printf( "> 0x%x\n", vinstr.vm_handler ); std::printf("> 0x%x\n", vinstr.vm_handler);
} }
} }
@ -118,26 +123,26 @@ int __cdecl main( int argc, const char *argv[] )
// //
auto compiled_labels = compiler.encrypt(); auto compiled_labels = compiler.encrypt();
std::printf( "[+] finished encrypting... encrypted labels below...\n" ); std::printf("[+] finished encrypting... encrypted labels below...\n");
for ( const auto &label : compiled_labels ) for (const auto& label : compiled_labels) {
{ std::printf("> %s must be allocated at = 0x%p, encrypted rva = 0x%p\n",
std::printf( "> %s must be allocated at = 0x%p, encrypted rva = 0x%p\n", label.label_name.c_str(), label.label_name.c_str(), label.alloc_rva, label.enc_alloc_rva);
label.alloc_rva, label.enc_alloc_rva );
std::printf( "> " ); std::printf("> ");
{ {
for ( auto byte : label.vinstrs ) for (auto byte : label.vinstrs)
std::printf( "0x%x ", byte ); 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 ); const auto cpp_result =
std::ofstream output( argp.get< std::string >( "out" ) ); gen::code(compiled_labels, argp.get<std::string>("vmpbin"), vmctx);
output.write( cpp_result.data(), cpp_result.size() ); std::ofstream output(argp.get<std::string>("out"));
output.write(cpp_result.data(), cpp_result.size());
output.close(); output.close();
std::printf( "> generated header file...\n" ); std::printf("> generated header file...\n");
} }

@ -1,36 +1,29 @@
#include "parser.h" #include <parser.hpp>
parse_t::parse_t() parse_t::parse_t() {}
{
}
auto parse_t::get_instance() -> parse_t * auto parse_t::get_instance() -> parse_t* {
{
static parse_t obj; static parse_t obj;
return &obj; return &obj;
} }
void parse_t::add_label( std::string label_name ) void parse_t::add_label(std::string label_name) {
{
// remove ":" from the end of the label name... // remove ":" from the end of the label name...
label_name.erase( label_name.end() - 1 ); label_name.erase(label_name.end() - 1);
virt_labels.push_back( { label_name } ); virt_labels.push_back({label_name});
} }
void parse_t::add_vinstr( std::string vinstr_name ) void parse_t::add_vinstr(std::string vinstr_name) {
{ virt_labels.back().vinstrs.push_back({vinstr_name, false, 0u});
virt_labels.back().vinstrs.push_back( { vinstr_name, false, 0u } );
} }
void parse_t::add_vinstr( std::string vinstr_name, std::uintptr_t 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});
virt_labels.back().vinstrs.push_back( { vinstr_name, true, imm_val } );
} }
bool parse_t::for_each( callback_t callback ) bool parse_t::for_each(callback_t callback) {
{ for (auto& entry : virt_labels)
for ( auto &entry : virt_labels ) if (!callback(&entry))
if ( !callback( &entry ) )
return false; return false;
return true; return true;

@ -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
Loading…
Cancel
Save