diff --git a/dependencies/vmprofiler b/dependencies/vmprofiler index 8ffe1ca..4cc0334 160000 --- a/dependencies/vmprofiler +++ b/dependencies/vmprofiler @@ -1 +1 @@ -Subproject commit 8ffe1cac5017b0258a44c1bbe9254621be771147 +Subproject commit 4cc033468e9f3b3583d07f307b9f5e9179db8762 diff --git a/dependencies/xtils b/dependencies/xtils index 7c32517..99a1fc7 160000 --- a/dependencies/xtils +++ b/dependencies/xtils @@ -1 +1 @@ -Subproject commit 7c32517322c29a866cbb1e67fb9051efa2e05553 +Subproject commit 99a1fc74e16af3261e7cfff4e03d470a7a05feb0 diff --git a/src/main.cpp b/src/main.cpp index 97dc22a..e10c42c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,56 +1,45 @@ -#include +#include #include +#include #include -#include #include #include "vmemu_t.hpp" -int __cdecl main(int argc, const char* argv[]) +int __cdecl main( int argc, const char *argv[] ) { argparse::argument_parser_t parser( "VMEmu", "VMProtect 2 Static VM Handler Emulator" ); parser.add_argument() - .name("--vmentry").required(true) - .description("relative virtual address to a vm entry..."); - - parser.add_argument() - .name("--vmpbin").required(true) - .description("path to unpacked virtualized binary..."); + .name( "--vmentry" ) + .required( true ) + .description( "relative virtual address to a vm entry..." ); - parser.add_argument() - .name("--out").required(true) - .description("output file name for trace file..."); + parser.add_argument().name( "--vmpbin" ).required( true ).description( "path to unpacked virtualized binary..." ); + parser.add_argument().name( "--out" ).required( true ).description( "output file name for trace file..." ); - parser.enable_help(); - auto result = parser.parse(argc, argv); + parser.enable_help(); + auto result = parser.parse( argc, argv ); - if (result) - { - std::printf("[!] error parsing commandline arguments... reason = %s\n", - result.what().c_str()); - - return -1; - } - - if (parser.exists("help")) - { - parser.print_help(); - return 0; - } - - const auto vm_entry_rva = std::strtoull( - parser.get("vmentry").c_str(), nullptr, 16); + if ( result ) + { + std::printf( "[!] error parsing commandline arguments... reason = %s\n", result.what().c_str() ); + return -1; + } - const auto image_base = - xtils::um_t::get_instance()->image_base( - parser.get< std::string >( "vmpbin" ).c_str() ); + if ( parser.exists( "help" ) ) + { + parser.print_help(); + return 0; + } - const auto module_base = reinterpret_cast( - LoadLibraryExA(parser.get("vmpbin").c_str(), - NULL, DONT_RESOLVE_DLL_REFERENCES)); + auto umtils = xtils::um_t::get_instance(); + const auto vm_entry_rva = std::strtoull( parser.get< std::string >( "vmentry" ).c_str(), nullptr, 16 ); + const auto image_base = umtils->image_base( parser.get< std::string >( "vmpbin" ).c_str() ); + const auto module_base = reinterpret_cast< std::uintptr_t >( + LoadLibraryExA( parser.get< std::string >( "vmpbin" ).c_str(), NULL, DONT_RESOLVE_DLL_REFERENCES ) ); - zydis_routine_t vm_entry, calc_jmp; + zydis_routine_t vm_entry, calc_jmp; if ( !vm::util::flatten( vm_entry, vm_entry_rva + module_base ) ) { std::printf( "> failed to flatten vm entry...\n" ); @@ -69,7 +58,7 @@ int __cdecl main(int argc, const char* argv[]) return -1; } - vm::util::deobfuscate( calc_jmp ); + vm::util::deobfuscate( calc_jmp ); std::printf( "> calc_jmp extracted from vm_entry... calc_jmp:\n" ); std::printf( "==================================================================================\n" ); vm::util::print( calc_jmp ); @@ -82,43 +71,43 @@ int __cdecl main(int argc, const char* argv[]) return -1; } - std::vector entries; - vm::emu_t emu(vm_entry_rva, image_base, module_base); + std::vector< vmp2::v2::entry_t > entries; + vm::emu_t emu( vm_entry_rva, image_base, module_base ); - if (!emu.init()) - { - std::printf("[!] failed to init emulator...\n"); - return -1; - } - - if (!emu.get_trace(entries)) - std::printf("[!] something failed during tracing, review the console for more information...\n"); + if ( !emu.init() ) + { + std::printf( "[!] failed to init emulator...\n" ); + return -1; + } - std::printf("> finished tracing... number of virtual instructions = %d\n", - entries.size()); + if ( !emu.get_trace( entries ) ) + std::printf( "[!] something failed during tracing, review the console for more information...\n" ); - std::printf("> creating trace file...\n"); - std::ofstream output(parser.get("out"), - std::ios::binary); + std::printf( "> creating trace file...\n" ); + std::printf( "> finished tracing... number of virtual instructions = %d\n", entries.size() ); + std::ofstream output( parser.get< std::string >( "out" ), std::ios::binary ); - vmp2::file_header file_header; - memcpy(&file_header.magic, "VMP2", sizeof("VMP2") - 1); + vmp2::v2::file_header file_header; + memcpy( &file_header.magic, "VMP2", sizeof( "VMP2" ) - 1 ); - file_header.epoch_time = time(nullptr); - file_header.entry_offset = sizeof file_header; + file_header.epoch_time = time( nullptr ); + file_header.entry_offset = sizeof file_header + NT_HEADER( module_base )->OptionalHeader.SizeOfImage; + file_header.entry_count = entries.size(); file_header.advancement = advancment.value(); + file_header.image_base = image_base; + file_header.vm_entry_rva = vm_entry_rva; - file_header.version = vmp2::version_t::v1; - file_header.module_base = module_base; - file_header.entry_count = entries.size(); + file_header.version = vmp2::version_t::v2; + file_header.module_base = module_base; + file_header.module_offset = sizeof file_header; + file_header.module_size = umtils->image_size( parser.get< std::string >( "vmpbin" ).c_str() ); - output.write(reinterpret_cast( - &file_header), sizeof file_header); + output.write( reinterpret_cast< const char * >( &file_header ), sizeof file_header ); + output.write( reinterpret_cast< const char * >( module_base ), file_header.module_size ); - for (auto& entry : entries) - output.write(reinterpret_cast( - &entry), sizeof entry); + for ( auto &entry : entries ) + output.write( reinterpret_cast< const char * >( &entry ), sizeof entry ); - output.close(); - std::printf("> finished writing trace to disk...\n"); + output.close(); + std::printf( "> finished writing trace to disk...\n" ); } diff --git a/src/vmemu.vcxproj b/src/vmemu.vcxproj index 7c4ee4e..2ae7137 100644 --- a/src/vmemu.vcxproj +++ b/src/vmemu.vcxproj @@ -76,11 +76,14 @@ - + - + + {88a23124-5640-35a0-b890-311d7a67a7d2} + + {d0b6092a-9944-4f24-9486-4b7dae372619} diff --git a/src/vmemu.vcxproj.filters b/src/vmemu.vcxproj.filters index 2f1536f..9bc4ecc 100644 --- a/src/vmemu.vcxproj.filters +++ b/src/vmemu.vcxproj.filters @@ -220,9 +220,6 @@ Header Files\vmprofiler - - Header Files - Header Files @@ -232,5 +229,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index 34f35d6..a11e935 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -123,7 +123,7 @@ namespace vm if (uc) uc_close(uc); } - bool emu_t::get_trace(std::vector& entries) + bool emu_t::get_trace(std::vector& entries) { // hook_code will fill this vector up with values... trace_entries = &entries; @@ -139,7 +139,7 @@ namespace vm return true; } - uc_err emu_t::create_entry(vmp2::entry_t* entry) + uc_err emu_t::create_entry(vmp2::v2::entry_t* entry) { uc_reg_read(uc, UC_X86_REG_R15, &entry->regs.r15); uc_reg_read(uc, UC_X86_REG_R14, &entry->regs.r14); @@ -200,7 +200,7 @@ namespace vm if (address == obj->vm_entry[obj->vm_entry.size() - 1].addr) { uc_err err; - vmp2::entry_t new_entry; + vmp2::v2::entry_t new_entry; if ((err = obj->create_entry(&new_entry))) { std::printf("[!] failed to create new entry... reason = %u, %s\n", @@ -241,7 +241,7 @@ namespace vm return; uc_err err; - vmp2::entry_t new_entry; + vmp2::v2::entry_t new_entry; if ((err = obj->create_entry(&new_entry))) { std::printf("[!] failed to create new entry... reason = %u, %s\n", diff --git a/src/vmemu_t.hpp b/src/vmemu_t.hpp index 85fe5ea..a76014b 100644 --- a/src/vmemu_t.hpp +++ b/src/vmemu_t.hpp @@ -20,9 +20,9 @@ namespace vm ~emu_t(); bool init(); - bool get_trace(std::vector& entries); + bool get_trace(std::vector& entries); private: - uc_err create_entry(vmp2::entry_t* entry); + uc_err create_entry(vmp2::v2::entry_t* entry); static void hook_code(uc_engine* uc, uint64_t address, uint32_t size, vm::emu_t* obj); static bool hook_mem_invalid(uc_engine* uc, uc_mem_type type, uint64_t address, int size, int64_t value, vm::emu_t* obj); @@ -36,6 +36,6 @@ namespace vm zydis_routine_t vm_entry; std::uintptr_t* vm_handler_table; std::vector vm_handlers; - std::vector* trace_entries; + std::vector* trace_entries; }; } \ No newline at end of file diff --git a/vmemu.sln b/vmemu.sln index b2791c0..2f62ea5 100644 --- a/vmemu.sln +++ b/vmemu.sln @@ -5,10 +5,10 @@ VisualStudioVersion = 16.0.30907.101 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmemu", "src\vmemu.vcxproj", "{F0D51879-E659-4BD3-B688-7864DB3C82AA}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmprofiler", "dependencies\vmprofiler\src\vmprofiler.vcxproj", "{D0B6092A-9944-4F24-9486-4B7DAE372619}" -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 Global GlobalSection(SolutionConfigurationPlatforms) = preSolution DBG|x64 = DBG|x64 @@ -88,56 +88,6 @@ Global {F0D51879-E659-4BD3-B688-7864DB3C82AA}.Release|x64.ActiveCfg = Release|x64 {F0D51879-E659-4BD3-B688-7864DB3C82AA}.Release|x64.Build.0 = Release|x64 {F0D51879-E659-4BD3-B688-7864DB3C82AA}.Release|x86.ActiveCfg = Release|x64 - {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 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug Kernel|x64.Build.0 = Release|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 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD|x64.Build.0 = Release|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 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT DLL|x64.Build.0 = Release|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 = Release|x64 - {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT|x64.Build.0 = Release|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 {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 @@ -194,6 +144,56 @@ Global {88A23124-5640-35A0-B890-311D7A67A7D2}.Release|x64.Build.0 = Release MD DLL|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}.Debug|x64.ActiveCfg = DBG|x64 + {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug|x64.Build.0 = DBG|x64 + {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug|x86.ActiveCfg = DBG|x64 + {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug|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}.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 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE