Merge branch 'dev' into 'master'

Dev

See merge request vmp2/vmassembler!2
merge-requests/3/merge v1.2
_xeroxz 3 years ago
commit 2da8022aec

@ -17,4 +17,134 @@ The repo contains the following notable folders and files:
* `compiler.cpp` - responsible for encoding and encrypting virtual instructions...
* `parser.cpp` - a singleton class which is used in `parser.y`...
* `parser.y` - bison rules for parsing tokens. This contains only a handful of rules...
* `lexer.l` - lex rules for the vmassembler...
* `lexer.l` - lex rules for the vmassembler...
### Usage Requirements
In order to use the virtual instruction assembler you must first have a few values at hand. You must have an unpacked vmprotect 2 binary. This file cannot be a dump, it must be unpacked. Second, you must know the RVA to the vm entry address of the first push instruction. This first push instruction must not be `push contant_value`, it must be of type `push reg` as the constant values are pushed onto the stack by the generated c++ header file. The last thing you need is a virtual instruction assembly file. You can make one of these easily. Simply open a text editor and create your first label:
***Note: you can use ANY virtual instruction which is defined by vmprofiler... you can see them all [here](https://githacks.org/vmp2/vmprofiler/-/tree/a419fa4633f98e2f819b1119dc0884154e207482/src/vmprofiles)***
```
get_hello:
SREGQ 0x90
SREGQ 0x88
SREGQ 0x80
SREGQ 0x78
SREGQ 0x70
SREGQ 0x68
SREGQ 0x60
SREGQ 0x58
SREGQ 0x50
SREGQ 0x48
SREGQ 0x40
SREGQ 0x38
SREGQ 0x30
SREGQ 0x28
SREGQ 0x20
SREGQ 0x18
SREGQ 0x10
SREGQ 0x8
SREGQ 0x0
LCONSTQ 0x6F6C6C6568
SREGQ 0x78
SREGQ 0x0
SREGQ 0x0
LREGQ 0x0
LREGQ 0x8
LREGQ 0x10
LREGQ 0x18
LREGQ 0x20
LREGQ 0x28
LREGQ 0x30
LREGQ 0x38
LREGQ 0x40
LREGQ 0x48
LREGQ 0x50
LREGQ 0x58
LREGQ 0x60
LREGQ 0x68
LREGQ 0x70
LREGQ 0x78
LREGQ 0x80
LREGQ 0x88
LREGQ 0x90
VMEXIT
get_world:
SREGQ 0x90
SREGQ 0x88
SREGQ 0x80
SREGQ 0x78
SREGQ 0x70
SREGQ 0x68
SREGQ 0x60
SREGQ 0x58
SREGQ 0x50
SREGQ 0x48
SREGQ 0x40
SREGQ 0x38
SREGQ 0x30
SREGQ 0x28
SREGQ 0x20
SREGQ 0x18
SREGQ 0x10
SREGQ 0x8
SREGQ 0x0
LCONSTQ 0x646C726F77
SREGQ 0x78
SREGQ 0x0
SREGQ 0x0
LREGQ 0x0
LREGQ 0x8
LREGQ 0x10
LREGQ 0x18
LREGQ 0x20
LREGQ 0x28
LREGQ 0x30
LREGQ 0x38
LREGQ 0x40
LREGQ 0x48
LREGQ 0x50
LREGQ 0x58
LREGQ 0x60
LREGQ 0x68
LREGQ 0x70
LREGQ 0x78
LREGQ 0x80
LREGQ 0x88
LREGQ 0x90
VMEXIT
```
# Usage Example
Once you have defined a vasm file, you can now generate the c++ header file which will handle everything for you. Simply execute the following command:
```
vmassembler.exe --input [filename] --vmpbin [vmprotect'ed binary] --vmentry [make sure this rva is correct!] --out test.hpp
```
If the file is generated without any errors you can now include this file inside of your project. This header file uses no STL, nor any CRT functions, however it does create a RWX section so if you want to use this in a driver it cannot run on HVCI systems...
To call your vasm routine all you must do is pass the label name as a template param...
```cpp
#include <iostream>
#include "test.hpp"
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 );
}
```

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{1dc5c971-7d10-488d-a4bf-8702fa804559}</ProjectGuid>
<RootNamespace>demo</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>ClangCL</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="test.hpp" />
</ItemGroup>
<ItemGroup>
<None Include="..\.clang-format" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="test.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\.clang-format">
<Filter>Header Files</Filter>
</None>
</ItemGroup>
</Project>

@ -0,0 +1,9 @@
#include <iostream>
#include "test.hpp"
int main()
{
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 );
}

File diff suppressed because it is too large Load Diff

@ -1 +1 @@
Subproject commit e58c23c40e13528f5d9b84feb7e23b62a886ed5a
Subproject commit 0f6ba9bad30d67f25f01b6c1e872077efdff61d4

