porting the project to cmkr...

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

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

2
.gitignore vendored

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

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

@ -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 );
}
```

@ -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
#include <compiler.hpp>
#include <fstream>
#include <vmprofiler.hpp>
#include <xtils.hpp>
#include "compiler.h"
namespace gen
{
/// <summary>
/// function pasted from https://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprintf
/// </summary>
/// <typeparam name="...Args"></typeparam>
/// <param name="format"></param>
/// <param name="...args"></param>
/// <returns></returns>
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 );
}
/// <summary>
/// generates c++ header file which MUST BE COMPILED USING CLANG BECAUSE MSVC CANT HANDLE HUGE STATIC INITS (6/13/2021)....
/// </summary>
/// <param name="labels">vector of compiled labels...</param>
/// <param name="image_path">path to the image on disk...</param>
/// <param name="vmctx"></param>
/// <returns></returns>
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 {
/// <summary>
/// function pasted from
/// https://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprintf
/// </summary>
/// <typeparam name="...Args"></typeparam>
/// <param name="format"></param>
/// <param name="...args"></param>
/// <returns></returns>
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);
}
/// <summary>
/// generates c++ header file which MUST BE COMPILED USING CLANG BECAUSE MSVC
/// CANT HANDLE HUGE STATIC INITS (6/13/2021)....
/// </summary>
/// <param name="labels">vector of compiled labels...</param>
/// <param name="image_path">path to the image on disk...</param>
/// <param name="vmctx"></param>
/// <returns></returns>
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;
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
result.append("\n}");
return result;
}
} // namespace gen

@ -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 <compiler.hpp>
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<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) {
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<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);
}
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<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...
}
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<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);
});
}
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
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

@ -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,138 +6,143 @@
#include <transform.hpp>
#include <xtils.hpp>
#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 <parser.tab.h>
#include <compiler.hpp>
#include <gen_code.hpp>
#include <parser.hpp>
#include <vmprofiler.hpp>
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<std::string>("input").c_str(), "r")) == nullptr) {
std::printf("[!] failed to open vasm file...\n");
return -1;
}
//
// parse vasm file for all of the instructions...
//
yyparse();
std::printf("[+] finished parsing vasm file...\n");
//
// init vm variables...
//
const auto module_base = reinterpret_cast<std::uintptr_t>(
LoadLibraryExA(argp.get<std::string>("vmpbin").c_str(), NULL,
DONT_RESOLVE_DLL_REFERENCES));
const auto vm_entry_rva =
std::strtoull(argp.get<std::string>("vmentry").c_str(), nullptr, 16);
const auto image_base = xtils::um_t::get_instance()->image_base(
argp.get<std::string>("vmpbin").c_str());
const auto image_size = NT_HEADER(module_base)->OptionalHeader.SizeOfImage;
vm::ctx_t vmctx(module_base, image_base, image_size, vm_entry_rva);
if (!vmctx.init()) {
std::printf(
"> failed to init vmctx... make sure all arguments are valid\n"
"and that the binary you are providing is unpacked and protected\n"
"by VMProtect 2...\n");
return -1;
}
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<std::string>("vmpbin"), vmctx);
std::ofstream output(argp.get<std::string>("out"));
output.write(cpp_result.data(), cpp_result.size());
output.close();
std::printf( "> generated header file...\n" );
std::printf("> generated header file...\n");
}

@ -1,37 +1,30 @@
#include "parser.h"
#include <parser.hpp>
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;
}

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