Browse Source

added source code

multi-vm
_xeroxz 1 year ago
parent
commit
2130f86ea8
  1. 388
      .gitignore
  2. 72
      include/vmp2.hpp
  3. 118
      include/vmtracer.hpp
  4. 154
      src/main.cpp
  5. 72
      src/vmp2.hpp
  6. 114
      src/vmtracer.cpp
  7. 118
      src/vmtracer.hpp
  8. 160
      src/vmtracer.vcxproj
  9. 31
      src/vmtracer.vcxproj.filters
  10. 87
      src/vtrap.asm
  11. 31
      vmtracer.sln

388
.gitignore vendored

@ -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

72
include/vmp2.hpp

@ -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;
};
}

118
include/vmtracer.hpp

@ -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);

154
src/main.cpp

@ -0,0 +1,154 @@
#include <iostream>
#include <Windows.h>
#include <fstream>
#include <filesystem>
#include "vmtracer.hpp"
#include "vmp2.hpp"
#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, char** argv)
{
/*
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 handler_table_rva = std::strtoull(argv[3], nullptr, 16);
const auto image_base = std::strtoull(argv[2], nullptr, 16);
const auto module_base =
reinterpret_cast<std::uintptr_t>(
LoadLibraryExA(argv[1], NULL, DONT_RESOLVE_DLL_REFERENCES));
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;
entry.regs = *reinterpret_cast<decltype(&entry.regs)>(&regs->r15);
entry.vregs = *reinterpret_cast<decltype(&entry.vregs)>(regs->rdi);
// stack grows down... so we gotta load the values in reverse...
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
);
std::ofstream vmp2_file("output.vmp2", 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...
reinterpret_cast<void (*)()>(
NT_HEADER(module_base)->OptionalHeader.AddressOfEntryPoint + module_base)();
// 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();
}

72
src/vmp2.hpp

@ -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;
};
}

114
src/vmtracer.cpp

@ -0,0 +1,114 @@
#include "vmtracer.hpp"
namespace vm
{
namespace handler
{
table_t::table_t(u64* table_addr, edit_entry_t edit_entry)
:
table_addr(table_addr),
edit_entry(edit_entry)
{}
u64 table_t::get_entry(u8 idx) const
{
return table_addr[idx];
}
entry_t table_t::get_meta_data(u8 idx) const
{
return handlers[idx];
}
void table_t::set_entry(u8 idx, u64 entry)
{
edit_entry(table_addr + idx, entry);
}
void table_t::set_meta_data(u8 idx, const entry_t& entry)
{
handlers[idx] = entry;
}
void table_t::set_callback(u8 idx, entry_callback_t callback)
{
handlers[idx].callback = callback;
}
}
tracer_t::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
)
:
decrypt_handler(decrypt_handler),
encrypt_handler(encrypt_handler),
handler_table(vm_handler_table),
module_base(module_base),
image_base(image_base)
{
for (auto idx = 0u; idx < 256; ++idx)
{
vm::handler::entry_t entry =
vm_handler_table->get_meta_data(idx);
entry.encrypted = vm_handler_table->get_entry(idx);
entry.decrypted = decrypt(entry.encrypted);
entry.virt = (entry.decrypted - image_base) + module_base;
vm_handler_table->set_meta_data(idx, entry);
}
vm::g_vmctx = this;
vtrap_encrypted = encrypt(
(reinterpret_cast<std::uintptr_t>(
&__vtrap) - module_base) + image_base);
}
u64 tracer_t::encrypt(u64 val) const
{
return encrypt_handler(val);
}
u64 tracer_t::decrypt(u64 val) const
{
return decrypt_handler(val);
}
void tracer_t::set_trap(u64 val) const
{
for (auto idx = 0u; idx < 256; ++idx)
handler_table->set_entry(idx, val);
}
void tracer_t::start() const
{
for (auto idx = 0u; idx < 256; ++idx)
handler_table->set_entry(idx, vtrap_encrypted);
}
void tracer_t::stop() const
{
for (auto idx = 0u; idx < 256; ++idx)
{
const auto handler_entry =
handler_table->get_meta_data(idx).encrypted;
handler_table->set_entry(idx, handler_entry);
}
}
}
void vtrap_wrapper(vm::registers* regs, u8 handler_idx)
{
regs->vm_handler = vm::g_vmctx->
handler_table->get_meta_data(handler_idx).virt;
const auto callback = vm::g_vmctx->
handler_table->get_meta_data(handler_idx).callback;
// per-virtual instruction callbacks...
if (callback) callback(regs, handler_idx);
}

118
src/vmtracer.hpp

@ -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);

160
src/vmtracer.vcxproj

@ -0,0 +1,160 @@
<?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>{D257C9F6-C705-49D5-84ED-64C9C513C419}</ProjectGuid>
<RootNamespace>vmtracer</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>vmtracer</ProjectName>
</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>StaticLibrary</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)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="vmtracer.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="vmp2.hpp" />
<ClInclude Include="vmtracer.hpp" />
</ItemGroup>
<ItemGroup>
<MASM Include="vtrap.asm">
<FileType>Document</FileType>
</MASM>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
</ImportGroup>
</Project>

31
src/vmtracer.vcxproj.filters

@ -0,0 +1,31 @@
<?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="vmtracer.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>
</ItemGroup>
<ItemGroup>
<MASM Include="vtrap.asm">
<Filter>Source Files</Filter>
</MASM>
</ItemGroup>
</Project>

87
src/vtrap.asm

@ -0,0 +1,87 @@
extern vtrap_wrapper : proc
.code
__vtrap proc
sub rsp, 8 ; make room for return address...
pushfq
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
sub rsp, 0108h ; 16 xmm registers...
movaps [rsp], xmm0
movaps [rsp + 010h], xmm1
movaps [rsp + 020h], xmm2
movaps [rsp + 030h], xmm3
movaps [rsp + 040h], xmm4
movaps [rsp + 050h], xmm5
movaps [rsp + 060h], xmm6
movaps [rsp + 070h], xmm7
movaps [rsp + 080h], xmm8
movaps [rsp + 090h], xmm9
movaps [rsp + 0A0h], xmm10
movaps [rsp + 0B0h], xmm11
movaps [rsp + 0C0h], xmm12
movaps [rsp + 0D0h], xmm13
movaps [rsp + 0E0h], xmm14
movaps [rsp + 0F0h], xmm15
; vm::registers* regs
; u8 handler_idx
mov rcx, rsp
mov rdx, rax
sub rsp, 20h
call vtrap_wrapper
add rsp, 20h
movups xmm0, [rsp]
movups xmm1, [rsp + 010h]
movups xmm2, [rsp + 020h]
movups xmm3, [rsp + 030h]
movups xmm4, [rsp + 040h]
movups xmm5, [rsp + 050h]
movups xmm6, [rsp + 060h]
movups xmm7, [rsp + 070h]
movups xmm8, [rsp + 080h]
movups xmm9, [rsp + 090h]
movups xmm10, [rsp + 0A0h]
movups xmm11, [rsp + 0B0h]
movups xmm12, [rsp + 0C0h]
movups xmm13, [rsp + 0D0h]
movups xmm14, [rsp + 0E0h]
movups xmm15, [rsp + 0F0h]
add rsp, 0108h ; 16 xmm registers...
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
popfq
; note that the original VM handler will be on the stack here...
ret
__vtrap endp
end

31
vmtracer.sln

@ -0,0 +1,31 @@

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}") = "vmtracer", "src\vmtracer.vcxproj", "{D257C9F6-C705-49D5-84ED-64C9C513C419}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D257C9F6-C705-49D5-84ED-64C9C513C419}.Debug|x64.ActiveCfg = Debug|x64
{D257C9F6-C705-49D5-84ED-64C9C513C419}.Debug|x64.Build.0 = Debug|x64
{D257C9F6-C705-49D5-84ED-64C9C513C419}.Debug|x86.ActiveCfg = Debug|Win32
{D257C9F6-C705-49D5-84ED-64C9C513C419}.Debug|x86.Build.0 = Debug|Win32
{D257C9F6-C705-49D5-84ED-64C9C513C419}.Release|x64.ActiveCfg = Release|x64
{D257C9F6-C705-49D5-84ED-64C9C513C419}.Release|x64.Build.0 = Release|x64
{D257C9F6-C705-49D5-84ED-64C9C513C419}.Release|x86.ActiveCfg = Release|Win32
{D257C9F6-C705-49D5-84ED-64C9C513C419}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CC700881-2AAD-4B71-BC5B-4870C480C75E}
EndGlobalSection
EndGlobal
Loading…
Cancel
Save