@ -2,37 +2,42 @@
namespace vm
{
compiler_t::compiler_t( base_data_t base_data, vmp2::exec_type_t exec_type,
std::vector< vm::handler::handler_t > *vm_handlers, zydis_routine_t *calc_jmp,
zydis_routine_t *vm_entry )
: module_base( base_data.module_base ), image_base( base_data.image_base ), exec_type( exec_type ),
vm_handlers( vm_handlers ), calc_jmp( calc_jmp ), vm_entry( vm_entry )
compiler_t::compiler_t( vm::ctx_t *vmctx ) : vmctx( vmctx )
{
if ( !parse_t::get_instance()->for_each( [ & ]( _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 );
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() );
for ( auto &vm_handler : *vm_handlers )
if ( vm_handler.profile && vm_handler.profile->name == vinstr->name )
return true;
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() );
std::printf( "[!] this vm protected file does not have the vm handler for: %s...\n",
vinstr->name.c_str() );
return true;
} );
return false;
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( *calc_jmp, calc_jmp_transforms ) )
if ( !vm::handler::get_operand_transforms( vmctx->calc_jmp, calc_jmp_transforms ) )
{
std::printf( "[!] failed to extract calc_jmp transformations...\n" );
exit( -1 );
}
if ( !vm::instrs::get_rva_decrypt( *vm_entry, encrypt_vinstrs_rva ) )
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 );
@ -45,106 +50,145 @@ namespace vm
}
}
std::pair< bool, std::vector< vinstr_data > * > compiler_t::encode()
std::vector< vlabel_data > *compiler_t::encode()
{
parse_t::get_instance()->for_each( [ & ]( _vinstr_meta *vinstr ) -> bool {
for ( auto itr = vm_handlers->begin(); itr != vm_handlers->end(); ++itr )
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 )
{
if ( itr->profile && itr->profile->name == vinstr->name )
for ( auto idx = 0u; idx < 256; ++idx )
{
vinstrs.push_back(
{ ( std::uint8_t )( itr - vm_handlers->begin() ), vinstr->imm, itr->profile->imm_size } );
break;
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;
}
}
}
return true;
} );
return { true, &vinstrs };
return &virt_labels;
}
std::pair< std::uint64_t, std::vector< std::uint8_t > * > compiler_t::encrypt()
std::vector< compiled_label_data > compiler_t::encrypt()
{
const auto end_of_module = NT_HEADER( module_base )->OptionalHeader.SizeOfImage + image_base;
//
// init decryption key...
//
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 ( exec_type == vmp2::exec_type_t::backward )
{
std::for_each( vinstrs.begin(), vinstrs.end(), [ & ]( const vinstr_data &vinstr ) {
( ++decrypt_key ) += vinstr.imm_size ? vinstr.imm_size / 8 : 0;
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;
} );
}
start_addr = decrypt_key;
//
// invert the encoded virtual instructions operands if vip advances backward...
//
if ( exec_type == vmp2::exec_type_t::backward )
std::reverse( vinstrs.begin(), vinstrs.end() );
//
// loop over the instructions and encrypt them...
//
for ( auto &vinstr : vinstrs )
if ( opcode_fetch == vmctx->calc_jmp.end() )
{
std::printf( "> decrypt key = 0x%p\n", decrypt_key );
auto vm_handler_idx = vinstr.vm_handler;
std::tie( vinstr.vm_handler, decrypt_key ) =
vm::instrs::encrypt_operand( calc_jmp_transforms, vinstr.vm_handler, decrypt_key );
if ( !vinstr.imm_size )
{
result_buffer.push_back( vinstr.vm_handler );
continue;
}
std::printf( "> critical error trying to find opcode fetch inside of compiler_t::encrypt...\n" );
exit( 0 );
}
auto transforms = vm_handlers->at( vm_handler_idx ).transforms;
std::tie( vinstr.operand, decrypt_key ) =
vm::instrs::encrypt_operand( transforms, vinstr.operand, decrypt_key );
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 );
//
// operands must be backwards if VIP advances backward...
//
decrypt_key = start_addr;
result.push_back( { label.label_name, start_addr } );
if ( exec_type == vmp2::exec_type_t::backward )
if ( vmctx->exec_type == vmp2::exec_type_t::forward )
{
for ( auto idx = 0u; idx < vinstr.imm_size / 8; ++idx )
result_buffer.push_back( reinterpret_cast< std::uint8_t * >( &vinstr.operand )[ idx ] );
result_buffer.push_back( vinstr.vm_handler );
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
{
result_buffer.push_back( vinstr.vm_handler );
for ( auto idx = 0u; idx < vinstr.imm_size / 8; ++idx )
result_buffer.push_back( reinterpret_cast< std::uint8_t * >( &vinstr.operand )[ idx ] );
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 );
} );
}
}
return { start_addr, &result_buffer };
result.back().enc_alloc_rva = encrypt_rva( start_addr );
start_addr += result.back().vinstrs.size() - 1; // make it zero based...
} );
return result;
}
std::uint64_t compiler_t::encrypt_rva( std::uint64_t rva )
{
std::printf( "> encrypt virtual instruction rva transformations:\n" );
for ( auto &transform : encrypt_vinstrs_rva )
vm::util::print( transform );
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 );
std::printf( "> encrypted rva = 0x%p\n", rva );
return rva;
}
} // namespace vm

@ -23,25 +23,32 @@ namespace vm
std::uint8_t imm_size; // size in bits...
};
struct vlabel_data
{
std::string label_name;
std::vector< vinstr_data > vinstrs;
};
struct compiled_label_data
{
std::string label_name;
std::uintptr_t alloc_rva, enc_alloc_rva;
std::vector< std::uint8_t > vinstrs;
};
class compiler_t
{
public:
explicit compiler_t( base_data_t base_data, vmp2::exec_type_t exec_type,
std::vector< vm::handler::handler_t > *vm_handlers, zydis_routine_t *calc_jmp,
zydis_routine_t *vm_entry );
explicit compiler_t( vm::ctx_t *vmctx );
std::vector< vlabel_data > *encode();
std::vector< compiled_label_data > encrypt();
std::pair< bool, std::vector< vinstr_data > * > encode();
std::pair< std::uint64_t, std::vector< std::uint8_t > * > encrypt();
private:
std::uint64_t encrypt_rva( std::uint64_t rva );
private:
vm::ctx_t *vmctx;
transform::map_t calc_jmp_transforms;
zydis_routine_t *calc_jmp, *vm_entry;
std::vector< vm::handler::handler_t > *vm_handlers;
vmp2::exec_type_t exec_type;
std::vector< vinstr_data > vinstrs;
std::vector< std::uint8_t > result_buffer;
std::vector< vlabel_data > virt_labels;
std::vector< zydis_decoded_instr_t > encrypt_vinstrs_rva;
std::uintptr_t image_base, module_base;
};
} // namespace vm

