parent
79d43e43db
commit
ca4f747cc2
@ -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
|
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "dependencies/vmtracer"]
|
||||||
|
path = dependencies/vmtracer
|
||||||
|
url = https://githacks.org/vmp2/vmtracer.git
|
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 2130f86ea886b5a8b81d368b3b6a6f2412c37194
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,580 @@
|
|||||||
|
/**
|
||||||
|
* License: Apache 2.0 with LLVM Exception or GPL v3
|
||||||
|
*
|
||||||
|
* Author: Jesse Laning
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ARGPARSE_H
|
||||||
|
#define ARGPARSE_H
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <locale>
|
||||||
|
#include <map>
|
||||||
|
#include <numeric>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
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 <typename InputIt>
|
||||||
|
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<int>(s[i]))) {
|
||||||
|
if (s[i] == '=') {
|
||||||
|
return static_cast<int>(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<int>(s[i]))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace is_vector_impl {
|
||||||
|
template <typename T>
|
||||||
|
struct is_vector : std::false_type {};
|
||||||
|
template <typename... Args>
|
||||||
|
struct is_vector<std::vector<Args...>> : std::true_type {};
|
||||||
|
} // namespace is_vector_impl
|
||||||
|
|
||||||
|
// type trait to utilize the implementation type traits as well as decay the
|
||||||
|
// type
|
||||||
|
template <typename T>
|
||||||
|
struct is_vector {
|
||||||
|
static constexpr bool const value =
|
||||||
|
is_vector_impl::is_vector<typename std::decay<T>::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<std::string> 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 T>
|
||||||
|
typename std::enable_if<detail::is_vector<T>::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 T>
|
||||||
|
typename std::enable_if<!detail::is_vector<T>::value, T>::type get() {
|
||||||
|
std::istringstream in(get<std::string>());
|
||||||
|
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<std::string> _names{};
|
||||||
|
std::string _desc{};
|
||||||
|
bool _found{ false };
|
||||||
|
bool _required{ false };
|
||||||
|
int _index{ -1 };
|
||||||
|
|
||||||
|
std::vector<std::string> _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<int>(_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<int>(_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<int>(_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<size_t>(v.second)]._names[0],
|
||||||
|
[](int c) -> bool { return c != static_cast<int>('-'); })
|
||||||
|
<< "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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<size_t>(it->second)]._names[0],
|
||||||
|
[](int c) -> bool { return c != static_cast<int>('-'); })
|
||||||
|
<< "]";
|
||||||
|
}
|
||||||
|
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<size_t>(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<int>('-'); });
|
||||||
|
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<size_t>(_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<size_t>(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<int>('-');
|
||||||
|
});
|
||||||
|
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<int>('-'); });
|
||||||
|
auto it = _name_map.find(n);
|
||||||
|
if (it != _name_map.end()) {
|
||||||
|
return _arguments[static_cast<size_t>(it->second)]._found;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T get(const std::string& name) {
|
||||||
|
auto t = _name_map.find(name);
|
||||||
|
if (t != _name_map.end()) {
|
||||||
|
return _arguments[static_cast<size_t>(t->second)].get<T>();
|
||||||
|
}
|
||||||
|
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<size_t>(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<size_t>(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<size_t>(_current)];
|
||||||
|
if (a._count >= 0 && static_cast<int>(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<int>(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<size_t>(it->second)];
|
||||||
|
a._values.push_back(value);
|
||||||
|
a._found = true;
|
||||||
|
}
|
||||||
|
// TODO
|
||||||
|
return Result();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result _end_argument() {
|
||||||
|
if (_current >= 0) {
|
||||||
|
Argument& a = _arguments[static_cast<size_t>(_current)];
|
||||||
|
_current = -1;
|
||||||
|
if (static_cast<int>(a._values.size()) < a._count) {
|
||||||
|
return Result("Too few arguments given for " + a._names[0]);
|
||||||
|
}
|
||||||
|
if (a._count >= 0) {
|
||||||
|
if (static_cast<int>(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<Argument> _arguments{};
|
||||||
|
std::map<int, int> _positional_arguments{};
|
||||||
|
std::map<std::string, int> _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<std::string>() {
|
||||||
|
return detail::_join(_values.begin(), _values.end());
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
inline std::vector<std::string>
|
||||||
|
argument_parser_t::Argument::get<std::vector<std::string>>() {
|
||||||
|
return _values;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace argparse
|
||||||
|
#endif
|
@ -0,0 +1,36 @@
|
|||||||
|
.data
|
||||||
|
__mbase dq 0h
|
||||||
|
public __mbase
|
||||||
|
|
||||||
|
.code
|
||||||
|
__lconstbzx proc
|
||||||
|
mov al, [rsi]
|
||||||
|
lea rsi, [rsi+1]
|
||||||
|
xor al, bl
|
||||||
|
dec al
|
||||||
|
ror al, 1
|
||||||
|
neg al
|
||||||
|
xor bl, al
|
||||||
|
|
||||||
|
pushfq ; save flags...
|
||||||
|
cmp ax, 01Ch
|
||||||
|
je swap_val
|
||||||
|
|
||||||
|
; the constant is not 0x1C
|
||||||
|
popfq ; restore flags...
|
||||||
|
sub rbp, 2
|
||||||
|
mov [rbp], ax
|
||||||
|
mov rax, __mbase
|
||||||
|
add rax, 059FEh ; calc jmp rva is 0x59FE...
|
||||||
|
jmp rax
|
||||||
|
|
||||||
|
swap_val: ; the constant is 0x1C
|
||||||
|
popfq ; restore flags...
|
||||||
|
mov ax, 5 ; bit 5 is VMX in ECX after CPUID...
|
||||||
|
sub rbp, 2
|
||||||
|
mov [rbp], ax
|
||||||
|
mov rax, __mbase
|
||||||
|
add rax, 059FEh ; calc jmp rva is 0x59FE...
|
||||||
|
jmp rax
|
||||||
|
__lconstbzx endp
|
||||||
|
end
|
@ -0,0 +1,210 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <filesystem>
|
||||||
|
#include "vmtracer.hpp"
|
||||||
|
#include "vmp2.hpp"
|
||||||
|
#include "cli-parser.hpp"
|
||||||
|
|
||||||
|
extern "C" void __lconstbzx(void);
|
||||||
|
extern "C" u64 __mbase;
|
||||||
|
|
||||||
|
#define NT_HEADER(x) \
|
||||||
|
reinterpret_cast<PIMAGE_NT_HEADERS64>( \
|
||||||
|
reinterpret_cast<PIMAGE_DOS_HEADER>(x)->e_lfanew + x)
|
||||||
|
|
||||||
|
inline std::vector<vmp2::entry_t> traces;
|
||||||
|
inline vmp2::file_header trace_header;
|
||||||
|
|
||||||
|
int __cdecl main(int argc, const char** argv)
|
||||||
|
{
|
||||||
|
argparse::argument_parser_t parser(
|
||||||
|
"um-tracer", "usermode virtual instruction tracer");
|
||||||
|
|
||||||
|
parser.add_argument()
|
||||||
|
.names({ "--bin", "--vmpbin" })
|
||||||
|
.description("path to a binary protected with VMProtect 2")
|
||||||
|
.required(true);
|
||||||
|
|
||||||
|
parser.add_argument()
|
||||||
|
.names({ "--table", "--vmtable" })
|
||||||
|
.description("relative virtual address to the vm handler table")
|
||||||
|
.required(true);
|
||||||
|
|
||||||
|
parser.add_argument()
|
||||||
|
.names({ "--base", "--imagebase" })
|
||||||
|
.description("image base from OptionalHeader::ImageBase")
|
||||||
|
.required(true);
|
||||||
|
|
||||||
|
parser.add_argument()
|
||||||
|
.names({ "--out", "--output" })
|
||||||
|
.description("name and/or path to output file")
|
||||||
|
.required(true);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
the vm_handlers are encrypted/encoded with a basic
|
||||||
|
math operation... typically a NOT, XOR, NEG, etc...
|
||||||
|
|
||||||
|
You can determine what type of encryption your binary
|
||||||
|
is using by first finding where the LEA r12, vm_handlers
|
||||||
|
is located, then follow the usage of r12 until you see
|
||||||
|
MOV GP, [r12 + rax * 8], then follow the usage of the GP...
|
||||||
|
|
||||||
|
For example:
|
||||||
|
.vmp1:00000001401D1015 lea r12, vm_handlers
|
||||||
|
.vmp1:00000001401D0C0A mov rdx, [r12+rax*8]
|
||||||
|
.vmp1:00000001401D0C10 ror rdx, 25h
|
||||||
|
|
||||||
|
Note:
|
||||||
|
R12 and RAX always seem to be used for this vm handler index...
|
||||||
|
You could signature scan for LEA r12, ? ? ? ? and find the vm handler
|
||||||
|
table really easily by manually inspecting each result...
|
||||||
|
*/
|
||||||
|
|
||||||
|
vm::decrypt_handler_t _decrypt_handler =
|
||||||
|
[](u64 val) -> u64
|
||||||
|
{
|
||||||
|
return val ^ 0x7F3D2149;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm::encrypt_handler_t _encrypt_handler =
|
||||||
|
[](u64 val) -> u64
|
||||||
|
{
|
||||||
|
return val ^ 0x7F3D2149;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm::handler::edit_entry_t _edit_entry =
|
||||||
|
[](u64* entry_ptr, u64 val) -> void
|
||||||
|
{
|
||||||
|
DWORD old_prot;
|
||||||
|
VirtualProtect(entry_ptr, sizeof val,
|
||||||
|
PAGE_EXECUTE_READWRITE, &old_prot);
|
||||||
|
|
||||||
|
*entry_ptr = val;
|
||||||
|
VirtualProtect(entry_ptr, sizeof val,
|
||||||
|
old_prot, &old_prot);
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto module_base =
|
||||||
|
reinterpret_cast<std::uintptr_t>(
|
||||||
|
LoadLibraryExA(parser.get<std::string>("bin").c_str(),
|
||||||
|
NULL, DONT_RESOLVE_DLL_REFERENCES));
|
||||||
|
|
||||||
|
// used in LCONSTBZX hook...
|
||||||
|
__mbase = module_base;
|
||||||
|
|
||||||
|
const auto handler_table_rva = std::strtoul(
|
||||||
|
parser.get<std::string>("table").c_str(), nullptr, 16);
|
||||||
|
|
||||||
|
const auto image_base = std::strtoull(
|
||||||
|
parser.get<std::string>("base").c_str(), nullptr, 16);
|
||||||
|
|
||||||
|
const auto handler_table_ptr =
|
||||||
|
reinterpret_cast<std::uintptr_t*>(
|
||||||
|
module_base + handler_table_rva);
|
||||||
|
|
||||||
|
/*
|
||||||
|
the VM handler table is an array of 256 QWORD's... each encrypted differently per-binary...
|
||||||
|
each one of these is an encrypted RVA to a virtual instruction...
|
||||||
|
|
||||||
|
.vmp1:00000001401D25D3 vm_handlers dq 3A28FA000000028h, 3A40E4000000028h, 3A2F5C000000028h
|
||||||
|
.vmp1:00000001401D25D3 dq 3A1096000000028h, 3A3DBC000000028h, 3A1DDA000000028h
|
||||||
|
.vmp1:00000001401D25D3 dq 3A6032000000028h, 2 dup(3A40E4000000028h), 3A2B5A000000028h
|
||||||
|
.vmp1:00000001401D25D3 dq 3A4004000000028h, 3A2810000000028h, 3A446A000000028h
|
||||||
|
.vmp1:00000001401D25D3 dq 3A39B6000000028h, 3A6728000000028h, 3A6032000000028h
|
||||||
|
.vmp1:00000001401D25D3 dq 3A34F0000000028h, 3A46F2000000028h, 3A0170000000028h
|
||||||
|
.vmp1:00000001401D25D3 dq 3A0952000000028h, 3A4004000000028h, 3A494E000000028h
|
||||||
|
.vmp1:00000001401D25D3 dq 3A35C2000000028h, 3A4A1E000000028h, 3A37D8000000028h
|
||||||
|
.vmp1:00000001401D25D3 dq 3A1482000000028h, 3A6492000000028h, 3A2948000000028h
|
||||||
|
.vmp1:00000001401D25D3 dq 3A2D1C000000028h, 2 dup(3A6ABE000000028h), 3A068A000000028h
|
||||||
|
.vmp1:00000001401D25D3 dq 3A3F52000000028h, 3A118E000000028h, 3A27BE000000028h
|
||||||
|
|
||||||
|
// .... many more ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
vm::handler::table_t handler_table(handler_table_ptr, _edit_entry);
|
||||||
|
|
||||||
|
// set all vm handler callbacks to just
|
||||||
|
// print the rolling decrypt key and handler idx...
|
||||||
|
for (auto idx = 0u; idx < 256; ++idx)
|
||||||
|
{
|
||||||
|
handler_table.set_callback(idx,
|
||||||
|
[](vm::registers* regs, u8 handler_idx) -> void
|
||||||
|
{
|
||||||
|
vmp2::entry_t entry;
|
||||||
|
entry.decrypt_key = regs->rbx;
|
||||||
|
entry.handler_idx = handler_idx;
|
||||||
|
entry.vip = regs->rsi;
|
||||||
|
|
||||||
|
memcpy(&entry.regs, ®s->r15, sizeof entry.regs);
|
||||||
|
memcpy(&entry.vregs, (void*)regs->rdi, sizeof entry.vregs);
|
||||||
|
|
||||||
|
for (auto idx = 0u; idx < sizeof(entry.vsp) / 8; ++idx)
|
||||||
|
entry.vsp.qword[idx] = reinterpret_cast<u64*>(regs->rbp)[idx];
|
||||||
|
|
||||||
|
traces.push_back(entry);
|
||||||
|
std::printf("> TID = %d, handler idx = %d, decryption key = 0x%p\n",
|
||||||
|
GetCurrentThreadId(), handler_idx, regs->rbx);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
vm::tracer_t tracer(
|
||||||
|
module_base,
|
||||||
|
image_base,
|
||||||
|
_decrypt_handler,
|
||||||
|
_encrypt_handler,
|
||||||
|
&handler_table
|
||||||
|
);
|
||||||
|
|
||||||
|
// change vm handler 0x55 (LCONSTBZX) to our implimentation of it...
|
||||||
|
auto _meta_data = handler_table.get_meta_data(0x55);
|
||||||
|
_meta_data.virt = reinterpret_cast<u64>(&__lconstbzx);
|
||||||
|
handler_table.set_meta_data(0x55, _meta_data);
|
||||||
|
|
||||||
|
std::ofstream vmp2_file(parser.get<std::string>("out"), std::ios::binary);
|
||||||
|
memcpy(&trace_header.magic, "VMP2", sizeof "VMP2" - 1);
|
||||||
|
trace_header.epoch_time = time(nullptr);
|
||||||
|
trace_header.entry_offset = sizeof trace_header;
|
||||||
|
trace_header.advancement = vmp2::exec_type_t::forward;
|
||||||
|
trace_header.version = vmp2::version_t::v1;
|
||||||
|
trace_header.module_base = module_base;
|
||||||
|
|
||||||
|
// patch vm handler table...
|
||||||
|
tracer.start();
|
||||||
|
|
||||||
|
// call entry point...
|
||||||
|
auto result = reinterpret_cast<int (*)()>(
|
||||||
|
NT_HEADER(module_base)->OptionalHeader.AddressOfEntryPoint + module_base)();
|
||||||
|
|
||||||
|
std::printf("result = %d\n", result);
|
||||||
|
|
||||||
|
// unpatch vm handler table...
|
||||||
|
tracer.stop();
|
||||||
|
|
||||||
|
// write vmp2 file to disk...
|
||||||
|
trace_header.entry_count = traces.size();
|
||||||
|
vmp2_file.write((char*)&trace_header, sizeof trace_header);
|
||||||
|
|
||||||
|
for (auto& trace : traces)
|
||||||
|
vmp2_file.write((char*)&trace, sizeof trace);
|
||||||
|
|
||||||
|
vmp2_file.close();
|
||||||
|
std::printf("> finished vm trace...\n");
|
||||||
|
std::getchar();
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{3f97516b-dc38-4c7f-857b-0b2d4e079208}</ProjectGuid>
|
||||||
|
<RootNamespace>vmtracer</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
<ProjectName>um-tracer</ProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>$(ProjectDir)..\libs\*;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="main.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="cli-parser.hpp" />
|
||||||
|
<ClInclude Include="vmp2.hpp" />
|
||||||
|
<ClInclude Include="vmtracer.hpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<MASM Include="lconstbzx.asm" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\vmptest\vmptest.vcxproj">
|
||||||
|
<Project>{f98aafdc-aa2d-4ac2-924a-9bc9895e34d5}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="main.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="vmtracer.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vmp2.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="cli-parser.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<MASM Include="lconstbzx.asm">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</MASM>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "vmtracer.hpp"
|
||||||
|
|
||||||
|
namespace vmp2
|
||||||
|
{
|
||||||
|
enum class exec_type_t
|
||||||
|
{
|
||||||
|
forward,
|
||||||
|
backward
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class version_t
|
||||||
|
{
|
||||||
|
invalid,
|
||||||
|
v1 = 0x101
|
||||||
|
};
|
||||||
|
|
||||||
|
struct file_header
|
||||||
|
{
|
||||||
|
u32 magic; // VMP2!
|
||||||
|
u64 epoch_time;
|
||||||
|
u64 module_base;
|
||||||
|
exec_type_t advancement;
|
||||||
|
version_t version;
|
||||||
|
|
||||||
|
u32 entry_count;
|
||||||
|
u32 entry_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct entry_t
|
||||||
|
{
|
||||||
|
u8 handler_idx;
|
||||||
|
u64 decrypt_key;
|
||||||
|
u64 vip;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u64 r15;
|
||||||
|
u64 r14;
|
||||||
|
u64 r13;
|
||||||
|
u64 r12;
|
||||||
|
u64 r11;
|
||||||
|
u64 r10;
|
||||||
|
u64 r9;
|
||||||
|
u64 r8;
|
||||||
|
u64 rbp;
|
||||||
|
u64 rdi;
|
||||||
|
u64 rsi;
|
||||||
|
u64 rdx;
|
||||||
|
u64 rcx;
|
||||||
|
u64 rbx;
|
||||||
|
u64 rax;
|
||||||
|
u64 rflags;
|
||||||
|
};
|
||||||
|
u64 raw[16];
|
||||||
|
} regs;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
u64 qword[0x28];
|
||||||
|
u8 raw[0x140];
|
||||||
|
} vregs;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
u64 qword[0x20];
|
||||||
|
u8 raw[0x100];
|
||||||
|
} vsp;
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,118 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
#include <xmmintrin.h>
|
||||||
|
|
||||||
|
using u8 = unsigned char;
|
||||||
|
using u16 = unsigned short;
|
||||||
|
using u32 = unsigned int;
|
||||||
|
using u64 = unsigned long long;
|
||||||
|
using u128 = __m128;
|
||||||
|
extern "C" void __vtrap(void);
|
||||||
|
|
||||||
|
namespace vm
|
||||||
|
{
|
||||||
|
typedef struct _registers
|
||||||
|
{
|
||||||
|
u128 xmm0;
|
||||||
|
u128 xmm1;
|
||||||
|
u128 xmm2;
|
||||||
|
u128 xmm3;
|
||||||
|
u128 xmm4;
|
||||||
|
u128 xmm5;
|
||||||
|
u128 xmm6;
|
||||||
|
u128 xmm7;
|
||||||
|
u128 xmm8;
|
||||||
|
u128 xmm9;
|
||||||
|
u128 xmm10;
|
||||||
|
u128 xmm11;
|
||||||
|
u128 xmm12;
|
||||||
|
u128 xmm13;
|
||||||
|
u128 xmm14;
|
||||||
|
u128 xmm15;
|
||||||
|
|
||||||
|
u64 gap0;
|
||||||
|
|
||||||
|
u64 r15;
|
||||||
|
u64 r14;
|
||||||
|
u64 r13;
|
||||||
|
u64 r12;
|
||||||
|
u64 r11;
|
||||||
|
u64 r10;
|
||||||
|
u64 r9;
|
||||||
|
u64 r8;
|
||||||
|
u64 rbp;
|
||||||
|
u64 rdi;
|
||||||
|
u64 rsi;
|
||||||
|
u64 rdx;
|
||||||
|
u64 rcx;
|
||||||
|
u64 rbx;
|
||||||
|
u64 rax;
|
||||||
|
u64 rflags;
|
||||||
|
u64 vm_handler;
|
||||||
|
} registers, * pregisters;
|
||||||
|
|
||||||
|
using decrypt_handler_t = u64(*)(u64);
|
||||||
|
using encrypt_handler_t = u64(*)(u64);
|
||||||
|
|
||||||
|
namespace handler
|
||||||
|
{
|
||||||
|
// these lambdas handle page protections...
|
||||||
|
using edit_entry_t = void (*)(u64*, u64);
|
||||||
|
using entry_callback_t = void (*)(vm::registers* regs, u8 handler_idx);
|
||||||
|
|
||||||
|
struct entry_t
|
||||||
|
{
|
||||||
|
u64 virt;
|
||||||
|
u64 encrypted;
|
||||||
|
u64 decrypted;
|
||||||
|
entry_callback_t callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
class table_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit table_t(u64* table_addr, edit_entry_t edit_entry);
|
||||||
|
u64 get_entry(u8 idx) const;
|
||||||
|
entry_t get_meta_data(u8 idx) const;
|
||||||
|
|
||||||
|
void set_entry(u8 idx, u64 entry);
|
||||||
|
void set_meta_data(u8 idx, const entry_t& entry);
|
||||||
|
void set_callback(u8 idx, entry_callback_t callback);
|
||||||
|
private:
|
||||||
|
u64* table_addr;
|
||||||
|
edit_entry_t edit_entry;
|
||||||
|
entry_t handlers[256];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class tracer_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit tracer_t(
|
||||||
|
u64 module_base,
|
||||||
|
u64 image_base,
|
||||||
|
decrypt_handler_t decrypt_handler,
|
||||||
|
encrypt_handler_t encrypt_handler,
|
||||||
|
vm::handler::table_t* vm_handler_table
|
||||||
|
);
|
||||||
|
|
||||||
|
u64 encrypt(u64 val) const;
|
||||||
|
u64 decrypt(u64 val) const;
|
||||||
|
void set_trap(u64 val) const;
|
||||||
|
|
||||||
|
void start() const;
|
||||||
|
void stop() const;
|
||||||
|
|
||||||
|
vm::handler::table_t* handler_table;
|
||||||
|
private:
|
||||||
|
const u64 module_base, image_base;
|
||||||
|
u64 vtrap_encrypted;
|
||||||
|
|
||||||
|
const decrypt_handler_t decrypt_handler;
|
||||||
|
const encrypt_handler_t encrypt_handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::tracer_t* g_vmctx = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void vtrap_wrapper(vm::registers * regs, u8 handler_idx);
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,17 @@
|
|||||||
|
#include <intrin.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include "ia32.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
/*cpuid_eax_01 cpuid_info;
|
||||||
|
__cpuid((int*)&cpuid_info, 1);
|
||||||
|
|
||||||
|
if (cpuid_info.cpuid_feature_information_ecx.avx_support)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;*/
|
||||||
|
|
||||||
|
MessageBoxA(NULL, "Hello World", "Hello World", NULL);
|
||||||
|
}
|
@ -0,0 +1,162 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{f98aafdc-aa2d-4ac2-924a-9bc9895e34d5}</ProjectGuid>
|
||||||
|
<RootNamespace>vmptest</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<ExceptionHandling>false</ExceptionHandling>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
<ControlFlowGuard>false</ControlFlowGuard>
|
||||||
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EntryPointSymbol>main</EntryPointSymbol>
|
||||||
|
<GenerateMapFile>true</GenerateMapFile>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<ExceptionHandling>false</ExceptionHandling>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
<ControlFlowGuard>false</ControlFlowGuard>
|
||||||
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EntryPointSymbol>main</EntryPointSymbol>
|
||||||
|
<GenerateMapFile>true</GenerateMapFile>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="main.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="ia32.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="ia32.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="main.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
Loading…
Reference in new issue