From 845f93375d7a0a17a09c0c8e9eaaa85866f5c11f Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Tue, 18 May 2021 19:41:00 -0700 Subject: [PATCH] added source and sub modules --- .gitignore | 388 +++++++++++++++++++ .gitmodules | 3 + src/ZycoreExportConfig.h | 42 +++ src/ZydisExportConfig.h | 42 +++ src/cli-parser.hpp | 580 +++++++++++++++++++++++++++++ src/icon.ico | Bin 0 -> 232878 bytes src/icon.rc | 3 + src/main.cpp | 153 ++++++++ src/vmprofiler-cli.vcxproj | 129 +++++++ src/vmprofiler-cli.vcxproj.filters | 198 ++++++++++ vmprofiler-cli.sln | 175 +++++++++ 11 files changed, 1713 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 src/ZycoreExportConfig.h create mode 100644 src/ZydisExportConfig.h create mode 100644 src/cli-parser.hpp create mode 100644 src/icon.ico create mode 100644 src/icon.rc create mode 100644 src/main.cpp create mode 100644 src/vmprofiler-cli.vcxproj create mode 100644 src/vmprofiler-cli.vcxproj.filters create mode 100644 vmprofiler-cli.sln diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..72de34f --- /dev/null +++ b/.gitignore @@ -0,0 +1,388 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Nuget personal access tokens and Credentials +nuget.config + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +.idea/ +*.sln.iml \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..af8ad4c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "dependancies/vmprofiler"] + path = dependancies/vmprofiler + url = https://githacks.org/vmp2/vmprofiler diff --git a/src/ZycoreExportConfig.h b/src/ZycoreExportConfig.h new file mode 100644 index 0000000..f050d37 --- /dev/null +++ b/src/ZycoreExportConfig.h @@ -0,0 +1,42 @@ + +#ifndef ZYCORE_EXPORT_H +#define ZYCORE_EXPORT_H + +#ifdef ZYCORE_STATIC_DEFINE +# define ZYCORE_EXPORT +# define ZYCORE_NO_EXPORT +#else +# ifndef ZYCORE_EXPORT +# ifdef Zycore_EXPORTS + /* We are building this library */ +# define ZYCORE_EXPORT __declspec(dllexport) +# else + /* We are using this library */ +# define ZYCORE_EXPORT __declspec(dllimport) +# endif +# endif + +# ifndef ZYCORE_NO_EXPORT +# define ZYCORE_NO_EXPORT +# endif +#endif + +#ifndef ZYCORE_DEPRECATED +# define ZYCORE_DEPRECATED __declspec(deprecated) +#endif + +#ifndef ZYCORE_DEPRECATED_EXPORT +# define ZYCORE_DEPRECATED_EXPORT ZYCORE_EXPORT ZYCORE_DEPRECATED +#endif + +#ifndef ZYCORE_DEPRECATED_NO_EXPORT +# define ZYCORE_DEPRECATED_NO_EXPORT ZYCORE_NO_EXPORT ZYCORE_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef ZYCORE_NO_DEPRECATED +# define ZYCORE_NO_DEPRECATED +# endif +#endif + +#endif /* ZYCORE_EXPORT_H */ diff --git a/src/ZydisExportConfig.h b/src/ZydisExportConfig.h new file mode 100644 index 0000000..2e0b4a2 --- /dev/null +++ b/src/ZydisExportConfig.h @@ -0,0 +1,42 @@ + +#ifndef ZYDIS_EXPORT_H +#define ZYDIS_EXPORT_H + +#ifdef ZYDIS_STATIC_DEFINE +# define ZYDIS_EXPORT +# define ZYDIS_NO_EXPORT +#else +# ifndef ZYDIS_EXPORT +# ifdef Zydis_EXPORTS + /* We are building this library */ +# define ZYDIS_EXPORT __declspec(dllexport) +# else + /* We are using this library */ +# define ZYDIS_EXPORT __declspec(dllimport) +# endif +# endif + +# ifndef ZYDIS_NO_EXPORT +# define ZYDIS_NO_EXPORT +# endif +#endif + +#ifndef ZYDIS_DEPRECATED +# define ZYDIS_DEPRECATED __declspec(deprecated) +#endif + +#ifndef ZYDIS_DEPRECATED_EXPORT +# define ZYDIS_DEPRECATED_EXPORT ZYDIS_EXPORT ZYDIS_DEPRECATED +#endif + +#ifndef ZYDIS_DEPRECATED_NO_EXPORT +# define ZYDIS_DEPRECATED_NO_EXPORT ZYDIS_NO_EXPORT ZYDIS_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef ZYDIS_NO_DEPRECATED +# define ZYDIS_NO_DEPRECATED +# endif +#endif + +#endif /* ZYDIS_EXPORT_H */ diff --git a/src/cli-parser.hpp b/src/cli-parser.hpp new file mode 100644 index 0000000..0b404ee --- /dev/null +++ b/src/cli-parser.hpp @@ -0,0 +1,580 @@ +/** + * License: Apache 2.0 with LLVM Exception or GPL v3 + * + * Author: Jesse Laning + */ + +#ifndef ARGPARSE_H +#define ARGPARSE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace argparse { + namespace detail { + static inline bool _not_space(int ch) { return !std::isspace(ch); } + static inline void _ltrim(std::string& s, bool (*f)(int) = _not_space) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), f)); + } + static inline void _rtrim(std::string& s, bool (*f)(int) = _not_space) { + s.erase(std::find_if(s.rbegin(), s.rend(), f).base(), s.end()); + } + static inline void _trim(std::string& s, bool (*f)(int) = _not_space) { + _ltrim(s, f); + _rtrim(s, f); + } + static inline std::string _ltrim_copy(std::string s, + bool (*f)(int) = _not_space) { + _ltrim(s, f); + return s; + } + static inline std::string _rtrim_copy(std::string s, + bool (*f)(int) = _not_space) { + _rtrim(s, f); + return s; + } + static inline std::string _trim_copy(std::string s, + bool (*f)(int) = _not_space) { + _trim(s, f); + return s; + } + template + static inline std::string _join(InputIt begin, InputIt end, + const std::string& separator = " ") { + std::ostringstream ss; + if (begin != end) { + ss << *begin++; + } + while (begin != end) { + ss << separator; + ss << *begin++; + } + return ss.str(); + } + static inline bool _is_number(const std::string& arg) { + std::istringstream iss(arg); + float f; + iss >> std::noskipws >> f; + return iss.eof() && !iss.fail(); + } + + static inline int _find_equal(const std::string& s) { + for (size_t i = 0; i < s.length(); ++i) { + // if find graph symbol before equal, end search + // i.e. don't accept --asd)f=0 arguments + // but allow --asd_f and --asd-f arguments + if (std::ispunct(static_cast(s[i]))) { + if (s[i] == '=') { + return static_cast(i); + } + else if (s[i] == '_' || s[i] == '-') { + continue; + } + return -1; + } + } + return -1; + } + + static inline size_t _find_name_end(const std::string& s) { + size_t i; + for (i = 0; i < s.length(); ++i) { + if (std::ispunct(static_cast(s[i]))) { + break; + } + } + return i; + } + + namespace is_vector_impl { + template + struct is_vector : std::false_type {}; + template + struct is_vector> : std::true_type {}; + } // namespace is_vector_impl + + // type trait to utilize the implementation type traits as well as decay the + // type + template + struct is_vector { + static constexpr bool const value = + is_vector_impl::is_vector::type>::value; + }; + } // namespace detail + + class argument_parser_t { + private: + public: + class Argument; + + class Result { + public: + Result() {} + Result(std::string err) noexcept : _error(true), _what(err) {} + + operator bool() const { return _error; } + + friend std::ostream& operator<<(std::ostream& os, const Result& dt); + + const std::string& what() const { return _what; } + + private: + bool _error{ false }; + std::string _what{}; + }; + + class Argument { + public: + enum Position : int { LAST = -1, DONT_CARE = -2 }; + enum Count : int { ANY = -1 }; + + Argument& name(const std::string& name) { + _names.push_back(name); + return *this; + } + + Argument& names(std::vector names) { + _names.insert(_names.end(), names.begin(), names.end()); + return *this; + } + + Argument& description(const std::string& description) { + _desc = description; + return *this; + } + + Argument& required(bool req) { + _required = req; + return *this; + } + + Argument& position(int position) { + if (position != Position::LAST) { + // position + 1 because technically argument zero is the name of the + // executable + _position = position + 1; + } + else { + _position = position; + } + return *this; + } + + Argument& count(int count) { + _count = count; + return *this; + } + + bool found() const { return _found; } + + template + typename std::enable_if::value, T>::type get() { + T t = T(); + typename T::value_type vt; + for (auto& s : _values) { + std::istringstream in(s); + in >> vt; + t.push_back(vt); + } + return t; + } + + template + typename std::enable_if::value, T>::type get() { + std::istringstream in(get()); + T t = T(); + in >> t >> std::ws; + return t; + } + + private: + Argument(const std::string& name, const std::string& desc, + bool required = false) + : _desc(desc), _required(required) { + _names.push_back(name); + } + + Argument() {} + + friend class argument_parser_t; + int _position{ Position::DONT_CARE }; + int _count{ Count::ANY }; + std::vector _names{}; + std::string _desc{}; + bool _found{ false }; + bool _required{ false }; + int _index{ -1 }; + + std::vector _values{}; + }; + + argument_parser_t(std::string bin, std::string desc) + : _bin(bin), _desc(desc) {} + + Argument& add_argument() { + _arguments.push_back({}); + _arguments.back()._index = static_cast(_arguments.size()) - 1; + return _arguments.back(); + } + + Argument& add_argument(const std::string& name, const std::string& long_name, + const std::string& desc, const bool required = false) { + _arguments.push_back(Argument(name, desc, required)); + _arguments.back()._names.push_back(long_name); + _arguments.back()._index = static_cast(_arguments.size()) - 1; + return _arguments.back(); + } + + Argument& add_argument(const std::string& name, const std::string& desc, + const bool required = false) { + _arguments.push_back(Argument(name, desc, required)); + _arguments.back()._index = static_cast(_arguments.size()) - 1; + return _arguments.back(); + } + + void print_help(size_t count = 0, size_t page = 0) { + if (page * count > _arguments.size()) { + return; + } + if (page == 0) { + std::cout << "Usage: " << _bin; + if (_positional_arguments.empty()) { + std::cout << " [options...]" << std::endl; + } + else { + int current = 1; + for (auto& v : _positional_arguments) { + if (v.first != Argument::Position::LAST) { + for (; current < v.first; current++) { + std::cout << " [" << current << "]"; + } + std::cout + << " [" + << detail::_ltrim_copy( + _arguments[static_cast(v.second)]._names[0], + [](int c) -> bool { return c != static_cast('-'); }) + << "]"; + } + } + auto it = _positional_arguments.find(Argument::Position::LAST); + if (it == _positional_arguments.end()) { + std::cout << " [options...]"; + } + else { + std::cout + << " [options...] [" + << detail::_ltrim_copy( + _arguments[static_cast(it->second)]._names[0], + [](int c) -> bool { return c != static_cast('-'); }) + << "]"; + } + std::cout << std::endl; + } + std::cout << "Options:" << std::endl; + } + if (count == 0) { + page = 0; + count = _arguments.size(); + } + for (size_t i = page * count; + i < std::min(page * count + count, _arguments.size()); i++) { + Argument& a = _arguments[i]; + std::string name = a._names[0]; + for (size_t n = 1; n < a._names.size(); ++n) { + name.append(", " + a._names[n]); + } + std::cout << " " << std::setw(23) << std::left << name << std::setw(23) + << a._desc; + if (a._required) { + std::cout << " (Required)"; + } + std::cout << std::endl; + } + } + + Result parse(int argc, const char* argv[]) { + Result err; + if (argc > 1) { + // build name map + for (auto& a : _arguments) { + for (auto& n : a._names) { + std::string name = detail::_ltrim_copy( + n, [](int c) -> bool { return c != static_cast('-'); }); + if (_name_map.find(name) != _name_map.end()) { + return Result("Duplicate of argument name: " + n); + } + _name_map[name] = a._index; + } + if (a._position >= 0 || a._position == Argument::Position::LAST) { + _positional_arguments[a._position] = a._index; + } + } + if (err) { + return err; + } + + // parse + std::string current_arg; + size_t arg_len; + for (int argv_index = 1; argv_index < argc; ++argv_index) { + current_arg = std::string(argv[argv_index]); + arg_len = current_arg.length(); + if (arg_len == 0) { + continue; + } + if (_help_enabled && (current_arg == "-h" || current_arg == "--help")) { + _arguments[static_cast(_name_map["help"])]._found = true; + } + else if (argv_index == argc - 1 && + _positional_arguments.find(Argument::Position::LAST) != + _positional_arguments.end()) { + err = _end_argument(); + Result b = err; + err = _add_value(current_arg, Argument::Position::LAST); + if (b) { + return b; + } + if (err) { + return err; + } + } + else if (arg_len >= 2 && + !detail::_is_number(current_arg)) { // ignores the case if + // the arg is just a - + // look for -a (short) or --arg (long) args + if (current_arg[0] == '-') { + err = _end_argument(); + if (err) { + return err; + } + // look for --arg (long) args + if (current_arg[1] == '-') { + err = _begin_argument(current_arg.substr(2), true, argv_index); + if (err) { + return err; + } + } + else { // short args + err = _begin_argument(current_arg.substr(1), false, argv_index); + if (err) { + return err; + } + } + } + else { // argument value + err = _add_value(current_arg, argv_index); + if (err) { + return err; + } + } + } + else { // argument value + err = _add_value(current_arg, argv_index); + if (err) { + return err; + } + } + } + } + if (_help_enabled && exists("help")) { + return Result(); + } + err = _end_argument(); + if (err) { + return err; + } + for (auto& p : _positional_arguments) { + Argument& a = _arguments[static_cast(p.second)]; + if (a._values.size() > 0 && a._values[0][0] == '-') { + std::string name = detail::_ltrim_copy(a._values[0], [](int c) -> bool { + return c != static_cast('-'); + }); + if (_name_map.find(name) != _name_map.end()) { + if (a._position == Argument::Position::LAST) { + return Result( + "Poisitional argument expected at the end, but argument " + + a._values[0] + " found instead"); + } + else { + return Result("Poisitional argument expected in position " + + std::to_string(a._position) + ", but argument " + + a._values[0] + " found instead"); + } + } + } + } + for (auto& a : _arguments) { + if (a._required && !a._found) { + return Result("Required argument not found: " + a._names[0]); + } + if (a._position >= 0 && argc >= a._position && !a._found) { + return Result("Argument " + a._names[0] + " expected in position " + + std::to_string(a._position)); + } + } + return Result(); + } + + void enable_help() { + add_argument("-h", "--help", "Shows this page", false); + _help_enabled = true; + } + + bool exists(const std::string& name) const { + std::string n = detail::_ltrim_copy( + name, [](int c) -> bool { return c != static_cast('-'); }); + auto it = _name_map.find(n); + if (it != _name_map.end()) { + return _arguments[static_cast(it->second)]._found; + } + return false; + } + + template + T get(const std::string& name) { + auto t = _name_map.find(name); + if (t != _name_map.end()) { + return _arguments[static_cast(t->second)].get(); + } + return T(); + } + + private: + Result _begin_argument(const std::string& arg, bool longarg, int position) { + auto it = _positional_arguments.find(position); + if (it != _positional_arguments.end()) { + Result err = _end_argument(); + Argument& a = _arguments[static_cast(it->second)]; + a._values.push_back((longarg ? "--" : "-") + arg); + a._found = true; + return err; + } + if (_current != -1) { + return Result("Current argument left open"); + } + size_t name_end = detail::_find_name_end(arg); + std::string arg_name = arg.substr(0, name_end); + if (longarg) { + int equal_pos = detail::_find_equal(arg); + auto nmf = _name_map.find(arg_name); + if (nmf == _name_map.end()) { + return Result("Unrecognized command line option '" + arg_name + "'"); + } + _current = nmf->second; + _arguments[static_cast(nmf->second)]._found = true; + if (equal_pos == 0 || + (equal_pos < 0 && + arg_name.length() < arg.length())) { // malformed argument + return Result("Malformed argument: " + arg); + } + else if (equal_pos > 0) { + std::string arg_value = arg.substr(name_end + 1); + _add_value(arg_value, position); + } + } + else { + Result r; + if (arg_name.length() == 1) { + return _begin_argument(arg, true, position); + } + else { + for (char& c : arg_name) { + r = _begin_argument(std::string(1, c), true, position); + if (r) { + return r; + } + r = _end_argument(); + if (r) { + return r; + } + } + } + } + return Result(); + } + + Result _add_value(const std::string& value, int location) { + if (_current >= 0) { + Result err; + Argument& a = _arguments[static_cast(_current)]; + if (a._count >= 0 && static_cast(a._values.size()) >= a._count) { + err = _end_argument(); + if (err) { + return err; + } + goto unnamed; + } + a._values.push_back(value); + if (a._count >= 0 && static_cast(a._values.size()) >= a._count) { + err = _end_argument(); + if (err) { + return err; + } + } + return Result(); + } + else { + unnamed: + auto it = _positional_arguments.find(location); + if (it != _positional_arguments.end()) { + Argument& a = _arguments[static_cast(it->second)]; + a._values.push_back(value); + a._found = true; + } + // TODO + return Result(); + } + } + + Result _end_argument() { + if (_current >= 0) { + Argument& a = _arguments[static_cast(_current)]; + _current = -1; + if (static_cast(a._values.size()) < a._count) { + return Result("Too few arguments given for " + a._names[0]); + } + if (a._count >= 0) { + if (static_cast(a._values.size()) > a._count) { + return Result("Too many arguments given for " + a._names[0]); + } + } + } + return Result(); + } + + bool _help_enabled{ false }; + int _current{ -1 }; + std::string _bin{}; + std::string _desc{}; + std::vector _arguments{}; + std::map _positional_arguments{}; + std::map _name_map{}; + }; + + std::ostream& operator<<(std::ostream& os, const argument_parser_t::Result& r) { + os << r.what(); + return os; + } + template <> + inline std::string argument_parser_t::Argument::get() { + return detail::_join(_values.begin(), _values.end()); + } + template <> + inline std::vector + argument_parser_t::Argument::get>() { + return _values; + } + +} // namespace argparse +#endif \ No newline at end of file diff --git a/src/icon.ico b/src/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..6254374ac74923506d911c0d767ae8afd7068f4a GIT binary patch literal 232878 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 KchRjD=>I=Q?(KvC literal 0 HcmV?d00001 diff --git a/src/icon.rc b/src/icon.rc new file mode 100644 index 0000000..ac3155f --- /dev/null +++ b/src/icon.rc @@ -0,0 +1,3 @@ +// Icon Resource Definition +#define MAIN_ICON 102 +MAIN_ICON ICON "icon.ico" \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..619aa8a --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int __cdecl main(int argc, const char* argv[]) +{ + argparse::argument_parser_t parser( + "vmprofiler-cli", "virtual instruction pseudo code generator"); + + parser.add_argument() + .names({ "--bin", "--vmpbin" }) + .description("unpacked binary protected with VMProtect 2") + .required(true); + + parser.add_argument() + .names({ "--vmentry", "--entry" }) + .description("rva to push prior to a vm_entry") + .required(true); + + parser.add_argument() + .names({ "--imagebase", "--base" }) + .description("image base from OptionalHeader::ImageBase") + .required(true); + + parser.add_argument() + .names({ "--vmtrace", "--trace" }) + .description("a vmp2 file generated by a vmtracer"); + + parser.enable_help(); + auto err = parser.parse(argc, argv); + + if (err) + { + std::cout << err << std::endl; + return -1; + } + + if (parser.exists("help")) + { + parser.print_help(); + return 0; + } + + const auto module_base = + reinterpret_cast( + LoadLibraryExA(parser.get("bin").c_str(), + NULL, DONT_RESOLVE_DLL_REFERENCES)); + + const auto vm_entry_ptr = + module_base + std::strtoull( + parser.get("vmentry").c_str(), nullptr, 16); + + const auto image_base = std::strtoull( + parser.get("imagebase").c_str(), nullptr, 16); + + zydis_routine_t vm_entry; + std::printf("> vm entry start = 0x%p\n", vm_entry_ptr); + + if (!vm::util::flatten(vm_entry, vm_entry_ptr)) + { + std::printf("> failed to flatten vm entry...\n"); + return -1; + } + + vm::util::deobfuscate(vm_entry); + std::printf("> flattened vm entry...\n"); + std::printf("> deobfuscated vm entry...\n"); + vm::util::print(vm_entry); + + const auto vm_handler_table = vm::handler::table::get(vm_entry); + + if (!vm_handler_table) + { + std::printf("> failed to locate vm handler table...\n"); + return -1; + } + + std::printf("> located vm handler table... at = 0x%p, rva = 0x%p\n", vm_handler_table, + (reinterpret_cast(vm_handler_table) - module_base) + image_base); + + std::vector vm_handlers; + if (!vm::handler::get_all(module_base, image_base, vm_entry, vm_handler_table, vm_handlers)) + { + std::printf("> failed to get all vm handler meta data...\n"); + return -1; + } + + for (auto idx = 0u; idx < vm_handlers.size(); ++idx) + { + auto vm_handler = vm_handlers[idx]; + std::printf("==========[vm handler %s, idx = %d, imm size = %d]========\n", + vm_handler.profile ? vm_handler.profile->name : "UNKNOWN", idx, + vm_handler.imm_size); + + std::printf("================[vm handler instructions]==============\n"); + vm::util::print(vm_handler.instrs); + + if (vm_handler.imm_size) + { + std::printf("=================[vm handler transforms]===============\n"); + for (const auto& [transform_type, transform] : vm_handler.transforms) + vm::util::print(transform); + } + + std::printf("=======================================================\n\n"); + } + + if (parser.exists("vmtrace")) + { + std::ifstream vmp2_file( + parser.get("vmtrace").c_str(), std::ios::binary); + + const auto file_size = + std::filesystem::file_size( + parser.get("vmtrace").c_str()); + + const auto file_header = + reinterpret_cast(malloc(file_size)); + + vmp2_file.read((char*)file_header, file_size); + + const auto entry_list = + reinterpret_cast( + reinterpret_cast( + file_header) + file_header->entry_offset); + + std::printf("> module base = 0x%p\n", file_header->module_base); + std::getchar(); + + vm::vmctx_t vmctx( + file_header, + entry_list, + vm_handlers, + module_base, + image_base + ); + + for (auto [virt_instr, log_entry] = vmctx.step(); log_entry && !virt_instr.empty(); + std::tie(virt_instr, log_entry) = vmctx.step()) + { + std::printf("> %s (VSP[0] = 0x%p) (VSP[1] = 0x%p)\n", + virt_instr.c_str(), log_entry->vsp.qword[0], log_entry->vsp.qword[1]); + } + } + + std::printf("> finished...\n"); + std::getchar(); +} \ No newline at end of file diff --git a/src/vmprofiler-cli.vcxproj b/src/vmprofiler-cli.vcxproj new file mode 100644 index 0000000..e337914 --- /dev/null +++ b/src/vmprofiler-cli.vcxproj @@ -0,0 +1,129 @@ + + + + + Release + x64 + + + + 16.0 + Win32Proj + {92e23fae-8aba-48e7-8771-9fd837ab8db7} + vmprofiler + 10.0 + vmprofiler-cli + + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + false + $(ProjectDir)..\dependancies\vmprofiler\include\;$(ProjectDir);$(IncludePath) + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpplatest + Disabled + + + Console + true + true + true + $(ProjectDir)..\libs\*;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {88a23124-5640-35a0-b890-311d7a67a7d2} + + + {d0b6092a-9944-4f24-9486-4b7dae372619} + + + + + + \ No newline at end of file diff --git a/src/vmprofiler-cli.vcxproj.filters b/src/vmprofiler-cli.vcxproj.filters new file mode 100644 index 0000000..0fc137f --- /dev/null +++ b/src/vmprofiler-cli.vcxproj.filters @@ -0,0 +1,198 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {faf4cf50-0bc3-4674-80ff-fec015d82127} + + + {4e807ab2-7dfc-48a3-a092-039f09dd57f4} + + + {a10f8ff1-7349-4a48-9061-facf5a836ee4} + + + {82afe7a2-4ff1-4e12-806d-297e714bad9c} + + + {a8d11bd2-d945-406f-aeb4-c28feb79a31d} + + + {94c3a376-8f65-450f-9b11-740f95bef4d6} + + + + + Source Files + + + + + Resource Files + + + + + Resource Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis\Generated + + + Header Files\Zydis\Generated + + + Header Files\Zydis\Generated + + + Header Files\Zydis\Generated + + + Header Files\Zydis\Generated + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore\API + + + Header Files\Zycore\API + + + Header Files\Zycore\API + + + Header Files\Zycore\API + + + Header Files\Zycore\API + + + \ No newline at end of file diff --git a/vmprofiler-cli.sln b/vmprofiler-cli.sln new file mode 100644 index 0000000..7ffd55e --- /dev/null +++ b/vmprofiler-cli.sln @@ -0,0 +1,175 @@ + +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}") = "vmprofiler", "dependancies\vmprofiler\src\vmprofiler.vcxproj", "{D0B6092A-9944-4F24-9486-4B7DAE372619}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmprofiler-cli", "src\vmprofiler-cli.vcxproj", "{92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Zydis", "dependancies\vmprofiler\dependancies\zydis\msvc\zydis\Zydis.vcxproj", "{88A23124-5640-35A0-B890-311D7A67A7D2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + 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 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {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 = Release|x64 + {D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD DLL|x64.Build.0 = Release|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}.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 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug Kernel|x64.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug Kernel|x64.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug Kernel|x86.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug Kernel|x86.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MD DLL|x64.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MD DLL|x64.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MD DLL|x86.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MD DLL|x86.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MD|x64.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MD|x64.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MD|x86.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MD|x86.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MT DLL|x64.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MT DLL|x64.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MT DLL|x86.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MT DLL|x86.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MT|x64.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MT|x64.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MT|x86.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Debug MT|x86.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release Kernel|x64.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release Kernel|x64.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release Kernel|x86.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release Kernel|x86.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MD DLL|x64.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MD DLL|x64.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MD DLL|x86.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MD DLL|x86.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MD|x64.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MD|x64.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MD|x86.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MD|x86.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MT DLL|x64.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MT DLL|x64.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MT DLL|x86.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MT DLL|x86.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MT|x64.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MT|x64.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MT|x86.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release MT|x86.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release|x64.ActiveCfg = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release|x64.Build.0 = Release|x64 + {92E23FAE-8ABA-48E7-8771-9FD837AB8DB7}.Release|x86.ActiveCfg = Release|x64 + {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|x86.ActiveCfg = Debug Kernel|Win32 + {88A23124-5640-35A0-B890-311D7A67A7D2}.Debug Kernel|x86.Build.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|x86.ActiveCfg = Release Kernel|Win32 + {88A23124-5640-35A0-B890-311D7A67A7D2}.Release Kernel|x86.Build.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}.Release|x86.ActiveCfg = Release MD DLL|Win32 + {88A23124-5640-35A0-B890-311D7A67A7D2}.Release|x86.Build.0 = Release MD DLL|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B8861886-C9EA-4C44-878C-D7BC28AB3413} + EndGlobalSection +EndGlobal