@ -0,0 +1,344 @@
#pragma once
#include <vmprofiler.hpp>
#include <fstream>
#include "compiler.h"
namespace gen
{
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 );
}
inline void open_binary_file( const std::string &file, std::vector< uint8_t > &data )
{
std::ifstream fstr( file, std::ios::binary );
fstr.unsetf( std::ios::skipws );
fstr.seekg( 0, std::ios::end );
const auto file_size = fstr.tellg();
fstr.seekg( NULL, std::ios::beg );
data.reserve( static_cast< uint32_t >( file_size ) );
data.insert( data.begin(), std::istream_iterator< uint8_t >( fstr ), std::istream_iterator< uint8_t >() );
}
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;
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;
using s16 = signed short;
using u32 = unsigned int;
using s32 = signed int;
using u64 = unsigned long long;
using s64 = signed long long;
using __vmcall_t = void* (*)(...);
constexpr u8 IMAGE_DIRECTORY_ENTRY_BASERELOC = 5;
constexpr u8 IMAGE_REL_BASED_ABSOLUTE = 0;
constexpr u8 IMAGE_REL_BASED_DIR64 = 10;
typedef struct _IMAGE_DOS_HEADER
{
/* 0x0000 */ unsigned short e_magic;
/* 0x0002 */ unsigned short e_cblp;
/* 0x0004 */ unsigned short e_cp;
/* 0x0006 */ unsigned short e_crlc;
/* 0x0008 */ unsigned short e_cparhdr;
/* 0x000a */ unsigned short e_minalloc;
/* 0x000c */ unsigned short e_maxalloc;
/* 0x000e */ unsigned short e_ss;
/* 0x0010 */ unsigned short e_sp;
/* 0x0012 */ unsigned short e_csum;
/* 0x0014 */ unsigned short e_ip;
/* 0x0016 */ unsigned short e_cs;
/* 0x0018 */ unsigned short e_lfarlc;
/* 0x001a */ unsigned short e_ovno;
/* 0x001c */ unsigned short e_res[ 4 ];
/* 0x0024 */ unsigned short e_oemid;
/* 0x0026 */ unsigned short e_oeminfo;
/* 0x0028 */ unsigned short e_res2[ 10 ];
/* 0x003c */ long e_lfanew;
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; /* size: 0x0040 */
typedef struct _IMAGE_FILE_HEADER
{
/* 0x0000 */ unsigned short Machine;
/* 0x0002 */ unsigned short NumberOfSections;
/* 0x0004 */ unsigned long TimeDateStamp;
/* 0x0008 */ unsigned long PointerToSymbolTable;
/* 0x000c */ unsigned long NumberOfSymbols;
/* 0x0010 */ unsigned short SizeOfOptionalHeader;
/* 0x0012 */ unsigned short Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; /* size: 0x0014 */
typedef struct _IMAGE_DATA_DIRECTORY
{
/* 0x0000 */ unsigned long VirtualAddress;
/* 0x0004 */ unsigned long Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; /* size: 0x0008 */
typedef struct _IMAGE_OPTIONAL_HEADER64
{
/* 0x0000 */ unsigned short Magic;
/* 0x0002 */ unsigned char MajorLinkerVersion;
/* 0x0003 */ unsigned char MinorLinkerVersion;
/* 0x0004 */ unsigned long SizeOfCode;
/* 0x0008 */ unsigned long SizeOfInitializedData;
/* 0x000c */ unsigned long SizeOfUninitializedData;
/* 0x0010 */ unsigned long AddressOfEntryPoint;
/* 0x0014 */ unsigned long BaseOfCode;
/* 0x0018 */ unsigned __int64 ImageBase;
/* 0x0020 */ unsigned long SectionAlignment;
/* 0x0024 */ unsigned long FileAlignment;
/* 0x0028 */ unsigned short MajorOperatingSystemVersion;
/* 0x002a */ unsigned short MinorOperatingSystemVersion;
/* 0x002c */ unsigned short MajorImageVersion;
/* 0x002e */ unsigned short MinorImageVersion;
/* 0x0030 */ unsigned short MajorSubsystemVersion;
/* 0x0032 */ unsigned short MinorSubsystemVersion;
/* 0x0034 */ unsigned long Win32VersionValue;
/* 0x0038 */ unsigned long SizeOfImage;
/* 0x003c */ unsigned long SizeOfHeaders;
/* 0x0040 */ unsigned long CheckSum;
/* 0x0044 */ unsigned short Subsystem;
/* 0x0046 */ unsigned short DllCharacteristics;
/* 0x0048 */ unsigned __int64 SizeOfStackReserve;
/* 0x0050 */ unsigned __int64 SizeOfStackCommit;
/* 0x0058 */ unsigned __int64 SizeOfHeapReserve;
/* 0x0060 */ unsigned __int64 SizeOfHeapCommit;
/* 0x0068 */ unsigned long LoaderFlags;
/* 0x006c */ unsigned long NumberOfRvaAndSizes;
/* 0x0070 */ struct _IMAGE_DATA_DIRECTORY DataDirectory[ 16 ];
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64; /* size: 0x00f0 */
typedef struct _IMAGE_NT_HEADERS64
{
/* 0x0000 */ unsigned long Signature;
/* 0x0004 */ struct _IMAGE_FILE_HEADER FileHeader;
/* 0x0018 */ struct _IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64; /* size: 0x0108 */
typedef struct _IMAGE_SECTION_HEADER
{
/* 0x0000 */ unsigned char Name[ 8 ];
union
{
union
{
/* 0x0008 */ unsigned long PhysicalAddress;
/* 0x0008 */ unsigned long VirtualSize;
}; /* size: 0x0004 */
} /* size: 0x0004 */ Misc;
/* 0x000c */ unsigned long VirtualAddress;
/* 0x0010 */ unsigned long SizeOfRawData;
/* 0x0014 */ unsigned long PointerToRawData;
/* 0x0018 */ unsigned long PointerToRelocations;
/* 0x001c */ unsigned long PointerToLinenumbers;
/* 0x0020 */ unsigned short NumberOfRelocations;
/* 0x0022 */ unsigned short NumberOfLinenumbers;
/* 0x0024 */ unsigned long Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; /* size: 0x0028 */
typedef struct _IMAGE_BASE_RELOCATION
{
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, " );
}
// 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( "\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;
const char *s = ( char * )src;
while ( len-- )
*d++ = *s++;
return dest;
};
const auto dos_header = reinterpret_cast< IMAGE_DOS_HEADER * >( bin );
const auto nt_headers = reinterpret_cast< PIMAGE_NT_HEADERS64 >( bin + dos_header->e_lfanew );
_memcpy( map_area, bin, nt_headers->OptionalHeader.SizeOfHeaders );
auto sections = reinterpret_cast< PIMAGE_SECTION_HEADER >( ( u8 * )&nt_headers->OptionalHeader +
nt_headers->FileHeader.SizeOfOptionalHeader );
// map sections...
for ( u32 i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i )
{
PIMAGE_SECTION_HEADER section = &sections[ i ];
_memcpy( ( void * )( map_area + section->VirtualAddress ),
( void * )( bin + section->PointerToRawData ), section->SizeOfRawData );
}
// handle relocations...
const auto reloc_dir = &nt_headers->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];
if ( reloc_dir->VirtualAddress )
{
auto reloc = reinterpret_cast< IMAGE_BASE_RELOCATION * >( map_area + reloc_dir->VirtualAddress );
for ( auto current_size = 0u; current_size < reloc_dir->Size; )
{
u32 reloc_count = ( reloc->SizeOfBlock - sizeof( IMAGE_BASE_RELOCATION ) ) / sizeof( u16 );
u16 *reloc_data = ( u16 * )( ( u8 * )reloc + sizeof( IMAGE_BASE_RELOCATION ) );
u8 *reloc_base = map_area + reloc->VirtualAddress;
for ( auto idx = 0; idx < reloc_count; ++idx, ++reloc_data )
{
u16 data = *reloc_data;
u16 type = data >> 12;
u16 offset = data & 0xFFF;
switch ( type )
{
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_DIR64:
{
u64 *rva = ( u64 * )( reloc_base + offset );
*rva = ( u64 )( map_area + ( *rva - nt_headers->OptionalHeader.ImageBase ) );
break;
}
default:
break;
}
}
current_size += reloc->SizeOfBlock;
reloc = ( IMAGE_BASE_RELOCATION * )reloc_data;
}
}
// fix shellcode up...
for ( auto idx = 0u; idx < ( sizeof( __vmcall_shell_code ) / 15 ); ++idx )
{
// first push encrypted rva value...
*reinterpret_cast< u32 * >( &__vmcall_shell_code[ idx ][ 1 ] ) =
static_cast< u32 >( call_map[ idx ].second );
// second push encrypted rva value...
*reinterpret_cast< u32 * >( &__vmcall_shell_code[ idx ][ 6 ] ) =
static_cast< u32 >( call_map[ idx ].second );
// signed rip relative rva to vm entry...
*reinterpret_cast< u32 * >( &__vmcall_shell_code[ idx ][ 11 ] ) = reinterpret_cast< s32 >(
( map_area - ( reinterpret_cast< u64 >( &__vmcall_shell_code[ idx ] ) + 15 ) ) + entry_rva );
}
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( R"( template < calls e_call, class T, class ... Ts > auto call(const Ts... args) -> T
{
static auto __init_result = gen_data.init();
__vmcall_t vmcall = nullptr;
for ( auto idx = 0u; idx < sizeof( call_map ) / sizeof( _pair_t< u8, calls > ); ++idx )
if ( call_map[ idx ].second == e_call )
vmcall = reinterpret_cast< __vmcall_t >( &gen_data.__vmcall_shell_code[ idx ] );
return reinterpret_cast< T >( vmcall( args... ) );
})" );
result.append( "\n}" );
return result;
}
} // namespace gen

@ -352,8 +352,8 @@ static void yynoreturn yy_fatal_error ( const char* msg );
(yy_hold_char) = *yy_cp; \
*yy_cp = '\0'; \
(yy_c_buf_p) = yy_cp;
#define YY_NUM_RULES 5
#define YY_END_OF_BUFFER 6
#define YY_NUM_RULES 6
#define YY_END_OF_BUFFER 7
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@ -361,10 +361,10 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
static const flex_int16_t yy_accept[13] =
static const flex_int16_t yy_accept[14] =
{ 0,
0, 0, 6, 5, 4, 3, 2, 2, 2, 2,
1, 0
0, 0, 7, 6, 5, 4, 3, 3, 3, 2,
3, 1, 0
} ;
static const YY_CHAR yy_ec[256] =
@ -374,15 +374,15 @@ static const YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 4, 5, 5,
5, 5, 5, 5, 5, 5, 5, 1, 1, 1,
5, 5, 5, 5, 5, 5, 5, 6, 1, 1,
1, 1, 2, 1, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 7, 6, 6,
1, 1, 1, 1, 6, 1, 5, 5, 5, 5,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 8, 7, 7,
1, 1, 1, 1, 7, 1, 5, 5, 5, 5,
5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 7,
6, 6, 1, 1, 1, 1, 1, 1, 1, 1,
5, 5, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 8,
7, 7, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@ -399,33 +399,35 @@ static const YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1
} ;
static const YY_CHAR yy_meta[8] =
static const YY_CHAR yy_meta[9] =
{ 0,
1, 1, 1, 2, 2, 2, 2
1, 1, 1, 2, 2, 2, 2, 2
} ;
static const flex_int16_t yy_base[14] =
static const flex_int16_t yy_base[15] =
{ 0,
0, 0, 12, 13, 13, 13, 4, 0, 0, 4,
0, 13, 8
0, 0, 15, 16, 16, 16, 3, 8, 0, 16,
8, 0, 16, 8
} ;
static const flex_int16_t yy_def[14] =
static const flex_int16_t yy_def[15] =
{ 0,
12, 1, 12, 12, 12, 12, 13, 13, 13, 13,
10, 0, 12
13, 1, 13, 13, 13, 13, 14, 14, 8, 13,
8, 11, 0, 13
} ;
static const flex_int16_t yy_nxt[21] =
static const flex_int16_t yy_nxt[25] =
{ 0,
4, 5, 6, 7, 8, 8, 8, 11, 11, 9,
10, 12, 3, 12, 12, 12, 12, 12, 12, 12
4, 5, 6, 7, 8, 4, 8, 8, 10, 9,
11, 12, 12, 10, 13, 3, 13, 13, 13, 13,
13, 13, 13, 13
} ;
static const flex_int16_t yy_chk[21] =
static const flex_int16_t yy_chk[25] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 10, 10, 13,
7, 3, 12, 12, 12, 12, 12, 12, 12, 12
1, 1, 1, 1, 1, 1, 1, 1, 7, 14,
7, 11, 11, 8, 3, 13, 13, 13, 13, 13,
13, 13, 13, 13
} ;
static yy_state_type yy_last_accepting_state;
@ -446,8 +448,8 @@ char *yytext;
#line 2 "lexer.l"
#include "parser.tab.h"
#include <stdlib.h>
#line 449 "lexer.flex.cpp"
#line 450 "lexer.flex.cpp"
#line 451 "lexer.flex.cpp"
#line 452 "lexer.flex.cpp"
#define INITIAL 0
@ -663,7 +665,7 @@ YY_DECL
{
#line 6 "lexer.l"
#line 666 "lexer.flex.cpp"
#line 668 "lexer.flex.cpp"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
@ -690,13 +692,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 13 )
if ( yy_current_state >= 14 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
while ( yy_base[yy_current_state] != 13 );
while ( yy_base[yy_current_state] != 16 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@ -728,26 +730,31 @@ YY_RULE_SETUP
case 2:
YY_RULE_SETUP
#line 8 "lexer.l"
{ strcpy(yylval.vinstr_name, yytext); return VINSTR; }
{ strcpy(yylval.label_name, yytext); return LABEL; }
YY_BREAK
case 3:
/* rule 3 can match eol */
YY_RULE_SETUP
#line 9 "lexer.l"
{ yylineno++; }
{ strcpy(yylval.vinstr_name, yytext); return VINSTR; }
YY_BREAK
case 4:
/* rule 4 can match eol */
YY_RULE_SETUP
#line 10 "lexer.l"
{ yylineno++; }
YY_BREAK
case 5:
/* rule 5 can match eol */
YY_RULE_SETUP
#line 11 "lexer.l"
YY_BREAK
case 6:
YY_RULE_SETUP
#line 12 "lexer.l"
ECHO;
YY_BREAK
#line 750 "lexer.flex.cpp"
#line 757 "lexer.flex.cpp"
case YY_STATE_EOF(INITIAL):
yyterminate();
@ -1044,7 +1051,7 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 13 )
if ( yy_current_state >= 14 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@ -1072,11 +1079,11 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 13 )
if ( yy_current_state >= 14 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
yy_is_jam = (yy_current_state == 12);
yy_is_jam = (yy_current_state == 13);
return yy_is_jam ? 0 : yy_current_state;
}
@ -1752,5 +1759,5 @@ void yyfree (void * ptr )
#define YYTABLES_NAME "yytables"
#line 11 "lexer.l"
#line 12 "lexer.l"

@ -5,6 +5,7 @@
%%
0[xX][0-9a-fA-F]+ { yylval.imm_val = strtoull(yytext, nullptr, 16); return IMM; }
[a-zA-Z0-9_]+: { strcpy(yylval.label_name, yytext); return LABEL; }
[a-zA-Z0-9_]+ { strcpy(yylval.vinstr_name, yytext); return VINSTR; }
"\n" { yylineno++; }
[ ?\t\n\r]

@ -9,7 +9,8 @@
#include "compiler.h"
#include "parser.h"
#include "parser.tab.h"
#include "vmasm.hpp"
#include "vmprofiler.hpp"
#include "gen_code.hpp"
extern FILE *yyin;
extern "C" int yywrap()
@ -33,7 +34,7 @@ int __cdecl main( int argc, const char *argv[] )
argp.add_argument().names( { "--vmpbin", "--bin" } ).description( "path to protected binary..." ).required( true );
argp.add_argument().names( { "--vmentry", "--entry" } ).description( "rva to vm entry..." ).required( true );
argp.add_argument().name( { "--output" } ).description( "output file name and path..." ).required( true );
argp.add_argument().names( { "--out", "--output" } ).description( "output file name and path..." ).required( true );
argp.enable_help();
auto err = argp.parse( argc, argv );
@ -76,118 +77,67 @@ int __cdecl main( int argc, const char *argv[] )
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 );
zydis_routine_t vm_entry, calc_jmp;
std::vector< vm::handler::handler_t > vm_handlers;
std::uintptr_t *vm_handler_table;
if ( !vm::util::flatten( vm_entry, module_base + vm_entry_rva ) )
{
std::printf( "[!] failed to flatten vm entry...\n" );
return -1;
}
std::printf( "[+] flattened vm_entry...\n" );
std::printf( "[+] deobfuscated vm_entry...\n" );
vm::util::deobfuscate( vm_entry );
vm::util::print( vm_entry );
if ( !( vm_handler_table = vm::handler::table::get( vm_entry ) ) )
{
std::printf( "[!] failed to obtain vm handler table...\n" );
return -1;
}
if ( !vm::handler::get_all( module_base, image_base, vm_entry, vm_handler_table, vm_handlers ) )
{
std::printf( "[!] failed to get all vm handlers...\n" );
return -1;
}
if ( !vm::calc_jmp::get( vm_entry, calc_jmp ) )
{
std::printf( "[!] failed to get calc_jmp...\n" );
return -1;
}
const auto advancement = vm::calc_jmp::get_advancement( calc_jmp );
if ( !advancement.has_value() )
if ( !vmctx.init() )
{
std::printf( "[!] failed to determine advancement direction...\n" );
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( "> virtual instruction pointer advances %s...\n",
advancement.value() == vmp2::exec_type_t::forward ? "forward" : "backward" );
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( { module_base, image_base }, advancement.value(), &vm_handlers, &calc_jmp, &vm_entry );
vm::compiler_t compiler( &vmctx );
//
// encode virtual instructions...
//
auto [ encoded_success, vinstrs ] = compiler.encode();
auto virt_labels = compiler.encode();
std::printf( "[+] finished encoding... encoded instructions below...\n" );
if ( !encoded_success )
for ( auto &label : *virt_labels )
{
std::printf( "[!] failed to encode virtual instructions...\n" );
return -1;
}
for ( auto &vinstr : *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 );
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 [ entry_rva, result_buffer ] = compiler.encrypt();
std::printf( "[+] finished encrypting... encrypted instructions below...\n" );
auto compiled_labels = compiler.encrypt();
std::printf( "[+] finished encrypting... encrypted labels below...\n" );
if ( !entry_rva )
for ( const auto &label : compiled_labels )
{
std::printf( "[!] failed to encrypt virtual instructions...\n" );
return -1;
}
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( "> virtual instructions must be allocated at = 0x%p\n", entry_rva );
std::printf( "> " );
{
auto idx = 0u;
for ( auto byte : *result_buffer )
std::printf( "> " );
{
std::printf( "0x%x ", byte );
if ( ++idx == 10 )
{
std::printf( "\n" );
idx = 0u;
}
for ( auto byte : label.vinstrs )
std::printf( "0x%x ", byte );
std::printf( "\n" );
}
}
std::printf( "\n" );
//
// write the result to disk...
//
vmasm::file_header_t file_header;
file_header.magic = VASM_MAGIC;
file_header.epoch_time = std::time( nullptr );
file_header.vasm_size = result_buffer->size();
file_header.alloc_rva = ( entry_rva - image_base );
file_header.vasm_offset = sizeof vmasm::file_header_t;
file_header.encrypted_rva = compiler.encrypt_rva( entry_rva );
std::ofstream output( argp.get< std::string >( "output" ), std::ios::binary );
output.write( reinterpret_cast< char * >( &file_header ), sizeof file_header );
output.write( reinterpret_cast< char * >( result_buffer->data() ), result_buffer->size() );
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" );
}

