Merge branch 'cmkr_port' into 'master'

Cmkr port

See merge request vmp2/vmassembler!3
master
IDontCode 2 years ago
commit d71b9050bc

@ -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,96 @@
# 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/lexer.flex.cpp"
"src/main.cpp"
"src/parser.cpp"
"src/parser.tab.cpp"
"src/lexer.l"
"src/parser.y"
"include/compiler.hpp"
"include/gen_code.hpp"
"include/parser.hpp"
"src/parser.tab.h"
)
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
src
)
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", "src/**.l", "src/**.y", "include/**.hpp", "src/**.h"]
include-directories = ["include", "src"]
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()

@ -3,7 +3,7 @@
int main()
{
const auto hello = vm::call< vm::calls::get_hello, vm::u64 >();
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 );
std::printf( "> %s %s\n", ( char * )&hello, (char*)&world );
}

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

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

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
%{
#include "parser.tab.h"
#include <parser.tab.h>
#include <stdlib.h>
%}

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

File diff suppressed because it is too large Load Diff

@ -0,0 +1,91 @@
/* A Bison parser, made by GNU Bison 2.7. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef YY_YY_PARSER_TAB_H_INCLUDED
# define YY_YY_PARSER_TAB_H_INCLUDED
/* Enabling traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
#if YYDEBUG
extern int yydebug;
#endif
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
LABEL = 258,
VINSTR = 259,
IMM = 260
};
#endif
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
{
/* Line 2058 of yacc.c */
#line 10 "parser.y"
char vinstr_name[20];
char label_name[256];
unsigned long long imm_val;
/* Line 2058 of yacc.c */
#line 69 "parser.tab.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif
extern YYSTYPE yylval;
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
int yyparse (void *YYPARSE_PARAM);
#else
int yyparse ();
#endif
#else /* ! YYPARSE_PARAM */
#if defined __STDC__ || defined __cplusplus
int yyparse (void);
#else
int yyparse ();
#endif
#endif /* ! YYPARSE_PARAM */
#endif /* !YY_YY_PARSER_TAB_H_INCLUDED */

@ -1,6 +1,6 @@
%{
#include <stdlib.h>
#include "parser.h"
#include <parser.hpp>
int yylex(void);
void yyerror(char *);
extern int yylineno;

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