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 0000000..6254374 Binary files /dev/null and b/src/icon.ico differ 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