@ -10,21 +10,26 @@ auto parse_t::get_instance() -> parse_t *
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_vinstr( std::string vinstr_name )
{
_vinstr_meta data{ vinstr_name, false, 0u };
vinstrs.push_back( data );
virt_labels.back().vinstrs.push_back( { vinstr_name, false, 0u } );
}
void parse_t::add_vinstr( std::string vinstr_name, std::uintptr_t imm_val )
{
_vinstr_meta data{ vinstr_name, true, imm_val };
vinstrs.push_back( data );
virt_labels.back().vinstrs.push_back( { vinstr_name, true, imm_val } );
}
bool parse_t::for_each( callback_t callback )
{
for ( auto &entry : vinstrs )
for ( auto &entry : virt_labels )
if ( !callback( &entry ) )
return false;

@ -7,12 +7,17 @@
struct _vinstr_meta
{
std::string name;
bool has_imm;
std::uintptr_t imm;
};
using callback_t = std::function< bool( _vinstr_meta * ) >;
struct _vlabel_meta
{
std::string label_name;
std::vector< _vinstr_meta > vinstrs;
};
using callback_t = std::function< bool( _vlabel_meta * ) >;
// this singleton class contains all the
// information for parsed virtual instructions...
@ -20,11 +25,11 @@ class parse_t
{
public:
static auto get_instance() -> parse_t *;
void add_label( std::string label_name );
void add_vinstr( std::string vinstr_name );
void add_vinstr( std::string vinstr_name, std::uintptr_t imm_val );
bool for_each( callback_t callback );
std::vector< _vlabel_meta > virt_labels;
private:
parse_t();
std::vector< _vinstr_meta > vinstrs;
};

@ -108,8 +108,9 @@ extern int yydebug;
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
VINSTR = 258,
IMM = 259
LABEL = 258,
VINSTR = 259,
IMM = 260
};
#endif
@ -121,11 +122,12 @@ typedef union YYSTYPE
#line 10 "parser.y"
char vinstr_name[20];
char label_name[256];
unsigned long long imm_val;
/* Line 387 of yacc.c */
#line 129 "parser.tab.cpp"
#line 131 "parser.tab.cpp"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
@ -153,7 +155,7 @@ int yyparse ();
/* Copy the second part of user declarations. */
/* Line 390 of yacc.c */
#line 157 "parser.tab.cpp"
#line 159 "parser.tab.cpp"
#ifdef short
# undef short
@ -371,22 +373,22 @@ union yyalloc
#endif /* !YYCOPY_NEEDED */
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 4
#define YYFINAL 3
/* YYLAST -- Last index in YYTABLE. */
#define YYLAST 6
#define YYLAST 7
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 5
#define YYNTOKENS 6
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 2
#define YYNNTS 3
/* YYNRULES -- Number of rules. */
#define YYNRULES 5
#define YYNRULES 9
/* YYNRULES -- Number of states. */
#define YYNSTATES 7
#define YYNSTATES 10
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
#define YYMAXUTOK 259
#define YYMAXUTOK 260
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@ -419,7 +421,8 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 1, 2, 3, 4
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5
};
#if YYDEBUG
@ -427,20 +430,21 @@ static const yytype_uint8 yytranslate[] =
YYRHS. */
static const yytype_uint8 yyprhs[] =
{
0, 0, 3, 5, 8, 11
0, 0, 3, 5, 8, 11, 12, 14, 17, 20
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int8 yyrhs[] =
{
6, 0, -1, 3, -1, 3, 4, -1, 6, 3,
-1, 6, 3, 4, -1
7, 0, -1, 3, -1, 7, 3, -1, 7, 8,
-1, -1, 4, -1, 4, 5, -1, 8, 4, -1,
8, 4, 5, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
0, 20, 20, 21, 22, 23
0, 22, 22, 23, 24, 25, 29, 30, 31, 32
};
#endif
@ -449,7 +453,8 @@ static const yytype_uint8 yyrline[] =
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
"$end", "error", "$undefined", "VINSTR", "IMM", "$accept", "PROGRAM", YY_NULL
"$end", "error", "$undefined", "LABEL", "VINSTR", "IMM", "$accept",
"PROGRAM", "VINSTRS", YY_NULL
};
#endif
@ -458,20 +463,20 @@ static const char *const yytname[] =
token YYLEX-NUM. */
static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259
0, 256, 257, 258, 259, 260
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
0, 5, 6, 6, 6, 6
0, 6, 7, 7, 7, 7, 8, 8, 8, 8
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
0, 2, 1, 2, 2, 3
0, 2, 1, 2, 2, 0, 1, 2, 2, 3
};
/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
@ -479,27 +484,27 @@ static const yytype_uint8 yyr2[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
0, 2, 0, 3, 1, 4, 5
5, 2, 0, 1, 3, 6, 4, 7, 8, 9
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
-1, 2
-1, 2, 6
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
#define YYPACT_NINF -3
#define YYPACT_NINF -4
static const yytype_int8 yypact[] =
{
-2, 1, 0, -3, -3, 2, -3
-2, -4, 0, -4, -4, -3, 1, -4, 2, -4
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
-3, -3
-4, -4, -4
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
@ -508,25 +513,25 @@ static const yytype_int8 yypgoto[] =
#define YYTABLE_NINF -1
static const yytype_uint8 yytable[] =
{
4, 1, 0, 5, 0, 3, 6
3, 1, 7, 4, 5, 8, 0, 9
};
#define yypact_value_is_default(Yystate) \
(!!((Yystate) == (-3)))
(!!((Yystate) == (-4)))
#define yytable_value_is_error(Yytable_value) \
YYID (0)
static const yytype_int8 yycheck[] =
{
0, 3, -1, 3, -1, 4, 4
0, 3, 5, 3, 4, 4, -1, 5
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
0, 3, 6, 4, 0, 3, 4
0, 3, 7, 0, 3, 4, 8, 5, 4, 5
};
#define yyerrok (yyerrstatus = 0)
@ -1328,31 +1333,43 @@ yyreduce:
{
case 2:
/* Line 1792 of yacc.c */
#line 20 "parser.y"
{ parse_t::get_instance()->add_vinstr((yyvsp[(1) - (1)].vinstr_name)); }
#line 22 "parser.y"
{ parse_t::get_instance()->add_label((yyvsp[(1) - (1)].label_name)); }
break;
case 3:
/* Line 1792 of yacc.c */
#line 21 "parser.y"
#line 23 "parser.y"
{ parse_t::get_instance()->add_label((yyvsp[(2) - (2)].label_name)); }
break;
case 6:
/* Line 1792 of yacc.c */
#line 29 "parser.y"
{ parse_t::get_instance()->add_vinstr((yyvsp[(1) - (1)].vinstr_name)); }
break;
case 7:
/* Line 1792 of yacc.c */
#line 30 "parser.y"
{ parse_t::get_instance()->add_vinstr((yyvsp[(1) - (2)].vinstr_name), (yyvsp[(2) - (2)].imm_val)); }
break;
case 4:
case 8:
/* Line 1792 of yacc.c */
#line 22 "parser.y"
#line 31 "parser.y"
{ parse_t::get_instance()->add_vinstr((yyvsp[(2) - (2)].vinstr_name)); }
break;
case 5:
case 9:
/* Line 1792 of yacc.c */
#line 23 "parser.y"
#line 32 "parser.y"
{ parse_t::get_instance()->add_vinstr((yyvsp[(2) - (3)].vinstr_name), (yyvsp[(3) - (3)].imm_val)); }
break;
/* Line 1792 of yacc.c */
#line 1356 "parser.tab.cpp"
#line 1373 "parser.tab.cpp"
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@ -1402,7 +1419,7 @@ yyerrlab:
{
++yynerrs;
#if ! YYERROR_VERBOSE
yyerror (YY_((char*)"syntax error"));
yyerror (YY_("syntax error"));
#else
# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
yyssp, yytoken)
@ -1546,7 +1563,7 @@ yyabortlab:
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
yyexhaustedlab:
yyerror (YY_((char*)"memory exhausted"));
yyerror (YY_("memory exhausted"));
yyresult = 2;
/* Fall through. */
#endif
@ -1584,4 +1601,4 @@ yyreturn:
/* Line 2055 of yacc.c */
#line 25 "parser.y"
#line 34 "parser.y"

@ -46,8 +46,9 @@ extern int yydebug;
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
VINSTR = 258,
IMM = 259
LABEL = 258,
VINSTR = 259,
IMM = 260
};
#endif
@ -59,11 +60,12 @@ typedef union YYSTYPE
#line 10 "parser.y"
char vinstr_name[20];
char label_name[256];
unsigned long long imm_val;
/* Line 2058 of yacc.c */
#line 67 "parser.tab.h"
#line 69 "parser.tab.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */

@ -9,17 +9,26 @@ extern int yylineno;
%union {
char vinstr_name[20];
char label_name[256];
unsigned long long imm_val;
}
%token <label_name> LABEL
%token <vinstr_name> VINSTR
%token <imm_val> IMM
%%
PROGRAM:
LABEL { parse_t::get_instance()->add_label($1); }
| PROGRAM LABEL { parse_t::get_instance()->add_label($2); }
| PROGRAM VINSTRS
|
;
VINSTRS:
VINSTR { parse_t::get_instance()->add_vinstr($1); }
| VINSTR IMM { parse_t::get_instance()->add_vinstr($1, $2); }
| PROGRAM VINSTR { parse_t::get_instance()->add_vinstr($2); }
| PROGRAM VINSTR IMM { parse_t::get_instance()->add_vinstr($2, $3); }
| VINSTRS VINSTR { parse_t::get_instance()->add_vinstr($2); }
| VINSTRS VINSTR IMM { parse_t::get_instance()->add_vinstr($2, $3); }
;
%%

@ -1,22 +0,0 @@
#pragma once
#include <cstdint>
#define VASM_MAGIC 'MSAV'
namespace vmasm
{
enum class version_t
{
v1
};
struct file_header_t
{
std::uint32_t magic; // VASM
version_t version;
std::uint64_t epoch_time;
std::uint64_t alloc_rva;
std::uint64_t encrypted_rva;
std::uint32_t vasm_size;
std::uint32_t vasm_offset;
};
} // namespace vmasm

@ -43,13 +43,16 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<AssemblyDebug>true</AssemblyDebug>
</Link>
<Bison />
<Bison>
@ -128,9 +131,9 @@
<ClInclude Include="..\dependencies\vmprofiler\include\Zydis\Zydis.h" />
<ClInclude Include="..\dependencies\xtils\xtils.hpp" />
<ClInclude Include="compiler.h" />
<ClInclude Include="gen_code.hpp" />
<ClInclude Include="parser.h" />
<ClInclude Include="parser.tab.h" />
<ClInclude Include="vmasm.hpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="icon.rc" />
@ -146,6 +149,9 @@
<Project>{d0b6092a-9944-4f24-9486-4b7dae372619}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="..\.clang-format" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="custom_build_rules\win_flex_bison_custom_build.targets" />

@ -72,9 +72,6 @@
<ClInclude Include="compiler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="vmasm.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\dependencies\vmprofiler\include\Zycore\API\Memory.h">
<Filter>Header Files\vmprofiler\Zycore\API</Filter>
</ClInclude>
@ -231,6 +228,9 @@
<ClInclude Include="..\dependencies\cli-parser\cli-parser.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="gen_code.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="icon.rc">
@ -242,4 +242,9 @@
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<None Include="..\.clang-format">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
</Project>

@ -9,30 +9,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Zydis", "dependencies\vmpro
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
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
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
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
@ -41,46 +25,10 @@ Global
{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}.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}.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|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
@ -88,100 +36,36 @@ Global
{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}.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 MD DLL|x64
{88A23124-5640-35A0-B890-311D7A67A7D2}.Release|x64.Build.0 = Release MD DLL|x64
{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|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 = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug Kernel|x86.Build.0 = DBG|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 = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD DLL|x86.Build.0 = DBG|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 = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD|x86.Build.0 = DBG|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 = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT DLL|x86.Build.0 = DBG|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 = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT|x86.Build.0 = DBG|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 = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Release Kernel|x86.Build.0 = DBG|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 = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MD DLL|x86.Build.0 = DBG|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 = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MD|x86.Build.0 = DBG|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 = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MT DLL|x86.Build.0 = DBG|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 = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Release MT|x86.Build.0 = DBG|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|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|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|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

Loading…
Cancel
Save