diff --git a/.gitignore b/.gitignore
index 56ba727..b4a2b87 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,2 @@
/.vs
-*.ilk
-*.iobj
-*.ipdb
*pycache*
-/files/vmm_example.exe
-/files/lib
-/files/temp
diff --git a/MemProcFS-plugins.sln b/MemProcFS-plugins.sln
new file mode 100644
index 0000000..e051bf8
--- /dev/null
+++ b/MemProcFS-plugins.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28307.489
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "py-pypykatz", "py-pypykatz", "{93BE03F6-8DCA-4149-8E50-47329420A693}"
+ ProjectSection(SolutionItems) = preProject
+ files\plugins\pym_pypykatz\__init__.py = files\plugins\pym_pypykatz\__init__.py
+ files\plugins\pym_pypykatz\pym_pypykatz.py = files\plugins\pym_pypykatz\pym_pypykatz.py
+ files\plugins\pym_pypykatz\pypyreader.py = files\plugins\pym_pypykatz\pypyreader.py
+ files\plugins\pym_pypykatz\sysinfo_helpers.py = files\plugins\pym_pypykatz\sysinfo_helpers.py
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9E009C89-6E32-4879-825C-77FB3407EE4D}"
+ ProjectSection(SolutionItems) = preProject
+ README.md = README.md
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {F06B8B58-971D-4603-AC0F-4A055FBA612C}
+ EndGlobalSection
+EndGlobal
diff --git a/MemProcFS.sln b/MemProcFS.sln
deleted file mode 100644
index a53596c..0000000
--- a/MemProcFS.sln
+++ /dev/null
@@ -1,111 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27703.2026
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MemProcFS", "MemProcFS\MemProcFS.vcxproj", "{A9CE6DD1-A834-4FFD-A4C2-50D9D2F14BFD}"
- ProjectSection(ProjectDependencies) = postProject
- {6326FCE0-1BA5-4AEC-9973-7783309FFD6B} = {6326FCE0-1BA5-4AEC-9973-7783309FFD6B}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmm", "vmm\vmm.vcxproj", "{6326FCE0-1BA5-4AEC-9973-7783309FFD6B}"
- ProjectSection(ProjectDependencies) = postProject
- {3476ABD2-5DEA-43E6-A676-8BE25F74535A} = {3476ABD2-5DEA-43E6-A676-8BE25F74535A}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "m_vmemd", "m_vmemd\m_vmemd.vcxproj", "{BC6D11FF-3B1E-480E-A1AB-AAE5868FE9B3}"
- ProjectSection(ProjectDependencies) = postProject
- {6326FCE0-1BA5-4AEC-9973-7783309FFD6B} = {6326FCE0-1BA5-4AEC-9973-7783309FFD6B}
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "python", "python", "{50E46B01-0786-4222-B8C8-8D1612DA8A3B}"
- ProjectSection(SolutionItems) = preProject
- files\vmmpy.py = files\vmmpy.py
- files\vmmpy_example.py = files\vmmpy_example.py
- files\vmmpyplugin.py = files\vmmpyplugin.py
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmmpyc", "vmmpyc\vmmpyc.vcxproj", "{9E47796D-B834-470E-B437-0754BC14DF09}"
- ProjectSection(ProjectDependencies) = postProject
- {6326FCE0-1BA5-4AEC-9973-7783309FFD6B} = {6326FCE0-1BA5-4AEC-9973-7783309FFD6B}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmmpycplugin", "vmmpycplugin\vmmpycplugin.vcxproj", "{283FF01B-31A6-465A-A728-F187F974EFF4}"
- ProjectSection(ProjectDependencies) = postProject
- {6326FCE0-1BA5-4AEC-9973-7783309FFD6B} = {6326FCE0-1BA5-4AEC-9973-7783309FFD6B}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmm_example", "vmm_example\vmm_example.vcxproj", "{45CC506E-E97A-45B8-8050-B2C5BC8A4B15}"
- ProjectSection(ProjectDependencies) = postProject
- {6326FCE0-1BA5-4AEC-9973-7783309FFD6B} = {6326FCE0-1BA5-4AEC-9973-7783309FFD6B}
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugins.pym_procstruct", "plugins.pym_procstruct", "{7BEEEE90-F2CC-4ADD-BA8B-82599E3D1408}"
- ProjectSection(SolutionItems) = preProject
- files\plugins\pym_procstruct\__init__.py = files\plugins\pym_procstruct\__init__.py
- files\plugins\pym_procstruct\pym_procstruct.py = files\plugins\pym_procstruct\pym_procstruct.py
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dissect.cstruct", "dissect.cstruct", "{A8B68178-FE06-42E2-80C9-2C936973B5FA}"
- ProjectSection(SolutionItems) = preProject
- files\dissect\cstruct\__init__.py = files\dissect\cstruct\__init__.py
- files\dissect\cstruct\cstruct.py = files\dissect\cstruct\cstruct.py
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "leechcore", "..\LeechCore\leechcore\leechcore.vcxproj", "{3476ABD2-5DEA-43E6-A676-8BE25F74535A}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "leechsvc", "..\LeechCore\leechsvc\leechsvc.vcxproj", "{4FAF78C0-D61B-41CE-830E-62C38DACDD52}"
- ProjectSection(ProjectDependencies) = postProject
- {3476ABD2-5DEA-43E6-A676-8BE25F74535A} = {3476ABD2-5DEA-43E6-A676-8BE25F74535A}
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|x64 = Debug|x64
- Release|x64 = Release|x64
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {A9CE6DD1-A834-4FFD-A4C2-50D9D2F14BFD}.Debug|x64.ActiveCfg = Debug|x64
- {A9CE6DD1-A834-4FFD-A4C2-50D9D2F14BFD}.Debug|x64.Build.0 = Debug|x64
- {A9CE6DD1-A834-4FFD-A4C2-50D9D2F14BFD}.Release|x64.ActiveCfg = Release|x64
- {A9CE6DD1-A834-4FFD-A4C2-50D9D2F14BFD}.Release|x64.Build.0 = Release|x64
- {6326FCE0-1BA5-4AEC-9973-7783309FFD6B}.Debug|x64.ActiveCfg = Debug|x64
- {6326FCE0-1BA5-4AEC-9973-7783309FFD6B}.Debug|x64.Build.0 = Debug|x64
- {6326FCE0-1BA5-4AEC-9973-7783309FFD6B}.Release|x64.ActiveCfg = Release|x64
- {6326FCE0-1BA5-4AEC-9973-7783309FFD6B}.Release|x64.Build.0 = Release|x64
- {BC6D11FF-3B1E-480E-A1AB-AAE5868FE9B3}.Debug|x64.ActiveCfg = Debug|x64
- {BC6D11FF-3B1E-480E-A1AB-AAE5868FE9B3}.Debug|x64.Build.0 = Debug|x64
- {BC6D11FF-3B1E-480E-A1AB-AAE5868FE9B3}.Release|x64.ActiveCfg = Release|x64
- {BC6D11FF-3B1E-480E-A1AB-AAE5868FE9B3}.Release|x64.Build.0 = Release|x64
- {9E47796D-B834-470E-B437-0754BC14DF09}.Debug|x64.ActiveCfg = Debug|x64
- {9E47796D-B834-470E-B437-0754BC14DF09}.Debug|x64.Build.0 = Debug|x64
- {9E47796D-B834-470E-B437-0754BC14DF09}.Release|x64.ActiveCfg = Release|x64
- {9E47796D-B834-470E-B437-0754BC14DF09}.Release|x64.Build.0 = Release|x64
- {283FF01B-31A6-465A-A728-F187F974EFF4}.Debug|x64.ActiveCfg = Debug|x64
- {283FF01B-31A6-465A-A728-F187F974EFF4}.Debug|x64.Build.0 = Debug|x64
- {283FF01B-31A6-465A-A728-F187F974EFF4}.Release|x64.ActiveCfg = Release|x64
- {283FF01B-31A6-465A-A728-F187F974EFF4}.Release|x64.Build.0 = Release|x64
- {45CC506E-E97A-45B8-8050-B2C5BC8A4B15}.Debug|x64.ActiveCfg = Debug|x64
- {45CC506E-E97A-45B8-8050-B2C5BC8A4B15}.Debug|x64.Build.0 = Debug|x64
- {45CC506E-E97A-45B8-8050-B2C5BC8A4B15}.Release|x64.ActiveCfg = Release|x64
- {45CC506E-E97A-45B8-8050-B2C5BC8A4B15}.Release|x64.Build.0 = Release|x64
- {3476ABD2-5DEA-43E6-A676-8BE25F74535A}.Debug|x64.ActiveCfg = Debug|x64
- {3476ABD2-5DEA-43E6-A676-8BE25F74535A}.Debug|x64.Build.0 = Debug|x64
- {3476ABD2-5DEA-43E6-A676-8BE25F74535A}.Release|x64.ActiveCfg = Release|x64
- {3476ABD2-5DEA-43E6-A676-8BE25F74535A}.Release|x64.Build.0 = Release|x64
- {4FAF78C0-D61B-41CE-830E-62C38DACDD52}.Debug|x64.ActiveCfg = Debug|x64
- {4FAF78C0-D61B-41CE-830E-62C38DACDD52}.Debug|x64.Build.0 = Debug|x64
- {4FAF78C0-D61B-41CE-830E-62C38DACDD52}.Release|x64.ActiveCfg = Release|x64
- {4FAF78C0-D61B-41CE-830E-62C38DACDD52}.Release|x64.Build.0 = Release|x64
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {7BEEEE90-F2CC-4ADD-BA8B-82599E3D1408} = {50E46B01-0786-4222-B8C8-8D1612DA8A3B}
- {A8B68178-FE06-42E2-80C9-2C936973B5FA} = {50E46B01-0786-4222-B8C8-8D1612DA8A3B}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {CE6C3AA7-477A-4329-B4E3-5F219ACF4063}
- EndGlobalSection
-EndGlobal
diff --git a/MemProcFS/MemProcFS.rc b/MemProcFS/MemProcFS.rc
deleted file mode 100644
index c26a624..0000000
Binary files a/MemProcFS/MemProcFS.rc and /dev/null differ
diff --git a/MemProcFS/MemProcFS.vcxproj b/MemProcFS/MemProcFS.vcxproj
deleted file mode 100644
index 87cd77c..0000000
--- a/MemProcFS/MemProcFS.vcxproj
+++ /dev/null
@@ -1,126 +0,0 @@
-
-
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- 15.0
- {A9CE6DD1-A834-4FFD-A4C2-50D9D2F14BFD}
- MemProcFS
- 10.0.17763.0
-
-
-
- Application
- true
- v141
- Unicode
- false
-
-
- Application
- false
- v141
- true
- Unicode
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(SolutionDir)\files\
- $(SolutionDir)\files\temp\$(ProjectName)\
-
-
- $(SolutionDir)\files\
- $(SolutionDir)\files\temp\$(ProjectName)\
-
-
-
- Level3
- Disabled
- true
- CompileAsC
- false
-
-
-
-
-
-
-
-
-
- $(OutDir)\lib\$(TargetName).pdb
-
-
- copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y
-copy $(SolutionDir)\files\vmmdll.h $(ProjectDir)\ /y
-
-
-
-
- Level3
- MaxSpeed
- true
- true
- true
- CompileAsC
- MultiThreadedDLL
- false
-
-
-
-
-
- true
- true
- $(OutDir)\lib\$(TargetName).pdb
- UseLinkTimeCodeGeneration
-
-
-
-
-
-
- copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y
-copy $(SolutionDir)\files\vmmdll.h $(ProjectDir)\ /y
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/MemProcFS/MemProcFS.vcxproj.filters b/MemProcFS/MemProcFS.vcxproj.filters
deleted file mode 100644
index 35c8ac2..0000000
--- a/MemProcFS/MemProcFS.vcxproj.filters
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
- {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
-
-
- {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
- rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
-
-
- {3df63be8-ffcd-417a-a1f9-c8d774863692}
-
-
- {ef93cbf4-5326-46d3-a5e0-6fb6d61d08f0}
-
-
- {5c8e3ce6-1d2e-46ff-b5a6-a928f4c1569f}
-
-
-
-
- Source Files
-
-
- Source Files
-
-
-
-
- Header Files
-
-
- Header Files\dokan
-
-
- Header Files\dokan
-
-
- Header Files\dokan
-
-
- Header Files\vmm
-
-
- Header Files\leechcore
-
-
- Header Files
-
-
-
-
- Resource Files
-
-
-
\ No newline at end of file
diff --git a/MemProcFS/MemProcFS.vcxproj.user b/MemProcFS/MemProcFS.vcxproj.user
deleted file mode 100644
index fa6ed15..0000000
--- a/MemProcFS/MemProcFS.vcxproj.user
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
- WindowsLocalDebugger
-
-
- WindowsLocalDebugger
-
-
\ No newline at end of file
diff --git a/MemProcFS/dokan.h b/MemProcFS/dokan.h
deleted file mode 100644
index 7dccaa1..0000000
--- a/MemProcFS/dokan.h
+++ /dev/null
@@ -1,865 +0,0 @@
-/*
- Dokan : user-mode file system library for Windows
-
- Copyright (C) 2015 - 2018 Adrien J. and Maxime C.
- Copyright (C) 2007 - 2011 Hiroki Asakawa
-
- http://dokan-dev.github.io
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU Lesser General Public License as published by the Free
-Software Foundation; either version 3 of the License, or (at your option) any
-later version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program. If not, see .
-*/
-
-#ifndef DOKAN_H_
-#define DOKAN_H_
-
-/** Do not include NTSTATUS. Fix duplicate preprocessor definitions */
-#define WIN32_NO_STATUS
-#include
-#undef WIN32_NO_STATUS
-#include
-
-#include "fileinfo.h"
-#include "public.h"
-
-#ifdef _EXPORTING
-/** Export dokan API see also dokan.def for export */
-#define DOKANAPI __stdcall
-#else
-/** Import dokan API */
-#define DOKANAPI __declspec(dllimport) __stdcall
-#endif
-
-/** Change calling convention to standard call */
-#define DOKAN_CALLBACK __stdcall
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** @file */
-
-/**
- * \defgroup Dokan Dokan
- * \brief Dokan Library const and methods
- */
-/** @{ */
-
-/** The current Dokan version (ver 1.2.0). \ref DOKAN_OPTIONS.Version */
-#define DOKAN_VERSION 121
-/** Minimum Dokan version (ver 1.1.0) accepted. */
-#define DOKAN_MINIMUM_COMPATIBLE_VERSION 110
-/** Maximum number of dokan instances.*/
-#define DOKAN_MAX_INSTANCES 32
-/** Driver file name including the DOKAN_MAJOR_API_VERSION */
-#define DOKAN_DRIVER_NAME L"dokan" DOKAN_MAJOR_API_VERSION L".sys"
-/** Network provider name including the DOKAN_MAJOR_API_VERSION */
-#define DOKAN_NP_NAME L"Dokan" DOKAN_MAJOR_API_VERSION
-
-/** @} */
-
-/**
- * \defgroup DOKAN_OPTION DOKAN_OPTION
- * \brief All DOKAN_OPTION flags used in DOKAN_OPTIONS.Options
- * \see DOKAN_FILE_INFO
- */
-/** @{ */
-
-/** Enable ouput debug message */
-#define DOKAN_OPTION_DEBUG 1
-/** Enable ouput debug message to stderr */
-#define DOKAN_OPTION_STDERR 2
-/** Use alternate stream */
-#define DOKAN_OPTION_ALT_STREAM 4
-/** Enable mount drive as write-protected */
-#define DOKAN_OPTION_WRITE_PROTECT 8
-/** Use network drive - Dokan network provider needs to be installed */
-#define DOKAN_OPTION_NETWORK 16
-/** Use removable drive */
-#define DOKAN_OPTION_REMOVABLE 32
-/** Use mount manager */
-#define DOKAN_OPTION_MOUNT_MANAGER 64
-/** Mount the drive on current session only */
-#define DOKAN_OPTION_CURRENT_SESSION 128
-/** Enable Lockfile/Unlockfile operations. Otherwise Dokan will take care of it */
-#define DOKAN_OPTION_FILELOCK_USER_MODE 256
-
-/** @} */
-
-/**
- * \struct DOKAN_OPTIONS
- * \brief Dokan mount options used to describe Dokan device behavior.
- * \see DokanMain
- */
-typedef struct _DOKAN_OPTIONS {
- /** Version of the Dokan features requested without dots (version "123" is equal to Dokan version 1.2.3). */
- USHORT Version;
- /** Number of threads to be used by Dokan library internally. More threads will handle more events at the same time. */
- USHORT ThreadCount;
- /** Features enabled for the mount. See \ref DOKAN_OPTION. */
- ULONG Options;
- /** FileSystem can store anything here. */
- ULONG64 GlobalContext;
- /** Mount point. It can be a driver letter like "M:\" or a folder path "C:\mount\dokan" on a NTFS partition. */
- LPCWSTR MountPoint;
- /**
- * UNC Name for the Network Redirector
- * \see Support for UNC Naming
- */
- LPCWSTR UNCName;
- /** Max timeout in milliseconds of each request before Dokan gives up to wait events to complete. */
- ULONG Timeout;
- /** Allocation Unit Size of the volume. This will affect the file size. */
- ULONG AllocationUnitSize;
- /** Sector Size of the volume. This will affect the file size. */
- ULONG SectorSize;
-} DOKAN_OPTIONS, *PDOKAN_OPTIONS;
-
-/**
- * \struct DOKAN_FILE_INFO
- * \brief Dokan file information on the current operation.
- */
-typedef struct _DOKAN_FILE_INFO {
- /**
- * Context that can be used to carry information between operations.
- * The context can carry whatever type like \c HANDLE, struct, int,
- * internal reference that will help the implementation understand the request context of the event.
- */
- ULONG64 Context;
- /** Reserved. Used internally by Dokan library. Never modify. */
- ULONG64 DokanContext;
- /** A pointer to DOKAN_OPTIONS which was passed to DokanMain. */
- PDOKAN_OPTIONS DokanOptions;
- /**
- * Process ID for the thread that originally requested a given I/O operation.
- */
- ULONG ProcessId;
- /**
- * Requesting a directory file.
- * Must be set in \ref DOKAN_OPERATIONS.ZwCreateFile if the file appears to be a folder.
- */
- UCHAR IsDirectory;
- /** Flag if the file has to be deleted during DOKAN_OPERATIONS. Cleanup event. */
- UCHAR DeleteOnClose;
- /** Read or write is paging IO. */
- UCHAR PagingIo;
- /** Read or write is synchronous IO. */
- UCHAR SynchronousIo;
- /** Read or write directly from data source without cache */
- UCHAR Nocache;
- /** If \c TRUE, write to the current end of file instead of using the Offset parameter. */
- UCHAR WriteToEndOfFile;
-} DOKAN_FILE_INFO, *PDOKAN_FILE_INFO;
-
-/**
- * \brief FillFindData Used to add an entry in FindFiles operation
- * \return 1 if buffer is full, otherwise 0 (currently it never returns 1)
- */
-typedef int(WINAPI *PFillFindData)(PWIN32_FIND_DATAW, PDOKAN_FILE_INFO);
-
-/**
- * \brief FillFindStreamData Used to add an entry in FindStreams
- * \return 1 if buffer is full, otherwise 0 (currently it never returns 1)
- */
-typedef int(WINAPI *PFillFindStreamData)(PWIN32_FIND_STREAM_DATA,
- PDOKAN_FILE_INFO);
-
-// clang-format off
-
-/**
- * \struct DOKAN_OPERATIONS
- * \brief Dokan API callbacks interface
- *
- * DOKAN_OPERATIONS is a struct of callbacks that describe all Dokan API operations
- * that will be called when Windows access to the filesystem.
- *
- * If an error occurs, return NTSTATUS (https://support.microsoft.com/en-us/kb/113996).
- * Win32 Error can be converted to \c NTSTATUS with \ref DokanNtStatusFromWin32
- *
- * All callbacks can be set to \c NULL or return \c STATUS_NOT_IMPLEMENTED
- * if supporting one of them is not desired. Be aware that returning such values to important callbacks
- * such as DOKAN_OPERATIONS.ZwCreateFile / DOKAN_OPERATIONS.ReadFile / ... would make the filesystem not work or become unstable.
- */
-typedef struct _DOKAN_OPERATIONS {
- /**
- * \brief CreateFile Dokan API callback
- *
- * CreateFile is called each time a request is made on a file system object.
- *
- * In case \c OPEN_ALWAYS & \c CREATE_ALWAYS are successfully opening an
- * existing file, \c STATUS_OBJECT_NAME_COLLISION should be returned instead of \c STATUS_SUCCESS .
- * This will inform Dokan that the file has been opened and not created during the request.
- *
- * If the file is a directory, CreateFile is also called.
- * In this case, CreateFile should return \c STATUS_SUCCESS when that directory
- * can be opened and DOKAN_FILE_INFO.IsDirectory has to be set to \c TRUE.
- * On the other hand, if DOKAN_FILE_INFO.IsDirectory is set to \c TRUE
- * but the path targets a file, \c STATUS_NOT_A_DIRECTORY must be returned.
- *
- * DOKAN_FILE_INFO.Context can be used to store Data (like \c HANDLE)
- * that can be retrieved in all other requests related to the Context.
- * To avoid memory leak, Context needs to be released in DOKAN_OPERATIONS.Cleanup.
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param SecurityContext SecurityContext, see https://msdn.microsoft.com/en-us/library/windows/hardware/ff550613(v=vs.85).aspx
- * \param DesiredAccess Specifies an ACCESS_MASK value that determines the requested access to the object.
- * \param FileAttributes Specifies one or more FILE_ATTRIBUTE_XXX flags, which represent the file attributes to set if a file is created or overwritten.
- * \param ShareAccess Type of share access, which is specified as zero or any combination of FILE_SHARE_* flags.
- * \param CreateDisposition Specifies the action to perform if the file does or does not exist.
- * \param CreateOptions Specifies the options to apply when the driver creates or opens the file.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- * \see See ZwCreateFile for more information about the parameters of this callback (MSDN).
- * \see DokanMapKernelToUserCreateFileFlags
- */
- NTSTATUS(DOKAN_CALLBACK *ZwCreateFile)(LPCWSTR FileName,
- PDOKAN_IO_SECURITY_CONTEXT SecurityContext,
- ACCESS_MASK DesiredAccess,
- ULONG FileAttributes,
- ULONG ShareAccess,
- ULONG CreateDisposition,
- ULONG CreateOptions,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief Cleanup Dokan API callback
- *
- * Cleanup request before \ref CloseFile is called.
- *
- * When DOKAN_FILE_INFO.DeleteOnClose is \c TRUE, the file in Cleanup must be deleted.
- * See DeleteFile documentation for explanation.
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param DokanFileInfo Information about the file or directory.
- * \see DeleteFile
- * \see DeleteDirectory
- */
- void(DOKAN_CALLBACK *Cleanup)(LPCWSTR FileName,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief CloseFile Dokan API callback
- *
- * Clean remaining Context
- *
- * CloseFile is called at the end of the life of the context.
- * Anything remaining in \ref DOKAN_FILE_INFO.Context must be cleared before returning.
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param DokanFileInfo Information about the file or directory.
- */
- void(DOKAN_CALLBACK *CloseFile)(LPCWSTR FileName,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief ReadFile Dokan API callback
- *
- * ReadFile callback on the file previously opened in DOKAN_OPERATIONS.ZwCreateFile.
- * It can be called by different threads at the same time, so the read/context has to be thread safe.
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param Buffer Read buffer that has to be filled with the read result.
- * \param BufferLength Buffer length and read size to continue with.
- * \param ReadLength Total data size that has been read.
- * \param Offset Offset from where the read has to be continued.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- * \see WriteFile
- */
- NTSTATUS(DOKAN_CALLBACK *ReadFile)(LPCWSTR FileName,
- LPVOID Buffer,
- DWORD BufferLength,
- LPDWORD ReadLength,
- LONGLONG Offset,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief WriteFile Dokan API callback
- *
- * WriteFile callback on the file previously opened in DOKAN_OPERATIONS.ZwCreateFile
- * It can be called by different threads at the same time, sp the write/context has to be thread safe.
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param Buffer Data that has to be written.
- * \param NumberOfBytesToWrite Buffer length and write size to continue with.
- * \param NumberOfBytesWritten Total number of bytes that have been written.
- * \param Offset Offset from where the write has to be continued.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- * \see ReadFile
- */
- NTSTATUS(DOKAN_CALLBACK *WriteFile)(LPCWSTR FileName,
- LPCVOID Buffer,
- DWORD NumberOfBytesToWrite,
- LPDWORD NumberOfBytesWritten,
- LONGLONG Offset,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief FlushFileBuffers Dokan API callback
- *
- * Clears buffers for this context and causes any buffered data to be written to the file.
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- */
- NTSTATUS(DOKAN_CALLBACK *FlushFileBuffers)(LPCWSTR FileName,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief GetFileInformation Dokan API callback
- *
- * Get specific information on a file.
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param Buffer BY_HANDLE_FILE_INFORMATION struct to fill.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- */
- NTSTATUS(DOKAN_CALLBACK *GetFileInformation)(LPCWSTR FileName,
- LPBY_HANDLE_FILE_INFORMATION Buffer,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief FindFiles Dokan API callback
- *
- * List all files in the requested path
- * \ref DOKAN_OPERATIONS.FindFilesWithPattern is checked first. If it is not implemented or
- * returns \c STATUS_NOT_IMPLEMENTED, then FindFiles is called, if implemented.
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param FillFindData Callback that has to be called with PWIN32_FIND_DATAW that contain file information.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- * \see FindFilesWithPattern
- */
- NTSTATUS(DOKAN_CALLBACK *FindFiles)(LPCWSTR FileName,
- PFillFindData FillFindData,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief FindFilesWithPattern Dokan API callback
- *
- * Same as \ref DOKAN_OPERATIONS.FindFiles but with a search pattern.
- *
- * \param PathName Path requested by the Kernel on the FileSystem.
- * \param SearchPattern Search pattern.
- * \param FillFindData Callback that has to be called with PWIN32_FIND_DATAW that contains file information.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- * \see FindFiles
- */
- NTSTATUS(DOKAN_CALLBACK *FindFilesWithPattern)(LPCWSTR PathName,
- LPCWSTR SearchPattern,
- PFillFindData FillFindData,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief SetFileAttributes Dokan API callback
- *
- * Set file attributes on a specific file
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param FileAttributes FileAttributes to set on file.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- */
- NTSTATUS(DOKAN_CALLBACK *SetFileAttributes)(LPCWSTR FileName,
- DWORD FileAttributes,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief SetFileTime Dokan API callback
- *
- * Set file attributes on a specific file
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param CreationTime Creation FILETIME.
- * \param LastAccessTime LastAccess FILETIME.
- * \param LastWriteTime LastWrite FILETIME.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- */
- NTSTATUS(DOKAN_CALLBACK *SetFileTime)(LPCWSTR FileName,
- CONST FILETIME *CreationTime,
- CONST FILETIME *LastAccessTime,
- CONST FILETIME *LastWriteTime,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief DeleteFile Dokan API callback
- *
- * Check if it is possible to delete a file.
- *
- * DeleteFile will also be called with DOKAN_FILE_INFO.DeleteOnClose set to \c FALSE
- * to notify the driver when the file is no longer requested to be deleted.
- *
- * The file in DeleteFile should not be deleted, but instead the file
- * must be checked as to whether or not it can be deleted,
- * and \c STATUS_SUCCESS should be returned (when it can be deleted) or
- * appropriate error codes, such as \c STATUS_ACCESS_DENIED or
- * \c STATUS_OBJECT_NAME_NOT_FOUND, should be returned.
- *
- * When \c STATUS_SUCCESS is returned, a Cleanup call is received afterwards with
- * DOKAN_FILE_INFO.DeleteOnClose set to \c TRUE. Only then must the closing file
- * be deleted.
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- * \see DeleteDirectory
- * \see Cleanup
- */
- NTSTATUS(DOKAN_CALLBACK *DeleteFile)(LPCWSTR FileName,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief DeleteDirectory Dokan API callback
- *
- * Check if it is possible to delete a directory.
- *
- * DeleteDirectory will also be called with DOKAN_FILE_INFO.DeleteOnClose set to \c FALSE
- * to notify the driver when the file is no longer requested to be deleted.
- *
- * The Directory in DeleteDirectory should not be deleted, but instead
- * must be checked as to whether or not it can be deleted,
- * and \c STATUS_SUCCESS should be returned (when it can be deleted) or
- * appropriate error codes, such as \c STATUS_ACCESS_DENIED,
- * \c STATUS_OBJECT_PATH_NOT_FOUND, or \c STATUS_DIRECTORY_NOT_EMPTY, should
- * be returned.
- *
- * When \c STATUS_SUCCESS is returned, a Cleanup call is received afterwards with
- * DOKAN_FILE_INFO.DeleteOnClose set to \c TRUE. Only then must the closing file
- * be deleted.
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or \c NTSTATUS appropriate to the request result.
- * \ref DeleteFile
- * \ref Cleanup
- */
- NTSTATUS(DOKAN_CALLBACK *DeleteDirectory)(LPCWSTR FileName,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief MoveFile Dokan API callback
- *
- * Move a file or directory to a new destination
- *
- * \param FileName Path for the file to be moved.
- * \param NewFileName Path for the new location of the file.
- * \param ReplaceIfExisting If destination already exists, can it be replaced?
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- */
- NTSTATUS(DOKAN_CALLBACK *MoveFile)(LPCWSTR FileName,
- LPCWSTR NewFileName,
- BOOL ReplaceIfExisting,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief SetEndOfFile Dokan API callback
- *
- * SetEndOfFile is used to truncate or extend a file (physical file size).
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param ByteOffset File length to set.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- */
- NTSTATUS(DOKAN_CALLBACK *SetEndOfFile)(LPCWSTR FileName,
- LONGLONG ByteOffset,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief SetAllocationSize Dokan API callback
- *
- * SetAllocationSize is used to truncate or extend a file.
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param AllocSize File length to set.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- */
- NTSTATUS(DOKAN_CALLBACK *SetAllocationSize)(LPCWSTR FileName,
- LONGLONG AllocSize,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief LockFile Dokan API callback
- *
- * Lock file at a specific offset and data length.
- * This is only used if \ref DOKAN_OPTION_FILELOCK_USER_MODE is enabled.
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param ByteOffset Offset from where the lock has to be continued.
- * \param Length Data length to lock.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- * \see UnlockFile
- */
- NTSTATUS(DOKAN_CALLBACK *LockFile)(LPCWSTR FileName,
- LONGLONG ByteOffset,
- LONGLONG Length,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief UnlockFile Dokan API callback
- *
- * Unlock file at a specific offset and data length.
- * This is only used if \ref DOKAN_OPTION_FILELOCK_USER_MODE is enabled.
- *
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param ByteOffset Offset from where the lock has to be continued.
- * \param Length Data length to lock.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- * \see LockFile
- */
- NTSTATUS(DOKAN_CALLBACK *UnlockFile)(LPCWSTR FileName,
- LONGLONG ByteOffset,
- LONGLONG Length,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief GetDiskFreeSpace Dokan API callback
- *
- * Retrieves information about the amount of space that is available on a disk volume.
- * It consits of the total amount of space, the total amount of free space, and
- * the total amount of free space available to the user that is associated with the calling thread.
- *
- * Neither GetDiskFreeSpace nor \ref GetVolumeInformation
- * save the DOKAN_FILE_INFO.Context.
- * Before these methods are called, \ref ZwCreateFile may not be called.
- * (ditto \ref CloseFile and \ref Cleanup)
- *
- * \param FreeBytesAvailable Amount of available space.
- * \param TotalNumberOfBytes Total size of storage space
- * \param TotalNumberOfFreeBytes Amount of free space
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or \c NTSTATUS appropriate to the request result.
- * \see GetDiskFreeSpaceEx function (MSDN)
- * \see GetVolumeInformation
- */
- NTSTATUS(DOKAN_CALLBACK *GetDiskFreeSpace)(PULONGLONG FreeBytesAvailable,
- PULONGLONG TotalNumberOfBytes,
- PULONGLONG TotalNumberOfFreeBytes,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief GetVolumeInformation Dokan API callback
- *
- * Retrieves information about the file system and volume associated with the specified root directory.
- *
- * Neither GetVolumeInformation nor GetDiskFreeSpace
- * save the \ref DOKAN_FILE_INFO#Context.
- * Before these methods are called, \ref ZwCreateFile may not be called.
- * (ditto \ref CloseFile and \ref Cleanup)
- *
- * FileSystemName could be anything up to 10 characters.
- * But Windows check few feature availability based on file system name.
- * For this, it is recommended to set NTFS or FAT here.
- *
- * \c FILE_READ_ONLY_VOLUME is automatically added to the
- * FileSystemFlags if \ref DOKAN_OPTION_WRITE_PROTECT was
- * specified in DOKAN_OPTIONS when the volume was mounted.
- *
- * \param VolumeNameBuffer A pointer to a buffer that receives the name of a specified volume.
- * \param VolumeNameSize The length of a volume name buffer.
- * \param VolumeSerialNumber A pointer to a variable that receives the volume serial number.
- * \param MaximumComponentLength A pointer to a variable that receives the maximum length.
- * \param FileSystemFlags A pointer to a variable that receives flags associated with the specified file system.
- * \param FileSystemNameBuffer A pointer to a buffer that receives the name of the file system.
- * \param FileSystemNameSize The length of the file system name buffer.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- * \see GetVolumeInformation function (MSDN)
- * \see GetDiskFreeSpace
- */
- NTSTATUS(DOKAN_CALLBACK *GetVolumeInformation)(LPWSTR VolumeNameBuffer,
- DWORD VolumeNameSize,
- LPDWORD VolumeSerialNumber,
- LPDWORD MaximumComponentLength,
- LPDWORD FileSystemFlags,
- LPWSTR FileSystemNameBuffer,
- DWORD FileSystemNameSize,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief Mounted Dokan API callback
- *
- * Called when Dokan successfully mounts the volume.
- *
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- * \see Unmounted
- */
- NTSTATUS(DOKAN_CALLBACK *Mounted)(PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief Unmounted Dokan API callback
- *
- * Called when Dokan is unmounting the volume.
- *
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or \c NTSTATUS appropriate to the request result.
- * \see Unmounted
- */
- NTSTATUS(DOKAN_CALLBACK *Unmounted)(PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief GetFileSecurity Dokan API callback
- *
- * Get specified information about the security of a file or directory.
- *
- * Return \c STATUS_NOT_IMPLEMENTED to let dokan library build a sddl of the current process user with authenticate user rights for context menu.
- * Return \c STATUS_BUFFER_OVERFLOW if buffer size is too small.
- *
- * \since Supported since version 0.6.0. The version must be specified in \ref DOKAN_OPTIONS.Version.
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param SecurityInformation A SECURITY_INFORMATION value that identifies the security information being requested.
- * \param SecurityDescriptor A pointer to a buffer that receives a copy of the security descriptor of the requested file.
- * \param BufferLength Specifies the size, in bytes, of the buffer.
- * \param LengthNeeded A pointer to the variable that receives the number of bytes necessary to store the complete security descriptor.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- * \see SetFileSecurity
- * \see GetFileSecurity function (MSDN)
- */
- NTSTATUS(DOKAN_CALLBACK *GetFileSecurity)(LPCWSTR FileName,
- PSECURITY_INFORMATION SecurityInformation,
- PSECURITY_DESCRIPTOR SecurityDescriptor,
- ULONG BufferLength,
- PULONG LengthNeeded,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief SetFileSecurity Dokan API callback
- *
- * Sets the security of a file or directory object.
- *
- * \since Supported since version 0.6.0. The version must be specified in \ref DOKAN_OPTIONS.Version.
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param SecurityInformation Structure that identifies the contents of the security descriptor pointed by \a SecurityDescriptor param.
- * \param SecurityDescriptor A pointer to a SECURITY_DESCRIPTOR structure.
- * \param BufferLength Specifies the size, in bytes, of the buffer.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- * \see GetFileSecurity
- * \see SetFileSecurity function (MSDN)
- */
- NTSTATUS(DOKAN_CALLBACK *SetFileSecurity)(LPCWSTR FileName,
- PSECURITY_INFORMATION SecurityInformation,
- PSECURITY_DESCRIPTOR SecurityDescriptor,
- ULONG BufferLength,
- PDOKAN_FILE_INFO DokanFileInfo);
-
- /**
- * \brief FindStreams Dokan API callback
- *
- * Retrieve all NTFS Streams informations on the file.
- * This is only called if \ref DOKAN_OPTION_ALT_STREAM is enabled.
- *
- * \since Supported since version 0.8.0. The version must be specified in \ref DOKAN_OPTIONS.Version.
- * \param FileName File path requested by the Kernel on the FileSystem.
- * \param FillFindStreamData Callback that has to be called with PWIN32_FIND_STREAM_DATA that contain stream information.
- * \param DokanFileInfo Information about the file or directory.
- * \return \c STATUS_SUCCESS on success or NTSTATUS appropriate to the request result.
- */
- NTSTATUS(DOKAN_CALLBACK *FindStreams)(LPCWSTR FileName,
- PFillFindStreamData FillFindStreamData,
- PDOKAN_FILE_INFO DokanFileInfo);
-
-} DOKAN_OPERATIONS, *PDOKAN_OPERATIONS;
-
-// clang-format on
-
-/**
- * \defgroup DokanMainResult DokanMainResult
- * \brief \ref DokanMain returns error codes
- */
-/** @{ */
-
-/** Dokan mount succeed. */
-#define DOKAN_SUCCESS 0
-/** Dokan mount error. */
-#define DOKAN_ERROR -1
-/** Dokan mount failed - Bad drive letter. */
-#define DOKAN_DRIVE_LETTER_ERROR -2
-/** Dokan mount failed - Can't install driver. */
-#define DOKAN_DRIVER_INSTALL_ERROR -3
-/** Dokan mount failed - Driver answer that something is wrong. */
-#define DOKAN_START_ERROR -4
-/**
- * Dokan mount failed.
- * Can't assign a drive letter or mount point.
- * Probably already used by another volume.
- */
-#define DOKAN_MOUNT_ERROR -5
-/**
- * Dokan mount failed.
- * Mount point is invalid.
- */
-#define DOKAN_MOUNT_POINT_ERROR -6
-/**
- * Dokan mount failed.
- * Requested an incompatible version.
- */
-#define DOKAN_VERSION_ERROR -7
-
-/** @} */
-
-/**
- * \defgroup Dokan Dokan
- */
-/** @{ */
-
-/**
- * \brief Mount a new Dokan Volume.
- *
- * This function block until the device is unmounted.
- * If the mount fails, it will directly return a \ref DokanMainResult error.
- *
- * \param DokanOptions a \ref DOKAN_OPTIONS that describe the mount.
- * \param DokanOperations Instance of \ref DOKAN_OPERATIONS that will be called for each request made by the kernel.
- * \return \ref DokanMainResult status.
- */
-int DOKANAPI DokanMain(PDOKAN_OPTIONS DokanOptions,
- PDOKAN_OPERATIONS DokanOperations);
-
-/**
- * \brief Unmount a Dokan device from a driver letter.
- *
- * \param DriveLetter Dokan driver letter to unmount.
- * \return \c TRUE if device was unmounted or \c FALSE in case of failure or device not found.
- */
-BOOL DOKANAPI DokanUnmount(WCHAR DriveLetter);
-
-/**
- * \brief Unmount a Dokan device from a mount point
- *
- * \param MountPoint Mount point to unmount ("Z", "Z:", "Z:\", "Z:\MyMountPoint").
- * \return \c TRUE if device was unmounted or \c FALSE in case of failure or device not found.
- */
-BOOL DOKANAPI DokanRemoveMountPoint(LPCWSTR MountPoint);
-
-/**
- * \brief Unmount a Dokan device from a mount point
- *
- * Same as \ref DokanRemoveMountPoint
- * If Safe is \c TRUE, it will broadcast to all desktops and Shells
- * Safe should not be used during DLL_PROCESS_DETACH
- *
- * \see DokanRemoveMountPoint
- *
- * \param MountPoint Mount point to unmount ("Z", "Z:", "Z:\", "Z:\MyMountPoint").
- * \param Safe Process is not in DLL_PROCESS_DETACH state.
- * \return \c TRUE if device was unmounted or \c FALSE in case of failure or device not found.
- */
-BOOL DOKANAPI DokanRemoveMountPointEx(LPCWSTR MountPoint, BOOL Safe);
-
-/**
- * \brief Checks whether Name matches Expression
- *
- * \param Expression Expression can contain wildcard characters (? and *)
- * \param Name Name to check
- * \param IgnoreCase Case sensitive or not
- * \return result if name matches the expression
- */
-BOOL DOKANAPI DokanIsNameInExpression(LPCWSTR Expression, LPCWSTR Name,
- BOOL IgnoreCase);
-
-/**
- * \brief Get the version of Dokan.
- * The returned ULONG is the version number without the dots.
- * \return The version of Dokan
- */
-ULONG DOKANAPI DokanVersion();
-
-/**
- * \brief Get the version of the Dokan driver.
- * The returned ULONG is the version number without the dots.
- * \return The version of Dokan driver.
- */
-ULONG DOKANAPI DokanDriverVersion();
-
-/**
- * \brief Extends the timeout of the current IO operation in driver.
- *
- * \param Timeout Extended time in milliseconds requested.
- * \param DokanFileInfo \ref DOKAN_FILE_INFO of the operation to extend.
- * \return If the operation was successful.
- */
-BOOL DOKANAPI DokanResetTimeout(ULONG Timeout, PDOKAN_FILE_INFO DokanFileInfo);
-
-/**
- * \brief Get the handle to Access Token.
- *
- * This method needs be called in CreateFile callback.
- * The caller must call CloseHandle
- * for the returned handle.
- *
- * \param DokanFileInfo \ref DOKAN_FILE_INFO of the operation to extend.
- * \return A handle to the account token for the user on whose behalf the code is running.
- */
-HANDLE DOKANAPI DokanOpenRequestorToken(PDOKAN_FILE_INFO DokanFileInfo);
-
-/**
- * \brief Get active Dokan mount points.
- *
- * \param list Allocate array of DOKAN_CONTROL.
- * \param length Number of \ref DOKAN_CONTROL instances in list.
- * \param uncOnly Get only instances that have UNC Name.
- * \param nbRead Number of instances successfully retrieved.
- * \return List retrieved or not.
- */
-BOOL DOKANAPI DokanGetMountPointList(PDOKAN_CONTROL list, ULONG length,
- BOOL uncOnly, PULONG nbRead);
-
-/**
- * \brief Convert \ref DOKAN_OPERATIONS.ZwCreateFile parameters to CreateFile parameters.
- *
- * Dokan Kernel forward the DesiredAccess directly from the IRP_MJ_CREATE.
- * This DesiredAccess has been converted from generic rights (user CreateFile request) to standard rights and will be converted back here.
- * https://msdn.microsoft.com/windows/hardware/drivers/ifs/access-mask
- *
- * \param DesiredAccess DesiredAccess from \ref DOKAN_OPERATIONS.ZwCreateFile.
- * \param FileAttributes FileAttributes from \ref DOKAN_OPERATIONS.ZwCreateFile.
- * \param CreateOptions CreateOptions from \ref DOKAN_OPERATIONS.ZwCreateFile.
- * \param CreateDisposition CreateDisposition from \ref DOKAN_OPERATIONS.ZwCreateFile.
- * \param outDesiredAccess New CreateFile dwDesiredAccess.
- * \param outFileAttributesAndFlags New CreateFile dwFlagsAndAttributes.
- * \param outCreationDisposition New CreateFile dwCreationDisposition.
- * \see CreateFile function (MSDN)
- */
-void DOKANAPI DokanMapKernelToUserCreateFileFlags(
- ACCESS_MASK DesiredAccess, ULONG FileAttributes, ULONG CreateOptions, ULONG CreateDisposition,
- ACCESS_MASK* outDesiredAccess, DWORD *outFileAttributesAndFlags, DWORD *outCreationDisposition);
-
-/**
- * \brief Convert WIN32 error to NTSTATUS
- *
- * https://support.microsoft.com/en-us/kb/113996
- *
- * \param Error Win32 Error to convert
- * \return NTSTATUS associate to the ERROR.
- */
-NTSTATUS DOKANAPI DokanNtStatusFromWin32(DWORD Error);
-
-/** @} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // DOKAN_H_
diff --git a/MemProcFS/fileinfo.h b/MemProcFS/fileinfo.h
deleted file mode 100644
index 50ac60e..0000000
--- a/MemProcFS/fileinfo.h
+++ /dev/null
@@ -1,1248 +0,0 @@
-/*
- Dokan : user-mode file system library for Windows
-
- Copyright (C) 2015 - 2018 Adrien J. and Maxime C.
- Copyright (C) 2007 - 2011 Hiroki Asakawa
-
- http://dokan-dev.github.io
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU Lesser General Public License as published by the Free
-Software Foundation; either version 3 of the License, or (at your option) any
-later version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program. If not, see .
-*/
-
-#ifndef FILEINFO_H_
-#define FILEINFO_H_
-
-#define IRP_MJ_CREATE 0x00
-#define IRP_MJ_CREATE_NAMED_PIPE 0x01
-#define IRP_MJ_CLOSE 0x02
-#define IRP_MJ_READ 0x03
-#define IRP_MJ_WRITE 0x04
-#define IRP_MJ_QUERY_INFORMATION 0x05
-#define IRP_MJ_SET_INFORMATION 0x06
-#define IRP_MJ_QUERY_EA 0x07
-#define IRP_MJ_SET_EA 0x08
-#define IRP_MJ_FLUSH_BUFFERS 0x09
-#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
-#define IRP_MJ_SET_VOLUME_INFORMATION 0x0b
-#define IRP_MJ_DIRECTORY_CONTROL 0x0c
-#define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d
-#define IRP_MJ_DEVICE_CONTROL 0x0e
-#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f
-#define IRP_MJ_SHUTDOWN 0x10
-#define IRP_MJ_LOCK_CONTROL 0x11
-#define IRP_MJ_CLEANUP 0x12
-#define IRP_MJ_CREATE_MAILSLOT 0x13
-#define IRP_MJ_QUERY_SECURITY 0x14
-#define IRP_MJ_SET_SECURITY 0x15
-#define IRP_MJ_POWER 0x16
-#define IRP_MJ_SYSTEM_CONTROL 0x17
-#define IRP_MJ_DEVICE_CHANGE 0x18
-#define IRP_MJ_QUERY_QUOTA 0x19
-#define IRP_MJ_SET_QUOTA 0x1a
-#define IRP_MJ_PNP 0x1b
-#define IRP_MJ_PNP_POWER IRP_MJ_PNP
-#define IRP_MJ_MAXIMUM_FUNCTION 0x1b
-
-#define IRP_MN_LOCK 0x01
-#define IRP_MN_UNLOCK_SINGLE 0x02
-#define IRP_MN_UNLOCK_ALL 0x03
-#define IRP_MN_UNLOCK_ALL_BY_KEY 0x04
-
-typedef enum _FILE_INFORMATION_CLASS {
- FileDirectoryInformation = 1,
- FileFullDirectoryInformation, // 2
- FileBothDirectoryInformation, // 3
- FileBasicInformation, // 4
- FileStandardInformation, // 5
- FileInternalInformation, // 6
- FileEaInformation, // 7
- FileAccessInformation, // 8
- FileNameInformation, // 9
- FileRenameInformation, // 10
- FileLinkInformation, // 11
- FileNamesInformation, // 12
- FileDispositionInformation, // 13
- FilePositionInformation, // 14
- FileFullEaInformation, // 15
- FileModeInformation, // 16
- FileAlignmentInformation, // 17
- FileAllInformation, // 18
- FileAllocationInformation, // 19
- FileEndOfFileInformation, // 20
- FileAlternateNameInformation, // 21
- FileStreamInformation, // 22
- FilePipeInformation, // 23
- FilePipeLocalInformation, // 24
- FilePipeRemoteInformation, // 25
- FileMailslotQueryInformation, // 26
- FileMailslotSetInformation, // 27
- FileCompressionInformation, // 28
- FileObjectIdInformation, // 29
- FileCompletionInformation, // 30
- FileMoveClusterInformation, // 31
- FileQuotaInformation, // 32
- FileReparsePointInformation, // 33
- FileNetworkOpenInformation, // 34
- FileAttributeTagInformation, // 35
- FileTrackingInformation, // 36
- FileIdBothDirectoryInformation, // 37
- FileIdFullDirectoryInformation, // 38
- FileValidDataLengthInformation, // 39
- FileShortNameInformation, // 40
- FileIoCompletionNotificationInformation, // 41
- FileIoStatusBlockRangeInformation, // 42
- FileIoPriorityHintInformation, // 43
- FileSfioReserveInformation, // 44
- FileSfioVolumeInformation, // 45
- FileHardLinkInformation, // 46
- FileProcessIdsUsingFileInformation, // 47
- FileNormalizedNameInformation, // 48
- FileNetworkPhysicalNameInformation, // 49
- FileIdGlobalTxDirectoryInformation, // 50
- FileIsRemoteDeviceInformation, // 51
- FileUnusedInformation, // 52
- FileNumaNodeInformation, // 53
- FileStandardLinkInformation, // 54
- FileRemoteProtocolInformation, // 55
-
- //
- // These are special versions of these operations (defined earlier)
- // which can be used by kernel mode drivers only to bypass security
- // access checks for Rename and HardLink operations. These operations
- // are only recognized by the IOManager, a file system should never
- // receive these.
- //
-
- FileRenameInformationBypassAccessCheck, // 56
- FileLinkInformationBypassAccessCheck, // 57
-
- //
- // End of special information classes reserved for IOManager.
- //
-
- FileVolumeNameInformation, // 58
- FileIdInformation, // 59
- FileIdExtdDirectoryInformation, // 60
- FileReplaceCompletionInformation, // 61
- FileHardLinkFullIdInformation, // 62
- FileIdExtdBothDirectoryInformation, // 63
- FileDispositionInformationEx, // 64
- FileRenameInformationEx, // 65
- FileRenameInformationExBypassAccessCheck, // 66
- FileDesiredStorageClassInformation, // 67
- FileStatInformation, // 68
- FileMemoryPartitionInformation, // 69
-
- FileMaximumInformation
-} FILE_INFORMATION_CLASS,
- *PFILE_INFORMATION_CLASS;
-
-typedef enum _FSINFOCLASS {
- FileFsVolumeInformation = 1,
- FileFsLabelInformation, // 2
- FileFsSizeInformation, // 3
- FileFsDeviceInformation, // 4
- FileFsAttributeInformation, // 5
- FileFsControlInformation, // 6
- FileFsFullSizeInformation, // 7
- FileFsObjectIdInformation, // 8
- FileFsDriverPathInformation, // 9
- FileFsVolumeFlagsInformation, // 10
- FileFsMaximumInformation
-} FS_INFORMATION_CLASS,
- *PFS_INFORMATION_CLASS;
-
-/**
- * \struct FILE_ALIGNMENT_INFORMATION
- * \brief Used as an argument to the ZwQueryInformationFile routine.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileAllInformation
- */
-typedef struct _FILE_ALIGNMENT_INFORMATION {
- /**
- * The buffer alignment required by the underlying device. For a list of system-defined values, see DEVICE_OBJECT.
- * The value must be one of the FILE_XXX_ALIGNMENT values defined in Wdm.h.
- * For more information, see DEVICE_OBJECT and Initializing a Device Object.
- */
- ULONG AlignmentRequirement;
-} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION;
-
-/**
- * \struct FILE_NAME_INFORMATION
- * \brief Used as argument to the ZwQueryInformationFile and ZwSetInformationFile routines.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileNameInformation
- */
-typedef struct _FILE_NAME_INFORMATION {
- /**
- * Specifies the length, in bytes, of the file name string.
- */
- ULONG FileNameLength;
- /**
- * Specifies the first character of the file name string. This is followed in memory by the remainder of the string.
- */
- WCHAR FileName[1];
-} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
-
-/**
- * \struct FILE_ATTRIBUTE_TAG_INFORMATION
- * \brief Used as an argument to ZwQueryInformationFile.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileAttributeTagInformation
- */
-typedef struct _FILE_ATTRIBUTE_TAG_INFORMATION {
- /**
- * Specifies one or more FILE_ATTRIBUTE_XXX flags.
- * For descriptions of these flags, see the documentation of the GetFileAttributes function in the Microsoft Windows SDK.
- */
- ULONG FileAttributes;
- /**
- * Specifies the reparse point tag. If the FileAttributes member includes the FILE_ATTRIBUTE_REPARSE_POINT attribute flag,
- * this member specifies the reparse tag. Otherwise, this member is unused.
- */
- ULONG ReparseTag;
-} FILE_ATTRIBUTE_TAG_INFORMATION, *PFILE_ATTRIBUTE_TAG_INFORMATION;
-
-/**
- * \struct FILE_DISPOSITION_INFORMATION
- * \brief Used as an argument to the ZwSetInformationFile routine.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileDispositionInformation
- */
-typedef struct _FILE_DISPOSITION_INFORMATION {
- /**
- * Indicates whether the operating system file should delete the file when the file is closed.
- * Set this member to TRUE to delete the file when it is closed.
- * Otherwise, set to FALSE. Setting this member to FALSE has no effect if the handle was opened with FILE_FLAG_DELETE_ON_CLOSE.
- */
- BOOLEAN DeleteFile;
-} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION;
-
-/**
- * \struct FILE_END_OF_FILE_INFORMATION
- * \brief Used as an argument to the ZwSetInformationFile routine.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileEndOfFileInformation
- */
-typedef struct _FILE_END_OF_FILE_INFORMATION {
- /**
- * The absolute new end of file position as a byte offset from the start of the file.
- */
- LARGE_INTEGER EndOfFile;
-} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION;
-
-/**
- * \struct FILE_VALID_DATA_LENGTH_INFORMATION
- * \brief Used as an argument to ZwSetInformationFile.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileValidDataLengthInformation
- */
-typedef struct _FILE_VALID_DATA_LENGTH_INFORMATION {
- /**
- * Specifies the new valid data length for the file.
- * This parameter must be a positive value that is greater than the current valid data length, but less than or equal to the current file size.
- */
- LARGE_INTEGER ValidDataLength;
-} FILE_VALID_DATA_LENGTH_INFORMATION, *PFILE_VALID_DATA_LENGTH_INFORMATION;
-
-/**
- * \struct FILE_BASIC_INFORMATION
- * \brief Used as an argument to routines that query or set file information.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileBasicInformation and FileAllInformation
- */
-typedef struct _FILE_BASIC_INFORMATION {
- /**
- * Specifies the time that the file was created.
- */
- LARGE_INTEGER CreationTime;
- /**
- * Specifies the time that the file was last accessed.
- */
- LARGE_INTEGER LastAccessTime;
- /**
- * Specifies the time that the file was last written to.
- */
- LARGE_INTEGER LastWriteTime;
- /**
- * Specifies the last time the file was changed.
- */
- LARGE_INTEGER ChangeTime;
- /**
- * Specifies one or more FILE_ATTRIBUTE_XXX flags. For descriptions of these flags,
- * see the documentation for the GetFileAttributes function in the Microsoft Windows SDK.
- */
- ULONG FileAttributes;
-} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
-
-/**
- * \struct FILE_STANDARD_INFORMATION
- * \brief Used as an argument to routines that query or set file information.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileStandardInformation and FileAllInformation
- */
-typedef struct _FILE_STANDARD_INFORMATION {
- /**
- * The file allocation size in bytes. Usually, this value is a multiple of the sector or cluster size of the underlying physical device.
- */
- LARGE_INTEGER AllocationSize;
- /**
- * The end of file location as a byte offset.
- */
- LARGE_INTEGER EndOfFile;
- /**
- * The number of hard links to the file.
- */
- ULONG NumberOfLinks;
- /**
- * The delete pending status. TRUE indicates that a file deletion has been requested.
- */
- BOOLEAN DeletePending;
- /**
- * The file directory status. TRUE indicates the file object represents a directory.
- */
- BOOLEAN Directory;
-} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
-
-/**
- * \struct FILE_POSITION_INFORMATION
- * \brief Used as an argument to routines that query or set file information.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FilePositionInformation and FileAllInformation
- */
-typedef struct _FILE_POSITION_INFORMATION {
- /**
- * The byte offset of the current file pointer.
- */
- LARGE_INTEGER CurrentByteOffset;
-} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;
-
-/**
- * \struct FILE_DIRECTORY_INFORMATION
- * \brief Used to query detailed information for the files in a directory.
- */
-typedef struct _FILE_DIRECTORY_INFORMATION {
- /**
- * Byte offset of the next FILE_DIRECTORY_INFORMATION entry, if multiple entries are present in a buffer.
- * This member is zero if no other entries follow this one.
- */
- ULONG NextEntryOffset;
- /**
- * Byte offset of the file within the parent directory. This member is undefined for file systems, such as NTFS,
- * in which the position of a file within the parent directory is not fixed and can be changed at any time to maintain sort order.
- */
- ULONG FileIndex;
- /**
- * Time when the file was created.
- */
- LARGE_INTEGER CreationTime;
- /**
- * Last time the file was accessed.
- */
- LARGE_INTEGER LastAccessTime;
- /**
- * Last time information was written to the file.
- */
- LARGE_INTEGER LastWriteTime;
- /**
- * Last time the file was changed.
- */
- LARGE_INTEGER ChangeTime;
- /**
- * Absolute new end-of-file position as a byte offset from the start of the file.
- * EndOfFile specifies the byte offset to the end of the file.
- * Because this value is zero-based, it actually refers to the first free byte in the file. In other words,
- * EndOfFile is the offset to the byte immediately following the last valid byte in the file.
- */
- LARGE_INTEGER EndOfFile;
- /**
- * File allocation size, in bytes. Usually, this value is a multiple of the sector or cluster size of the underlying physical device.
- */
- LARGE_INTEGER AllocationSize;
- /**
- * File attributes, which can be any valid combination of the following:
- *
- * \li \c FILE_ATTRIBUTE_READONLY
- * \li \c FILE_ATTRIBUTE_HIDDEN
- * \li \c FILE_ATTRIBUTE_SYSTEM
- * \li \c FILE_ATTRIBUTE_DIRECTORY
- * \li \c FILE_ATTRIBUTE_ARCHIVE
- * \li \c FILE_ATTRIBUTE_NORMAL
- * \li \c FILE_ATTRIBUTE_TEMPORARY
- * \li \c FILE_ATTRIBUTE_COMPRESSED
- */
- ULONG FileAttributes;
- /**
- * Specifies the length of the file name string.
- */
- ULONG FileNameLength;
- /**
- * Specifies the first character of the file name string.
- * This is followed in memory by the remainder of the string.
- */
- WCHAR FileName[1];
-} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
-
-/**
- * \struct FILE_FULL_DIR_INFORMATION
- * \brief Used to query detailed information for the files in a directory.
- */
-typedef struct _FILE_FULL_DIR_INFORMATION {
- /**
- * Byte offset of the next FILE_DIRECTORY_INFORMATION entry, if multiple entries are present in a buffer.
- * This member is zero if no other entries follow this one.
- */
- ULONG NextEntryOffset;
- /**
- * Byte offset of the file within the parent directory. This member is undefined for file systems, such as NTFS,
- * in which the position of a file within the parent directory is not fixed and can be changed at any time to maintain sort order.
- */
- ULONG FileIndex;
- /**
- * Time when the file was created.
- */
- LARGE_INTEGER CreationTime;
- /**
- * Last time the file was accessed.
- */
- LARGE_INTEGER LastAccessTime;
- /**
- * Last time information was written to the file.
- */
- LARGE_INTEGER LastWriteTime;
- /**
- * Last time the file was changed.
- */
- LARGE_INTEGER ChangeTime;
- /**
- * Absolute new end-of-file position as a byte offset from the start of the file.
- * EndOfFile specifies the byte offset to the end of the file.
- * Because this value is zero-based, it actually refers to the first free byte in the file. In other words,
- * EndOfFile is the offset to the byte immediately following the last valid byte in the file.
- */
- LARGE_INTEGER EndOfFile;
- /**
- * File allocation size, in bytes. Usually, this value is a multiple of the sector or cluster size of the underlying physical device.
- */
- LARGE_INTEGER AllocationSize;
- /**
- * File attributes, which can be any valid combination of the following:
- *
- * \li \c FILE_ATTRIBUTE_READONLY
- * \li \c FILE_ATTRIBUTE_HIDDEN
- * \li \c FILE_ATTRIBUTE_SYSTEM
- * \li \c FILE_ATTRIBUTE_DIRECTORY
- * \li \c FILE_ATTRIBUTE_ARCHIVE
- * \li \c FILE_ATTRIBUTE_NORMAL
- * \li \c FILE_ATTRIBUTE_TEMPORARY
- * \li \c FILE_ATTRIBUTE_COMPRESSED
- */
- ULONG FileAttributes;
- /**
- * Specifies the length of the file name string.
- */
- ULONG FileNameLength;
- /**
- * Combined length, in bytes, of the extended attributes (EA) for the file.
- */
- ULONG EaSize;
- /**
- * Specifies the first character of the file name string.
- * This is followed in memory by the remainder of the string.
- */
- WCHAR FileName[1];
-} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION;
-
-/**
- * \struct FILE_ID_FULL_DIR_INFORMATION
- * \brief Used to query detailed information for the files in a directory.
- */
-typedef struct _FILE_ID_FULL_DIR_INFORMATION {
- /**
- * Byte offset of the next FILE_DIRECTORY_INFORMATION entry, if multiple entries are present in a buffer.
- * This member is zero if no other entries follow this one.
- */
- ULONG NextEntryOffset;
- /**
- * Byte offset of the file within the parent directory. This member is undefined for file systems, such as NTFS,
- * in which the position of a file within the parent directory is not fixed and can be changed at any time to maintain sort order.
- */
- ULONG FileIndex;
- /**
- * Time when the file was created.
- */
- LARGE_INTEGER CreationTime;
- /**
- * Last time the file was accessed.
- */
- LARGE_INTEGER LastAccessTime;
- /**
- * Last time information was written to the file.
- */
- LARGE_INTEGER LastWriteTime;
- /**
- * Last time the file was changed.
- */
- LARGE_INTEGER ChangeTime;
- /**
- * Absolute new end-of-file position as a byte offset from the start of the file.
- * EndOfFile specifies the byte offset to the end of the file.
- * Because this value is zero-based, it actually refers to the first free byte in the file. In other words,
- * EndOfFile is the offset to the byte immediately following the last valid byte in the file.
- */
- LARGE_INTEGER EndOfFile;
- /**
- * File allocation size, in bytes. Usually, this value is a multiple of the sector or cluster size of the underlying physical device.
- */
- LARGE_INTEGER AllocationSize;
- /**
- * File attributes, which can be any valid combination of the following:
- *
- * \li \c FILE_ATTRIBUTE_READONLY
- * \li \c FILE_ATTRIBUTE_HIDDEN
- * \li \c FILE_ATTRIBUTE_SYSTEM
- * \li \c FILE_ATTRIBUTE_DIRECTORY
- * \li \c FILE_ATTRIBUTE_ARCHIVE
- * \li \c FILE_ATTRIBUTE_NORMAL
- * \li \c FILE_ATTRIBUTE_TEMPORARY
- * \li \c FILE_ATTRIBUTE_COMPRESSED
- */
- ULONG FileAttributes;
- /**
- * Specifies the length of the file name string.
- */
- ULONG FileNameLength;
- /**
- * Combined length, in bytes, of the extended attributes (EA) for the file.
- */
- ULONG EaSize;
- /**
- * The 8-byte file reference number for the file. (Note that this is not the same as the 16-byte
- * "file object ID" that was added to NTFS for Microsoft Windows 2000.)
- */
- LARGE_INTEGER FileId;
- /**
- * Specifies the first character of the file name string.
- * This is followed in memory by the remainder of the string.
- */
- WCHAR FileName[1];
-} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION;
-
-/**
- * \struct FILE_BOTH_DIR_INFORMATION
- * \brief Used to query detailed information for the files in a directory.
- */
-typedef struct _FILE_BOTH_DIR_INFORMATION {
- /**
- * Byte offset of the next FILE_DIRECTORY_INFORMATION entry, if multiple entries are present in a buffer.
- * This member is zero if no other entries follow this one.
- */
- ULONG NextEntryOffset;
- /**
- * Byte offset of the file within the parent directory. This member is undefined for file systems, such as NTFS,
- * in which the position of a file within the parent directory is not fixed and can be changed at any time to maintain sort order.
- */
- ULONG FileIndex;
- /**
- * Time when the file was created.
- */
- LARGE_INTEGER CreationTime;
- /**
- * Last time the file was accessed.
- */
- LARGE_INTEGER LastAccessTime;
- /**
- * Last time information was written to the file.
- */
- LARGE_INTEGER LastWriteTime;
- /**
- * Last time the file was changed.
- */
- LARGE_INTEGER ChangeTime;
- /**
- * Absolute new end-of-file position as a byte offset from the start of the file.
- * EndOfFile specifies the byte offset to the end of the file.
- * Because this value is zero-based, it actually refers to the first free byte in the file. In other words,
- * EndOfFile is the offset to the byte immediately following the last valid byte in the file.
- */
- LARGE_INTEGER EndOfFile;
- /**
- * File allocation size, in bytes. Usually, this value is a multiple of the sector or cluster size of the underlying physical device.
- */
- LARGE_INTEGER AllocationSize;
- /**
- * File attributes, which can be any valid combination of the following:
- *
- * \li \c FILE_ATTRIBUTE_READONLY
- * \li \c FILE_ATTRIBUTE_HIDDEN
- * \li \c FILE_ATTRIBUTE_SYSTEM
- * \li \c FILE_ATTRIBUTE_DIRECTORY
- * \li \c FILE_ATTRIBUTE_ARCHIVE
- * \li \c FILE_ATTRIBUTE_NORMAL
- * \li \c FILE_ATTRIBUTE_TEMPORARY
- * \li \c FILE_ATTRIBUTE_COMPRESSED
- */
- ULONG FileAttributes;
- /**
- * Specifies the length of the file name string.
- */
- ULONG FileNameLength;
- /**
- * Combined length, in bytes, of the extended attributes (EA) for the file.
- */
- ULONG EaSize;
- /**
- * Specifies the length, in bytes, of the short file name string.
- */
- CCHAR ShortNameLength;
- /**
- * Unicode string containing the short (8.3) name for the file.
- */
- WCHAR ShortName[12];
- /**
- * Specifies the first character of the file name string. This is followed in memory by the remainder of the string.
- */
- WCHAR FileName[1];
-} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
-
-/**
- * \struct FILE_ID_BOTH_DIR_INFORMATION
- * \brief Used to query detailed information for the files in a directory.
- */
-typedef struct _FILE_ID_BOTH_DIR_INFORMATION {
- /**
- * Byte offset of the next FILE_DIRECTORY_INFORMATION entry, if multiple entries are present in a buffer.
- * This member is zero if no other entries follow this one.
- */
- ULONG NextEntryOffset;
- /**
- * Byte offset of the file within the parent directory. This member is undefined for file systems, such as NTFS,
- * in which the position of a file within the parent directory is not fixed and can be changed at any time to maintain sort order.
- */
- ULONG FileIndex;
- /**
- * Time when the file was created.
- */
- LARGE_INTEGER CreationTime;
- /**
- * Last time the file was accessed.
- */
- LARGE_INTEGER LastAccessTime;
- /**
- * Last time information was written to the file.
- */
- LARGE_INTEGER LastWriteTime;
- /**
- * Last time the file was changed.
- */
- LARGE_INTEGER ChangeTime;
- /**
- * Absolute new end-of-file position as a byte offset from the start of the file.
- * EndOfFile specifies the byte offset to the end of the file.
- * Because this value is zero-based, it actually refers to the first free byte in the file. In other words,
- * EndOfFile is the offset to the byte immediately following the last valid byte in the file.
- */
- LARGE_INTEGER EndOfFile;
- /**
- * File allocation size, in bytes. Usually, this value is a multiple of the sector or cluster size of the underlying physical device.
- */
- LARGE_INTEGER AllocationSize;
- /**
- * File attributes, which can be any valid combination of the following:
- *
- * \li \c FILE_ATTRIBUTE_READONLY
- * \li \c FILE_ATTRIBUTE_HIDDEN
- * \li \c FILE_ATTRIBUTE_SYSTEM
- * \li \c FILE_ATTRIBUTE_DIRECTORY
- * \li \c FILE_ATTRIBUTE_ARCHIVE
- * \li \c FILE_ATTRIBUTE_NORMAL
- * \li \c FILE_ATTRIBUTE_TEMPORARY
- * \li \c FILE_ATTRIBUTE_COMPRESSED
- */
- ULONG FileAttributes;
- /**
- * Specifies the length of the file name string.
- */
- ULONG FileNameLength;
- /**
- * Combined length, in bytes, of the extended attributes (EA) for the file.
- */
- ULONG EaSize;
- /**
- * Specifies the length, in bytes, of the short file name string.
- */
- CCHAR ShortNameLength;
- /**
- * Unicode string containing the short (8.3) name for the file.
- */
- WCHAR ShortName[12];
- /**
- * The 8-byte file reference number for the file. This number is generated and assigned to the file by the file system.
- * (Note that the FileId is not the same as the 16-byte "file object ID" that was added to NTFS for Microsoft Windows 2000.)
- */
- LARGE_INTEGER FileId;
- /**
- * Specifies the first character of the file name string. This is followed in memory by the remainder of the string.
- */
- WCHAR FileName[1];
-} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION;
-
-/**
- * \struct FILE_NAMES_INFORMATION
- * \brief Used to query detailed information about the names of files in a directory.
- */
-typedef struct _FILE_NAMES_INFORMATION {
- /**
- * Byte offset for the next FILE_NAMES_INFORMATION entry, if multiple entries are present in a buffer.
- * This member is zero if no other entries follow this one.
- */
- ULONG NextEntryOffset;
- /**
- * Byte offset of the file within the parent directory. This member is undefined for file systems, such as NTFS,
- * in which the position of a file within the parent directory is not fixed and can be changed at any time to maintain sort order.
- */
- ULONG FileIndex;
- /**
- * Specifies the length of the file name string.
- */
- ULONG FileNameLength;
- /**
- * Specifies the first character of the file name string. This is followed in memory by the remainder of the string.
- */
- WCHAR FileName[1];
-} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;
-
-#define ANSI_DOS_STAR ('<')
-#define ANSI_DOS_QM ('>')
-#define ANSI_DOS_DOT ('"')
-
-#define DOS_STAR (L'<')
-#define DOS_QM (L'>')
-#define DOS_DOT (L'"')
-
-/**
- * \struct FILE_INTERNAL_INFORMATION
- * \brief Used to query for the file system's 8-byte file reference number for a file.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileInternalInformation
- */
-typedef struct _FILE_INTERNAL_INFORMATION {
- /**
- * The 8-byte file reference number for the file. This number is assigned by the file system and is file-system-specific.
- * (Note that this is not the same as the 16-byte "file object ID" that was added to NTFS for Microsoft Windows 2000.)
- */
- LARGE_INTEGER IndexNumber;
-} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
-
-/**
- * \struct FILE_ID_INFORMATION
- * \brief Contains identification information for a file.
- *
- * This structure is returned from the GetFileInformationByHandleEx function when FileIdInfo is passed in the FileInformationClass parameter.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileIdInformation
- */
-typedef struct _FILE_ID_INFORMATION {
- /**
- * The serial number of the volume that contains a file.
- */
- ULONGLONG VolumeSerialNumber;
- /**
- * The 128-bit file identifier for the file. The file identifier and the volume serial number uniquely identify a file on a single computer.
- * To determine whether two open handles represent the same file, combine the identifier and the volume serial number for each file and compare them.
- */
- FILE_ID_128 FileId;
-} FILE_ID_INFORMATION, *PFILE_ID_INFORMATION;
-
-/**
- * \struct FILE_EA_INFORMATION
- * \brief Used to query for the size of the extended attributes (EA) for a file.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileEaInformation and FileAllInformation
- */
-typedef struct _FILE_EA_INFORMATION {
- /**
- * Specifies the combined length, in bytes, of the extended attributes for the file.
- */
- ULONG EaSize;
-} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;
-
-/**
- * \struct FILE_ACCESS_INFORMATION
- * \brief Used to query for or set the access rights of a file.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileAllInformation
- */
-typedef struct _FILE_ACCESS_INFORMATION {
- /**
- * Flags that specify a set of access rights in the access mask of an access control entry.
- * This member is a value of type ACCESS_MASK.
- */
- ACCESS_MASK AccessFlags;
-} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;
-
-/**
- * \struct FILE_MODE_INFORMATION
- * \brief Used to query or set the access mode of a file.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileAllInformation
- */
-typedef struct _FILE_MODE_INFORMATION {
- /**
- * Specifies the mode in which the file will be accessed following a create-file or open-file operation.
- * This parameter is either zero or the bitwise OR of one or more of the following file option flags:
- *
- * \li \c FILE_WRITE_THROUGH
- * \li \c FILE_SEQUENTIAL_ONLY
- * \li \c FILE_NO_INTERMEDIATE_BUFFERING
- * \li \c FILE_SYNCHRONOUS_IO_ALERT
- * \li \c FILE_SYNCHRONOUS_IO_NONALERT
- * \li \c FILE_DELETE_ON_CLOSE
- */
- ULONG Mode;
-} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
-
-/**
- * \struct FILE_ALL_INFORMATION
- * \brief Structure is a container for several FILE_XXX_INFORMATION structures.
- *
- * The struct is requested during IRP_MJ_QUERY_INFORMATION with query FileAllInformation
- */
-typedef struct _FILE_ALL_INFORMATION {
- /** \see FILE_BASIC_INFORMATION */
- FILE_BASIC_INFORMATION BasicInformation;
- /** \see FILE_STANDARD_INFORMATION */
- FILE_STANDARD_INFORMATION StandardInformation;
- /** \see FILE_INTERNAL_INFORMATION */
- FILE_INTERNAL_INFORMATION InternalInformation;
- /** \see FILE_EA_INFORMATION */
- FILE_EA_INFORMATION EaInformation;
- /** \see FILE_ACCESS_INFORMATION */
- FILE_ACCESS_INFORMATION AccessInformation;
- /** \see FILE_POSITION_INFORMATION */
- FILE_POSITION_INFORMATION PositionInformation;
- /** \see FILE_MODE_INFORMATION */
- FILE_MODE_INFORMATION ModeInformation;
- /** \see FILE_ALIGNMENT_INFORMATION */
- FILE_ALIGNMENT_INFORMATION AlignmentInformation;
- /** \see FILE_NAME_INFORMATION */
- FILE_NAME_INFORMATION NameInformation;
-} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;
-
-/**
- * \struct FILE_ALLOCATION_INFORMATION
- * \brief Used to set the allocation size for a file.
- *
- * The struct is requested during IRP_MJ_SET_INFORMATION with query FileAllocationInformation
- */
-typedef struct _FILE_ALLOCATION_INFORMATION {
- /**
- * File allocation size, in bytes. Usually this value is a multiple
- * of the sector or cluster size of the underlying physical device.
- */
- LARGE_INTEGER AllocationSize;
-} FILE_ALLOCATION_INFORMATION, *PFILE_ALLOCATION_INFORMATION;
-
-/**
- * \struct FILE_LINK_INFORMATION
- * \brief Used to create an NTFS hard link to an existing file.
- *
- * The struct is requested during IRP_MJ_SET_INFORMATION with query FileLinkInformation
- */
-typedef struct _FILE_LINK_INFORMATION {
- /**
- * Set to TRUE to specify that if the link already exists, it should be replaced with the new link.
- * Set to FALSE if the link creation operation should fail if the link already exists.
- */
- BOOLEAN ReplaceIfExists;
- /**
- * If the link is to be created in the same directory as the file that is being linked to,
- * or if the FileName member contains the full pathname for the link to be created, this is NULL.
- * Otherwise it is a handle for the directory where the link is to be created.
- */
- HANDLE RootDirectory;
- /**
- * Length, in bytes, of the file name string.
- */
- ULONG FileNameLength;
- /**
- * The first character of the name to be assigned to the newly created link.
- * This is followed in memory by the remainder of the string.
- * If the RootDirectory member is NULL and the link is to be created in a different directory from the file that is being linked to,
- * this member specifies the full pathname for the link to be created. Otherwise, it specifies only the file name.
- * (See the Remarks section for ZwQueryInformationFile for details on the syntax of this file name string.)
- */
- WCHAR FileName[1];
-} FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION;
-
-/**
- * \struct FILE_RENAME_INFORMATION
- * \brief Used to rename a file.
- *
- * The struct is requested during IRP_MJ_SET_INFORMATION with query FileRenameInformation
- */
-typedef struct _FILE_RENAME_INFORMATION {
- /**
- * Set to TRUE to specify that if a file with the given name already exists, it should be replaced with the given file.
- * Set to FALSE if the rename operation should fail if a file with the given name already exists.
- */
- BOOLEAN ReplaceIfExists;
- /**
- * If the file is not being moved to a different directory,
- * or if the FileName member contains the full pathname, this member is NULL. Otherwise,
- * it is a handle for the root directory under which the file will reside after it is renamed.
- */
- HANDLE RootDirectory;
- /**
- * Length, in bytes, of the new name for the file.
- */
- ULONG FileNameLength;
- /**
- * The first character of a wide-character string containing the new name for the file.
- * This is followed in memory by the remainder of the string. If the RootDirectory member is NULL,
- * and the file is being moved to a different directory, this member specifies the full pathname to be assigned to the file.
- * Otherwise, it specifies only the file name or a relative pathname.
- */
- WCHAR FileName[1];
-} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;
-
-/**
- * \struct FILE_STREAM_INFORMATION
- * \brief Used to enumerate the streams for a file.
- *
- * The struct is requested during IRP_MJ_SET_INFORMATION query FileStreamInformation
- */
-typedef struct _FILE_STREAM_INFORMATION {
- /**
- * The offset of the next FILE_STREAM_INFORMATION entry.
- * This member is zero if no other entries follow this one.
- */
- ULONG NextEntryOffset;
- /**
- * Length, in bytes, of the StreamName string.
- */
- ULONG StreamNameLength;
- /**
- * Size, in bytes, of the stream.
- */
- LARGE_INTEGER StreamSize;
- /**
- * File stream allocation size, in bytes. Usually this value is a multiple of the sector
- * or cluster size of the underlying physical device.
- */
- LARGE_INTEGER StreamAllocationSize;
- /**
- * Unicode string that contains the name of the stream.
- */
- WCHAR StreamName[1];
-} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION;
-
-/**
- * \struct FILE_FS_LABEL_INFORMATION
- * \brief Used to set the label for a file system volume.
- *
- * The struct is requested during IRP_MJ_SET_VOLUME_INFORMATION query FileFsLabelInformation
- */
-typedef struct _FILE_FS_LABEL_INFORMATION {
- /**
- * Length, in bytes, of the name for the volume.
- */
- ULONG VolumeLabelLength;
- /**
- * Name for the volume.
- */
- WCHAR VolumeLabel[1];
-} FILE_FS_LABEL_INFORMATION, *PFILE_FS_LABEL_INFORMATION;
-
-/**
- * \struct FILE_FS_VOLUME_INFORMATION
- * \brief Used to query information about a volume on which a file system is mounted.
- *
- * The struct is requested during IRP_MJ_QUERY_VOLUME_INFORMATION query FileFsVolumeInformation
- */
-typedef struct _FILE_FS_VOLUME_INFORMATION {
- /**
- * Time when the volume was created.
- */
- LARGE_INTEGER VolumeCreationTime;
- /**
- * Serial number of the volume.
- */
- ULONG VolumeSerialNumber;
- /**
- * Length, in bytes, of the name of the volume.
- */
- ULONG VolumeLabelLength;
- /**
- * TRUE if the file system supports object-oriented file system objects, FALSE otherwise.
- */
- BOOLEAN SupportsObjects;
- /**
- * Name of the volume.
- */
- WCHAR VolumeLabel[1];
-} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION;
-
-/**
- * \struct FILE_FS_SIZE_INFORMATION
- * \brief Used to query sector size information for a file system volume.
- *
- * The struct is requested during IRP_MJ_QUERY_VOLUME_INFORMATION query FileFsSizeInformation
- */
-typedef struct _FILE_FS_SIZE_INFORMATION {
- /**
- * Total number of allocation units on the volume that are available to the user associated with the calling thread.
- * If per-user quotas are in use, this value may be less than the total number of allocation units on the disk.
- */
- LARGE_INTEGER TotalAllocationUnits;
- /**
- * Total number of free allocation units on the volume that are available to the user associated with the calling thread.
- * If per-user quotas are in use, this value may be less than the total number of free allocation units on the disk.
- */
- LARGE_INTEGER AvailableAllocationUnits;
- /**
- * Number of sectors in each allocation unit.
- */
- ULONG SectorsPerAllocationUnit;
- /**
- * Number of bytes in each sector.
- */
- ULONG BytesPerSector;
-} FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION;
-
-/**
- * \struct FILE_FS_FULL_SIZE_INFORMATION
- * \brief Used to query sector size information for a file system volume.
- *
- * The struct is requested during IRP_MJ_QUERY_VOLUME_INFORMATION query FileFsFullSizeInformation
- */
-typedef struct _FILE_FS_FULL_SIZE_INFORMATION {
- /**
- * Total number of allocation units on the volume that are available to the user associated with the calling thread.
- * If per-user quotas are in use, this value may be less than the total number of allocation units on the disk.
- */
- LARGE_INTEGER TotalAllocationUnits;
- /**
- * Total number of free allocation units on the volume that are available to the user associated with the calling thread.
- * If per-user quotas are in use, this value may be less than the total number of free allocation units on the disk.
- */
- LARGE_INTEGER CallerAvailableAllocationUnits;
- /**
- * Total number of free allocation units on the volume.
- */
- LARGE_INTEGER ActualAvailableAllocationUnits;
- /**
- * Number of sectors in each allocation unit.
- */
- ULONG SectorsPerAllocationUnit;
- /**
- * Number of bytes in each sector.
- */
- ULONG BytesPerSector;
-} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
-
-/**
- * \struct FILE_FS_ATTRIBUTE_INFORMATION
- * \brief Used to query attribute information for a file system.
- *
- * The struct is requested during IRP_MJ_QUERY_VOLUME_INFORMATION query FileFsAttributeInformation
- */
-typedef struct _FILE_FS_ATTRIBUTE_INFORMATION {
- /**
- * Bitmask of flags specifying attributes of the specified file system.
- * \see https://msdn.microsoft.com/en-us/library/windows/hardware/ff540251(v=vs.85).aspx
- */
- ULONG FileSystemAttributes;
- /**
- * Maximum file name component length, in bytes, supported by the specified file system.
- * A file name component is that portion of a file name between backslashes.
- */
- LONG MaximumComponentNameLength;
- /**
- * Length, in bytes, of the file system name.
- */
- ULONG FileSystemNameLength;
- /**
- * File system name.
- */
- WCHAR FileSystemName[1];
-} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION;
-
-/**
- * \struct FILE_NETWORK_OPEN_INFORMATION
- * \brief Used as an argument to ZwQueryInformationFile.
- *
- * The struct is requested during IRP_MJ_QUERY_VOLUME_INFORMATION query FileNetworkOpenInformation
- */
-typedef struct _FILE_NETWORK_OPEN_INFORMATION {
- /**
- * Specifies the time that the file was created.
- */
- LARGE_INTEGER CreationTime;
- /**
- * Specifies the time that the file was last accessed.
- */
- LARGE_INTEGER LastAccessTime;
- /**
- * Specifies he time that the file was last written to.
- */
- LARGE_INTEGER LastWriteTime;
- /**
- * Specifies the time that the file was last changed.
- */
- LARGE_INTEGER ChangeTime;
- /**
- * Specifies the file allocation size, in bytes. Usually,
- * this value is a multiple of the sector or cluster size of the underlying physical device.
- */
- LARGE_INTEGER AllocationSize;
- /**
- * Specifies the absolute end-of-file position as a byte offset from the start of the file.
- * EndOfFile specifies the byte offset to the end of the file. Because this value is zero-based,
- * it actually refers to the first free byte in the file. In other words,
- * EndOfFile is the offset to the byte immediately following the last valid byte in the file.
- */
- LARGE_INTEGER EndOfFile;
- /**
- * Specifies one or more FILE_ATTRIBUTE_XXX flags. For descriptions of these flags,
- * see the documentation of the GetFileAttributes function in the Microsoft Windows SDK.
- */
- ULONG FileAttributes;
-} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION;
-
-/**
- * \struct FILE_NETWORK_PHYSICAL_NAME_INFORMATION
- * \brief Contains the full UNC physical pathname for a file or directory on a remote file share.
- *
- * The struct is requested during IRP_MJ_QUERY_VOLUME_INFORMATION query FileNetworkPhysicalNameInformation
- */
-typedef struct _FILE_NETWORK_PHYSICAL_NAME_INFORMATION {
- /**
- * The length, in bytes, of the physical name in FileName.
- */
- ULONG FileNameLength;
- /**
- * The full UNC path of the network file share of the target.
- */
- WCHAR FileName[1];
-} FILE_NETWORK_PHYSICAL_NAME_INFORMATION,
- *PFILE_NETWORK_PHYSICAL_NAME_INFORMATION;
-
-#define SL_RESTART_SCAN 0x01
-#define SL_RETURN_SINGLE_ENTRY 0x02
-#define SL_INDEX_SPECIFIED 0x04
-#define SL_FORCE_ACCESS_CHECK 0x01
-
-#define SL_OPEN_PAGING_FILE 0x02
-#define SL_OPEN_TARGET_DIRECTORY 0x04
-#define SL_CASE_SENSITIVE 0x80
-
-#define ALIGN_DOWN(length, type) ((ULONG)(length) & ~(sizeof(type) - 1))
-
-#define ALIGN_UP(length, type) \
- (ALIGN_DOWN(((ULONG)(length) + sizeof(type) - 1), type))
-
-#define ALIGN_DOWN_POINTER(address, type) \
- ((PVOID)((ULONG_PTR)(address) & ~((ULONG_PTR)sizeof(type) - 1)))
-
-#define ALIGN_UP_POINTER(address, type) \
- (ALIGN_DOWN_POINTER(((ULONG_PTR)(address) + sizeof(type) - 1), type))
-
-#define WordAlign(Val) (ALIGN_UP(Val, WORD))
-
-#define WordAlignPtr(Ptr) (ALIGN_UP_POINTER(Ptr, WORD))
-
-#define LongAlign(Val) (ALIGN_UP(Val, LONG))
-
-#define LongAlignPtr(Ptr) (ALIGN_UP_POINTER(Ptr, LONG))
-
-#define QuadAlign(Val) (ALIGN_UP(Val, ULONGLONG))
-
-#define QuadAlignPtr(Ptr) (ALIGN_UP_POINTER(Ptr, ULONGLONG))
-
-#define IsPtrQuadAligned(Ptr) (QuadAlignPtr(Ptr) == (PVOID)(Ptr))
-
-// from wdm.h
-#define FILE_SUPERSEDE 0x00000000
-#define FILE_OPEN 0x00000001
-#define FILE_CREATE 0x00000002
-#define FILE_OPEN_IF 0x00000003
-#define FILE_OVERWRITE 0x00000004
-#define FILE_OVERWRITE_IF 0x00000005
-#define FILE_MAXIMUM_DISPOSITION 0x00000005
-
-#define FILE_DIRECTORY_FILE 0x00000001
-#define FILE_WRITE_THROUGH 0x00000002
-#define FILE_SEQUENTIAL_ONLY 0x00000004
-#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008
-
-#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010
-#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
-#define FILE_NON_DIRECTORY_FILE 0x00000040
-#define FILE_CREATE_TREE_CONNECTION 0x00000080
-
-#define FILE_COMPLETE_IF_OPLOCKED 0x00000100
-#define FILE_NO_EA_KNOWLEDGE 0x00000200
-#define FILE_OPEN_REMOTE_INSTANCE 0x00000400
-#define FILE_RANDOM_ACCESS 0x00000800
-
-#define FILE_DELETE_ON_CLOSE 0x00001000
-#define FILE_OPEN_BY_FILE_ID 0x00002000
-#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000
-#define FILE_NO_COMPRESSION 0x00008000
-
-#if (_WIN32_WINNT >= _WIN32_WINNT_WIN7)
-#define FILE_OPEN_REQUIRING_OPLOCK 0x00010000
-#define FILE_DISALLOW_EXCLUSIVE 0x00020000
-#endif /* _WIN32_WINNT >= _WIN32_WINNT_WIN7 */
-#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
-#define FILE_SESSION_AWARE 0x00040000
-#endif /* _WIN32_WINNT >= _WIN32_WINNT_WIN7 */
-
-#define FILE_RESERVE_OPFILTER 0x00100000
-#define FILE_OPEN_REPARSE_POINT 0x00200000
-#define FILE_OPEN_NO_RECALL 0x00400000
-#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000
-
-#define FILE_VALID_OPTION_FLAGS 0x00ffffff
-
-#define FILE_SUPERSEDED 0x00000000
-#define FILE_OPENED 0x00000001
-#define FILE_CREATED 0x00000002
-#define FILE_OVERWRITTEN 0x00000003
-#define FILE_EXISTS 0x00000004
-#define FILE_DOES_NOT_EXIST 0x00000005
-
-#define FILE_WRITE_TO_END_OF_FILE 0xffffffff
-#define FILE_USE_FILE_POINTER_POSITION 0xfffffffe
-
-/**
- * \struct UNICODE_STRING
- * \brief Structure is used to define Unicode strings.
- */
-typedef struct _UNICODE_STRING {
- /**
- * The length, in bytes, of the string stored in Buffer.
- */
- USHORT Length;
- /**
- * The length, in bytes, of Buffer.
- */
- USHORT MaximumLength;
- /**
- * Pointer to a buffer used to contain a string of wide characters.
- */
- PWSTR Buffer;
-} UNICODE_STRING, *PUNICODE_STRING;
-
-#endif // FILEINFO_H_
diff --git a/MemProcFS/leechcore.h b/MemProcFS/leechcore.h
deleted file mode 100644
index a2da3e6..0000000
--- a/MemProcFS/leechcore.h
+++ /dev/null
@@ -1,466 +0,0 @@
-// leechcore.h : header file for the leechcore module - which purpose is to
-// expose low-level device physical memory functionality.
-//
-// This library is thread-safe in all functions with the notable exceptions of
-// the LeechCore_Open() and LeechCore_Close() functions. Some devices may allow
-// multi-threaded access while in reality most devices are single-threaded and
-// will control synchronization where necessary with locks.
-//
-// The library is initialized by calling LeechCore_Open with a LEECHCORE_CONFIG
-// struct containing the correct configuration paramters. Note that the version
-// and magic values must be set in addition to the szDevice configuration value
-// Also, it may be possible to optionally connect to a remote leechcore service
-// or instance over RPC by specifying a szRemote configuration value.
-//
-// ----------------------------------------------------------------------------
-//
-// Remote instance: szRemote configuration value. Connect to a remote leechcore
-// instance by specifying a configuration value in the szRemote parameter. If a
-// loaded already valid instance exists remotely this will be prioritized above
-// the value in szDevice. If the acquisition device is not yet loaded by the
-// remote instance the value in szDevice will be used. Normally, the connection
-// will take place as a mutually authenticated encrypted connection secured by
-// kerberos. If not possible or desirable the 'insecure' value may be specified
-// to disable authentication and security.
-// Syntax:
-// rpc://:: (port = optional, remote_spn = kerberos)
-// (SPN of remote service or 'insecure' )
-// Examples:
-// rpc://insecure:remotehost.example.com (connect insecure to remote host )
-// rpc://user@ad.domain.com:192.0.0.5 (connect secure to remote host )
-// rpc://insecure:127.0.0.0:6666 (connect insecure non-default port)
-//
-// ----------------------------------------------------------------------------
-//
-// Device to connect to: szDevice contains the device to capture memory from.
-// Supported memory acquisition devices are:
-// USB3380 : hardware, read/write, 32-bit (4GB) addressing only. Requires a
-// PCILeech flashed USB3380 device connected over USB and Google
-// Android WinUSB drivers to be installed. Download and install from:
-// http://developer.android.com/sdk/win-usb.html#download
-// Syntax:
-// USB3380
-// USB3380://USB2 (force USB2 connection speed)
-//
-// FPGA : hardware, read/write - requires a PCILeech FPGA flashed hardware
-// device as shown at: https://github.com/ufrisk/pcileech-fpga
-// Also requires the FTD3XX.DLL from ftdichip to be placed in the
-// same directory as the executable. Download from ftdichip at:
-// http://www.ftdichip.com/Drivers/D3XX/FTD3XXLibrary_v1.2.0.6.zip
-// Syntax:
-// FGPA
-// FPGA://[:[:]] (values are optional)
-//
-// SP605TCP : hardware, read/write - connect to a remote SP605 FPGA over the
-// network using the implementation created by @d_olex.
-// https://github.com/Cr4sh/s6_pcie_microblaze
-// Syntax:
-// SP605TCP://[:] (port is optional)
-//
-// RAWTCP : read/write - connect to a remote raw tcp device - such as HPE iLO
-// that have been patched to support DMA as per blog entry below:
-// https://www.synacktiv.com/posts/exploit/using-your-bmc-as-a-dma-device-plugging-pcileech-to-hpe-ilo-4.html
-// Syntax:
-// RAWTCP://[:] (port is optional)
-//
-// HvSavedState : read-only - connect to a Hyper-V saved state file. In order
-// to do so the .dll file 'vmsavedstatedumpprovider.dll' must be
-// placed in same directory as the executable file.
-//
-// PMEM : load the rekall winpmem driver into the kernel and connect to it
-// to acquire memory. The driver file 'winpmem_x64.sys' is found in
-// the Rekall directory after most recent version has been installed.
-// Copy 'winpmem_x64.sys' to the directory of leechcore.dll and run
-// executable as elevated admin using syntax below:
-// Syntax:
-// PMEM (use winpmem_x64.sys in directory of executable)
-// PMEM://
-//
-// TOTALMELTDOWN : read/write - requires a Windows 7 system vulnerable to the
-// "Total Meltdown" vulnerability - CVE-2018-1038.
-// Syntax:
-// TOTALMELTDOWN
-//
-// FILE : use dump file, either a raw linear memory dump or full crash dump.
-// Which format to use is auto-detected. If it looks like a full cash
-// dump that format will be used, otherwise it will be assumed that a
-// raw linear memory dump is to be used.
-// Syntax:
-// (no device-type prefix - just use the file name)
-// FILE://
-//
-// DumpIt : DumpIt is a "virtual" device. It's only possible to use the DumpIt
-// device if the main process containing LeechCore has been started
-// with DumpIt in LiveKD mode.
-// Example 1:
-// DumpIt.exe /LIVEKD /A MemProcFS.exe
-// Example 2:
-// DumpIt.exe /LIVEKD /A LeechSvc.exe /C "interactive insecure"
-// and then connect to remote service by:
-// MemProcFS.exe -remote rpc://insecure:192.168.x.x -device DumpIt
-//
-// EXISTING : Attach to existing already loaded configuration. This is done
-// instead of the default behaviour of closing any existing devices
-// and initializing the new requested device. If no existing device
-// exists the call to LeechCore_Open will fail.
-// Syntax:
-// EXISTING
-//
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 1.0
-//
-#ifndef __LEECHCORE_H__
-#define __LEECHCORE_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// WINDOWS / LINUX COMPATIBILITY BELOW:
-//-----------------------------------------------------------------------------
-
-#ifdef _WIN32
-#include
-typedef unsigned __int64 QWORD, *PQWORD;
-#define DLLEXPORT __declspec(dllexport)
-#endif /* _WIN32 */
-#ifdef LINUX
-#include
-#include
-typedef void VOID, *PVOID, *LPVOID;
-typedef void *HANDLE, **PHANDLE;
-typedef uint32_t BOOL, *PBOOL;
-typedef uint8_t BYTE, *PBYTE;
-typedef char CHAR, *PCHAR, *PSTR, *LPSTR;
-typedef uint16_t WORD, *PWORD, USHORT, *PUSHORT;
-typedef uint32_t DWORD, *PDWORD;
-typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64;
-#define MAX_PATH 260
-#define DLLEXPORT __attribute__((visibility("default")))
-#define _In_
-#define _Out_
-#define _In_z_
-#define _Inout_
-#define _In_opt_
-#define _Out_opt_
-#define _Out_writes_(x)
-#define _Check_return_opt_
-#define _Printf_format_string_
-#define _Inout_updates_bytes_(x)
-#define _In_reads_(cbDataIn)
-#define _Success_(return)
-#endif /* LINUX */
-
-//-----------------------------------------------------------------------------
-// GENERAL HEADER DEFINES BELOW:
-//-----------------------------------------------------------------------------
-
-#define MEM_IO_SCATTER_HEADER_MAGIC 0xffff6548
-#define MEM_IO_SCATTER_HEADER_VERSION 0x0003
-
-typedef struct tdMEM_IO_SCATTER_HEADER {
- DWORD magic; // magic
- WORD version; // version
- WORD Future1;
- ULONG64 qwA; // base address.
- DWORD cbMax; // bytes to read (DWORD boundry, max 0x1000); pb must have room for this.
- DWORD cb; // bytes read into result buffer.
- PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
- PVOID pvReserved1; // reserved for use by caller.
- PVOID pvReserved2; // reserved for use by caller.
- PVOID Future2[8];
-} MEM_IO_SCATTER_HEADER, *PMEM_IO_SCATTER_HEADER, **PPMEM_IO_SCATTER_HEADER;
-
-//-----------------------------------------------------------------------------
-// LEECHCORE INITIALIZATION / CLOSE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-typedef enum tdLEECHCORE_DEVICE {
- LEECHCORE_DEVICE_NA = 0,
- LEECHCORE_DEVICE_FILE = 1,
- LEECHCORE_DEVICE_PMEM = 2,
- LEECHCORE_DEVICE_FPGA = 3,
- LEECHCORE_DEVICE_SP605_TCP = 4,
- LEECHCORE_DEVICE_USB3380 = 5,
- LEECHCORE_DEVICE_TOTALMELTDOWN = 6,
- LEECHCORE_DEVICE_HVSAVEDSTATE = 7,
- LEECHCORE_DEVICE_RAWTCP = 8,
-} LEECHCORE_DEVICE;
-
-#define LEECHCORE_CONFIG_MAGIC 0xffff6549
-#define LEECHCORE_CONFIG_VERSION 0x0001
-
-#define LEECHCORE_CONFIG_FLAG_PRINTF 0x0001
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_1 0x0002
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_2 0x0004
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_3 0x0008
-#define LEECHCORE_CONFIG_FLAG_REMOTE_NO_COMPRESS 0x0010
-
-typedef struct tdLEECHCORE_CONFIG {
- DWORD magic; // set by caller.
- WORD version; // set by caller.
- WORD flags; // set by caller, updated by device.
- ULONG64 paMax; // set by caller, updated by device.
- ULONG64 cbMaxSizeMemIo; // set by caller, updated by device.
- ULONG64 paMaxNative; // set by device.
- LEECHCORE_DEVICE tpDevice; // set by device.
- BOOL fWritable; // set by device. (is device writable?)
- BOOL fVolatile; // set by device. (is device volatile / memory may change?)
- BOOL fVolatileMaxAddress; // set by device. (is max address volatile? - poll changes with LEECHCORE_OPT_MEMORYINFO_ADDR_MAX)
- BOOL fRemote; // set by device.
- WORD VersionMajor; // set by device.
- WORD VersionMinor; // set by device.
- WORD VersionRevision; // set by device.
- CHAR szDevice[MAX_PATH]; // set by caller.
- CHAR szRemote[MAX_PATH]; // set by caller.
- // optional 'printf' function pointer. if set to non null value 'printf'
- // calls will be redirected. useful when logging to files.
- _Check_return_opt_ int(*pfn_printf_opt)(_In_z_ _Printf_format_string_ char const* const _Format, ...); // set by caller.
-} LEECHCORE_CONFIG, *PLEECHCORE_CONFIG;
-
-typedef struct tdLEECHCORE_PAGESTAT_MINIMAL {
- HANDLE h;
- VOID(*pfnPageStatUpdate)(HANDLE h, ULONG64 pa, ULONG64 cPageSuccessAdd, ULONG64 cPageFailAdd);
-} LEECHCORE_PAGESTAT_MINIMAL, *PLEECHCORE_PAGESTAT_MINIMAL;
-
-/*
-* Open a connection to the target device.
-* -- pInformation
-* -- result
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Open(_Inout_ PLEECHCORE_CONFIG pConfig);
-
-/*
-* Clean up various device related stuff and deallocate memory buffers.
-*/
-DLLEXPORT VOID LeechCore_Close();
-
-
-
-//-----------------------------------------------------------------------------
-// LEECHCORE CORE READ AND WRITE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_FLAG_READ_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_VERIFY 0x02
-
-/*
-* Allocate a scatter buffer containing empty 0x1000-sized ppMEMs with address
-* set to zero. Caller is responsible for calling LocalFree(ppMEMs).
-* -- cMEMs
-* -- pppMEMs = pointer to receive ppMEMs on success.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_AllocScatterEmpty(_In_ DWORD cMEMs, _Out_ PPMEM_IO_SCATTER_HEADER *pppMEMs);
-
-/*
-* Read memory in various non-contigious locations specified by the items in the
-* phDMAs array. Result for each unit of work will be given individually. No upper
-* limit of number of items to read, but no performance boost will be given if
-* above hardware limit. Max size of each unit of work is one 4k page (4096 bytes).
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-*/
-DLLEXPORT VOID LeechCore_ReadScatter(_Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_Read(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_READ_RETRY
-* -- pPageStat = optional minimal statistic struct to update.
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_ReadEx(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb, _In_ DWORD flags, _In_opt_ PLEECHCORE_PAGESTAT_MINIMAL pPageStat);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Write(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_WRITE_*
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_WriteEx(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD flags);
-
-/*
-* Probe the memory of the target system to check whether it's readable or not.
-* Please note that not all devices support this natively.
-* -- pa = address to start probe from.
-* -- cPages = number of 4kB pages to probe.
-* -- pbResultMap = result map, 1 byte represents 1 page, 0 = fail, 1 = success.
-* (individual page elements in pbResultMap must be set to 0 [fail] on call
-* for probe to take place on individual page).
-* -- return = FALSE if not supported by underlying hardware, TRUE if supported.
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Probe(_In_ QWORD pa, _In_ DWORD cPages, _Inout_updates_bytes_(cPages) PBYTE pbResultMap);
-
-
-
-//-----------------------------------------------------------------------------
-// GET/SET DEVICE OPTIONS BELOW. SOME OPTIONS ARE GENERAL LEECHCORE OPTIONS
-// WHILE OTHER ARE DEVICE SPECIFIC. USE FUNCTIONS:
-// LeechCore_GetOption() AND LeechCore_GetOption() TO GET/SET OPTIONS.
-// FOR DEVICE-SPECIFIC OPTIONS PLEASE SEE INDIVIDUAL DEVICE FILES FOR MORE
-// DETAILED INFORMATION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE 0x80000002 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-
-#define LEECHCORE_OPT_CORE_VERSION_MAJOR 0x01000001 // R
-#define LEECHCORE_OPT_CORE_VERSION_MINOR 0x01000002 // R
-#define LEECHCORE_OPT_CORE_VERSION_REVISION 0x01000003 // R
-
-#define LEECHCORE_OPT_MEMORYINFO_VALID 0x02000001 // R
-#define LEECHCORE_OPT_MEMORYINFO_ADDR_MAX 0x02000002 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_32BIT 0x02000003 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_PAE 0x02000004 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MINOR 0x02000005 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MAJOR 0x02000006 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_DTB 0x02000007 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PFN 0x02000008 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsLoadedModuleList 0x02000009 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsActiveProcessHead 0x0200000a // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_MACHINE_IMAGE_TP 0x0200000b // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_NUM_PROCESSORS 0x0200000c // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_SYSTEMTIME 0x0200000d // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_UPTIME 0x0200000e // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELBASE 0x0200000f // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELHINT 0x02000010 // R
-
-#define LEECHCORE_OPT_FPGA_PROBE_MAXPAGES 0x03000001 // RW
-#define LEECHCORE_OPT_FPGA_RX_FLUSH_LIMIT 0x03000002 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_RX 0x03000003 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_TX 0x03000004 // RW
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_READ 0x03000005 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_WRITE 0x03000006 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_WRITE 0x03000007 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_READ 0x03000008 // RW - uS
-#define LEECHCORE_OPT_FPGA_RETRY_ON_ERROR 0x03000009 // RW
-#define LEECHCORE_OPT_FPGA_DEVICE_ID 0x03000080 // R
-#define LEECHCORE_OPT_FPGA_FPGA_ID 0x03000081 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MAJOR 0x03000082 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MINOR 0x03000083 // R
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- pqwValue = pointer to QWORD to receive option value.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_GetOption(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- qwValue
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_SetOption(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// TRANSFER DEVICE DEPENDANT COMMANDS OR DATA TO/FROM UNDERLYING DEVICES AND
-// PERFORM ACTIONS USING THE LeechCore_CommandData() FUNCTION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_COMMANDDATA_FPGA_WRITE_TLP 0x00000101 // R
-#define LEECHCORE_COMMANDDATA_FPGA_LISTEN_TLP 0x00000102 // R
-#define LEECHCORE_COMMANDDATA_STATISTICS_GET 0x80000100 // R
-
-#define LEECHCORE_STATISTICS_MAGIC 0xffff6550
-#define LEECHCORE_STATISTICS_VERSION 0x0001
-#define LEECHCORE_STATISTICS_ID_OPEN 0x00
-#define LEECHCORE_STATISTICS_ID_READSCATTER 0x01
-#define LEECHCORE_STATISTICS_ID_WRITE 0x02
-#define LEECHCORE_STATISTICS_ID_PROBE 0x03
-#define LEECHCORE_STATISTICS_ID_GETOPTION 0x04
-#define LEECHCORE_STATISTICS_ID_SETOPTION 0x05
-#define LEECHCORE_STATISTICS_ID_COMMANDDATA 0x06
-#define LEECHCORE_STATISTICS_ID_MAX 0x06
-
-static const LPSTR LEECHCORE_STATISTICS_NAME[] = {
- "LeechCore_Open",
- "LeechCore_ReadScatter",
- "LeechCore_Write",
- "LeechCore_Probe",
- "LeechCore_GetOption",
- "LeechCore_SetOption",
- "LeechCore_CommandData"
-};
-
-typedef struct tdLEECHCORE_STATISTICS {
- DWORD magic;
- WORD version;
- WORD Reserved0;
- DWORD Reserved1;
- QWORD qwFreq;
- struct {
- QWORD c;
- QWORD tm; // total time in qwFreq ticks
- } Call[0x10];
-} LEECHCORE_STATISTICS, *PLEECHCORE_STATISTICS;
-
-/*
-* Transfer device dependant commands/data to/from the underlying device and
-* perform device dependant actions.
-* -- fOption
-* -- cbDataIn
-* -- pbDataIn
-* -- pbDataOut
-* -- cbDataOut
-* -- pcbDataOut
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_CommandData(
- _In_ ULONG64 fOption,
- _In_reads_(cbDataIn) PBYTE pbDataIn,
- _In_ DWORD cbDataIn,
- _Out_writes_(cbDataOut) PBYTE pbDataOut,
- _In_ DWORD cbDataOut,
- _Out_ PDWORD pcbDataOut
-);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __LEECHCORE_H__ */
diff --git a/MemProcFS/memprocfs.c b/MemProcFS/memprocfs.c
deleted file mode 100644
index e265df2..0000000
--- a/MemProcFS/memprocfs.c
+++ /dev/null
@@ -1,83 +0,0 @@
-// memprocfs.h : implementation of core functionality for the Memory Process File System
-// This is just a thin loader for the virtual memory manager dll which contains the logic.
-//
-// (c) Ulf Frisk, 2018
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include
-#include
-#include "vmmdll.h"
-#include "vfs.h"
-
-/*
-* Retrieve the mount point from the command line arguments. If no '-mount'
-* command line argument is given the default mount point will be: M:
-* -- argc
-* -- argv
-* -- return = the mount point as a drive letter.
-*/
-CHAR GetMountPoint(_In_ DWORD argc, _In_ char* argv[])
-{
- CHAR chMountMount = 'M';
- DWORD i = 1;
- for(i = 0; i < argc - 1; i++) {
- if(0 == strcmp(argv[i], "-mount")) {
- chMountMount = argv[i + 1][0];
- break;
- }
- }
- if((chMountMount > 'A' && chMountMount < 'Z') || (chMountMount > 'a' && chMountMount < 'z')) {
- return chMountMount;
- }
- return 'M';
-}
-
-/*
-* Main entry point of the memory process file system. The main function will
-* load and initialize VMM.DLL then initialize the VMM.DLL plugin manager and
-* then hand over control to vfs.c!VfsInitializeAndMount which will start the
-* dokany virtual file system and mount it at the correct mount point.
-* All 'interesting' functionality will take part in VMM.DLL - the memprocfs
-* executable should be considered as a thin wrapper around VMM.DLL.
-* -- argc
-* -- argv
-* -- return
-*/
-int main(_In_ int argc, _In_ char* argv[])
-{
- BOOL result;
- HMODULE hVMM;
- VMMDLL_FUNCTIONS VmmDll;
- LoadLibraryA("leechcore.dll");
- hVMM = LoadLibraryExA("vmm.dll", NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR);
- if(!hVMM) {
- printf("MemProcFS: Error loading vmm.dll - ensure vmm.dll resides in the memprocfs.exe application directory!\n");
- return 1;
- }
- VmmDll.Initialize = (BOOL(*)(DWORD, LPSTR*))GetProcAddress(hVMM, "VMMDLL_Initialize");
- VmmDll.ConfigGet = (BOOL(*)(ULONG64, PULONG64))GetProcAddress(hVMM, "VMMDLL_ConfigGet");
- VmmDll.ConfigSet = (BOOL(*)(ULONG64, ULONG64))GetProcAddress(hVMM, "VMMDLL_ConfigSet");
- VmmDll.VfsList = (BOOL(*)(LPCWSTR, PVMMDLL_VFS_FILELIST))GetProcAddress(hVMM, "VMMDLL_VfsList");
- VmmDll.VfsRead = (DWORD(*)(LPCWSTR, LPVOID, DWORD, PDWORD, ULONG64))GetProcAddress(hVMM, "VMMDLL_VfsRead");
- VmmDll.VfsWrite = (DWORD(*)(LPCWSTR, LPVOID, DWORD, PDWORD, ULONG64))GetProcAddress(hVMM, "VMMDLL_VfsWrite");
- VmmDll.VfsInitializePlugins = (BOOL(*)())GetProcAddress(hVMM, "VMMDLL_VfsInitializePlugins");
- if(!VmmDll.Initialize || !VmmDll.ConfigGet || !VmmDll.VfsList || !VmmDll.VfsRead || !VmmDll.VfsWrite || !VmmDll.VfsInitializePlugins) {
- printf("MemProcFS: Error loading vmm.dll - invalid version of vmm.dll found!\n");
- return 1;
- }
- argv[0] = "-printf";
- result = VmmDll.Initialize(argc, argv);
- if(!result) {
- // any error message will already be shown by the InitializeReserved function.
- return 1;
- }
- VmmDll.ConfigSet(VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL, 1);
- result = VmmDll.VfsInitializePlugins();
- if(!result) {
- printf("MemProcFS: Error file system plugins in vmm.dll!\n");
- return 1;
- }
- VfsInitializeAndMount(GetMountPoint(argc, argv), &VmmDll);
- ExitProcess(0);
- return 0;
-}
diff --git a/MemProcFS/public.h b/MemProcFS/public.h
deleted file mode 100644
index c828590..0000000
--- a/MemProcFS/public.h
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- Dokan : user-mode file system library for Windows
-
- Copyright (C) 2015 - 2018 Adrien J. and Maxime C.
- Copyright (C) 2017 Google, Inc.
- Copyright (C) 2007 - 2011 Hiroki Asakawa
-
- http://dokan-dev.github.io
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU Lesser General Public License as published by the Free
-Software Foundation; either version 3 of the License, or (at your option) any
-later version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program. If not, see .
-*/
-
-#ifndef PUBLIC_H_
-#define PUBLIC_H_
-
-#ifndef DOKAN_MAJOR_API_VERSION
-#define DOKAN_MAJOR_API_VERSION L"1"
-#include
-#endif
-
-#define DOKAN_DRIVER_VERSION 0x0000190
-
-#define EVENT_CONTEXT_MAX_SIZE (1024 * 32)
-
-#define IOCTL_TEST \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define IOCTL_SET_DEBUG_MODE \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define IOCTL_EVENT_WAIT \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define IOCTL_EVENT_INFO \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define IOCTL_EVENT_RELEASE \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define IOCTL_EVENT_START \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define IOCTL_EVENT_WRITE \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
-
-#define IOCTL_KEEPALIVE \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_NEITHER, FILE_ANY_ACCESS)
-
-#define IOCTL_SERVICE_WAIT \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80A, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define IOCTL_RESET_TIMEOUT \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80B, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define IOCTL_GET_ACCESS_TOKEN \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80C, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define IOCTL_EVENT_MOUNTPOINT_LIST \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80D, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define IOCTL_MOUNTPOINT_CLEANUP \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80E, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-// DeviceIoControl code to send to a keepalive handle to activate it (see the
-// documentation for the keepalive flags in the DokanFCB struct).
-#define FSCTL_ACTIVATE_KEEPALIVE \
- CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x80F, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define DRIVER_FUNC_INSTALL 0x01
-#define DRIVER_FUNC_REMOVE 0x02
-
-#define DOKAN_MOUNTED 1
-#define DOKAN_USED 2
-#define DOKAN_START_FAILED 3
-
-#define DOKAN_DEVICE_MAX 10
-
-#define DOKAN_DEFAULT_SECTOR_SIZE 512
-#define DOKAN_DEFAULT_ALLOCATION_UNIT_SIZE 512
-#define DOKAN_DEFAULT_DISK_SIZE 1024 * 1024 * 1024
-
-// used in CCB->Flags and FCB->Flags
-#define DOKAN_FILE_DIRECTORY 1
-#define DOKAN_FILE_DELETED 2
-#define DOKAN_FILE_OPENED 4
-#define DOKAN_DIR_MATCH_ALL 8
-#define DOKAN_DELETE_ON_CLOSE 16
-#define DOKAN_PAGING_IO 32
-#define DOKAN_SYNCHRONOUS_IO 64
-#define DOKAN_WRITE_TO_END_OF_FILE 128
-#define DOKAN_NOCACHE 256
-#define DOKAN_FILE_CHANGE_LAST_WRITE 512
-
-// used in DOKAN_START->DeviceType
-#define DOKAN_DISK_FILE_SYSTEM 0
-#define DOKAN_NETWORK_FILE_SYSTEM 1
-
-#define DOKAN_KEEPALIVE_FILE_NAME L"\\__drive_fs_keepalive"
-
-/*
- * This structure is used for copying UNICODE_STRING from the kernel mode driver
- * into the user mode driver.
- * https://msdn.microsoft.com/en-us/library/windows/hardware/ff564879(v=vs.85).aspx
- */
-typedef struct _DOKAN_UNICODE_STRING_INTERMEDIATE {
- USHORT Length;
- USHORT MaximumLength;
- WCHAR Buffer[1];
-} DOKAN_UNICODE_STRING_INTERMEDIATE, *PDOKAN_UNICODE_STRING_INTERMEDIATE;
-
-/*
- * This structure is used for copying ACCESS_STATE from the kernel mode driver
- * into the user mode driver.
- * https://msdn.microsoft.com/en-us/library/windows/hardware/ff538840(v=vs.85).aspx
-*/
-typedef struct _DOKAN_ACCESS_STATE_INTERMEDIATE {
- BOOLEAN SecurityEvaluated;
- BOOLEAN GenerateAudit;
- BOOLEAN GenerateOnClose;
- BOOLEAN AuditPrivileges;
- ULONG Flags;
- ACCESS_MASK RemainingDesiredAccess;
- ACCESS_MASK PreviouslyGrantedAccess;
- ACCESS_MASK OriginalDesiredAccess;
-
- // Offset from the beginning of this structure to a SECURITY_DESCRIPTOR
- // if 0 that means there is no security descriptor
- ULONG SecurityDescriptorOffset;
-
- // Offset from the beginning of this structure to a
- // DOKAN_UNICODE_STRING_INTERMEDIATE
- ULONG UnicodeStringObjectNameOffset;
-
- // Offset from the beginning of this structure to a
- // DOKAN_UNICODE_STRING_INTERMEDIATE
- ULONG UnicodeStringObjectTypeOffset;
-} DOKAN_ACCESS_STATE_INTERMEDIATE, *PDOKAN_ACCESS_STATE_INTERMEDIATE;
-
-typedef struct _DOKAN_ACCESS_STATE {
- BOOLEAN SecurityEvaluated;
- BOOLEAN GenerateAudit;
- BOOLEAN GenerateOnClose;
- BOOLEAN AuditPrivileges;
- ULONG Flags;
- ACCESS_MASK RemainingDesiredAccess;
- ACCESS_MASK PreviouslyGrantedAccess;
- ACCESS_MASK OriginalDesiredAccess;
- PSECURITY_DESCRIPTOR SecurityDescriptor;
- UNICODE_STRING ObjectName;
- UNICODE_STRING ObjectType;
-} DOKAN_ACCESS_STATE, *PDOKAN_ACCESS_STATE;
-
-/*
- * This structure is used for copying IO_SECURITY_CONTEXT from the kernel mode
- * driver into the user mode driver.
- * https://msdn.microsoft.com/en-us/library/windows/hardware/ff550613(v=vs.85).aspx
- */
-typedef struct _DOKAN_IO_SECURITY_CONTEXT_INTERMEDIATE {
- DOKAN_ACCESS_STATE_INTERMEDIATE AccessState;
- ACCESS_MASK DesiredAccess;
-} DOKAN_IO_SECURITY_CONTEXT_INTERMEDIATE,
- *PDOKAN_IO_SECURITY_CONTEXT_INTERMEDIATE;
-
-typedef struct _DOKAN_IO_SECURITY_CONTEXT {
- DOKAN_ACCESS_STATE AccessState;
- ACCESS_MASK DesiredAccess;
-} DOKAN_IO_SECURITY_CONTEXT, *PDOKAN_IO_SECURITY_CONTEXT;
-
-typedef struct _CREATE_CONTEXT {
- DOKAN_IO_SECURITY_CONTEXT_INTERMEDIATE SecurityContext;
- ULONG FileAttributes;
- ULONG CreateOptions;
- ULONG ShareAccess;
- ULONG FileNameLength;
-
- // Offset from the beginning of this structure to the string
- ULONG FileNameOffset;
-} CREATE_CONTEXT, *PCREATE_CONTEXT;
-
-typedef struct _CLEANUP_CONTEXT {
- ULONG FileNameLength;
- WCHAR FileName[1];
-
-} CLEANUP_CONTEXT, *PCLEANUP_CONTEXT;
-
-typedef struct _CLOSE_CONTEXT {
- ULONG FileNameLength;
- WCHAR FileName[1];
-
-} CLOSE_CONTEXT, *PCLOSE_CONTEXT;
-
-typedef struct _DIRECTORY_CONTEXT {
- ULONG FileInformationClass;
- ULONG FileIndex;
- ULONG BufferLength;
- ULONG DirectoryNameLength;
- ULONG SearchPatternLength;
- ULONG SearchPatternOffset;
- WCHAR DirectoryName[1];
- WCHAR SearchPatternBase[1];
-
-} DIRECTORY_CONTEXT, *PDIRECTORY_CONTEXT;
-
-typedef struct _READ_CONTEXT {
- LARGE_INTEGER ByteOffset;
- ULONG BufferLength;
- ULONG FileNameLength;
- WCHAR FileName[1];
-} READ_CONTEXT, *PREAD_CONTEXT;
-
-typedef struct _WRITE_CONTEXT {
- LARGE_INTEGER ByteOffset;
- ULONG BufferLength;
- ULONG BufferOffset;
- ULONG RequestLength;
- ULONG FileNameLength;
- WCHAR FileName[2];
- // "2" means to keep last null of contents to write
-} WRITE_CONTEXT, *PWRITE_CONTEXT;
-
-typedef struct _FILEINFO_CONTEXT {
- ULONG FileInformationClass;
- ULONG BufferLength;
- ULONG FileNameLength;
- WCHAR FileName[1];
-} FILEINFO_CONTEXT, *PFILEINFO_CONTEXT;
-
-typedef struct _SETFILE_CONTEXT {
- ULONG FileInformationClass;
- ULONG BufferLength;
- ULONG BufferOffset;
- ULONG FileNameLength;
- WCHAR FileName[1];
-} SETFILE_CONTEXT, *PSETFILE_CONTEXT;
-
-typedef struct _VOLUME_CONTEXT {
- ULONG FsInformationClass;
- ULONG BufferLength;
-} VOLUME_CONTEXT, *PVOLUME_CONTEXT;
-
-typedef struct _LOCK_CONTEXT {
- LARGE_INTEGER ByteOffset;
- LARGE_INTEGER Length;
- ULONG Key;
- ULONG FileNameLength;
- WCHAR FileName[1];
-} LOCK_CONTEXT, *PLOCK_CONTEXT;
-
-typedef struct _FLUSH_CONTEXT {
- ULONG FileNameLength;
- WCHAR FileName[1];
-} FLUSH_CONTEXT, *PFLUSH_CONTEXT;
-
-typedef struct _UNMOUNT_CONTEXT {
- WCHAR DeviceName[64];
- ULONG Option;
-} UNMOUNT_CONTEXT, *PUNMOUNT_CONTEXT;
-
-typedef struct _SECURITY_CONTEXT {
- SECURITY_INFORMATION SecurityInformation;
- ULONG BufferLength;
- ULONG FileNameLength;
- WCHAR FileName[1];
-} SECURITY_CONTEXT, *PSECURITY_CONTEXT;
-
-typedef struct _SET_SECURITY_CONTEXT {
- SECURITY_INFORMATION SecurityInformation;
- ULONG BufferLength;
- ULONG BufferOffset;
- ULONG FileNameLength;
- WCHAR FileName[1];
-} SET_SECURITY_CONTEXT, *PSET_SECURITY_CONTEXT;
-
-typedef struct _EVENT_CONTEXT {
- ULONG Length;
- ULONG MountId;
- ULONG SerialNumber;
- ULONG ProcessId;
- UCHAR MajorFunction;
- UCHAR MinorFunction;
- ULONG Flags;
- ULONG FileFlags;
- ULONG64 Context;
- union {
- DIRECTORY_CONTEXT Directory;
- READ_CONTEXT Read;
- WRITE_CONTEXT Write;
- FILEINFO_CONTEXT File;
- CREATE_CONTEXT Create;
- CLOSE_CONTEXT Close;
- SETFILE_CONTEXT SetFile;
- CLEANUP_CONTEXT Cleanup;
- LOCK_CONTEXT Lock;
- VOLUME_CONTEXT Volume;
- FLUSH_CONTEXT Flush;
- UNMOUNT_CONTEXT Unmount;
- SECURITY_CONTEXT Security;
- SET_SECURITY_CONTEXT SetSecurity;
- } Operation;
-} EVENT_CONTEXT, *PEVENT_CONTEXT;
-
-#define WRITE_MAX_SIZE \
- (EVENT_CONTEXT_MAX_SIZE - sizeof(EVENT_CONTEXT) - 256 * sizeof(WCHAR))
-
-typedef struct _EVENT_INFORMATION {
- ULONG SerialNumber;
- NTSTATUS Status;
- ULONG Flags;
- union {
- struct {
- ULONG Index;
- } Directory;
- struct {
- ULONG Flags;
- ULONG Information;
- } Create;
- struct {
- LARGE_INTEGER CurrentByteOffset;
- } Read;
- struct {
- LARGE_INTEGER CurrentByteOffset;
- } Write;
- struct {
- UCHAR DeleteOnClose;
- } Delete;
- struct {
- ULONG Timeout;
- } ResetTimeout;
- struct {
- HANDLE Handle;
- } AccessToken;
- } Operation;
- ULONG64 Context;
- ULONG BufferLength;
- UCHAR Buffer[8];
-
-} EVENT_INFORMATION, *PEVENT_INFORMATION;
-
-#define DOKAN_EVENT_ALTERNATIVE_STREAM_ON 1
-#define DOKAN_EVENT_WRITE_PROTECT 2
-#define DOKAN_EVENT_REMOVABLE 4
-#define DOKAN_EVENT_MOUNT_MANAGER 8
-#define DOKAN_EVENT_CURRENT_SESSION 16
-#define DOKAN_EVENT_FILELOCK_USER_MODE 32
-
-typedef struct _EVENT_DRIVER_INFO {
- ULONG DriverVersion;
- ULONG Status;
- ULONG DeviceNumber;
- ULONG MountId;
- WCHAR DeviceName[64];
-} EVENT_DRIVER_INFO, *PEVENT_DRIVER_INFO;
-
-typedef struct _EVENT_START {
- ULONG UserVersion;
- ULONG DeviceType;
- ULONG Flags;
- WCHAR MountPoint[260];
- WCHAR UNCName[64];
- ULONG IrpTimeout;
-} EVENT_START, *PEVENT_START;
-
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4201)
-#endif
-typedef struct _DOKAN_RENAME_INFORMATION {
-#if (_WIN32_WINNT >= _WIN32_WINNT_WIN10_RS1)
- union {
- BOOLEAN ReplaceIfExists; // FileRenameInformation
- ULONG Flags; // FileRenameInformationEx
- } DUMMYUNIONNAME;
-#else
- BOOLEAN ReplaceIfExists;
-#endif
- ULONG FileNameLength;
- WCHAR FileName[1];
-} DOKAN_RENAME_INFORMATION, *PDOKAN_RENAME_INFORMATION;
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-typedef struct _DOKAN_LINK_INFORMATION {
- BOOLEAN ReplaceIfExists;
- ULONG FileNameLength;
- WCHAR FileName[1];
-} DOKAN_LINK_INFORMATION, *PDOKAN_LINK_INFORMATION;
-
-/**
-* \struct DOKAN_CONTROL
-* \brief Dokan Control
-*/
-typedef struct _DOKAN_CONTROL {
- /** File System Type */
- ULONG Type;
- /** Mount point. Can be "M:\" (drive letter) or "C:\mount\dokan" (path in NTFS) */
- WCHAR MountPoint[MAX_PATH];
- /** UNC name used for network volume */
- WCHAR UNCName[64];
- /** Disk Device Name */
- WCHAR DeviceName[64];
- /** Volume Device Object */
- PVOID64 DeviceObject;
- /** Session ID of calling process */
- ULONG SessionId;
-} DOKAN_CONTROL, *PDOKAN_CONTROL;
-
-#endif // PUBLIC_H_
diff --git a/MemProcFS/version.h b/MemProcFS/version.h
deleted file mode 100644
index e0fc772..0000000
--- a/MemProcFS/version.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#define STRINGIZE2(s) #s
-#define STRINGIZE(s) STRINGIZE2(s)
-
-#define VERSION_MAJOR 2
-#define VERSION_MINOR 0
-#define VERSION_REVISION 0
-#define VERSION_BUILD 0
-
-#define VER_FILE_DESCRIPTION_STR "The Memory Process File System"
-#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
-#define VER_FILE_VERSION_STR STRINGIZE(VERSION_MAJOR) \
- "." STRINGIZE(VERSION_MINOR) \
- "." STRINGIZE(VERSION_REVISION) \
- "." STRINGIZE(VERSION_BUILD) \
-
-#define VER_COMPANY_NAME_STR ""
-#define VER_PRODUCTNAME_STR "MemProcFS"
-#define VER_PRODUCT_VERSION VER_FILE_VERSION
-#define VER_PRODUCT_VERSION_STR VER_FILE_VERSION_STR
-#define VER_ORIGINAL_FILENAME_STR VER_PRODUCTNAME_STR ".exe"
-#define VER_INTERNAL_NAME_STR VER_ORIGINAL_FILENAME_STR
-#define VER_COPYRIGHT_STR "Copyright (c) Ulf Frisk 2018-2019"
diff --git a/MemProcFS/vfs.c b/MemProcFS/vfs.c
deleted file mode 100644
index 72cca6f..0000000
--- a/MemProcFS/vfs.c
+++ /dev/null
@@ -1,485 +0,0 @@
-// vfs.c : implementation of functions related to virtual file system support.
-//
-// (c) Ulf Frisk, 2018
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include
-#include
-#include "vfs.h"
-#include "vmmdll.h"
-#pragma warning( push )
-#pragma warning( disable : 4005 )
-#include "dokan.h"
-#pragma warning( pop )
-//#define dbg_GetTickCount64() GetTickCount64()
-//#define dbg_wprintf(format, ...) { wprintf(format, ##__VA_ARGS__); }
-#define dbg_wprintf(format, ...) {}
-#define dbg_GetTickCount64() 0
-
-//-------------------------------------------------------------------------------
-// DEFINES, TYPEDEFS AND FORWARD DECLARATIONS BELOW:
-//-------------------------------------------------------------------------------
-
-#define VFS_CONFIG_FILELIST_ITEMS 12
-#define VFS_CONFIG_FILELIST_MAGIC 0x7f646555caffee66
-typedef struct tdVFS_FILELIST {
- QWORD magic;
- struct tdVFS_FILELIST* FLink;
- DWORD cFiles;
- WIN32_FIND_DATAW pFiles[VFS_CONFIG_FILELIST_ITEMS];
-} VFS_FILELIST, *PVFS_FILELIST;
-
-BOOL VfsListVmmDirectory(_In_ LPWSTR wszDirectoryName);
-
-//-------------------------------------------------------------------------------
-// FILELIST FUNCTIONALITY BELOW:
-// (directory listing functions/structs for communicating between vfs and vfsproc).
-//-------------------------------------------------------------------------------
-
-PVFS_FILELIST VfsFileList_Alloc()
-{
- PVFS_FILELIST pFileList = LocalAlloc(LMEM_ZEROINIT, sizeof(VFS_FILELIST));
- if(pFileList) {
- pFileList->magic = VFS_CONFIG_FILELIST_MAGIC;
- }
- return pFileList;
-}
-
-VOID VfsFileList_Free(_Inout_ PVFS_FILELIST pFileList)
-{
- PVFS_FILELIST pFileListFlink;
- while(pFileList) {
- pFileListFlink = pFileList->FLink;
- LocalFree(pFileList);
- pFileList = pFileListFlink;
- }
-}
-
-VOID VfsFileList_AddDirectoryFileInternal(_Inout_ PVFS_FILELIST pFileList, _In_ DWORD dwFileAttributes, _In_ FILETIME ftCreationTime, _In_ FILETIME ftLastAccessTime, _In_ FILETIME ftLastWriteTime, _In_ DWORD nFileSizeHigh, _In_ DWORD nFileSizeLow, _In_ LPSTR szName)
-{
- DWORD i = 0;
- PWIN32_FIND_DATAW pFindData;
- // 1: check if required to allocate more FileList items
- while(pFileList->cFiles == VFS_CONFIG_FILELIST_ITEMS) {
- if(pFileList->FLink) {
- pFileList = pFileList->FLink;
- continue;
- }
- pFileList->FLink = VfsFileList_Alloc();
- if(!pFileList->FLink) { return; }
- pFileList = pFileList->FLink;
- }
- // 2: locate item to fill into
- pFindData = pFileList->pFiles + pFileList->cFiles;
- pFileList->cFiles++;
- // 3: fill
- pFindData->dwFileAttributes = dwFileAttributes;
- pFindData->ftCreationTime = ftCreationTime;
- pFindData->ftLastAccessTime = ftLastAccessTime;
- pFindData->ftLastWriteTime = ftLastWriteTime;
- pFindData->nFileSizeHigh = nFileSizeHigh;
- pFindData->nFileSizeLow = nFileSizeLow;
- while(i < MAX_PATH && szName[i]) {
- pFindData->cFileName[i] = szName[i];
- i++;
- }
- pFindData->cFileName[i] = 0;
-}
-
-VOID VfsFileList_AddFile(_Inout_ HANDLE hFileList, _In_ LPSTR szName, _In_ QWORD cb, _In_ PVOID pvReserved)
-{
- PVFS_FILELIST pFileList2 = (PVFS_FILELIST)hFileList;
- if(pFileList2 && (pFileList2->magic == VFS_CONFIG_FILELIST_MAGIC)) {
- VfsFileList_AddDirectoryFileInternal(
- pFileList2,
- FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
- ctxVfs->ftDefaultTime,
- ctxVfs->ftDefaultTime,
- ctxVfs->ftDefaultTime,
- (DWORD)(cb >> 32),
- (DWORD)cb,
- szName
- );
- }
-}
-
-VOID VfsFileList_AddDirectory(_Inout_ HANDLE hFileList, _In_ LPSTR szName, _In_ PVOID pvReserved)
-{
- PVFS_FILELIST pFileList2 = (PVFS_FILELIST)hFileList;
- if(pFileList2 && (pFileList2->magic == VFS_CONFIG_FILELIST_MAGIC)) {
- VfsFileList_AddDirectoryFileInternal(
- pFileList2,
- FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
- ctxVfs->ftDefaultTime,
- ctxVfs->ftDefaultTime,
- ctxVfs->ftDefaultTime,
- 0,
- 0,
- szName
- );
- }
-}
-
-VOID VfsFileList_DokanFillAll(PVFS_FILELIST pFileList, PDOKAN_FILE_INFO DokanFileInfo, PFillFindData FillFindData)
-{
- DWORD i;
- do {
- for(i = 0; i < pFileList->cFiles; i++) {
- FillFindData(pFileList->pFiles + i, DokanFileInfo);
- }
- pFileList = pFileList->FLink;
- } while(pFileList);
-}
-
-PWIN32_FIND_DATAW VfsFileList_FindSingle(_In_ PVFS_FILELIST pFileList, _In_ LPWSTR wszFile)
-{
- DWORD i;
- do {
- for(i = 0; i < pFileList->cFiles; i++) {
- if(!wcscmp(wszFile, pFileList->pFiles[i].cFileName)) {
- return pFileList->pFiles + i;
- }
- }
- pFileList = pFileList->FLink;
- } while(pFileList);
- return NULL;
-}
-
-//-------------------------------------------------------------------------------
-// DIRECTORY LISTINGS READ CACHE BELOW:
-// (caching is used to cache vmmproc directory listings for performance reasons)
-//-------------------------------------------------------------------------------
-
-_Success_(return)
-BOOL VfsCacheDirectory_GetSingle2(_In_ LPWSTR wszPath, _In_ LPWSTR wszFile, _Out_ PWIN32_FIND_DATAW pFindData, _Out_ PBOOL pIsDirectoryExisting)
-{
- QWORD i, qwCurrentTickCount;
- PWIN32_FIND_DATAW pFindDataCache;
- qwCurrentTickCount = GetTickCount64();
- *pIsDirectoryExisting = FALSE;
- EnterCriticalSection(&ctxVfs->CacheDirectoryLock);
- for(i = 0; i < VMMVFS_CACHE_DIRECTORY_ENTRIES; i++) {
- if(wcscmp(wszPath, ctxVfs->CacheDirectory[i].wszDirectoryName)) { continue; }
- if(qwCurrentTickCount > ctxVfs->CacheDirectory[i].qwExpireTickCount64) { continue; }
- *pIsDirectoryExisting = TRUE;
- pFindDataCache = VfsFileList_FindSingle(ctxVfs->CacheDirectory[i].pFileList, wszFile);
- if(!pFindDataCache) {
- LeaveCriticalSection(&ctxVfs->CacheDirectoryLock);
- return FALSE;
- }
- if(pFindData) {
- memcpy(pFindData, pFindDataCache, sizeof(WIN32_FIND_DATAW));
- }
- LeaveCriticalSection(&ctxVfs->CacheDirectoryLock);
- return TRUE;
- }
- LeaveCriticalSection(&ctxVfs->CacheDirectoryLock);
- return FALSE;
-}
-
-BOOL VfsCacheDirectory_GetSingle(_In_ LPWSTR wszPath, _In_ LPWSTR wszFile, _Out_ PWIN32_FIND_DATAW pFindData)
-{
- BOOL result, isDirectoryExisting;
- result = VfsCacheDirectory_GetSingle2(wszPath, wszFile, pFindData, &isDirectoryExisting);
- if(result) { return TRUE; }
- if(isDirectoryExisting) { return FALSE; }
- return VfsListVmmDirectory(wszPath) && VfsCacheDirectory_GetSingle2(wszPath, wszFile, pFindData, &isDirectoryExisting);
-}
-
-BOOL VfsCacheDirectory_DokanFillDirectory(_In_ LPCWSTR wcsPathFileName, _In_ PFillFindData FillFindData, _Inout_ PDOKAN_FILE_INFO DokanFileInfo)
-{
- QWORD i, qwCurrentTickCount;
- qwCurrentTickCount = GetTickCount64();
- EnterCriticalSection(&ctxVfs->CacheDirectoryLock);
- for(i = 0; i < VMMVFS_CACHE_DIRECTORY_ENTRIES; i++) {
- if(wcscmp(wcsPathFileName, ctxVfs->CacheDirectory[i].wszDirectoryName)) { continue; }
- if(qwCurrentTickCount > ctxVfs->CacheDirectory[i].qwExpireTickCount64) { continue; }
- VfsFileList_DokanFillAll(ctxVfs->CacheDirectory[i].pFileList, DokanFileInfo, FillFindData);
- LeaveCriticalSection(&ctxVfs->CacheDirectoryLock);
- return TRUE;
- }
- LeaveCriticalSection(&ctxVfs->CacheDirectoryLock);
- return FALSE;
-}
-
-VOID VfsCacheDirectory_Put(_In_ LPCWSTR wcsDirectoryName, _In_ PVFS_FILELIST pFileList)
-{
- EnterCriticalSection(&ctxVfs->CacheDirectoryLock);
- ctxVfs->CacheDirectory[ctxVfs->CacheDirectoryIndex].qwExpireTickCount64 = GetTickCount64() + VMMVFS_CACHE_DIRECTORY_LIFETIME_PROC_MS;
- wcscpy_s(ctxVfs->CacheDirectory[ctxVfs->CacheDirectoryIndex].wszDirectoryName, MAX_PATH, wcsDirectoryName);
- VfsFileList_Free(ctxVfs->CacheDirectory[ctxVfs->CacheDirectoryIndex].pFileList);
- ctxVfs->CacheDirectory[ctxVfs->CacheDirectoryIndex].pFileList = pFileList;
- ctxVfs->CacheDirectoryIndex = (ctxVfs->CacheDirectoryIndex + 1) % VMMVFS_CACHE_DIRECTORY_ENTRIES;
- LeaveCriticalSection(&ctxVfs->CacheDirectoryLock);
-}
-
-VOID VfsCacheDirectory_Close()
-{
- DWORD i;
- EnterCriticalSection(&ctxVfs->CacheDirectoryLock);
- for(i = 0; i < VMMVFS_CACHE_DIRECTORY_ENTRIES; i++) {
- ctxVfs->CacheDirectory[i].qwExpireTickCount64 = 0;
- VfsFileList_Free(ctxVfs->CacheDirectory[i].pFileList);
- ctxVfs->CacheDirectory[i].pFileList = NULL;
- }
- LeaveCriticalSection(&ctxVfs->CacheDirectoryLock);
-}
-
-//-------------------------------------------------------------------------------
-// UTILITY FUNCTIONS BELOW:
-//-------------------------------------------------------------------------------
-
-BOOL VfsListVmmDirectory(_In_ LPWSTR wszDirectoryName)
-{
- BOOL result;
- PVFS_FILELIST pFileList = VfsFileList_Alloc(ctxVfs->ftDefaultTime);
- VMMDLL_VFS_FILELIST VfsFileList;
- if(!pFileList) { return FALSE; }
- VfsFileList.h = (HANDLE)pFileList;
- VfsFileList.pfnAddFile = VfsFileList_AddFile;
- VfsFileList.pfnAddDirectory = VfsFileList_AddDirectory;
- result = ctxVfs->pVmmDll->VfsList(wszDirectoryName, &VfsFileList);
- if(!result) {
- VfsFileList_Free(pFileList);
- return FALSE;
- }
- VfsCacheDirectory_Put(wszDirectoryName, pFileList); // do not free pFileList since it's put into the cache
- return TRUE;
-}
-
-VOID Vfs_UtilSplitPathFile(_Out_writes_(MAX_PATH) PWCHAR wszPath, _Out_ LPWSTR *pwcsFile, _In_ LPCWSTR wcsFileName)
-{
- DWORD i, iSplitFilePath = 0;
- wcsncpy_s(wszPath, MAX_PATH, wcsFileName, _TRUNCATE);
- for(i = 0; i < MAX_PATH; i++) {
- if(wszPath[i] == '\\') {
- iSplitFilePath = i;
- }
- if(wszPath[i] == 0) {
- break;
- }
- }
- wszPath[iSplitFilePath] = 0;
- *pwcsFile = wszPath + iSplitFilePath + 1;
-}
-
-//-------------------------------------------------------------------------------
-// DOKAN CALLBACK FUNCTIONS BELOW:
-//-------------------------------------------------------------------------------
-
-NTSTATUS DOKAN_CALLBACK
-VfsCallback_CreateFile(LPCWSTR wcsFileName, PDOKAN_IO_SECURITY_CONTEXT SecurityContext, ACCESS_MASK DesiredAccess, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PDOKAN_FILE_INFO DokanFileInfo)
-{
- UINT64 tmStart = dbg_GetTickCount64();
- NTSTATUS nt;
- BOOL result;
- WIN32_FIND_DATAW FindData;
- WCHAR wszPath[MAX_PATH];
- LPWSTR wszFile;
- dbg_wprintf(L"DEBUG:: -------- VfsCallback_CreateFile:\t\t 0x%08x %s\n", 0, wcsFileName);
- UNREFERENCED_PARAMETER(SecurityContext);
- UNREFERENCED_PARAMETER(FileAttributes);
- UNREFERENCED_PARAMETER(CreateOptions);
- // root directory
- if(!wcscmp(wcsFileName, L"\\")) {
- if(CreateDisposition == CREATE_ALWAYS) {
- nt = ctxVfs->DokanNtStatusFromWin32(ERROR_ACCESS_DENIED);
- dbg_wprintf(L"DEBUG:: %8x VfsCallback_CreateFile:\t\t 0x%08x %s\n", (DWORD)(dbg_GetTickCount64() - tmStart), nt, wcsFileName);
- return nt;
- }
- DokanFileInfo->IsDirectory = TRUE;
- dbg_wprintf(L"DEBUG:: %8x VfsCallback_CreateFile:\t\t 0x%08x %s\n", (DWORD)(dbg_GetTickCount64() - tmStart), STATUS_SUCCESS, wcsFileName);
- return STATUS_SUCCESS;
- }
- // other files
- if(CreateDisposition == CREATE_ALWAYS) {
- nt = ctxVfs->DokanNtStatusFromWin32(ERROR_ACCESS_DENIED);
- dbg_wprintf(L"DEBUG:: %8x VfsCallback_CreateFile:\t\t 0x%08x %s\n", (DWORD)(dbg_GetTickCount64() - tmStart), nt, wcsFileName);
- return nt;
- }
- Vfs_UtilSplitPathFile(wszPath, &wszFile, wcsFileName);
- result = VfsCacheDirectory_GetSingle(wszPath[0] ? wszPath : L"\\", wszFile, &FindData);
- if(!result) {
- dbg_wprintf(L"DEBUG:: %8x VfsCallback_CreateFile:\t\t 0x%08x %s\n", (DWORD)(dbg_GetTickCount64() - tmStart), STATUS_FILE_INVALID, wcsFileName);
- return STATUS_FILE_INVALID;
- }
- DokanFileInfo->IsDirectory = (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? TRUE : FALSE;
- DokanFileInfo->Nocache = TRUE;
- nt = (CreateDisposition == OPEN_ALWAYS) ? STATUS_OBJECT_NAME_COLLISION : STATUS_SUCCESS;
- dbg_wprintf(L"DEBUG:: %8x VfsCallback_CreateFile:\t\t 0x%08x %s\n", (DWORD)(dbg_GetTickCount64() - tmStart), nt, wcsFileName);
- return nt;
-}
-
-NTSTATUS DOKAN_CALLBACK
-VfsCallback_GetFileInformation(_In_ LPCWSTR wcsFileName, _Inout_ LPBY_HANDLE_FILE_INFORMATION hfi, _In_ PDOKAN_FILE_INFO DokanFileInfo)
-{
- UINT64 tmStart = dbg_GetTickCount64();
- BOOL result;
- WIN32_FIND_DATAW FindData;
- WCHAR wszPath[MAX_PATH];
- LPWSTR wszFile;
- dbg_wprintf(L"DEBUG:: -------- VfsCallback_GetFileInformation:\t 0x%08x %s\n", 0, wcsFileName);
- // matches: root directory
- if(!wcscmp(wcsFileName, L"\\")) {
- hfi->ftCreationTime = ctxVfs->ftDefaultTime;
- hfi->ftLastWriteTime = ctxVfs->ftDefaultTime;
- hfi->ftLastAccessTime = ctxVfs->ftDefaultTime;
- hfi->nFileSizeHigh = 0;
- hfi->nFileSizeLow = 0;
- hfi->dwFileAttributes = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
- dbg_wprintf(L"DEBUG:: %8x VfsCallback_GetFileInformation:\t 0x%08x %s\n", (DWORD)(dbg_GetTickCount64() - tmStart), STATUS_SUCCESS, wcsFileName);
- return STATUS_SUCCESS;
- }
- Vfs_UtilSplitPathFile(wszPath, &wszFile, wcsFileName);
- result = VfsCacheDirectory_GetSingle((wszPath[0] ? wszPath : L"\\"), wszFile, &FindData);
- if(!result) {
- dbg_wprintf(L"DEBUG:: %8x VfsCallback_GetFileInformation:\t 0x%08x %s\n", (DWORD)(dbg_GetTickCount64() - tmStart), STATUS_FILE_NOT_AVAILABLE, wcsFileName);
- return STATUS_FILE_NOT_AVAILABLE;
- }
- hfi->dwFileAttributes = FindData.dwFileAttributes;
- hfi->ftCreationTime = FindData.ftCreationTime;
- hfi->ftLastAccessTime = FindData.ftLastAccessTime;
- hfi->ftLastWriteTime = FindData.ftLastWriteTime;
- hfi->nFileSizeHigh = FindData.nFileSizeHigh;
- hfi->nFileSizeLow = FindData.nFileSizeLow;
- dbg_wprintf(L"DEBUG:: %8x VfsCallback_GetFileInformation:\t 0x%08x %s\n", (DWORD)(dbg_GetTickCount64() - tmStart), STATUS_SUCCESS, wcsFileName);
- return STATUS_SUCCESS;
-}
-
-NTSTATUS DOKAN_CALLBACK
-VfsCallback_FindFiles(LPCWSTR wcsFileName, PFillFindData FillFindData, PDOKAN_FILE_INFO DokanFileInfo)
-{
- UINT64 tmStart = dbg_GetTickCount64();
- BOOL result;
- dbg_wprintf(L"DEBUG:: -------- VfsCallback_FindFiles:\t\t\t 0x%08x %s\n", 0, wcsFileName);
- result = VfsCacheDirectory_DokanFillDirectory(wcsFileName, FillFindData, DokanFileInfo);
- if(result) {
- dbg_wprintf(L"DEBUG:: %8x VfsCallback_FindFiles:\t\t\t 0x%08x %s\n", (DWORD)(dbg_GetTickCount64() - tmStart), STATUS_SUCCESS, wcsFileName);
- return STATUS_SUCCESS;
- }
- VfsListVmmDirectory((LPWSTR)wcsFileName);
- VfsCacheDirectory_DokanFillDirectory(wcsFileName, FillFindData, DokanFileInfo);
- dbg_wprintf(L"DEBUG:: %8x VfsCallback_FindFiles:\t\t\t 0x%08x %s\n", (DWORD)(dbg_GetTickCount64() - tmStart), STATUS_SUCCESS, wcsFileName);
- return STATUS_SUCCESS;
-}
-
-NTSTATUS DOKAN_CALLBACK
-VfsCallback_ReadFile(LPCWSTR wcsFileName, LPVOID Buffer, DWORD BufferLength, LPDWORD ReadLength, LONGLONG Offset, PDOKAN_FILE_INFO DokanFileInfo)
-{
- UINT64 tmStart = dbg_GetTickCount64();
- NTSTATUS nt;
- dbg_wprintf(L"DEBUG:: -------- VfsCallback_ReadFile:\t\t\t 0x%08x %s\n", 0, wcsFileName);
- nt = ctxVfs->pVmmDll->VfsRead(wcsFileName, Buffer, BufferLength, ReadLength, Offset);
- dbg_wprintf(L"DEBUG:: %8x VfsCallback_ReadFile:\t\t\t 0x%08x %s\n", (DWORD)(dbg_GetTickCount64() - tmStart), nt, wcsFileName);
- return nt;
-}
-
-NTSTATUS DOKAN_CALLBACK
-VfsCallback_WriteFile(LPCWSTR wcsFileName, LPCVOID Buffer, DWORD NumberOfBytesToWrite, LPDWORD NumberOfBytesWritten, LONGLONG Offset, PDOKAN_FILE_INFO DokanFileInfo)
-{
- UINT64 tmStart = dbg_GetTickCount64();
- NTSTATUS nt;
- dbg_wprintf(L"DEBUG:: -------- VfsCallback_WriteFile:\t\t\t 0x%08x %s\n", 0, wcsFileName);
- nt = ctxVfs->pVmmDll->VfsWrite(wcsFileName, (PBYTE)Buffer, NumberOfBytesToWrite, NumberOfBytesWritten, Offset);
- dbg_wprintf(L"DEBUG:: %8x VfsCallback_WriteFile:\t\t\t 0x%08x %s\n", (DWORD)(dbg_GetTickCount64() - tmStart), nt, wcsFileName);
- return nt;
-}
-
-//-------------------------------------------------------------------------------
-// VFS INITIALIZATION FUNCTIONALITY BELOW:
-//-------------------------------------------------------------------------------
-
-VOID VfsClose()
-{
- if(ctxVfs && ctxVfs->fInitialized) {
- VfsCacheDirectory_Close();
- DeleteCriticalSection(&ctxVfs->CacheDirectoryLock);
- }
- LocalFree(ctxVfs);
- ctxVfs = NULL;
-}
-
-VOID VfsInitializeAndMount(_In_ CHAR chMountPoint, _In_ PVMMDLL_FUNCTIONS pVmmDll)
-{
- int status;
- HMODULE hModuleDokan = NULL;
- PDOKAN_OPTIONS pDokanOptions = NULL;
- PDOKAN_OPERATIONS pDokanOperations = NULL;
- WCHAR wszMountPoint[] = { 'M', ':', '\\', 0 };
- SYSTEMTIME SystemTimeNow;
- int(*fnDokanMain)(PDOKAN_OPTIONS, PDOKAN_OPERATIONS);
- ULONG64 qwVersionMajor = 0, qwVersionMinor = 0, qwVersionRevision = 0;
- // get versions
- pVmmDll->ConfigGet(VMMDLL_OPT_CONFIG_VMM_VERSION_MAJOR, &qwVersionMajor);
- pVmmDll->ConfigGet(VMMDLL_OPT_CONFIG_VMM_VERSION_MINOR, &qwVersionMinor);
- pVmmDll->ConfigGet(VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION, &qwVersionRevision);
- // allocate
- hModuleDokan = LoadLibraryExA("dokan1.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
- if(!hModuleDokan) {
- printf("MOUNT: Failed. The required DOKANY file system library is not installed. \n");
- printf("Please download from : https://github.com/dokan-dev/dokany/releases/latest\n");
- goto fail;
- }
- fnDokanMain = (int(*)(PDOKAN_OPTIONS, PDOKAN_OPERATIONS))GetProcAddress(hModuleDokan, "DokanMain");
- if(!fnDokanMain) {
- printf("MOUNT: Failed. The required DOKANY file system library is not installed. \n");
- printf("Please download from : https://github.com/dokan-dev/dokany/releases/latest\n");
- goto fail;
- }
- pDokanOptions = (PDOKAN_OPTIONS)LocalAlloc(LMEM_ZEROINIT, sizeof(DOKAN_OPTIONS));
- pDokanOperations = (PDOKAN_OPERATIONS)LocalAlloc(LMEM_ZEROINIT, sizeof(DOKAN_OPERATIONS));
- if(!pDokanOptions || !pDokanOperations) {
- printf("MOUNT: Failed (out of memory).\n");
- goto fail;
- }
- // allocate empty vfs context
- ctxVfs = (PVMMVFS_CONFIG)LocalAlloc(LMEM_ZEROINIT, sizeof(VMMVFS_CONFIG));
- if(!ctxVfs) { goto fail; }
- ctxVfs->pVmmDll = pVmmDll;
- // set vfs context
- GetSystemTime(&SystemTimeNow);
- SystemTimeToFileTime(&SystemTimeNow, &ctxVfs->ftDefaultTime);
- InitializeCriticalSection(&ctxVfs->CacheDirectoryLock);
- ctxVfs->DokanNtStatusFromWin32 = (NTSTATUS(*)(DWORD))GetProcAddress(hModuleDokan, "DokanNtStatusFromWin32");
- ctxVfs->fInitialized = TRUE;
- // set options
- pDokanOptions->Version = DOKAN_VERSION;
- pDokanOptions->Options |= DOKAN_OPTION_NETWORK;
- pDokanOptions->UNCName = L"MemoryProcessFileSystem";
- wszMountPoint[0] = chMountPoint;
- pDokanOptions->MountPoint = wszMountPoint;
- pDokanOptions->Timeout = 60000;
- // set callbacks
- pDokanOperations->ZwCreateFile = VfsCallback_CreateFile;
- pDokanOperations->GetFileInformation = VfsCallback_GetFileInformation;
- pDokanOperations->FindFiles = VfsCallback_FindFiles;
- pDokanOperations->ReadFile = VfsCallback_ReadFile;
- pDokanOperations->WriteFile = VfsCallback_WriteFile;
- // enable
- printf(
- "MOUNTING THE MEMORY PROCESS FILE SYSTEM \n" \
- "===============================================================================\n" \
- "The Memory Process File System is mounted as: %S \n" \
- "Loaded VmmDll Version: %i.%i.%i \n" \
- "Memory from dump files or PCILeech supported devices are analyzed to provide \n" \
- "a convenient process file system for analysis purposes. \n" \
- " - File system is read-only when dump files are used. \n" \
- " - File system is read-write when FPGA hardware acquisition devices are used. \n" \
- " - Full support exists for Windows XP to Windows 10 (x86 and x64). \n" \
- " - Limited support for other x64 operating systems. \n" \
- " - Memory Process File System: https://github.com/ufrisk/MemProcFS \n" \
- " - File system by: Ulf Frisk - pcileech@frizk.net - https://frizk.net \n" \
- "===============================================================================\n",
- pDokanOptions->MountPoint, (DWORD)qwVersionMajor, (DWORD)qwVersionMinor, (DWORD)qwVersionRevision);
- status = fnDokanMain(pDokanOptions, pDokanOperations);
- while(status == DOKAN_SUCCESS) {
- printf("MOUNT: ReMounting as drive %S\n", pDokanOptions->MountPoint);
- status = fnDokanMain(pDokanOptions, pDokanOperations);
- }
- printf("MOUNT: Failed. Status Code: %i\n", status);
-fail:
- if(hModuleDokan) { FreeLibrary(hModuleDokan); }
- LocalFree(pDokanOptions);
- LocalFree(pDokanOperations);
- VfsClose();
-}
diff --git a/MemProcFS/vfs.h b/MemProcFS/vfs.h
deleted file mode 100644
index 7746af0..0000000
--- a/MemProcFS/vfs.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// vfs.h : definitions related to virtual file system support.
-//
-// (c) Ulf Frisk, 2018
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __VFS_H__
-#define __VFS_H__
-#include
-#include "vmmdll.h"
-
-typedef unsigned __int64 QWORD, *PQWORD;
-
-#define VMMVFS_CACHE_DIRECTORY_ENTRIES 15
-#define VMMVFS_CACHE_DIRECTORY_LIFETIME_PROC_MS 500
-
-typedef struct tdVMMDLL_FUNCTIONS {
- BOOL(*Initialize)(_In_ DWORD argc, _In_ LPSTR argv[]);
- BOOL(*VfsList)(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
- DWORD(*VfsRead)(LPCWSTR wcsFileName, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
- DWORD(*VfsWrite)(_In_ LPCWSTR wcsFileName, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
- BOOL(*VfsInitializePlugins)();
- BOOL(*ConfigGet)(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
- BOOL(*ConfigSet)(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-} VMMDLL_FUNCTIONS, *PVMMDLL_FUNCTIONS;
-
-typedef struct tdVMMVFS_CONFIG {
- PVMMDLL_FUNCTIONS pVmmDll;
- FILETIME ftDefaultTime;
- NTSTATUS(*DokanNtStatusFromWin32)(DWORD Error);
- CRITICAL_SECTION CacheDirectoryLock;
- BOOL fInitialized;
- QWORD CacheDirectoryIndex;
- struct {
- QWORD qwExpireTickCount64;
- WCHAR wszDirectoryName[MAX_PATH];
- PVOID pFileList;
- } CacheDirectory[VMMVFS_CACHE_DIRECTORY_ENTRIES];
-} VMMVFS_CONFIG, *PVMMVFS_CONFIG;
-
-PVMMVFS_CONFIG ctxVfs;
-
-/*
-* Mount a drive backed by the Memory Process File System. The mounted file system
-* will contain both a memory mapped ram files and the file system as seen from
-* the target system kernel. NB! This action requires a loaded kernel module and
-* that the Dokany file system library and driver have been installed. Please
-* see: https://github.com/dokan-dev/dokany/releases
-* This also initializes the globalcontext ctxVfs that should be closed by
-* calling VfsClose on exit.
-* -- chMountPoint
-* -- pVmmDll
-*/
-VOID VfsInitializeAndMount(_In_ CHAR chMountPoint, _In_ PVMMDLL_FUNCTIONS pVmmDll);
-
-/*
-* Close a vfs sub-context in ctxVfs - if exists.
-*/
-VOID VfsClose();
-
-#endif /* __VFS_H__ */
diff --git a/MemProcFS/vmmdll.h b/MemProcFS/vmmdll.h
deleted file mode 100644
index 353159a..0000000
--- a/MemProcFS/vmmdll.h
+++ /dev/null
@@ -1,550 +0,0 @@
-// vmmdll.h : header file to include in projects that use vmm.dll either as
-// stand anlone projects or as native plugins to vmm.dll.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 2.0
-//
-
-#include
-#include "leechcore.h"
-
-#ifndef __VMMDLL_H__
-#define __VMMDLL_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// INITIALIZATION FUNCTIONALITY BELOW:
-// Choose one way of initialzing the VMM / Memory Process File System.
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize VMM.DLL with command line parameters. For a more detailed info
-* about the parameters please see github wiki for Memory Process File System
-* and LeechCore. THIS IS THE PREFERED WAY OF INITIALIZING VMM.DLL
-* Important parameters are:
-* -vdll = show printf style outputs)
-* -v -vv -vvv = extra verbosity levels)
-* -device = device as on format for LeechCore - please see leechcore.h or
-* Github documentation for additional information. Some values
-* are: , fpga, usb3380, hvsavedstate, totalmeltdown, pmem
-* -remote = remote LeechCore instance - please see leechcore.h or Github
-* documentation for additional information.
-* -- argc
-* -- argv
-* -- return = success/fail
-*/
-_Success_(return)
-BOOL VMMDLL_Initialize(_In_ DWORD argc, _In_ LPSTR argv[]);
-
-/*
-* Close an initialized instance of VMM.DLL and clean up all allocated resources
-* including plugins, linked PCILeech.DLL and other memory resources.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_Close();
-
-
-
-//-----------------------------------------------------------------------------
-// CONFIGURATION SETTINGS BELOW:
-// Configure the memory process file system or the underlying memory
-// acquisition devices.
-//-----------------------------------------------------------------------------
-
-/*
-* Options used together with the functions: VMMDLL_GetOption & VMMDLL_SetOption
-* Options are defined with either: VMMDLL_OPT_* in this header file or as
-* MEMDEVICE_OPT_* in memdevice.h
-* For more detailed information check the sources for individual device types.
-*/
-#define VMMDLL_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define VMMDLL_OPT_CORE_VERBOSE 0x80000002 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
-#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
-#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
-#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
-
-#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
-#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
-#define VMMDLL_OPT_CONFIG_READCACHE_TICKS 0x40000003 // RW - memory cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_TLBCACHE_TICKS 0x40000004 // RW - page table (tlb) cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_PARTIAL 0x40000005 // RW - process refresh (partial) period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_TOTAL 0x40000006 // RW - process refresh (full) period (in ticks)
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MAJOR 0x40000007 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MINOR 0x40000008 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
-#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
-
-static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
-
-typedef enum tdVMMDLL_MEMORYMODEL_TP {
- VMMDLL_MEMORYMODEL_NA = 0,
- VMMDLL_MEMORYMODEL_X86 = 1,
- VMMDLL_MEMORYMODEL_X86PAE = 2,
- VMMDLL_MEMORYMODEL_X64 = 3
-} VMMDLL_MEMORYMODEL_TP;
-
-typedef enum tdVMMDLL_SYSTEM_TP {
- VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
- VMMDLL_SYSTEM_WINDOWS_X64 = 2,
- VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
- VMMDLL_SYSTEM_WINDOWS_X86 = 4
-} VMMDLL_SYSTEM_TP;
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- pqwValue = pointer to ULONG64 to receive option value.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- qwValue
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// VFS - VIRTUAL FILE SYSTEM FUNCTIONALITY BELOW:
-// This is the core of the memory process file system. All implementation and
-// analysis towards the file system is possible by using functionality below.
-//-----------------------------------------------------------------------------
-
-#define VMMDLL_STATUS_SUCCESS ((NTSTATUS)0x00000000L)
-#define VMMDLL_STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
-#define VMMDLL_STATUS_END_OF_FILE ((NTSTATUS)0xC0000011L)
-#define VMMDLL_STATUS_FILE_INVALID ((NTSTATUS)0xC0000098L)
-#define VMMDLL_STATUS_FILE_SYSTEM_LIMITATION ((NTSTATUS)0xC0000427L)
-
-typedef struct tdVMMDLL_VFS_FILELIST {
- VOID(*pfnAddFile) (_Inout_ HANDLE h, _In_ LPSTR szName, _In_ ULONG64 cb, _In_ PVOID pvReserved);
- VOID(*pfnAddDirectory)(_Inout_ HANDLE h, _In_ LPSTR szName, _In_ PVOID pvReserved);
- HANDLE h;
-} VMMDLL_VFS_FILELIST, *PVMMDLL_VFS_FILELIST;
-
-/*
-* Helper function macros for callbacks into the VMM_VFS_FILELIST structure.
-*/
-#define VMMDLL_VfsList_AddFile(pFileList, szName, cb) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddFile(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, cb, NULL); }
-#define VMMDLL_VfsList_AddDirectory(pFileList, szName) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddDirectory(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, NULL); }
-
-/*
-* List a directory of files in the memory process file system. Directories and
-* files will be listed by callbacks into functions supplied in the pFileList
-* parameter. If information of an individual file is needed it's neccessary
-* to list all files in its directory.
-* -- wcsPath
-* -- pFileList
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
-
-/*
-* Read select parts of a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbRead
-* -- cbOffset
-* -- return
-*
-*/
-NTSTATUS VMMDLL_VfsRead(_In_ LPCWSTR wcsFileName, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-
-/*
-* Write select parts to a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbWrite
-* -- cbOffset
-* -- return
-*/
-NTSTATUS VMMDLL_VfsWrite(_In_ LPCWSTR wcsFileName, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-
-/*
-* Utility functions for memory process file system read/write towards different
-* underlying data representations.
-*/
-NTSTATUS VMMDLL_UtilVfsReadFile_FromPBYTE(_In_ PBYTE pbFile, _In_ ULONG64 cbFile, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromQWORD(_In_ ULONG64 qwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromDWORD(_In_ DWORD dwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromBOOL(_In_ BOOL fValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_BOOL(_Inout_ PBOOL pfTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset, _In_ DWORD dwMinAllow);
-
-
-//-----------------------------------------------------------------------------
-// PLUGIN MANAGER FUNCTIONALITY BELOW:
-// Function and structures to initialize and use the memory process file system
-// plugin functionality. The plugin manager is started by a call to function:
-// VMM_VfsInitializePlugins. Each built-in plugin and external plugin of which
-// the DLL name matches m_*.dll will receive a call to its InitializeVmmPlugin
-// function. The plugin/module may decide to call pfnPluginManager_Register to
-// register plugins in the form of different names one or more times.
-// Example of registration function in a plugin DLL below:
-// 'VOID InitializeVmmPlugin(_In_ PVMM_PLUGIN_REGINFO pRegInfo)'
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize all potential plugins, both built-in and external, that maps into
-* the memory process file system. Please note that plugins are not loaded by
-* default - they have to be explicitly loaded by calling this function. They
-* will be unloaded on a general close of the vmm dll.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsInitializePlugins();
-
-#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
-#define VMMDLL_PLUGIN_CONTEXT_VERSION 2
-#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
-#define VMMDLL_PLUGIN_REGINFO_VERSION 3
-
-#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
-
-typedef struct tdVMMDLL_PLUGIN_CONTEXT {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- DWORD dwPID;
- PVOID pProcess;
- LPSTR szModule;
- LPSTR szPath;
- PVOID pvReserved1;
- PVOID pvReserved2;
-} VMMDLL_PLUGIN_CONTEXT, *PVMMDLL_PLUGIN_CONTEXT;
-
-typedef struct tdVMMDLL_PLUGIN_REGINFO {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel;
- VMMDLL_SYSTEM_TP tpSystem;
- HMODULE hDLL;
- HMODULE hReservedDll; // not for general use (only used for python).
- BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
- PVOID pvReserved1;
- PVOID pvReserved2;
- // general plugin registration info to be filled out by the plugin below:
- struct {
- CHAR szModuleName[32];
- BOOL fRootModule;
- BOOL fProcessModule;
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_info;
- // function plugin registration info to be filled out by the plugin below:
- struct {
- BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
- NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
- NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
- VOID(*pfnNotify)(_In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
- VOID(*pfnClose)();
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_fn;
-} VMMDLL_PLUGIN_REGINFO, *PVMMDLL_PLUGIN_REGINFO;
-
-//-----------------------------------------------------------------------------
-// VMM CORE FUNCTIONALITY BELOW:
-// Vmm core functaionlity such as read (and write) to both virtual and physical
-// memory. NB! writing will only work if the target is supported - i.e. not a
-// memory dump file...
-// To read physical memory specify dwPID as (DWORD)-1
-//-----------------------------------------------------------------------------
-
-// FLAG used to supress the default read cache in calls to VMM_MemReadEx()
-// which will lead to the read being fetched from the target system always.
-// Cached page tables (used for translating virtual2physical) are still used.
-#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
-#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
-
-/*
-* Read memory in various non-contigious locations specified by the pointers to
-* the items in the ppDMAs array. Result for each unit of work will be given
-* individually. No upper limit of number of items to read, but no performance
-* boost will be given if above hardware limit. Max size of each unit of work is
-* one 4k page (4096 bytes).
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-* -- pcpDMAsRead = optional count of number of successfully read ppDMAs.
-* -- flags = optional flags as given by VMM_FLAG_*
-* -- return = the number of successfully read items.
-*/
-DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs, _In_ DWORD flags);
-
-/*
-* Read a single 4096-byte page of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pbPage
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
-
-/*
-* Read a contigious arbitrary amount of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Read a contigious amount of memory and report the number of bytes read in pcbRead.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- pcbRead
-* -- flags = flags as in VMM_FLAG_*
-* -- return = success/fail. NB! reads may report as success even if 0 bytes are
-* read - it's recommended to verify pcbReadOpt parameter.
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
-
-/*
-* Write a contigious arbitrary amount of memory. Please note some virtual memory
-* such as pages of executables (such as DLLs) may be shared between different
-* virtual memory over different processes. As an example a write to kernel32.dll
-* in one process is likely to affect kernel32 in the whole system - in all
-* processes. Heaps and Stacks and other memory are usually safe to write to.
-* Please take care when writing to memory!
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = TRUE on success, FALSE on partial or zero write.
-*/
-_Success_(return)
-BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Translate a virtual address to a physical address by walking the page tables
-* of the specified process.
-* -- dwPID
-* -- qwVA
-* -- pqwPA
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
-
-
-
-//-----------------------------------------------------------------------------
-// VMM PROCESS FUNCTIONALITY BELOW:
-// Functionality below is mostly relating to Windows processes.
-//-----------------------------------------------------------------------------
-
-/*
-* Retrieve an active process given it's name. Please note that if multiple
-* processes with the same name exists only one will be returned. If required to
-* parse all processes with the same name please iterate over the PID list by
-* calling VMMDLL_PidList together with VMMDLL_ProcessGetInformation.
-* -- szProcName = process name (truncated max 15 chars) case insensitive.
-* -- pdwPID = pointer that will receive PID on success.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
-
-/*
-* List the PIDs in the system.
-* -- pPIDs = DWORD array of at least number of PIDs in system, or NULL.
-* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
-
-// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
-#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
-#define VMMDLL_MEMMAP_FLAG_PAGE_NS 0x0000000000000004
-#define VMMDLL_MEMMAP_FLAG_PAGE_NX 0x8000000000000000
-#define VMMDLL_MEMMAP_FLAG_PAGE_MASK 0x8000000000000006
-
-typedef struct tdVMMDLL_MEMMAP_ENTRY {
- ULONG64 AddrBase;
- ULONG64 cPages;
- ULONG64 fPage;
- BOOL fWoW64;
- CHAR szTag[32];
-} VMMDLL_MEMMAP_ENTRY, *PVMMDLL_MEMMAP_ENTRY;
-
-/*
-* Retrieve memory map entries from the specified process. Memory map entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries bytes.
-* If the pMemMapEntries is set to NULL the number of memory map entries will be
-* given in the pcMemMapEntries parameter.
-* -- dwPID
-* -- pMemMapEntries = buffer of minimum length sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries, or NULL.
-* -- pcMemMapEntries = pointer to number of memory map entries.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
-
-/*
-* Retrieve a single memory map entry given a virtual address within that entrys
-* range.
-* -- dwPID
-* -- pMemMapEntry
-* -- va = virtual address in the memory map entry to retrieve.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
-
-typedef struct tdVMMDLL_MODULEMAP_ENTRY {
- ULONG64 BaseAddress;
- ULONG64 EntryPoint;
- DWORD SizeOfImage;
- BOOL fWoW64;
- CHAR szName[32];
-} VMMDLL_MODULEMAP_ENTRY, *PVMMDLL_MODULEMAP_ENTRY;
-
-/*
-* Retrieve the module entries from the specified process. The module entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries bytes long. If the
-* pcModuleEntries is set to NULL the number of module entries will be given
-* in the pcModuleEntries parameter.
-* -- dwPID
-* -- pModuleEntries = buffer of minimum length sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries, or NULL.
-* -- pcModuleEntries = pointer to number of memory map entries.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
-
-/*
-* Retrieve a module (.exe or .dll or similar) given a module name.
-* -- dwPID
-* -- szModuleName
-* -- pModuleEntry
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
-
-#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
-#define VMMDLL_PROCESS_INFORMATION_VERSION 2
-
-typedef struct tdVMMDLL_PROCESS_INFORMATION {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
- VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
- BOOL fUserOnly; // only user mode pages listed
- DWORD dwPID;
- DWORD dwState;
- CHAR szName[16];
- ULONG64 paDTB;
- ULONG64 paDTB_UserOpt; // may not exist
- union {
- struct {
- ULONG64 vaEPROCESS;
- ULONG64 vaPEB;
- ULONG64 vaENTRY;
- BOOL fWow64;
- DWORD vaPEB32; // WoW64 only
- } win;
- } os;
-} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
-
-/*
-* Retrieve various process information from a PID. Process information such as
-* name, page directory bases and the process state may be retrieved.
-* -- dwPID
-* -- pProcessInformation = if null, size is given in *pcbProcessInfo
-* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
-
-typedef struct tdVMMDLL_EAT_ENTRY {
- ULONG64 vaFunction;
- DWORD vaFunctionOffset;
- CHAR szFunction[40];
-} VMMDLL_EAT_ENTRY, *PVMMDLL_EAT_ENTRY;
-
-typedef struct tdVMMDLL_IAT_ENTRY {
- ULONG64 vaFunction;
- CHAR szFunction[40];
- CHAR szModule[64];
-} VMMDLL_IAT_ENTRY, *PVMMDLL_IAT_ENTRY;
-
-/*
-* Retrieve information about: Data Directories, Sections, Export Address Table
-* and Import Address Table (IAT).
-* If the pData == NULL upon entry the number of entries of the pData array must
-* have in order to be able to hold the data is returned.
-* -- dwPID
-* -- szModule
-* -- pData
-* -- cData
-* -- pcData
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-
-
-
-//-----------------------------------------------------------------------------
-// VMM UTIL FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-/*
-* Fill a human readable hex ascii memory dump into the caller supplied sz buffer.
-* -- pb
-* -- cb
-* -- cbInitialOffset = offset, must be max 0x1000 and multiple of 0x10.
-* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
-* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
-*/
-_Success_(return)
-BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __VMMDLL_H__ */
diff --git a/README.md b/README.md
index 839e20e..a97493d 100644
--- a/README.md
+++ b/README.md
@@ -1,153 +1,24 @@
-The Memory Process File System:
+Plugins for MemProcFS
===============================
-The Memory Process File System is an easy and convenient way of accessing physical memory as files a virtual file system.
+This repository contains various non-core plugins for [MemProcFS - The Memory Process File System](https://github.com/ufrisk/MemProcFS).
-Easy trivial point and click memory analysis without the need for complicated commandline arguments! Access memory content and artifacts via files in a mounted virtual file system or via a feature rich application library to include in your own projects!
+Plugins range from non-core plugins to plugins that have offensive capabilities - such as _pypykatz_. Please find a short description for each plugin below:
-Analyze memory dump files, live memory via [DumpIt](https://www.comae.com/), loaded driver or even live memory in read-write mode via linked [PCILeech](https://github.com/ufrisk/pcileech/) and [PCILeech-FPGA](https://github.com/ufrisk/pcileech-fpga/) devices!
+## pypykatz
-It's even possible to connect to a remote LeechService memory acquisition service over a secured connection - allowing for remote live memory incident response - even over higher latency low band-width connections!
+#### Author:
+Tamas Jos ([@skelsec](https://twitter.com/SkelSec)) , info@skelsec.com , https://github.com/skelsec/
-Use your favorite tools to analyze memory - use your favorite hex editors, your python and powershell scripts, your disassemblers - all will work trivally with the Memory Process File System by just reading and writing files!
+#### Overview:
+_pypykatz_ for MemProcFS exposes mimikatz functionality in the folder `/py/secrets/` in the file system root provided that the target is a supported Windows system. Functionality includes retrieval of hashes, passwords, kerberos tickets and various other credentials.
-
+#### Installation instructions:
+1) Ensure MemProcFS supported version of 64-bit Python for Windows is on the system path (or specify in `-pythonpath` option when starting MemProcFS). NB! embedded Python will not work with _pypykatz_ since it requires access to Python pip installed packages.
+2) Install _pypykatz_ pip package, in correct python environment, by running `pip install pypykatz`.
+3) Copy the _pypykatz_ for _MemProcFS_ plugin by copying all files from [`/files/plugins/pym_pypykatz`](https://github.com/ufrisk/MemProcFS-plugins/tree/master/files/plugins) to corresponding folder in MemProcFS - overwriting any existing files there.
+4) Start MemProcFS.
+#### Functionality:
+
-Include the Memory Process File System in your Python or C/C++ programming projects! Almost everything in the Memory Process File System is exposed via an easy-to-use API for use in your own projects! The Plugin friendly architecture allows users to easily extend the Memory Process File System with native C .DLL plugins or Python .py plugins - providing additional analysis capabilities!
-
-Please check out the [project wiki](https://github.com/ufrisk/MemProcFS/wiki) for more in-depth detailed information about the file system itself, its API and its plugin modules!
-
-Please check out the [LeechCore project](https://github.com/ufrisk/LeechCore) for information about supported memory acquisition methods and remote memory access via the LeechService.
-
-Fast and easy memory analysis via mounted file system:
-======================================================
-No matter if you have no prior knowledge of memory analysis or are an advanced user the Memory Process File System (and the API) may be useful! Click around the memory objects in the file system
-
-
-
-Extensive Python and C/C++ API:
-===============================
-Everything in the Memory Process File System is exposed as APIs. APIs exist for both C/C++ `vmmdll.h` and Python `vmmpy.py`. The file system itself is made available virtually via the API without the need to mount it. Specialized process analysis and process alteration functionality is made easy by calling API functionality. It is possible to read both virtual process memory as well as physical memory! The example below shows reading 0x20 bytes from physical address 0x1000:
-```
->>> from vmmpy import *
->>> VmmPy_Initialize('c:/temp/win10_memdump.raw')
->>> print(VmmPy_UtilFillHexAscii(VmmPy_MemRead(-1, 0x1000, 0x20)))
-0000 e9 4d 06 00 01 00 00 00 01 00 00 00 3f 00 18 10 .M..........?...
-0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
-```
-
-Modular Plugin Architecture:
-============================
-Anyone is able to extend the Memory Process File System with custom plugins! It is as easy as dropping a python file in the correct directory or compiling a tiny C DLL. Existing functionality is already implemented as well documented C and Python plugins!
-
-Installing:
-===========
-## Windows
-Download or clone the Memory Process File System github repository. Pre-built binaries are found in the files folder. If the Memory Process File System is used as an API it is only dependant on the Microsoft Visual C++ Redistributables for Visual Studio 2017 (see below).
-
-The Memory Process File System is dependant on the [LeechCore project](https://github.com/ufrisk/LeechCore) for memory acquisition. The necessary _leechcore.dll_ file is already pre-built and included in the files folder.
-
-The Memory Process File System is also dependant in the Microsoft Visual C++ Redistributables for Visual Studio 2017. They can be downloaded from Microsoft [here](https://go.microsoft.com/fwlink/?LinkId=746572). Alternatively, if installing the Dokany file system driver please install the DokanSetup_redist version and it will install the required redistributables.
-
-Mounting the file system requires the Dokany file system library to be installed. Please download and install the latest version of Dokany at: https://github.com/dokan-dev/dokany/releases/latest It is recommended to download and install the DokanSetup_redist version.
-
-Python support requires Python 3.6. The user may specify the path to the Python 3.6 installation with the command line parameter `-pythonhome`, alternatively download [Python 3.6 - Windows x86-64 embeddable zip file](https://www.python.org/downloads/windows/) and unzip its contents into the `files/python36` folder when using Python modules in the file system. To use the Python API a normal Python 3.6 installation for Windows is required.
-
-To capture live memory (without PCILeech FPGA hardware) download [DumpIt](https://www.comae.com/) and start the Memory Process File System via the DumpIt /LIVEKD mode. Alternatively, get WinPMEM by downloading and installing the most recent version of [Rekall](https://github.com/google/rekall/releases) and copy the signed driver 'winpmem_x64.sys' from _C:\Program Files\Rekall\resources\WinPmem_ into the files folder. DumpIt is recommended over winpmem due to superior stability and lack of blue screens.
-
-PCILeech FPGA will require hardware as well as _FTD3XX.dll_ to be dropped in the files folder. Please check out the [LeechCore](https://github.com/ufrisk/LeechCore) project for instructions.
-
-## Linux
-The memory process file system is not yet supported on Linux.
-
-Examples:
-=========
-Start the Memory Process File System from the command line - possibly by using one of the examples below.
-
-Or register the memory dump extension with MemProcFS.exe so that the file system is mounted when double-clicking on a memory dump file!
-
-- mount the memory dump file as default M: `memprocfs.exe -device c:\temp\win10x64-dump.raw`
-- mount the memory dump file as default M: with extra verbosity: `memprocfs.exe -device c:\temp\win10x64-dump.raw -v`
-- mount the memory dump file as default M: with extra extra verbosity: `memprocfs.exe -device c:\temp\win10x64-dump.raw -v -vv`
-- mount the memory dump file as S: `memprocfs.exe -mount s -device c:\temp\win10x64-dump.raw`
-- mount live target memory, in verbose read-only mode, with DumpIt in /LIVEKD mode: `DumpIt.exe /LIVEKD /A memprocfs.exe /C "-v"`
-- mount live target memory, in read-only mode, with WinPMEM driver: `memprocfs.exe -device pmem`
-- mount live target memory, in read/write mode, with PCILeech FPGA memory acquisition device: `memprocfs.exe -device fpga`
-- mount live target memory, in read/write mode, with TotalMeltdown vulnerability acquisition device: `memprocfs.exe -device totalmeltdown`
-- mount an arbitrary x64 memory dump by specifying the process or kernel page table base in the cr3 option: `memprocfs.exe -device c:\temp\unknown-x64-dump.raw -cr3 0x1aa000`
-
-Documentation:
-==============
-For additional documentation please check out the [project wiki](https://github.com/ufrisk/MemProcFS/wiki) for in-depth detailed information about the file system itself, its API and its plugin modules! For additional information about memory acqusition methods check out the [LeechCore project](https://github.com/ufrisk/LeechCore/)
-
-Also check out my Microsoft BlueHatIL 2019 talk _Practical Uses for Hardware-assisted Memory Visualization_ about MemProcFS at Youtube below:
-
-
-Building:
-=========
-Pre-built binaries and other supporting files are found in the files folder. The Memory Process File System binaries are built with Visual Studio 2017. No binaries currently exists for Linux (future support - please see Current Limitations & Future Development below).
-
-Detailed build instructions may be found in the [Wiki](https://github.com/ufrisk/MemProcFS/wiki) in the [Building](https://github.com/ufrisk/MemProcFS/wiki/Dev_Building) section.
-
-Current Limitations & Future Development:
-=========================================
-The Memory Process File System is currently limited to analyzing Windows (32-bit and 64-bit XP to 10) memory dumps (other x64 dumps in a very limited way). Also, the Memory Process File System currently does not run on Linux.
-
-Please find some ideas for possible future expansions of the memory process file system listed below. This is a list of ideas - not a list of features that will be implemented. Even though some items are put as prioritized there is no guarantee that they will be implemented in a timely fashion.
-
-### Prioritized items:
-- More/new plugins.
-- Additional core functionality (exported functions in .DLL). Please request in Issues section if ideas exist.
-
-### Other items:
-- PFN support.
-- Linux support in mounted FUSE file system.
-- Support for analyzing x64 Linux, macOS and UEFI memory dumps.
-- Hash lookup of executable memory pages in DB.
-
-Links:
-======
-* Blog: http://blog.frizk.net
-* Twitter: https://twitter.com/UlfFrisk
-* PCILeech: https://github.com/ufrisk/pcileech/
-* LeechCore: https://github.com/ufrisk/LeechCore/
-* YouTube: https://www.youtube.com/channel/UC2aAi-gjqvKiC7s7Opzv9rg
-
-Changelog:
-===================
-v1.0
-* Initial Release.
-
-v1.1
-* Loaded kernel drivers in System process 'modules' sub-directory (Windows 10).
-
-v1.2
-* Support for 32-bit Windows - XP to 10.
-* Support for 32-bit memory models (x86 and PAE).
-* Improved auto-identification of memory model and Windows.
-* Loaded kernel drivers in System process 'modules' sub-directory (all Windows versions).
-* PE (exe/dll/sys) Sections and Data Directories as files in 'modules' sub-directory.
-
-v2.0
-* Major new release with multiple changes. Most noteworty are:
-* Multi-Threading support.
-* Performance optimizations.
-* Memory acqusition via the [LeechCore](https://github.com/ufrisk/LeechCore/) library with additional support for:
- * Live memory acquisition with DumpIt in /LIVEKD mode or loaded kernel driver.
- * Support for Microsoft Crash Dumps - such as created by default by [Comae DumpIt](https://www.comae.com).
- * Hyper-V save files.
- * Remote capture via remotely installed LeechService.
-
-v2.1
-* New APIs:
- * IAT/EAT hook functionality.
- * Limited Windows 10 MemCompression support.
-* Bug fixes.
-
-v2.2
-* New API:
- * Force refresh of process list and caches.
-
-Latest
-* Fix deadlock issue in Python plugin.
-* Pypykatz for MemProcFs
+#### Last updated: 2019-03-17
diff --git a/files/MemProcFS.exe b/files/MemProcFS.exe
deleted file mode 100644
index 023d694..0000000
Binary files a/files/MemProcFS.exe and /dev/null differ
diff --git a/files/dissect/cstruct/__init__.py b/files/dissect/cstruct/__init__.py
deleted file mode 100644
index 34da3a8..0000000
--- a/files/dissect/cstruct/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from dissect.cstruct.cstruct import (
- cstruct,
- ctypes,
- dumpstruct,
- hexdump,
- Instance,
- PointerInstance,
- Parser,
- RawType,
- BaseType,
- Error,
- ParserError,
- CompilerError,
- ResolveError,
- NullPointerDereference,
-)
-
-__all__ = [
- "cstruct",
- "ctypes",
- "dumpstruct",
- "hexdump",
- "Instance",
- "PointerInstance",
- "Parser",
- "RawType",
- "BaseType",
- "Error",
- "ParserError",
- "CompilerError",
- "ResolveError",
- "NullPointerDereference",
-]
diff --git a/files/dissect/cstruct/cstruct.py b/files/dissect/cstruct/cstruct.py
deleted file mode 100644
index 39ffc73..0000000
--- a/files/dissect/cstruct/cstruct.py
+++ /dev/null
@@ -1,1918 +0,0 @@
-# Copyright (c) 2018 Fox-IT Security Research Team
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-# TODO:
-# - Rework definition parsing, maybe pycparser?
-# - Change expression implementation
-# - Lazy reading?
-from __future__ import print_function
-import re
-import sys
-import ast
-import pprint
-import string
-import struct
-import ctypes as _ctypes
-from io import BytesIO
-from collections import OrderedDict
-
-try:
- from builtins import bytes as newbytes
-except ImportError:
- newbytes = bytes
-
-PY3 = sys.version_info > (3,)
-if PY3:
- long = int
- xrange = range
-
-DEBUG = False
-
-COLOR_RED = '\033[1;31m'
-COLOR_GREEN = '\033[1;32m'
-COLOR_YELLOW = '\033[1;33m'
-COLOR_BLUE = '\033[1;34m'
-COLOR_PURPLE = '\033[1;35m'
-COLOR_CYAN = '\033[1;36m'
-COLOR_WHITE = '\033[1;37m'
-COLOR_NORMAL = '\033[1;0m'
-
-COLOR_BG_RED = '\033[1;41m\033[1;37m'
-COLOR_BG_GREEN = '\033[1;42m\033[1;37m'
-COLOR_BG_YELLOW = '\033[1;43m\033[1;37m'
-COLOR_BG_BLUE = '\033[1;44m\033[1;37m'
-COLOR_BG_PURPLE = '\033[1;45m\033[1;37m'
-COLOR_BG_CYAN = '\033[1;46m\033[1;37m'
-COLOR_BG_WHITE = '\033[1;47m\033[1;30m'
-
-PRINTABLE = string.digits + string.ascii_letters + string.punctuation + " "
-
-COMPILE_TEMPL = """
-class {name}(Structure):
- def __init__(self, cstruct, structure, source=None):
- self.structure = structure
- self.source = source
- super({name}, self).__init__(cstruct, structure.name, structure.fields)
-
- def _read(self, stream):
- r = OrderedDict()
- sizes = {{}}
- bitreader = BitBuffer(stream, self.cstruct.endian)
-
-{read_code}
-
- return Instance(self, r, sizes)
-
- def add_fields(self, name, type_, offset=None):
- raise NotImplementedError("Can't add fields to a compiled structure")
-
- def __repr__(self):
- return ''
-"""
-
-
-class Error(Exception):
- pass
-
-
-class ParserError(Error):
- pass
-
-
-class CompilerError(Error):
- pass
-
-
-class ResolveError(Error):
- pass
-
-
-class NullPointerDereference(Error):
- pass
-
-
-def log(line, *args, **kwargs):
- if not DEBUG:
- return
-
- print(line.format(*args, **kwargs), file=sys.stderr)
-
-
-class cstruct(object):
- """Main class of cstruct. All types are registered in here.
-
- Args:
- endian: The endianness to use when parsing.
- pointer: The pointer type to use for Pointers.
- """
-
- DEF_CSTYLE = 1
-
- def __init__(self, endian='<', pointer='uint64'):
- self.endian = endian
-
- self.consts = {}
- self.lookups = {}
- self.typedefs = {
- 'byte': 'int8',
- 'ubyte': 'uint8',
- 'uchar': 'uint8',
- 'short': 'int16',
- 'ushort': 'uint16',
- 'long': 'int32',
- 'ulong': 'uint32',
- 'ulong64': 'uint64',
-
- 'u1': 'uint8',
- 'u2': 'uint16',
- 'u4': 'uint32',
- 'u8': 'uint64',
-
- 'word': 'uint16',
- 'dword': 'uint32',
-
- 'longlong': 'int64',
- 'ulonglong': 'uint64',
-
- 'int': 'int32',
- 'unsigned int': 'uint32',
-
- 'int8': PackedType(self, 'int8', 1, 'b'),
- 'uint8': PackedType(self, 'uint8', 1, 'B'),
- 'int16': PackedType(self, 'int16', 2, 'h'),
- 'uint16': PackedType(self, 'uint16', 2, 'H'),
- 'int32': PackedType(self, 'int32', 4, 'i'),
- 'uint32': PackedType(self, 'uint32', 4, 'I'),
- 'int64': PackedType(self, 'int64', 8, 'q'),
- 'uint64': PackedType(self, 'uint64', 8, 'Q'),
- 'float': PackedType(self, 'float', 4, 'f'),
- 'double': PackedType(self, 'double', 8, 'd'),
- 'char': CharType(self),
- 'wchar': WcharType(self),
-
- 'int24': BytesInteger(self, 'int24', 3, True),
- 'uint24': BytesInteger(self, 'uint24', 3, False),
- 'int48': BytesInteger(self, 'int48', 6, True),
- 'uint48': BytesInteger(self, 'uint48', 6, False),
-
- 'void': VoidType(),
- }
-
- self.pointer = self.resolve(pointer)
-
- def addtype(self, name, t, replace=False):
- """Add a type or type reference.
-
- Args:
- name: Name of the type to be added.
- t: The type to be added. Can be a str reference to another type
- or a compatible type class.
-
- Raises:
- ValueError: If the type already exists.
- """
- name = name.lower()
- if not replace and name.lower() in self.typedefs:
- raise ValueError("Duplicate type: %s" % name)
-
- self.typedefs[name] = t
-
- def load(self, s, deftype=None, **kwargs):
- """Parse structures from the given definitions using the given definition type.
-
- Definitions can be parsed using different parsers. Currently, there's
- only one supported parser - DEF_CSTYLE. Parsers can add types and
- modify this cstruct instance. Arguments can be passed to parsers
- using kwargs.
-
- Args:
- s: The definition to parse.
- deftype: The definition type to parse the definitions with.
- **kwargs: Keyword arguments for parsers.
- """
- deftype = deftype or cstruct.DEF_CSTYLE
-
- if deftype == cstruct.DEF_CSTYLE:
- parser = CStyleParser(self, **kwargs)
-
- parser.parse(s)
-
- def loadfile(self, s, deftype=None, **kwargs):
- """Load structure definitions from a file.
-
- The given path will be read and parsed using the .load() function.
-
- Args:
- s: The path to load definitions from.
- deftype: The definition type to parse the definitions with.
- **kwargs: Keyword arguments for parsers.
- """
- with open(s, 'r') as fh:
- self.load(fh.read(), deftype, **kwargs)
-
- def read(self, name, s):
- """Parse data using a given type.
-
- Args:
- name: Type name to read.
- s: File-like object or byte string to parse.
-
- Returns:
- The parsed data.
- """
- return self.resolve(name).read(s)
-
- def resolve(self, name):
- """Resolve a type name to get the actual type object.
-
- Types can be referenced using different names. When we want
- the actual type object, we need to resolve these references.
-
- Args:
- name: Type name to resolve.
-
- Returns:
- The resolved type object.
-
- Raises:
- ResolveError: If the type can't be resolved.
- """
- t = name
- if not isinstance(t, str):
- return t
-
- for i in xrange(10):
- if t.lower() not in self.typedefs:
- raise ResolveError("Unknown type %s" % name)
-
- t = self.typedefs[t.lower()]
-
- if not isinstance(t, str):
- return t
-
- raise ResolveError("Recursion limit exceeded while resolving type %s" % name)
-
- def __getattr__(self, attr):
- if attr.lower() in self.typedefs:
- return self.typedefs[attr.lower()]
-
- if attr in self.consts:
- return self.consts[attr]
-
- raise AttributeError("Invalid Attribute: %s" % attr)
-
-
-class Parser(object):
- """Base class for definition parsers.
-
- Args:
- cstruct: An instance of cstruct.
- """
-
- def __init__(self, cstruct):
- self.cstruct = cstruct
-
- def parse(self, data):
- """This function should parse definitions to cstruct types.
-
- Args:
- data: Data to parse definitions from, usually a string.
- """
- raise NotImplementedError()
-
-
-class CStyleParser(Parser):
- """Definition parser for C-like structure syntax.
-
- Args:
- cstruct: An instance of cstruct
- compiled: Whether structs should be compiled or not.
- """
-
- def __init__(self, cstruct, compiled=True):
- self.compiled = compiled
- super(CStyleParser, self).__init__(cstruct)
-
- # TODO: Implement proper parsing
- def parse(self, data):
- self._constants(data)
- self._enums(data)
- self._structs(data)
- self._lookups(data, self.cstruct.consts)
-
- def _constants(self, data):
- r = re.finditer(r'#define\s+(?P[^\s]+)\s+(?P[^\r\n]+)\s*\n', data)
- for t in r:
- d = t.groupdict()
- v = d['value'].rsplit('//')[0]
-
- try:
- v = ast.literal_eval(v)
- except (ValueError, SyntaxError):
- pass
-
- self.cstruct.consts[d['name']] = v
-
- def _enums(self, data):
- r = re.finditer(
- r'enum\s+(?P[^\s:{]+)\s*(:\s*(?P[^\s]+)\s*)?\{(?P[^}]+)\}\s*;',
- data,
- )
- for t in r:
- d = t.groupdict()
-
- nextval = 0
- values = {}
- for line in d['values'].split('\n'):
- line, sep, comment = line.partition("//")
- for v in line.split(","):
- key, sep, val = v.partition("=")
- key = key.strip()
- val = val.strip()
- if not key:
- continue
- if not val:
- val = nextval
- else:
- val = Expression(self.cstruct, val).evaluate({})
-
- nextval = val + 1
-
- values[key] = val
-
- if not d['type']:
- d['type'] = 'uint32'
-
- enum = Enum(
- self.cstruct, d['name'], self.cstruct.resolve(d['type']), values
- )
- self.cstruct.addtype(enum.name, enum)
-
- def _structs(self, data):
- compiler = Compiler(self.cstruct)
- r = re.finditer(
- r'(#(?P(?:compile))\s+)?((?Ptypedef)\s+)?(?P[^\s]+)\s+(?P[^\s]+)?(?P\s*\{[^}]+\}(?P\s+[^;\n]+)?)?\s*;',
- data,
- )
- for t in r:
- d = t.groupdict()
-
- if d['name']:
- name = d['name']
- elif d['defs']:
- name = d['defs'].strip().split(',')[0].strip()
- else:
- raise ParserError("No name for struct")
-
- if d['type'] == 'struct':
- data = self._parse_fields(d['fields'][1:-1].strip())
- st = Structure(self.cstruct, name, data)
- if d['flags'] == 'compile' or self.compiled:
- st = compiler.compile(st)
- elif d['typedef'] == 'typedef':
- st = d['type']
- else:
- continue
-
- if d['name']:
- self.cstruct.addtype(d['name'], st)
-
- if d['defs']:
- for td in d['defs'].strip().split(','):
- td = td.strip()
- self.cstruct.addtype(td, st)
-
- def _parse_fields(self, s):
- fields = re.finditer(
- r'(?P[^\s]+)\s+(?P[^\s\[:]+)(:(?P\d+))?(\[(?P[^;\n]*)\])?;',
- s,
- )
- r = []
- for f in fields:
- d = f.groupdict()
- if d['type'].startswith('//'):
- continue
-
- type_ = self.cstruct.resolve(d['type'])
-
- d['name'] = d['name'].replace('(', '').replace(')', '')
-
- # Maybe reimplement lazy type references later
- # _type = TypeReference(self, d['type'])
- if d['count'] is not None:
- if d['count'] == '':
- count = None
- else:
- count = Expression(self.cstruct, d['count'])
- try:
- count = count.evaluate()
- except Exception:
- pass
-
- type_ = Array(self.cstruct, type_, count)
-
- if d['name'].startswith('*'):
- d['name'] = d['name'][1:]
- type_ = Pointer(self.cstruct, type_)
-
- field = Field(d['name'], type_, int(d['bits']) if d['bits'] else None)
- r.append(field)
-
- return r
-
- def _lookups(self, data, consts):
- r = re.finditer(r'\$(?P[^\s]+) = ({[^}]+})\w*\n', data)
-
- for t in r:
- d = ast.literal_eval(t.group(2))
- self.cstruct.lookups[t.group(1)] = dict(
- [(self.cstruct.consts[k], v) for k, v in d.items()]
- )
-
-
-class Instance(object):
- """Holds parsed structure data."""
-
- def __init__(self, type_, values, sizes=None):
- object.__setattr__(self, '_type', type_)
- object.__setattr__(self, '_values', values)
- object.__setattr__(self, '_sizes', sizes)
-
- def write(self, fh):
- """Write this structure to a writable file-like object.
-
- Args:
- fh: File-like objects that supports writing.
-
- Returns:
- The amount of bytes written.
- """
- return self.__dict__['_type'].write(fh, self)
-
- def dumps(self):
- """Dump this structure to a byte string.
-
- Returns:
- The raw bytes of this structure.
- """
- s = BytesIO()
- self.write(s)
- return s.getvalue()
-
- def __getattr__(self, attr):
- if attr not in self.__dict__['_type'].lookup:
- raise AttributeError("Invalid attribute: %r" % attr)
-
- return self.__dict__['_values'][attr]
-
- def __setattr__(self, attr, value):
- if attr not in self.__dict__['_type'].lookup:
- raise AttributeError("Invalid attribute: %r" % attr)
-
- self.__dict__['_values'][attr] = value
-
- def __getitem__(self, item):
- return self.__dict__['_values'][item]
-
- def __contains__(self, attr):
- return attr in self.__dict__['_values']
-
- def __repr__(self):
- return '<%s %s>' % (
- self.__dict__['_type'].name,
- ', '.join(
- [
- '%s=%s' % (k, hex(v) if isinstance(v, (int, long)) else repr(v))
- for k, v in self.__dict__['_values'].items()
- ]
- ),
- )
-
- def __len__(self):
- return len(self.dumps())
-
- def _size(self, field):
- return self.__dict__['_sizes'][field]
-
-
-class PointerInstance(object):
- """Like the Instance class, but for structures referenced by a pointer."""
-
- def __init__(self, t, stream, addr, ctx):
- self._stream = stream
- self._type = t
- self._addr = addr
- self._ctx = ctx
- self._value = None
-
- def _get(self):
- log("Dereferencing pointer -> 0x{:016x} [{!r}]", self._addr, self._stream)
- if self._addr == 0:
- raise NullPointerDereference()
-
- if self._value is None:
- pos = self._stream.tell()
- self._stream.seek(self._addr)
- if isinstance(self._type, Array):
- r = self._type._read(self._stream, self._ctx)
- else:
- r = self._type._read(self._stream)
- self._stream.seek(pos)
- self._value = r
-
- return self._value
-
- def __getattr__(self, attr):
- return getattr(self._get(), attr)
-
- def __str__(self):
- return str(self._get())
-
- def __nonzero__(self):
- return self._addr != 0
-
- def __repr__(self):
- return "".format(self._type, self._addr)
-
-
-class Expression(object):
- """Expression parser for simple calculations in definitions."""
-
- operators = [
- ('+', lambda a, b: a + b),
- ('-', lambda a, b: a - b),
- ('*', lambda a, b: a * b),
- ('/', lambda a, b: a / b),
- ('&', lambda a, b: a & b),
- ('|', lambda a, b: a | b),
- ('>>', lambda a, b: a >> b),
- ('<<', lambda a, b: a << b),
- ]
-
- def __init__(self, cstruct, expr):
- self.cstruct = cstruct
- self.expr = expr
-
- def evaluate(self, context=None):
- context = context if context else {}
- level = 0
- levels = []
- buf = ''
-
- for i in xrange(len(self.expr)):
- if self.expr[i] == '(':
- level += 1
- levels.append(buf)
- buf = ''
- continue
-
- if self.expr[i] == ')':
- level -= 1
- val = self.evaluate_part(buf, context)
- buf = levels.pop()
- buf += str(val)
- continue
-
- buf += self.expr[i]
-
- return self.evaluate_part(buf, context)
-
- def evaluate_part(self, e, v):
- e = e.strip()
-
- for o in self.operators:
- if o[0] in e:
- a, b = e.rsplit(o[0], 1)
- return o[1](self.evaluate_part(a, v), self.evaluate_part(b, v))
-
- if e in v:
- return v[e]
-
- if e.startswith('0x'):
- return int(e, 16)
-
- if e in self.cstruct.consts:
- return self.cstruct.consts[e]
-
- return int(e)
-
- def __repr__(self):
- return self.expr
-
-
-class BaseType(object):
- """Base class for cstruct type classes."""
-
- def __init__(self, cstruct):
- self.cstruct = cstruct
-
- def reads(self, data):
- """Parse the given data according to the type that implements this class.
-
- Args:
- data: Byte string to parse.
-
- Returns:
- The parsed value of this type.
- """
- data = BytesIO(data)
- return self._read(data)
-
- def dumps(self, data):
- """Dump the given data according to the type that implements this class.
-
- Args:
- data: Data to dump.
-
- Returns:
- The resulting bytes.
- """
- out = BytesIO()
- self._write(out, data)
- return out.getvalue()
-
- def read(self, obj, *args, **kwargs):
- """Parse the given data according to the type that implements this class.
-
- Args:
- obj: Data to parse. Can be a (byte) string or a file-like object.
-
- Returns:
- The parsed value of this type.
- """
- if isinstance(obj, (str, bytes, newbytes)):
- return self.reads(obj)
-
- return self._read(obj)
-
- def write(self, stream, data):
- """Write the given data to a writable file-like object according to the
- type that implements this class.
-
- Args:
- stream: Writable file-like object to write to.
- data: Data to write.
-
- Returns:
- The amount of bytes written.
- """
- return self._write(stream, data)
-
- def _read(self, stream):
- raise NotImplementedError()
-
- def _read_array(self, stream, count):
- return [self._read(stream) for i in xrange(count)]
-
- def _read_0(self, stream):
- raise NotImplementedError()
-
- def _write(self, stream, data):
- raise NotImplementedError()
-
- def _write_array(self, stream, data):
- num = 0
- for i in data:
- num += self._write(stream, i)
- return num
-
- def _write_0(self, stream, data):
- raise NotImplementedError()
-
- def default(self):
- """Return a default value of this type."""
- raise NotImplementedError()
-
- def default_array(self):
- """Return a default array of this type."""
- raise NotImplementedError()
-
- def __getitem__(self, count):
- return Array(self.cstruct, self, count)
-
- def __call__(self, *args, **kwargs):
- if len(args) > 0:
- return self.read(*args, **kwargs)
-
- r = self.default()
- if kwargs:
- for k, v in kwargs.items():
- setattr(r, k, v)
-
- return r
-
-
-class RawType(BaseType):
- """Base class for raw types that have a name and size."""
-
- def __init__(self, cstruct, name=None, size=0):
- self.name = name
- self.size = size
- super(RawType, self).__init__(cstruct)
-
- def __len__(self):
- return self.size
-
- def __repr__(self):
- if self.name:
- return self.name
-
- return BaseType.__repr__(self)
-
-
-class Structure(BaseType):
- """Type class for structures."""
-
- def __init__(self, cstruct, name, fields=None):
- self.name = name
- self.size = None
- self.lookup = OrderedDict()
- self.fields = fields if fields else []
-
- for f in self.fields:
- self.lookup[f.name] = f
-
- self._calc_offsets()
- super(Structure, self).__init__(cstruct)
-
- def _calc_offsets(self):
- offset = 0
- bitstype = None
- bitsremaining = 0
-
- for field in self.fields:
- if field.bits:
- if bitsremaining == 0 or field.type != bitstype:
- bitstype = field.type
- bitsremaining = bitstype.size * 8
- if offset is not None:
- field.offset = offset
- offset += bitstype.size
- else:
- field.offset = None
-
- bitsremaining -= field.bits
- continue
-
- field.offset = offset
- if offset is not None:
- try:
- offset += len(field.type)
- except TypeError:
- offset = None
-
- def _calc_size(self):
- size = 0
- bitstype = None
- bitsremaining = 0
-
- for field in self.fields:
- if field.bits:
- if bitsremaining == 0 or field.type != bitstype:
- bitstype = field.type
- bitsremaining = bitstype.size * 8
- size += bitstype.size
-
- bitsremaining -= field.bits
- continue
-
- fieldlen = len(field.type)
- size += fieldlen
-
- if field.offset is not None:
- size = max(size, field.offset + fieldlen)
-
- return size
-
- def _read(self, stream, *args, **kwargs):
- log("[Structure::read] {} {}", self.name, self.size)
- bitbuffer = BitBuffer(stream, self.cstruct.endian)
-
- struct_start = stream.tell()
-
- r = OrderedDict()
- sizes = {}
- for field in self.fields:
- start = stream.tell()
- ft = self.cstruct.resolve(field.type)
-
- if field.offset:
- if start != struct_start + field.offset:
- log(
- "+ seeking to 0x{:x}+0x{:x} for {}".format(
- struct_start, field.offset, field.name
- )
- )
- stream.seek(struct_start + field.offset)
- start = struct_start + field.offset
-
- if field.bits:
- r[field.name] = bitbuffer.read(ft, field.bits)
- continue
- else:
- bitbuffer.reset()
-
- if isinstance(ft, (Array, Pointer)):
- v = ft._read(stream, r)
- else:
- v = ft._read(stream)
-
- sizes[field.name] = stream.tell() - start
- r[field.name] = v
-
- return Instance(self, r, sizes)
-
- def _write(self, stream, data):
- bitbuffer = BitBuffer(stream, self.cstruct.endian)
- num = 0
-
- for field in self.fields:
- if field.bits:
- bitbuffer.write(field.type, getattr(data, field.name), field.bits)
- continue
-
- if bitbuffer._type:
- bitbuffer.flush()
-
- num += field.type._write(stream, getattr(data, field.name))
-
- # Flush bitbuffer
- if bitbuffer._type:
- bitbuffer.flush()
-
- return num
-
- def add_field(self, name, type_, offset=None):
- """Add a field to this structure.
-
- Args:
- name: The field name.
- type_: The field type.
- offset: The field offset.
- """
- field = Field(name, type_, offset=offset)
- self.fields.append(field)
- self.lookup[name] = field
- self.size = None
- setattr(self, name, field)
-
- def default(self):
- """Create and return an empty Instance from this structure.
-
- Returns:
- An empty Instance from this structure.
- """
- r = OrderedDict()
- for field in self.fields:
- r[field.name] = field.type.default()
-
- return Instance(self, r)
-
- def __len__(self):
- if self.size is None:
- self.size = self._calc_size()
-
- return self.size
-
- def __repr__(self):
- return ''.format(self.name)
-
- def show(self, indent=0):
- """Pretty print this structure."""
- if indent == 0:
- print("struct {}".format(self.name))
-
- for field in self.fields:
- if field.offset is None:
- offset = '0x??'
- else:
- offset = '0x{:02x}'.format(field.offset)
-
- print("{}+{} {} {}".format(' ' * indent, offset, field.name, field.type))
-
- if isinstance(field.type, Structure):
- field.type.show(indent + 1)
-
-
-class BitBuffer(object):
- """Implements a bit buffer that can read and write bit fields."""
-
- def __init__(self, stream, endian):
- self.stream = stream
- self.endian = endian
-
- self._type = None
- self._buffer = 0
- self._remaining = 0
-
- def read(self, field_type, bits):
- if self._remaining < 1 or self._type != field_type:
- self._type = field_type
- self._remaining = field_type.size * 8
- self._buffer = field_type._read(self.stream)
-
- if self.endian != '>':
- v = self._buffer & ((1 << bits) - 1)
- self._buffer >>= bits
- self._remaining -= bits
- else:
- v = self._buffer & (
- ((1 << (self._remaining - bits)) - 1) ^ ((1 << self._remaining) - 1)
- )
- v >>= self._remaining - bits
- self._remaining -= bits
-
- return v
-
- def write(self, field_type, data, bits):
- if self._remaining == 0:
- self._remaining = field_type.size * 8
- self._type = field_type
-
- if self.endian != '>':
- self._buffer |= data << (self._type.size * 8 - self._remaining)
- else:
- self._buffer |= data << (self._remaining - bits)
-
- self._remaining -= bits
-
- def flush(self):
- self._type._write(self.stream, self._buffer)
- self._type = None
- self._remaining = 0
- self._buffer = 0
-
- def reset(self):
- self._type = None
- self._buffer = 0
- self._remaining = 0
-
-
-class Field(object):
- """Holds a structure field."""
-
- def __init__(self, name, type_, bits=None, offset=None):
- self.name = name
- self.type = type_
- self.bits = bits
- self.offset = offset
-
- def __repr__(self):
- return ''.format(self.name, self.type)
-
-
-class Array(BaseType):
- """Implements a fixed or dynamically sized array type.
-
- Example:
- When using the default C-style parser, the following syntax is supported:
-
- x[3] -> 3 -> static length.
- x[] -> None -> null-terminated.
- x[expr] -> expr -> dynamic length.
- """
-
- def __init__(self, cstruct, type_, count):
- self.type = type_
- self.count = count
- self.dynamic = isinstance(self.count, Expression) or self.count is None
-
- super(Array, self).__init__(cstruct)
-
- def _read(self, stream, context=None):
- if self.count is None:
- return self.type._read_0(stream)
-
- if self.dynamic:
- count = self.count.evaluate(context)
- else:
- count = self.count
-
- return self.type._read_array(stream, max(0, count))
-
- def _write(self, f, data):
- if self.count is None:
- return self.type._write_0(f, data)
-
- return self.type._write_array(f, data)
-
- def default(self):
- if self.dynamic or self.count is None:
- return []
-
- return [self.type.default() for i in xrange(self.count)]
-
- def __repr__(self):
- if self.count is None:
- return '{0!r}[]'.format(self.type)
-
- return '{0!r}[{1}]'.format(self.type, self.count)
-
- def __len__(self):
- if self.dynamic:
- raise TypeError("Dynamic size")
-
- return len(self.type) * self.count
-
-
-class PackedType(RawType):
- """Implements a packed type that uses Python struct packing characters."""
-
- def __init__(self, cstruct, name, size, packchar):
- self.packchar = packchar
- super(PackedType, self).__init__(cstruct, name, size)
-
- def _read(self, stream):
- return self._read_array(stream, 1)[0]
-
- def _read_array(self, stream, count):
- length = self.size * count
- data = stream.read(length)
- fmt = self.cstruct.endian + str(count) + self.packchar
- if len(data) != length:
- raise EOFError("Read %d bytes, but expected %d" % (len(data), length))
-
- return list(struct.unpack(fmt, data))
-
- def _read_0(self, stream):
- r = []
- while True:
- d = stream.read(self.size)
- v = struct.unpack(self.cstruct.endian + self.packchar, d)[0]
-
- if v == 0:
- break
-
- r.append(v)
-
- return r
-
- def _write(self, stream, data):
- return self._write_array(stream, [data])
-
- def _write_array(self, stream, data):
- fmt = self.cstruct.endian + str(len(data)) + self.packchar
- return stream.write(struct.pack(fmt, *data))
-
- def _write_0(self, stream, data):
- return self._write_array(stream, data + [0])
-
- def default(self):
- return 0
-
- def default_array(self, count):
- return [0] * count
-
-
-class CharType(RawType):
- """Implements a character type that can properly handle strings."""
-
- def __init__(self, cstruct):
- super(CharType, self).__init__(cstruct, 'char', 1)
-
- def _read(self, stream):
- return stream.read(1)
-
- def _read_array(self, stream, count):
- if count == 0:
- return b''
-
- return stream.read(count)
-
- def _read_0(self, stream):
- r = []
- while True:
- c = stream.read(1)
- if c == b'':
- raise EOFError()
-
- if c == b'\x00':
- break
-
- r.append(c)
-
- return b''.join(r)
-
- def _write(self, stream, data):
- if isinstance(data, int):
- data = chr(data)
-
- if PY3 and isinstance(data, str):
- data = data.encode('latin-1')
-
- return stream.write(data)
-
- def _write_array(self, stream, data):
- return self._write(stream, data)
-
- def _write_0(self, stream, data):
- return self._write(stream, data + b'\x00')
-
- def default(self):
- return b'\x00'
-
- def default_array(self, count):
- return b'\x00' * count
-
-
-class WcharType(RawType):
- """Implements a wide-character type."""
-
- def __init__(self, cstruct):
- super(WcharType, self).__init__(cstruct, 'wchar', 2)
-
- @property
- def encoding(self):
- if self.cstruct.endian == '<':
- return 'utf-16-le'
- elif self.cstruct.endian == '>':
- return 'utf-16-be'
-
- def _read(self, stream):
- return stream.read(2).decode(self.encoding)
-
- def _read_array(self, stream, count):
- if count == 0:
- return u''
-
- data = stream.read(2 * count)
- return data.decode(self.encoding)
-
- def _read_0(self, stream):
- r = b''
- while True:
- c = stream.read(2)
-
- if len(c) != 2:
- raise EOFError()
-
- if c == b'\x00\x00':
- break
-
- r += c
-
- return r.decode(self.encoding)
-
- def _write(self, stream, data):
- return stream.write(data.encode(self.encoding))
-
- def _write_array(self, stream, data):
- return self._write(stream, data)
-
- def _write_0(self, stream, data):
- return self._write(stream, data + u'\x00')
-
- def default(self):
- return u'\x00'
-
- def default_array(self, count):
- return u'\x00' * count
-
-
-class BytesInteger(RawType):
- """Implements an integer type that can span an arbitrary amount of bytes."""
-
- def __init__(self, cstruct, name, size, signed):
- self.signed = signed
- super(BytesInteger, self).__init__(cstruct, name, size)
-
- @staticmethod
- def parse(buf, size, count, signed, endian):
- nums = []
-
- for c in xrange(count):
- num = 0
- data = buf[c * size:(c + 1) * size]
- if endian == '<':
- data = b''.join(data[i:i + 1] for i in reversed(xrange(len(data))))
-
- ints = list(data) if PY3 else map(ord, data)
- for i in ints:
- num = (num << 8) | i
-
- if signed and num & 1 << (size * 8 - 1):
- bias = 1 << (size * 8 - 1)
- num -= bias * 2
-
- nums.append(num)
-
- return nums
-
- @staticmethod
- def pack(data, size, endian):
- buf = []
- for i in data:
- num = int(i)
- if num < 0:
- num += 1 << (size * 8)
-
- d = [b'\x00'] * size
- i = size - 1
-
- while i >= 0:
- b = num & 255
- d[i] = bytes((b,)) if PY3 else chr(b)
- num >>= 8
- i -= 1
-
- if endian == '<':
- d = b''.join(d[i:i + 1][0] for i in reversed(xrange(len(d))))
- else:
- d = b''.join(d)
-
- buf.append(d)
-
- return b''.join(buf)
-
- def _read(self, stream):
- return self.parse(stream.read(self.size * 1), self.size, 1, self.signed, self.cstruct.endian)[0]
-
- def _read_array(self, stream, count):
- return self.parse(stream.read(self.size * count), self.size, count, self.signed, self.cstruct.endian)
-
- def _read_0(self, stream):
- r = []
- while True:
- v = self._read(stream)
- if v == 0:
- break
- r.append(v)
-
- return r
-
- def _write(self, stream, data):
- return stream.write(self.pack([data], self.size, self.cstruct.endian))
-
- def _write_array(self, stream, data):
- return stream.write(self.pack(data, self.size, self.cstruct.endian))
-
- def _write_0(self, stream, data):
- return self._write_array(stream, data + [0])
-
- def default(self):
- return 0
-
- def default_array(self, count):
- return [0] * count
-
-
-class Enum(RawType):
- """Implements an Enum type.
-
- Enums can be made using any type. The API for accessing enums and their
- values is very similar to Python 3 native enums.
-
- Example:
- When using the default C-style parser, the following syntax is supported:
-
- enum [: ] {
-
- };
-
- For example, an enum that has A=1, B=5 and C=6 could be written like so:
-
- enum Test : uint16 {
- A, B=5, C
- };
- """
-
- def __init__(self, cstruct, name, type_, values):
- self.type = type_
- self.values = values
- self.reverse = {}
-
- for k, v in values.items():
- self.reverse[v] = k
-
- super(Enum, self).__init__(cstruct, name, len(self.type))
-
- def __call__(self, value):
- return EnumInstance(self, value)
-
- def _read(self, stream):
- v = self.type._read(stream)
- return self(v)
-
- def _read_array(self, stream, count):
- return list(map(self, self.type._read_array(stream, count)))
-
- def _read_0(self, stream):
- return list(map(self, self.type._read_0(stream)))
-
- def _write(self, stream, data):
- data = data.value if isinstance(data, EnumInstance) else data
- return self.type._write(stream, data)
-
- def _write_array(self, stream, data):
- data = [d.value if isinstance(d, EnumInstance) else d for d in data]
- return self.type._write_array(stream, data)
-
- def _write_0(self, stream, data):
- data = [d.value if isinstance(d, EnumInstance) else d for d in data]
- return self.type._write_0(stream, data)
-
- def default(self):
- return self(0)
-
- def __getitem__(self, attr):
- if attr in self.values:
- return self(self.values[attr])
-
- raise KeyError(attr)
-
- def __getattr__(self, attr):
- if attr in self.values:
- return self(self.values[attr])
-
- raise AttributeError(attr)
-
- def __contains__(self, attr):
- return attr in self.values
-
-
-class EnumInstance(object):
- """Implements a value instance of an Enum"""
-
- def __init__(self, enum, value):
- self.enum = enum
- self.value = value
-
- @property
- def name(self):
- if self.value not in self.enum.reverse:
- return '{}_{}'.format(self.enum.name, self.value)
- return self.enum.reverse[self.value]
-
- def __eq__(self, value):
- if isinstance(value, EnumInstance) and value.enum is not self.enum:
- return False
-
- if hasattr(value, 'value'):
- value = value.value
-
- return self.value == value
-
- def __ne__(self, value):
- return self.__eq__(value) is False
-
- def __hash__(self):
- return hash((self.enum, self.value))
-
- def __str__(self):
- return '{}.{}'.format(self.enum.name, self.name)
-
- def __repr__(self):
- return '<{}.{}: {}>'.format(self.enum.name, self.name, self.value)
-
-
-class Union(RawType):
- def __init__(self, cstruct):
- self.cstruct = cstruct
- super(Union, self).__init__(cstruct)
-
- def _read(self, stream):
- raise NotImplementedError()
-
-
-class Pointer(RawType):
- """Implements a pointer to some other type."""
-
- def __init__(self, cstruct, target):
- self.cstruct = cstruct
- self.type = target
- super(Pointer, self).__init__(cstruct)
-
- def _read(self, stream, ctx):
- addr = self.cstruct.pointer(stream)
- return PointerInstance(self.type, stream, addr, ctx)
-
- def __len__(self):
- return len(self.cstruct.pointer)
-
- def __repr__(self):
- return ''.format(self.type)
-
-
-class VoidType(RawType):
- """Implements a void type."""
-
- def __init__(self):
- super(VoidType, self).__init__(None, 'void', 0)
-
- def _read(self, stream):
- return None
-
-
-def ctypes(structure):
- """Create ctypes structures from cstruct structures."""
- fields = []
- for field in structure.fields:
- t = ctypes_type(field.type)
- fields.append((field.name, t))
-
- tt = type(structure.name, (_ctypes.Structure, ), {"_fields_": fields})
- return tt
-
-
-def ctypes_type(t):
- mapping = {
- "I": _ctypes.c_ulong,
- "i": _ctypes.c_long,
- "b": _ctypes.c_int8,
- }
-
- if isinstance(t, PackedType):
- return mapping[t.packchar]
-
- if isinstance(t, CharType):
- return _ctypes.c_char
-
- if isinstance(t, Array):
- subtype = ctypes_type(t._type)
- return subtype * t.count
-
- if isinstance(t, Pointer):
- subtype = ctypes_type(t._target)
- return ctypes.POINTER(subtype)
-
- raise NotImplementedError("Type not implemented: %s" % t.__class__.__name__)
-
-
-class Compiler(object):
- """Compiler for cstruct structures. Creates somewhat optimized parsing code."""
-
- def __init__(self, cstruct):
- self.cstruct = cstruct
-
- def compile(self, structure):
- source = self.gen_struct_class(structure)
- c = compile(source, '', 'exec')
-
- env = {
- 'OrderedDict': OrderedDict,
- 'Structure': Structure,
- 'Instance': Instance,
- 'Expression': Expression,
- 'EnumInstance': EnumInstance,
- 'PointerInstance': PointerInstance,
- 'BytesInteger': BytesInteger,
- 'BitBuffer': BitBuffer,
- 'struct': struct,
- 'xrange': xrange,
- }
-
- exec(c, env)
- sc = env[structure.name](self.cstruct, structure, source)
-
- return sc
-
- def gen_struct_class(self, structure):
- blocks = []
- classes = []
- cur_block = []
- read_size = 0
- prev_was_bits = False
-
- for field in structure.fields:
- ft = self.cstruct.resolve(field.type)
-
- if not isinstance(
- ft,
- (
- Structure,
- Pointer,
- Enum,
- Array,
- PackedType,
- CharType,
- WcharType,
- BytesInteger,
- ),
- ):
- raise CompilerError("Unsupported type for compiler: {}".format(ft))
-
- if isinstance(ft, Structure) or (
- isinstance(ft, Array) and isinstance(ft.type, Structure)
- ):
- if cur_block:
- blocks.append(self.gen_read_block(read_size, cur_block))
-
- struct_read = 's = stream.tell()\n'
- if isinstance(ft, Array):
- num = ft.count
-
- if isinstance(num, Expression):
- num = 'max(0, Expression(self.cstruct, "{expr}").evaluate(r))'.format(
- expr=num.expr
- )
-
- struct_read += (
- 'r["{name}"] = []\n'
- 'for _ in xrange({num}):\n'
- ' r["{name}"].append(self.cstruct.{struct_name}._read(stream))\n'.format(
- name=field.name, num=num, struct_name=ft.type.name
- )
- )
- else:
- struct_read += 'r["{name}"] = self.cstruct.{struct_name}._read(stream)\n'.format(
- name=field.name, struct_name=ft.name
- )
-
- struct_read += 'sizes["{name}"] = stream.tell() - s'.format(
- name=field.name
- )
- blocks.append(struct_read)
- read_size = 0
- cur_block = []
- continue
-
- if field.bits:
- if cur_block:
- blocks.append(self.gen_read_block(read_size, cur_block))
-
- blocks.append(
- 'r["{name}"] = bitreader.read(self.cstruct.{type_name}, {bits})'.format(
- name=field.name, type_name=field.type.name, bits=field.bits
- )
- )
- read_size = 0
- cur_block = []
- prev_was_bits = True
- continue
- elif prev_was_bits:
- blocks.append('bitreader.reset()')
- prev_was_bits = False
-
- try:
- count = len(ft)
- read_size += count
- cur_block.append(field)
- except Exception:
- if cur_block:
- blocks.append(self.gen_read_block(read_size, cur_block))
- blocks.append(self.gen_dynamic_block(field))
- read_size = 0
- cur_block = []
-
- if len(cur_block):
- blocks.append(self.gen_read_block(read_size, cur_block))
-
- read_code = '\n\n'.join(blocks)
- read_code = '\n'.join([' ' * 2 + line for line in read_code.split('\n')])
-
- classes.append(COMPILE_TEMPL.format(name=structure.name, read_code=read_code))
- return '\n\n'.join(classes)
-
- def gen_read_block(self, size, block):
- templ = (
- 'buf = stream.read({size})\n'
- 'if len(buf) != {size}: raise EOFError()\n'
- 'data = struct.unpack(self.cstruct.endian + "{{}}", buf)\n'
- '{{}}'.format(size=size)
- )
- readcode = []
- fmt = []
-
- curtype = None
- curcount = 0
-
- buf_offset = 0
- data_offset = 0
-
- for field in block:
- ft = self.cstruct.resolve(field.type)
- t = ft
- count = 1
- data_count = 1
- read_slice = ''
-
- if isinstance(t, Enum):
- t = t.type
- elif isinstance(t, Pointer):
- t = self.cstruct.pointer
-
- if isinstance(ft, Array):
- count = t.count
- data_count = count
- t = t.type
-
- if isinstance(t, Enum):
- t = t.type
- elif isinstance(t, Pointer):
- t = self.cstruct.pointer
-
- if isinstance(t, (CharType, WcharType, BytesInteger)):
- read_slice = '{}:{}'.format(
- buf_offset, buf_offset + (count * t.size)
- )
- else:
- read_slice = '{}:{}'.format(data_offset, data_offset + count)
- elif isinstance(t, CharType):
- read_slice = str(buf_offset)
- elif isinstance(t, (WcharType, BytesInteger)):
- read_slice = '{}:{}'.format(buf_offset, buf_offset + t.size)
- else:
- read_slice = str(data_offset)
-
- if not curtype:
- if isinstance(t, PackedType):
- curtype = t.packchar
- else:
- curtype = 'x'
-
- if isinstance(t, (PackedType, CharType, WcharType, BytesInteger, Enum)):
- charcount = count
-
- if isinstance(t, (CharType, WcharType, BytesInteger)):
- data_count = 0
- packchar = 'x'
- charcount *= t.size
- else:
- packchar = t.packchar
-
- if curtype != packchar:
- fmt.append('{}{}'.format(curcount, curtype))
- curcount = 0
-
- curcount += charcount
- curtype = packchar
-
- getter = ''
- if isinstance(t, BytesInteger):
- getter = 'BytesInteger.parse(buf[{slice}], {size}, {count}, {signed}, self.cstruct.endian){data_slice}'.format(
- slice=read_slice,
- size=t.size,
- count=count,
- signed=t.signed,
- data_slice='[0]' if count == 1 else '',
- )
- elif isinstance(t, (CharType, WcharType)):
- getter = 'buf[{}]'.format(read_slice)
- if isinstance(t, WcharType):
- getter += ".decode('utf-16-le' if self.cstruct.endian == '<' else 'utf-16-be')"
- else:
- getter = 'data[{}]'.format(read_slice)
-
- if isinstance(ft, Enum):
- getter = 'EnumInstance(self.cstruct.{type_name}, {getter})'.format(
- type_name=ft.name, getter=getter
- )
- elif isinstance(ft, Array) and isinstance(ft.type, Enum):
- getter = '[EnumInstance(self.cstruct.{type_name}, d) for d in {getter}]'.format(
- type_name=ft.type.name, getter=getter
- )
- elif isinstance(ft, Pointer):
- getter = 'PointerInstance(self.cstruct.{type_name}, stream, {getter}, r)'.format(
- type_name=ft.type.name, getter=getter
- )
- elif isinstance(ft, Array) and isinstance(ft.type, Pointer):
- getter = '[PointerInstance(self.cstruct.{type_name}, stream, d, r) for d in {getter}]'.format(
- type_name=ft.type.name, getter=getter
- )
- elif isinstance(ft, Array) and isinstance(t, PackedType):
- getter = 'list({})'.format(getter)
-
- readcode.append(
- 'r["{name}"] = {getter}'.format(name=field.name, getter=getter)
- )
- readcode.append(
- 'sizes["{name}"] = {size}'.format(name=field.name, size=count * t.size)
- )
-
- data_offset += data_count
- buf_offset += count * t.size
-
- if curcount:
- fmt.append('{}{}'.format(curcount, curtype))
-
- return templ.format(''.join(fmt), '\n'.join(readcode))
-
- def gen_dynamic_block(self, field):
- if not isinstance(field.type, Array):
- raise CompilerError(
- "Only Array can be dynamic, got {!r}".format(field.type)
- )
-
- t = field.type.type
- reader = None
-
- if not field.type.count: # Null terminated
- if isinstance(t, PackedType):
- reader = (
- 't = []\nwhile True:\n'
- ' d = stream.read({size})\n'
- ' if len(d) != {size}: raise EOFError()\n'
- ' v = struct.unpack(self.cstruct.endian + "{packchar}", d)[0]\n'
- ' if v == 0: break\n'
- ' t.append(v)'.format(size=t.size, packchar=t.packchar)
- )
-
- elif isinstance(t, (CharType, WcharType)):
- reader = (
- 't = []\n'
- 'while True:\n'
- ' c = stream.read({size})\n'
- ' if len(c) != {size}: raise EOFError()\n'
- ' if c == b"{null}": break\n'
- ' t.append(c)\nt = b"".join(t)'.format(
- size=t.size, null='\\x00' * t.size
- )
- )
-
- if isinstance(t, WcharType):
- reader += ".decode('utf-16-le' if self.cstruct.endian == '<' else 'utf-16-be')"
- elif isinstance(t, BytesInteger):
- reader = (
- 't = []\n'
- 'while True:\n'
- ' d = stream.read({size})\n'
- ' if len(d) != {size}: raise EOFError()\n'
- ' v = BytesInteger.parse(d, {size}, 1, {signed}, self.cstruct.endian)\n'
- ' if v == 0: break\n'
- ' t.append(v)'.format(size=t.size, signed=t.signed)
- )
-
- return '{reader}\nr["{name}"] = t\nsizes["{name}"] = len(t)'.format(
- reader=reader, name=field.name
- )
- else:
- expr = field.type.count.expr
- expr_read = (
- 'dynsize = max(0, Expression(self.cstruct, "{expr}").evaluate(r))\n'
- 'buf = stream.read(dynsize * {type_size})\n'
- 'if len(buf) != dynsize * {type_size}: raise EOFError()\n'
- 'r["{name}"] = {{reader}}\n'
- 'sizes["{name}"] = dynsize * {type_size}'.format(
- expr=expr, name=field.name, type_size=t.size
- )
- )
-
- if isinstance(t, PackedType):
- reader = 'list(struct.unpack(self.cstruct.endian + "{{:d}}{packchar}".format(dynsize), buf))'.format(
- packchar=t.packchar, type_size=t.size
- )
- elif isinstance(t, (CharType, WcharType)):
- reader = 'buf'
- if isinstance(t, WcharType):
- reader += ".decode('utf-16-le' if self.cstruct.endian == '<' else 'utf-16-be')"
- elif isinstance(t, BytesInteger):
- reader = 'BytesInteger.parse(buf, {size}, dynsize, {signed}, self.cstruct.endian)'.format(
- size=t.size, signed=t.signed
- )
-
- return expr_read.format(reader=reader, size=None)
-
-
-def hexdump(s, palette=None, offset=0, prefix="", is_retstr=False):
- """Hexdump some data.
-
- Args:
- s: Bytes to hexdump.
- palette: Colorize the hexdump using this color pattern.
- offset: Byte offset of the hexdump.
- prefix: Optional prefix.
- """
- if palette:
- palette = palette[::-1]
-
- remaining = 0
- active = None
- retstr = ""
-
- for i in xrange(0, len(s), 16):
- vals = ""
- chars = []
- for j in xrange(16):
- if not active and palette:
- remaining, active = palette.pop()
- vals += active
- elif active and j == 0:
- vals += active
-
- if i + j >= len(s):
- vals += " "
- else:
- c = s[i + j]
- c = chr(c) if PY3 else c
- p = c if c in PRINTABLE else "."
-
- if active:
- vals += "{:02x}".format(ord(c))
- chars.append(active + p + COLOR_NORMAL)
- else:
- vals += "{:02x}".format(ord(c))
- chars.append(p)
-
- remaining -= 1
- if remaining == 0:
- active = None
-
- if palette is not None:
- vals += COLOR_NORMAL
-
- if j == 15:
- if palette is not None:
- vals += COLOR_NORMAL
-
- vals += " "
-
- if j == 7:
- vals += " "
-
- chars = "".join(chars)
- line = "{}{:08x} {:48s} {}".format(prefix, offset + i, vals, chars)
- if is_retstr:
- retstr += line + "\n"
- else:
- print(line)
- if is_retstr:
- return retstr
-
-
-def dumpstruct(t, data=None, offset=0, is_color = True, is_retstr=False):
- """Dump a structure or parsed structure instance.
-
- Prints a colorized hexdump and parsed structure output.
-
- Args:
- t: Structure or Instance to dump.
- data: Bytes to parse the Structure on, if t is not a parsed Instance.
- offset: Byte offset of the hexdump.
- """
- if is_color:
- colors = [
- (COLOR_RED, COLOR_BG_RED),
- (COLOR_GREEN, COLOR_BG_GREEN),
- (COLOR_YELLOW, COLOR_BG_YELLOW),
- (COLOR_BLUE, COLOR_BG_BLUE),
- (COLOR_PURPLE, COLOR_BG_PURPLE),
- (COLOR_CYAN, COLOR_BG_CYAN),
- (COLOR_WHITE, COLOR_BG_WHITE),
- ]
- else:
- colors = [
- ('', ''),
- ('', ''),
- ('', ''),
- ('', ''),
- ('', ''),
- ('', ''),
- ('', ''),
- ]
-
- if isinstance(t, Instance):
- g = t
- t = t._type
- data = g.dumps()
- elif isinstance(t, Structure) and data:
- g = t(data)
- else:
- raise ValueError("Invalid arguments")
-
- palette = []
- ci = 0
- out = "struct {}".format(t.name) + ":\n"
- for field in g._type.fields:
- fg, bg = colors[ci % len(colors)]
- palette.append((g._size(field.name), bg))
- ci += 1
-
- v = getattr(g, field.name)
- if isinstance(v, str):
- v = repr(v)
- elif isinstance(v, int):
- v = hex(v)
- elif isinstance(v, list):
- v = pprint.pformat(v)
- if '\n' in v:
- v = v.replace('\n', '\n{}'.format(' ' * (len(field.name) + 4)))
-
- out += "- {}{}{}: {}\n".format(fg, field.name, COLOR_NORMAL if is_color else '', v)
-
- if is_retstr:
- retstr = "\n"
- retstr += hexdump(data, palette if is_color else None, offset=offset, is_retstr=True)
- retstr += "\n"
- retstr += out
- return retstr
- print()
- hexdump(data, palette if is_color else None, offset=offset)
- print()
- print(out)
diff --git a/files/leechcore.dll b/files/leechcore.dll
deleted file mode 100644
index 16519ec..0000000
Binary files a/files/leechcore.dll and /dev/null differ
diff --git a/files/leechcore.h b/files/leechcore.h
deleted file mode 100644
index 46af16a..0000000
--- a/files/leechcore.h
+++ /dev/null
@@ -1,471 +0,0 @@
-// leechcore.h : header file for the leechcore module - which purpose is to
-// expose low-level device physical memory functionality.
-//
-// This library is thread-safe in all functions with the notable exceptions of
-// the LeechCore_Open() and LeechCore_Close() functions. Some devices may allow
-// multi-threaded access while in reality most devices are single-threaded and
-// will control synchronization where necessary with locks.
-//
-// The library is initialized by calling LeechCore_Open with a LEECHCORE_CONFIG
-// struct containing the correct configuration paramters. Note that the version
-// and magic values must be set in addition to the szDevice configuration value
-// Also, it may be possible to optionally connect to a remote leechcore service
-// or instance over RPC by specifying a szRemote configuration value.
-//
-// ----------------------------------------------------------------------------
-//
-// Remote instance: szRemote configuration value. Connect to a remote leechcore
-// instance by specifying a configuration value in the szRemote parameter. If a
-// loaded already valid instance exists remotely this will be prioritized above
-// the value in szDevice. If the acquisition device is not yet loaded by the
-// remote instance the value in szDevice will be used. Normally, the connection
-// will take place as a mutually authenticated encrypted connection secured by
-// kerberos. If not possible or desirable the 'insecure' value may be specified
-// to disable authentication and security.
-// Syntax:
-// rpc://:: (port = optional, remote_spn = kerberos)
-// (SPN of remote service or 'insecure' )
-// Examples:
-// rpc://insecure:remotehost.example.com (connect insecure to remote host )
-// rpc://user@ad.domain.com:192.0.0.5 (connect secure to remote host )
-// rpc://insecure:127.0.0.0:6666 (connect insecure non-default port)
-//
-// ----------------------------------------------------------------------------
-//
-// Device to connect to: szDevice contains the device to capture memory from.
-// Supported memory acquisition devices are:
-// USB3380 : hardware, read/write, 32-bit (4GB) addressing only. Requires a
-// PCILeech flashed USB3380 device connected over USB and Google
-// Android WinUSB drivers to be installed. Download and install from:
-// http://developer.android.com/sdk/win-usb.html#download
-// Syntax:
-// USB3380
-// USB3380://USB2 (force USB2 connection speed)
-//
-// FPGA : hardware, read/write - requires a PCILeech FPGA flashed hardware
-// device as shown at: https://github.com/ufrisk/pcileech-fpga
-// Also requires the FTD3XX.DLL from ftdichip to be placed in the
-// same directory as the executable. Download from ftdichip at:
-// http://www.ftdichip.com/Drivers/D3XX/FTD3XXLibrary_v1.2.0.6.zip
-// Syntax:
-// FGPA
-// FPGA://[:[:]] (values are optional)
-//
-// SP605TCP : hardware, read/write - connect to a remote SP605 FPGA over the
-// network using the implementation created by @d_olex.
-// https://github.com/Cr4sh/s6_pcie_microblaze
-// Syntax:
-// SP605TCP://[:] (port is optional)
-//
-// RAWTCP : read/write - connect to a remote raw tcp device - such as HPE iLO
-// that have been patched to support DMA as per blog entry below:
-// https://www.synacktiv.com/posts/exploit/using-your-bmc-as-a-dma-device-plugging-pcileech-to-hpe-ilo-4.html
-// Syntax:
-// RAWTCP://[:] (port is optional)
-//
-// HvSavedState : read-only - connect to a Hyper-V saved state file. In order
-// to do so the .dll file 'vmsavedstatedumpprovider.dll' must be
-// placed in same directory as the executable file.
-//
-// PMEM : load the rekall winpmem driver into the kernel and connect to it
-// to acquire memory. The signed driver `.sys` file may be found at:
-// https://github.com/Velocidex/c-aff4/tree/master/tools/pmem/resources/winpmem
-// Download the driver file `att_winpmem_64.sys` and copy it to the
-// directory of leechcore.dll and run executable as elevated admin
-// using syntax below:
-// Syntax:
-// PMEM (use att_winpmem_64.sys in directory of executable)
-// PMEM://
-//
-// TOTALMELTDOWN : read/write - requires a Windows 7 system vulnerable to the
-// "Total Meltdown" vulnerability - CVE-2018-1038.
-// Syntax:
-// TOTALMELTDOWN
-//
-// FILE : use dump file, either a raw linear memory dump or full crash dump.
-// Which format to use is auto-detected. If it looks like a full cash
-// dump that format will be used, otherwise it will be assumed that a
-// raw linear memory dump is to be used.
-// Syntax:
-// (no device-type prefix - just use the file name)
-// FILE://
-//
-// DumpIt : DumpIt is a "virtual" device. It's only possible to use the DumpIt
-// device if the main process containing LeechCore has been started
-// with DumpIt in LiveKD mode.
-// Example 1:
-// DumpIt.exe /LIVEKD /A MemProcFS.exe
-// Example 2:
-// DumpIt.exe /LIVEKD /A LeechSvc.exe /C "interactive insecure"
-// and then connect to remote service by:
-// MemProcFS.exe -remote rpc://insecure:192.168.x.x -device DumpIt
-//
-// EXISTING : Attach to existing already loaded configuration. This is done
-// instead of the default behaviour of closing any existing devices
-// and initializing the new requested device. If no existing device
-// exists the call to LeechCore_Open will fail.
-// Syntax:
-// EXISTING
-//
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 1.1.0
-//
-#ifndef __LEECHCORE_H__
-#define __LEECHCORE_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// WINDOWS / LINUX COMPATIBILITY BELOW:
-//-----------------------------------------------------------------------------
-
-#ifdef _WIN32
-#include
-typedef unsigned __int64 QWORD, *PQWORD;
-#define DLLEXPORT __declspec(dllexport)
-#endif /* _WIN32 */
-#ifdef LINUX
-#include
-#include
-typedef void VOID, *PVOID, *LPVOID;
-typedef void *HANDLE, **PHANDLE;
-typedef uint32_t BOOL, *PBOOL;
-typedef uint8_t BYTE, *PBYTE;
-typedef char CHAR, *PCHAR, *PSTR, *LPSTR;
-typedef uint16_t WORD, *PWORD, USHORT, *PUSHORT;
-typedef uint32_t DWORD, *PDWORD;
-typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64;
-#define MAX_PATH 260
-#define DLLEXPORT __attribute__((visibility("default")))
-#define _In_
-#define _Out_
-#define _In_z_
-#define _Inout_
-#define _In_opt_
-#define _Out_opt_
-#define _Out_writes_(x)
-#define _Check_return_opt_
-#define _Printf_format_string_
-#define _Inout_updates_bytes_(x)
-#define _In_reads_(cbDataIn)
-#define _Out_writes_opt_(x)
-#define _Success_(return)
-#endif /* LINUX */
-
-//-----------------------------------------------------------------------------
-// GENERAL HEADER DEFINES BELOW:
-//-----------------------------------------------------------------------------
-
-#define MEM_IO_SCATTER_HEADER_MAGIC 0xffff6548
-#define MEM_IO_SCATTER_HEADER_VERSION 0x0003
-
-typedef struct tdMEM_IO_SCATTER_HEADER {
- DWORD magic; // magic
- WORD version; // version
- WORD Future1;
- ULONG64 qwA; // base address.
- DWORD cbMax; // bytes to read (DWORD boundry, max 0x1000); pb must have room for this.
- DWORD cb; // bytes read into result buffer.
- PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
- PVOID pvReserved1; // reserved for use by caller.
- PVOID pvReserved2; // reserved for use by caller.
- PVOID Future2[8];
-} MEM_IO_SCATTER_HEADER, *PMEM_IO_SCATTER_HEADER, **PPMEM_IO_SCATTER_HEADER;
-
-//-----------------------------------------------------------------------------
-// LEECHCORE INITIALIZATION / CLOSE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-typedef enum tdLEECHCORE_DEVICE {
- LEECHCORE_DEVICE_NA = 0,
- LEECHCORE_DEVICE_FILE = 1,
- LEECHCORE_DEVICE_PMEM = 2,
- LEECHCORE_DEVICE_FPGA = 3,
- LEECHCORE_DEVICE_SP605_TCP = 4,
- LEECHCORE_DEVICE_USB3380 = 5,
- LEECHCORE_DEVICE_TOTALMELTDOWN = 6,
- LEECHCORE_DEVICE_HVSAVEDSTATE = 7,
- LEECHCORE_DEVICE_RAWTCP = 8,
-} LEECHCORE_DEVICE;
-
-#define LEECHCORE_CONFIG_MAGIC 0xffff6549
-#define LEECHCORE_CONFIG_VERSION 0x0001
-
-#define LEECHCORE_CONFIG_FLAG_PRINTF 0x0001
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_1 0x0002
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_2 0x0004
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_3 0x0008
-#define LEECHCORE_CONFIG_FLAG_REMOTE_NO_COMPRESS 0x0010
-
-typedef struct tdLEECHCORE_CONFIG {
- DWORD magic; // set by caller.
- WORD version; // set by caller.
- WORD flags; // set by caller, updated by device.
- ULONG64 paMax; // set by caller, updated by device.
- ULONG64 cbMaxSizeMemIo; // set by caller, updated by device.
- ULONG64 paMaxNative; // set by device.
- LEECHCORE_DEVICE tpDevice; // set by device.
- BOOL fWritable; // set by device. (is device writable?)
- BOOL fVolatile; // set by device. (is device volatile / memory may change?)
- BOOL fVolatileMaxAddress; // set by device. (is max address volatile? - poll changes with LEECHCORE_OPT_MEMORYINFO_ADDR_MAX)
- BOOL fRemote; // set by device.
- WORD VersionMajor; // set by device.
- WORD VersionMinor; // set by device.
- WORD VersionRevision; // set by device.
- CHAR szDevice[MAX_PATH]; // set by caller.
- CHAR szRemote[MAX_PATH]; // set by caller.
- // optional 'printf' function pointer. if set to non null value 'printf'
- // calls will be redirected. useful when logging to files.
- _Check_return_opt_ int(*pfn_printf_opt)(_In_z_ _Printf_format_string_ char const* const _Format, ...); // set by caller.
-} LEECHCORE_CONFIG, *PLEECHCORE_CONFIG;
-
-typedef struct tdLEECHCORE_PAGESTAT_MINIMAL {
- HANDLE h;
- VOID(*pfnPageStatUpdate)(HANDLE h, ULONG64 pa, ULONG64 cPageSuccessAdd, ULONG64 cPageFailAdd);
-} LEECHCORE_PAGESTAT_MINIMAL, *PLEECHCORE_PAGESTAT_MINIMAL;
-
-/*
-* Open a connection to the target device. The LeechCore initialization may fail
-* if the underlying device cannot be opened or if the LeechCore is already
-* initialized. If already initialized please connect with device EXISTING or
-* call LeechCore_Close() before opening a new device.
-* -- pInformation
-* -- result
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Open(_Inout_ PLEECHCORE_CONFIG pConfig);
-
-/*
-* Clean up various device related stuff and deallocate memory buffers.
-*/
-DLLEXPORT VOID LeechCore_Close();
-
-
-
-//-----------------------------------------------------------------------------
-// LEECHCORE CORE READ AND WRITE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_FLAG_READ_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_VERIFY 0x02
-
-/*
-* Allocate a scatter buffer containing empty 0x1000-sized ppMEMs with address
-* set to zero. Caller is responsible for calling LocalFree(ppMEMs).
-* -- cMEMs
-* -- pppMEMs = pointer to receive ppMEMs on success.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_AllocScatterEmpty(_In_ DWORD cMEMs, _Out_ PPMEM_IO_SCATTER_HEADER *pppMEMs);
-
-/*
-* Read memory in various non-contigious locations specified by the items in the
-* phDMAs array. Result for each unit of work will be given individually. No upper
-* limit of number of items to read, but no performance boost will be given if
-* above hardware limit. Max size of each unit of work is one 4k page (4096 bytes).
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-*/
-DLLEXPORT VOID LeechCore_ReadScatter(_Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_Read(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_READ_RETRY
-* -- pPageStat = optional minimal statistic struct to update.
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_ReadEx(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb, _In_ DWORD flags, _In_opt_ PLEECHCORE_PAGESTAT_MINIMAL pPageStat);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Write(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_WRITE_*
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_WriteEx(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD flags);
-
-/*
-* Probe the memory of the target system to check whether it's readable or not.
-* Please note that not all devices support this natively.
-* -- pa = address to start probe from.
-* -- cPages = number of 4kB pages to probe.
-* -- pbResultMap = result map, 1 byte represents 1 page, 0 = fail, 1 = success.
-* (individual page elements in pbResultMap must be set to 0 [fail] on call
-* for probe to take place on individual page).
-* -- return = FALSE if not supported by underlying hardware, TRUE if supported.
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Probe(_In_ QWORD pa, _In_ DWORD cPages, _Inout_updates_bytes_(cPages) PBYTE pbResultMap);
-
-
-
-//-----------------------------------------------------------------------------
-// GET/SET DEVICE OPTIONS BELOW. SOME OPTIONS ARE GENERAL LEECHCORE OPTIONS
-// WHILE OTHER ARE DEVICE SPECIFIC. USE FUNCTIONS:
-// LeechCore_GetOption() AND LeechCore_GetOption() TO GET/SET OPTIONS.
-// FOR DEVICE-SPECIFIC OPTIONS PLEASE SEE INDIVIDUAL DEVICE FILES FOR MORE
-// DETAILED INFORMATION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE 0x80000002 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-
-#define LEECHCORE_OPT_CORE_VERSION_MAJOR 0x01000001 // R
-#define LEECHCORE_OPT_CORE_VERSION_MINOR 0x01000002 // R
-#define LEECHCORE_OPT_CORE_VERSION_REVISION 0x01000003 // R
-
-#define LEECHCORE_OPT_MEMORYINFO_VALID 0x02000001 // R
-#define LEECHCORE_OPT_MEMORYINFO_ADDR_MAX 0x02000002 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_32BIT 0x02000003 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_PAE 0x02000004 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MINOR 0x02000005 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MAJOR 0x02000006 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_DTB 0x02000007 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PFN 0x02000008 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsLoadedModuleList 0x02000009 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsActiveProcessHead 0x0200000a // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_MACHINE_IMAGE_TP 0x0200000b // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_NUM_PROCESSORS 0x0200000c // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_SYSTEMTIME 0x0200000d // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_UPTIME 0x0200000e // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELBASE 0x0200000f // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELHINT 0x02000010 // R
-
-#define LEECHCORE_OPT_FPGA_PROBE_MAXPAGES 0x03000001 // RW
-#define LEECHCORE_OPT_FPGA_RX_FLUSH_LIMIT 0x03000002 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_RX 0x03000003 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_TX 0x03000004 // RW
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_READ 0x03000005 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_WRITE 0x03000006 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_WRITE 0x03000007 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_READ 0x03000008 // RW - uS
-#define LEECHCORE_OPT_FPGA_RETRY_ON_ERROR 0x03000009 // RW
-#define LEECHCORE_OPT_FPGA_DEVICE_ID 0x03000080 // R
-#define LEECHCORE_OPT_FPGA_FPGA_ID 0x03000081 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MAJOR 0x03000082 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MINOR 0x03000083 // R
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- pqwValue = pointer to QWORD to receive option value.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_GetOption(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- qwValue
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_SetOption(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// TRANSFER DEVICE DEPENDANT COMMANDS OR DATA TO/FROM UNDERLYING DEVICES AND
-// PERFORM ACTIONS USING THE LeechCore_CommandData() FUNCTION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_COMMANDDATA_FPGA_WRITE_TLP 0x00000101 // R
-#define LEECHCORE_COMMANDDATA_FPGA_LISTEN_TLP 0x00000102 // R
-#define LEECHCORE_COMMANDDATA_STATISTICS_GET 0x80000100 // R
-
-#define LEECHCORE_STATISTICS_MAGIC 0xffff6550
-#define LEECHCORE_STATISTICS_VERSION 0x0001
-#define LEECHCORE_STATISTICS_ID_OPEN 0x00
-#define LEECHCORE_STATISTICS_ID_READSCATTER 0x01
-#define LEECHCORE_STATISTICS_ID_WRITE 0x02
-#define LEECHCORE_STATISTICS_ID_PROBE 0x03
-#define LEECHCORE_STATISTICS_ID_GETOPTION 0x04
-#define LEECHCORE_STATISTICS_ID_SETOPTION 0x05
-#define LEECHCORE_STATISTICS_ID_COMMANDDATA 0x06
-#define LEECHCORE_STATISTICS_ID_MAX 0x06
-
-static const LPSTR LEECHCORE_STATISTICS_NAME[] = {
- "LeechCore_Open",
- "LeechCore_ReadScatter",
- "LeechCore_Write",
- "LeechCore_Probe",
- "LeechCore_GetOption",
- "LeechCore_SetOption",
- "LeechCore_CommandData"
-};
-
-typedef struct tdLEECHCORE_STATISTICS {
- DWORD magic;
- WORD version;
- WORD Reserved0;
- DWORD Reserved1;
- QWORD qwFreq;
- struct {
- QWORD c;
- QWORD tm; // total time in qwFreq ticks
- } Call[0x10];
-} LEECHCORE_STATISTICS, *PLEECHCORE_STATISTICS;
-
-/*
-* Transfer device dependant commands/data to/from the underlying device and
-* perform device dependant actions.
-* -- fOption
-* -- cbDataIn
-* -- pbDataIn
-* -- pbDataOut
-* -- cbDataOut
-* -- pcbDataOut
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_CommandData(
- _In_ ULONG64 fOption,
- _In_reads_(cbDataIn) PBYTE pbDataIn,
- _In_ DWORD cbDataIn,
- _Out_writes_opt_(cbDataOut) PBYTE pbDataOut,
- _In_ DWORD cbDataOut,
- _Out_opt_ PDWORD pcbDataOut
-);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __LEECHCORE_H__ */
diff --git a/files/leechcore.lib b/files/leechcore.lib
deleted file mode 100644
index 4920775..0000000
Binary files a/files/leechcore.lib and /dev/null differ
diff --git a/files/leechsvc.exe b/files/leechsvc.exe
deleted file mode 100644
index c55e7d1..0000000
Binary files a/files/leechsvc.exe and /dev/null differ
diff --git a/files/plugins/m_vmemd.dll b/files/plugins/m_vmemd.dll
deleted file mode 100644
index fb3537c..0000000
Binary files a/files/plugins/m_vmemd.dll and /dev/null differ
diff --git a/files/plugins/pym_procstruct/__init__.py b/files/plugins/pym_procstruct/__init__.py
deleted file mode 100644
index 7bf3fa5..0000000
--- a/files/plugins/pym_procstruct/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from plugins.pym_procstruct.pym_procstruct import (
- Initialize,
- Close,
-)
-
-__all__ = [
- "Initialize",
- "Close",
-]
diff --git a/files/plugins/pym_procstruct/pym_procstruct.py b/files/plugins/pym_procstruct/pym_procstruct.py
deleted file mode 100644
index 90fe71e..0000000
--- a/files/plugins/pym_procstruct/pym_procstruct.py
+++ /dev/null
@@ -1,202 +0,0 @@
-# pym_procstruct.py
-#
-# Example python plugin module for the memory process file system. This module
-# shows how it is possible to display files in the file system and implement
-# Read and Write functionality for the files.
-#
-# The module displays binary and hexascii versions of EPROCESS and PEB in the
-# 'py/procstruct' directory.
-#
-# https://github.com/ufrisk/
-#
-# (c) Ulf Frisk, 2018
-# Author: Ulf Frisk, pcileech@frizk.net
-#
-
-from vmmpy import *
-from vmmpyplugin import *
-
-procstruct_eprocess_size_bin = 0x500
-procstruct_eprocess_size_hex = 0
-procstruct_peb_size_bin = 0x1000
-procstruct_peb_size_hex = 0
-procstruct_cache_proc_wow64 = {}
-
-def ReadEPROCESS_Binary(pid, file_name, file_attr, bytes_length, bytes_offset):
- #
- # Read binary data from the EPROCESS file that the List function put into
- # the VmmPyPlugin file list.
- #
- # Since this function was only put into the VmmPyPlugin file list for this
- # specific file no extra checks have to be made on pid (which could be none
- # if this plugin would have registered the file entry as a root file -
- # which it did not). Neither does the file_name need to be checked since
- # this is the only file that will call this read function.
- #
- # The plugin manager also checks that bytes_length and bytes_offset does
- # not exceed the file size that is registered in the plugin manager - if
- # it does they are automatically adjusted - so no need to check those for
- # validity either.
- #
- # Start by retrieving the process information for the given pid.
- procinfo = VmmPy_ProcessGetInformation(pid)
- # The procinfo is a dict that amongst other entries contains 'va-eprocess'
- # which is the virtual address for the eprocess struct in kernel memory.
- va_eprocess = procinfo['va-eprocess']
- # Read the amount of bytes from virtual memory with the specified offset.
- # Since EPROCESS resides in kernel memory (which is mapped into process
- # address space as supervisor only memory, but is filtered out by the
- # VMM) it is necessary to read it from the SYSTEM process - i.e. pid 4.
- memory_data = VmmPy_MemRead(4, va_eprocess + bytes_offset, bytes_length)
- # The read memory data should be of the correct size and correct offset,
- # and it's also already of the bytes data type - so just return it and
- # finish with the read!
- return memory_data
-
-
-
-def ReadEPROCESS_Hexdump(pid, file_name, file_attr, bytes_length, bytes_offset):
- # Read the binary data required for the EPROCESS struct by calling the
- # function ReadEPROCESS_Binary which already does this very conveniently.
- memory_data = ReadEPROCESS_Binary(pid, file_name, file_attr, bytes_length, bytes_offset)
- # Translate the binary data into hexascii memory dump format by calling
- # the VmmPy_UtilFillHexAscii function.
- hexdump_string = VmmPy_UtilFillHexAscii(memory_data)
- # Convert from string into bytes using ascii encoding.
- hexdump_binary = bytes(hexdump_string, 'ascii')
- # return the data that should be read as a bytes object.
- return hexdump_binary[bytes_offset:bytes_length+bytes_offset]
-
-
-
-def WriteEPROCESS_Binary(pid, file_name, file_attr, bytes_data, bytes_offset):
- # Write binary data to the EPROCESS struct in kernel memory.
- #
- # Since the List function only registered this function with one file which
- # is in a process directory we do not need to check pid, file_name and
- # bytes_offset since thise are all verified by the plugin manager.
- #
- # Start by retrieving the process information for the given pid.
- procinfo = VmmPy_ProcessGetInformation(pid)
- # The procinfo is a dict that amongst other entries contains 'va-eprocess'
- # which is the virtual address for the eprocess struct in kernel memory.
- va_eprocess = procinfo['va-eprocess']
- # Now all data which is required to make a write exists! Perform the write!
- VmmPy_MemWrite(4, va_eprocess+bytes_offset, bytes_data)
- return VMMPY_STATUS_SUCCESS
-
-
-
-def ReadPEB_Binary(pid, file_name, file_attr, bytes_length, bytes_offset):
- #
- # Read binary data from the PEB page. This is a compact version of the
- # Read function. Please see ReadEPROCESS_Binary for a detailed description
- #
- procinfo = VmmPy_ProcessGetInformation(pid)
- if '32' in file_name:
- va_peb = procinfo['va-peb32']
- else:
- va_peb = procinfo['va-peb']
- return VmmPy_MemRead(pid, va_peb + bytes_offset, bytes_length)
-
-
-
-def ReadPEB_Hexdump(pid, file_name, file_attr, bytes_length, bytes_offset):
- #
- # Read hexascii data from the PEB page. This is a compact version of the
- # Read function. Please see ReadEPROCESS_Hexdump for a detailed description
- #
- memory_data = ReadPEB_Binary(pid, file_name, file_attr, bytes_length, bytes_offset)
- hexdump_string = VmmPy_UtilFillHexAscii(memory_data)
- return bytes(hexdump_string, 'ascii')[bytes_offset:bytes_length+bytes_offset]
-
-
-
-def WritePEB_Binary(pid, file_name, file_attr, bytes_data, bytes_offset):
- #
- # Write binary data to the PEB page. This is a compact version of the
- # Write function. Please see WritePEB_Binary for a detailed description
- #
- procinfo = VmmPy_ProcessGetInformation(pid)
- if '32' in file_name:
- va_peb = procinfo['va-peb32']
- else:
- va_peb = procinfo['va-peb']
- VmmPy_MemWrite(pid, va_peb+bytes_offset, bytes_data)
- return VMMPY_STATUS_SUCCESS
-
-
-
-def IsProcessPeb6432(pid):
- #
- # Check if the pid is a regular process with a PEB at all or if it's a special
- # process like 'System' without a PEB. Also check whether a 32-bit PEB exists
- # or not (wow64 process).
- # Also employ a small caching functionality.
- #
- if pid in procstruct_cache_proc_wow64:
- return procstruct_cache_proc_wow64[pid]
- procinfo = VmmPy_ProcessGetInformation(pid)
- if(procinfo['state'] != 0):
- result = False, False
- else:
- result = procinfo['va-peb'] > 0, ('va-peb32' in procinfo and procinfo['va-peb32'] > 0)
- procstruct_cache_proc_wow64[pid] = result
- return result
-
-
-
-def List(pid, path):
- #
- # List function - this module employs a dynamic list function - which makes
- # it responsible for providing directory listings of its contents in a
- # highly optimized way. It is very important that the List function is as
- # speedy as possible - to avoid locking up the file system.
- #
- # First check the directory to be listed. Only the module root directory is
- # allowed. If it's not the module root directory return None.
- if path != 'procstruct':
- return None
- # Populate the 'common' files which are always in the module directory
- # below. Both binary and hexdump/hexascii versions are populated.
- result = {
- 'eprocess.bin': {'size': procstruct_eprocess_size_bin, 'read': ReadEPROCESS_Binary, 'write': WriteEPROCESS_Binary},
- 'eprocess.txt': {'size': procstruct_eprocess_size_hex, 'read': ReadEPROCESS_Hexdump, 'write': None}
- }
- # Populate PEB (if it exists), it almost always do, but there may be
- # some special processes like 'System', 'Registry' and so on that only
- # exist in kernel space without a PEB...
- fPeb64, fPeb32 = IsProcessPeb6432(pid)
- if fPeb64:
- result['peb.bin'] = {'size': procstruct_peb_size_bin, 'read': ReadPEB_Binary, 'write': WritePEB_Binary}
- result['peb.txt'] = {'size': procstruct_peb_size_hex, 'read': ReadPEB_Hexdump, 'write': None}
- # Optionally populate 32-bit PEBs into the directory listings if a 32-bit
- # process is to be listed.
- if fPeb32:
- result['peb32.bin'] = {'size': procstruct_peb_size_bin, 'read': ReadPEB_Binary, 'write': WritePEB_Binary}
- result['peb32.txt'] = {'size': procstruct_peb_size_hex, 'read': ReadPEB_Hexdump, 'write': None}
- return result
-
-
-
-def Close():
- # Nothing to clean up here for this plugin -> do nothing!
- pass
-
-
-
-def Initialize(target_system, target_memorymodel):
- # Check that the operating system is 32-bit or 64-bit Windows. If it's not
- # then raise an exception to terminate loading of this module.
- if target_system != VMMPY_SYSTEM_WINDOWS_X64 and target_system != VMMPY_SYSTEM_WINDOWS_X86:
- raise RuntimeError("Only Windows is supported by the pym_procstruct module.")
- # Calculate the size of the 'eprocess_size_hex' global variable. This is
- # only done once - at module instantiation to speed up the list operation.
- global procstruct_eprocess_size_hex
- procstruct_eprocess_size_hex = len(VmmPy_UtilFillHexAscii(bytes(procstruct_eprocess_size_bin)))
- # Calculate the size of the 'PEB page'
- global procstruct_peb_size_hex
- procstruct_peb_size_hex = len(VmmPy_UtilFillHexAscii(bytes(procstruct_peb_size_bin)))
- # Register a directory with the VmmPyPlugin plugin manager. The directory
- # is a non-root (i.e. a process) directory and have a custom List function.
- VmmPyPlugin_FileRegisterDirectory(True, 'procstruct', List)
diff --git a/files/python36/information.txt b/files/python36/information.txt
deleted file mode 100644
index 6406d8b..0000000
--- a/files/python36/information.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Put your Python 3.6 embedded for Windows 64-bit in this directory to enable Python functionality.
-Download Python 3.6 "Windows x86-64 embeddable zip file" and unzip in this folder.
-Python may be downloaded from: https://www.python.org/downloads/
-This is not required if Python 3.6 for Windows 64-bit is already on the path.
\ No newline at end of file
diff --git a/files/vmm.dll b/files/vmm.dll
deleted file mode 100644
index 4adf8c4..0000000
Binary files a/files/vmm.dll and /dev/null differ
diff --git a/files/vmm.lib b/files/vmm.lib
deleted file mode 100644
index 30509c6..0000000
Binary files a/files/vmm.lib and /dev/null differ
diff --git a/files/vmmdll.h b/files/vmmdll.h
deleted file mode 100644
index 6b1e71b..0000000
--- a/files/vmmdll.h
+++ /dev/null
@@ -1,656 +0,0 @@
-// vmmdll.h : header file to include in projects that use vmm.dll either as
-// stand anlone projects or as native plugins to vmm.dll.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 2.2
-//
-
-#include
-#include "leechcore.h"
-
-#ifndef __VMMDLL_H__
-#define __VMMDLL_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// INITIALIZATION FUNCTIONALITY BELOW:
-// Choose one way of initialzing the VMM / Memory Process File System.
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize VMM.DLL with command line parameters. For a more detailed info
-* about the parameters please see github wiki for Memory Process File System
-* and LeechCore. THIS IS THE PREFERED WAY OF INITIALIZING VMM.DLL
-* Important parameters are:
-* -printf = show printf style outputs)
-* -v -vv -vvv = extra verbosity levels)
-* -device = device as on format for LeechCore - please see leechcore.h or
-* Github documentation for additional information. Some values
-* are: , fpga, usb3380, hvsavedstate, totalmeltdown, pmem
-* -remote = remote LeechCore instance - please see leechcore.h or Github
-* documentation for additional information.
-* -norefresh = disable background refreshes (even if backing memory is
-* volatile memory).
-* -- argc
-* -- argv
-* -- return = success/fail
-*/
-_Success_(return)
-BOOL VMMDLL_Initialize(_In_ DWORD argc, _In_ LPSTR argv[]);
-
-/*
-* Close an initialized instance of VMM.DLL and clean up all allocated resources
-* including plugins, linked PCILeech.DLL and other memory resources.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_Close();
-
-/*
-* Perform a force refresh of all internal caches including:
-* - process listings
-* - memory cache
-* - page table cache
-* WARNING: function may take some time to execute!
-* -- dwReserved = reserved future use - must be zero
-* -- return = sucess/fail
-*/
-_Success_(return)
-BOOL VMMDLL_Refresh(_In_ DWORD dwReserved);
-
-
-//-----------------------------------------------------------------------------
-// CONFIGURATION SETTINGS BELOW:
-// Configure the memory process file system or the underlying memory
-// acquisition devices.
-//-----------------------------------------------------------------------------
-
-/*
-* Options used together with the functions: VMMDLL_GetOption & VMMDLL_SetOption
-* Options are defined with either: VMMDLL_OPT_* in this header file or as
-* MEMDEVICE_OPT_* in memdevice.h
-* For more detailed information check the sources for individual device types.
-*/
-#define VMMDLL_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define VMMDLL_OPT_CORE_VERBOSE 0x80000002 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
-#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
-#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
-#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
-
-#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
-#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
-#define VMMDLL_OPT_CONFIG_READCACHE_TICKS 0x40000003 // RW - memory cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_TLBCACHE_TICKS 0x40000004 // RW - page table (tlb) cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_PARTIAL 0x40000005 // RW - process refresh (partial) period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_TOTAL 0x40000006 // RW - process refresh (full) period (in ticks)
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MAJOR 0x40000007 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MINOR 0x40000008 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
-#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
-
-static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
-
-typedef enum tdVMMDLL_MEMORYMODEL_TP {
- VMMDLL_MEMORYMODEL_NA = 0,
- VMMDLL_MEMORYMODEL_X86 = 1,
- VMMDLL_MEMORYMODEL_X86PAE = 2,
- VMMDLL_MEMORYMODEL_X64 = 3
-} VMMDLL_MEMORYMODEL_TP;
-
-typedef enum tdVMMDLL_SYSTEM_TP {
- VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
- VMMDLL_SYSTEM_WINDOWS_X64 = 2,
- VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
- VMMDLL_SYSTEM_WINDOWS_X86 = 4
-} VMMDLL_SYSTEM_TP;
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- pqwValue = pointer to ULONG64 to receive option value.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- qwValue
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// VFS - VIRTUAL FILE SYSTEM FUNCTIONALITY BELOW:
-// This is the core of the memory process file system. All implementation and
-// analysis towards the file system is possible by using functionality below.
-//-----------------------------------------------------------------------------
-
-#define VMMDLL_STATUS_SUCCESS ((NTSTATUS)0x00000000L)
-#define VMMDLL_STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
-#define VMMDLL_STATUS_END_OF_FILE ((NTSTATUS)0xC0000011L)
-#define VMMDLL_STATUS_FILE_INVALID ((NTSTATUS)0xC0000098L)
-#define VMMDLL_STATUS_FILE_SYSTEM_LIMITATION ((NTSTATUS)0xC0000427L)
-
-typedef struct tdVMMDLL_VFS_FILELIST {
- VOID(*pfnAddFile) (_Inout_ HANDLE h, _In_ LPSTR szName, _In_ ULONG64 cb, _In_ PVOID pvReserved);
- VOID(*pfnAddDirectory)(_Inout_ HANDLE h, _In_ LPSTR szName, _In_ PVOID pvReserved);
- HANDLE h;
-} VMMDLL_VFS_FILELIST, *PVMMDLL_VFS_FILELIST;
-
-/*
-* Helper function macros for callbacks into the VMM_VFS_FILELIST structure.
-*/
-#define VMMDLL_VfsList_AddFile(pFileList, szName, cb) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddFile(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, cb, NULL); }
-#define VMMDLL_VfsList_AddDirectory(pFileList, szName) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddDirectory(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, NULL); }
-
-/*
-* List a directory of files in the memory process file system. Directories and
-* files will be listed by callbacks into functions supplied in the pFileList
-* parameter. If information of an individual file is needed it's neccessary
-* to list all files in its directory.
-* -- wcsPath
-* -- pFileList
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
-
-/*
-* Read select parts of a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbRead
-* -- cbOffset
-* -- return
-*
-*/
-NTSTATUS VMMDLL_VfsRead(_In_ LPCWSTR wcsFileName, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-
-/*
-* Write select parts to a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbWrite
-* -- cbOffset
-* -- return
-*/
-NTSTATUS VMMDLL_VfsWrite(_In_ LPCWSTR wcsFileName, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-
-/*
-* Utility functions for memory process file system read/write towards different
-* underlying data representations.
-*/
-NTSTATUS VMMDLL_UtilVfsReadFile_FromPBYTE(_In_ PBYTE pbFile, _In_ ULONG64 cbFile, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromQWORD(_In_ ULONG64 qwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromDWORD(_In_ DWORD dwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromBOOL(_In_ BOOL fValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_BOOL(_Inout_ PBOOL pfTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset, _In_ DWORD dwMinAllow);
-
-
-//-----------------------------------------------------------------------------
-// PLUGIN MANAGER FUNCTIONALITY BELOW:
-// Function and structures to initialize and use the memory process file system
-// plugin functionality. The plugin manager is started by a call to function:
-// VMM_VfsInitializePlugins. Each built-in plugin and external plugin of which
-// the DLL name matches m_*.dll will receive a call to its InitializeVmmPlugin
-// function. The plugin/module may decide to call pfnPluginManager_Register to
-// register plugins in the form of different names one or more times.
-// Example of registration function in a plugin DLL below:
-// 'VOID InitializeVmmPlugin(_In_ PVMM_PLUGIN_REGINFO pRegInfo)'
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize all potential plugins, both built-in and external, that maps into
-* the memory process file system. Please note that plugins are not loaded by
-* default - they have to be explicitly loaded by calling this function. They
-* will be unloaded on a general close of the vmm dll.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsInitializePlugins();
-
-#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
-#define VMMDLL_PLUGIN_CONTEXT_VERSION 2
-#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
-#define VMMDLL_PLUGIN_REGINFO_VERSION 3
-
-#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
-
-typedef struct tdVMMDLL_PLUGIN_CONTEXT {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- DWORD dwPID;
- PVOID pProcess;
- LPSTR szModule;
- LPSTR szPath;
- PVOID pvReserved1;
- PVOID pvReserved2;
-} VMMDLL_PLUGIN_CONTEXT, *PVMMDLL_PLUGIN_CONTEXT;
-
-typedef struct tdVMMDLL_PLUGIN_REGINFO {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel;
- VMMDLL_SYSTEM_TP tpSystem;
- HMODULE hDLL;
- HMODULE hReservedDll; // not for general use (only used for python).
- BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
- PVOID pvReserved1;
- PVOID pvReserved2;
- // general plugin registration info to be filled out by the plugin below:
- struct {
- CHAR szModuleName[32];
- BOOL fRootModule;
- BOOL fProcessModule;
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_info;
- // function plugin registration info to be filled out by the plugin below:
- struct {
- BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
- NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
- NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
- VOID(*pfnNotify)(_In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
- VOID(*pfnClose)();
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_fn;
-} VMMDLL_PLUGIN_REGINFO, *PVMMDLL_PLUGIN_REGINFO;
-
-//-----------------------------------------------------------------------------
-// VMM CORE FUNCTIONALITY BELOW:
-// Vmm core functaionlity such as read (and write) to both virtual and physical
-// memory. NB! writing will only work if the target is supported - i.e. not a
-// memory dump file...
-// To read physical memory specify dwPID as (DWORD)-1
-//-----------------------------------------------------------------------------
-
-// FLAG used to supress the default read cache in calls to VMM_MemReadEx()
-// which will lead to the read being fetched from the target system always.
-// Cached page tables (used for translating virtual2physical) are still used.
-#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
-#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
-
-/*
-* Read memory in various non-contigious locations specified by the pointers to
-* the items in the ppDMAs array. Result for each unit of work will be given
-* individually. No upper limit of number of items to read, but no performance
-* boost will be given if above hardware limit. Max size of each unit of work is
-* one 4k page (4096 bytes).
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-* -- pcpDMAsRead = optional count of number of successfully read ppDMAs.
-* -- flags = optional flags as given by VMMDLL_FLAG_*
-* -- return = the number of successfully read items.
-*/
-DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs, _In_ DWORD flags);
-
-/*
-* Read a single 4096-byte page of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pbPage
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
-
-/*
-* Read a contigious arbitrary amount of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Read a contigious amount of memory and report the number of bytes read in pcbRead.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- pcbRead
-* -- flags = flags as in VMMDLL_FLAG_*
-* -- return = success/fail. NB! reads may report as success even if 0 bytes are
-* read - it's recommended to verify pcbReadOpt parameter.
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
-
-/*
-* Prefetch a number of addresses (specified in the pA array) into the memory
-* cache. This function is to be used to batch larger known reads into local
-* cache before making multiple smaller reads - which will then happen from
-* the cache. Function exists for performance reasons.
-* -- dwPID = PID of target process, (DWORD)-1 for physical memory.
-* -- pPrefetchAddresses = array of addresses to read into cache.
-* -- cPrefetchAddresses
-*/
-_Success_(return)
-BOOL VMMDLL_MemPrefetchPages(_In_ DWORD dwPID, _In_reads_(cPrefetchAddresses) PULONG64 pPrefetchAddresses, _In_ DWORD cPrefetchAddresses);
-
-/*
-* Write a contigious arbitrary amount of memory. Please note some virtual memory
-* such as pages of executables (such as DLLs) may be shared between different
-* virtual memory over different processes. As an example a write to kernel32.dll
-* in one process is likely to affect kernel32 in the whole system - in all
-* processes. Heaps and Stacks and other memory are usually safe to write to.
-* Please take care when writing to memory!
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = TRUE on success, FALSE on partial or zero write.
-*/
-_Success_(return)
-BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Translate a virtual address to a physical address by walking the page tables
-* of the specified process.
-* -- dwPID
-* -- qwVA
-* -- pqwPA
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
-
-
-
-//-----------------------------------------------------------------------------
-// VMM PROCESS FUNCTIONALITY BELOW:
-// Functionality below is mostly relating to Windows processes.
-//-----------------------------------------------------------------------------
-
-/*
-* Retrieve an active process given it's name. Please note that if multiple
-* processes with the same name exists only one will be returned. If required to
-* parse all processes with the same name please iterate over the PID list by
-* calling VMMDLL_PidList together with VMMDLL_ProcessGetInformation.
-* -- szProcName = process name (truncated max 15 chars) case insensitive.
-* -- pdwPID = pointer that will receive PID on success.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
-
-/*
-* List the PIDs in the system.
-* -- pPIDs = DWORD array of at least number of PIDs in system, or NULL.
-* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
-
-// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
-#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
-#define VMMDLL_MEMMAP_FLAG_PAGE_NS 0x0000000000000004
-#define VMMDLL_MEMMAP_FLAG_PAGE_NX 0x8000000000000000
-#define VMMDLL_MEMMAP_FLAG_PAGE_MASK 0x8000000000000006
-
-typedef struct tdVMMDLL_MEMMAP_ENTRY {
- ULONG64 AddrBase;
- ULONG64 cPages;
- ULONG64 fPage;
- BOOL fWoW64;
- CHAR szTag[32];
-} VMMDLL_MEMMAP_ENTRY, *PVMMDLL_MEMMAP_ENTRY;
-
-/*
-* Retrieve memory map entries from the specified process. Memory map entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries bytes.
-* If the pMemMapEntries is set to NULL the number of memory map entries will be
-* given in the pcMemMapEntries parameter.
-* -- dwPID
-* -- pMemMapEntries = buffer of minimum length sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries, or NULL.
-* -- pcMemMapEntries = pointer to number of memory map entries.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
-
-/*
-* Retrieve a single memory map entry given a virtual address within that entrys
-* range.
-* -- dwPID
-* -- pMemMapEntry
-* -- va = virtual address in the memory map entry to retrieve.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
-
-typedef struct tdVMMDLL_MODULEMAP_ENTRY {
- ULONG64 BaseAddress;
- ULONG64 EntryPoint;
- DWORD SizeOfImage;
- BOOL fWoW64;
- CHAR szName[32];
-} VMMDLL_MODULEMAP_ENTRY, *PVMMDLL_MODULEMAP_ENTRY;
-
-/*
-* Retrieve the module entries from the specified process. The module entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries bytes long. If the
-* pcModuleEntries is set to NULL the number of module entries will be given
-* in the pcModuleEntries parameter.
-* -- dwPID
-* -- pModuleEntries = buffer of minimum length sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries, or NULL.
-* -- pcModuleEntries = pointer to number of memory map entries.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
-
-/*
-* Retrieve a module (.exe or .dll or similar) given a module name.
-* -- dwPID
-* -- szModuleName
-* -- pModuleEntry
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
-
-#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
-#define VMMDLL_PROCESS_INFORMATION_VERSION 2
-
-typedef struct tdVMMDLL_PROCESS_INFORMATION {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
- VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
- BOOL fUserOnly; // only user mode pages listed
- DWORD dwPID;
- DWORD dwState;
- CHAR szName[16];
- ULONG64 paDTB;
- ULONG64 paDTB_UserOpt; // may not exist
- union {
- struct {
- ULONG64 vaEPROCESS;
- ULONG64 vaPEB;
- ULONG64 vaENTRY;
- BOOL fWow64;
- DWORD vaPEB32; // WoW64 only
- } win;
- } os;
-} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
-
-/*
-* Retrieve various process information from a PID. Process information such as
-* name, page directory bases and the process state may be retrieved.
-* -- dwPID
-* -- pProcessInformation = if null, size is given in *pcbProcessInfo
-* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
-
-typedef struct tdVMMDLL_EAT_ENTRY {
- ULONG64 vaFunction;
- DWORD vaFunctionOffset;
- CHAR szFunction[40];
-} VMMDLL_EAT_ENTRY, *PVMMDLL_EAT_ENTRY;
-
-typedef struct tdVMMDLL_IAT_ENTRY {
- ULONG64 vaFunction;
- CHAR szFunction[40];
- CHAR szModule[64];
-} VMMDLL_IAT_ENTRY, *PVMMDLL_IAT_ENTRY;
-
-/*
-* Retrieve information about: Data Directories, Sections, Export Address Table
-* and Import Address Table (IAT).
-* If the pData == NULL upon entry the number of entries of the pData array must
-* have in order to be able to hold the data is returned.
-* -- dwPID
-* -- szModule
-* -- pData
-* -- cData
-* -- pcData
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-
-/*
-* Retrieve the virtual address of a given function inside a process/module.
-* -- dwPID
-* -- szModuleName
-* -- szFunctionName
-* -- return = virtual address of function, zero on fail.
-*/
-ULONG64 VMMDLL_ProcessGetProcAddress(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szFunctionName);
-
-/*
-* Retrieve the base address of a given module.
-* -- dwPID
-* -- szModuleName
-* -- return = virtual address of module base, zero on fail.
-*/
-ULONG64 VMMDLL_ProcessGetModuleBase(_In_ DWORD dwPID, _In_ LPSTR szModuleName);
-
-
-
-//-----------------------------------------------------------------------------
-// WINDOWS SPECIFIC UTILITY FUNCTIONS BELOW:
-//-----------------------------------------------------------------------------
-
-typedef struct tdVMMDLL_WIN_THUNKINFO_IAT {
- BOOL fValid;
- BOOL f32; // if TRUE fn is a 32-bit/4-byte entry, otherwise 64-bit/8-byte entry.
- ULONG64 vaThunk; // address of import address table 'thunk'.
- ULONG64 vaFunction; // value if import address table 'thunk' == address of imported function.
- ULONG64 vaNameModule; // address of name string for imported module.
- ULONG64 vaNameFunction; // address of name string for imported function.
-} VMMDLL_WIN_THUNKINFO_IAT, *PVMMDLL_WIN_THUNKINFO_IAT;
-
-typedef struct tdVMMDLL_WIN_THUNKINFO_EAT {
- BOOL fValid;
- DWORD valueThunk; // value of export address table 'thunk'.
- ULONG64 vaThunk; // address of import address table 'thunk'.
- ULONG64 vaNameFunction; // address of name string for exported function.
- ULONG64 vaFunction; // address of exported function (module base + value parameter).
-} VMMDLL_WIN_THUNKINFO_EAT, *PVMMDLL_WIN_THUNKINFO_EAT;
-
-/*
-* Retrieve information about the import address table IAT thunk for an imported
-* function. This includes the virtual address of the IAT thunk which is useful
-* for hooking.
-* -- dwPID
-* -- szModuleName
-* -- szImportModuleName
-* -- szImportFunctionName
-* -- pThunkIAT
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoIAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szImportModuleName, _In_ LPSTR szImportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_IAT pThunkInfoIAT);
-
-/*
-* Retrieve information about the export address table EAT thunk for an exported
-* function. This includes the virtual address of the EAT thunk which is useful
-* for hooking.
-* -- dwPID
-* -- szModuleName
-* -- pThunkEAT
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoEAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szExportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_EAT pThunkInfoEAT);
-
-/*
-* Decompress compressed memory page stored in the MemCompression process.
-* -- vaCompressedData = virtual address in 'MemCompression' to decompress.
-* -- cbCompressedData = length of compressed data in 'MemCompression' to decompress (or zero for auto-detect).
-* -- pbDecompressedPage
-* -- pcbCompressedData = optional ptr to receive length of compressed buffer.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinMemCompression_DecompressPage(
- _In_ ULONG64 vaCompressedData,
- _In_opt_ DWORD cbCompressedData,
- _Out_writes_(4096) PBYTE pbDecompressedPage,
- _Out_opt_ PDWORD pcbCompressedData
-);
-
-
-//-----------------------------------------------------------------------------
-// VMM UTIL FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-/*
-* Fill a human readable hex ascii memory dump into the caller supplied sz buffer.
-* -- pb
-* -- cb
-* -- cbInitialOffset = offset, must be max 0x1000 and multiple of 0x10.
-* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
-* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
-*/
-_Success_(return)
-BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __VMMDLL_H__ */
diff --git a/files/vmmpy.py b/files/vmmpy.py
deleted file mode 100644
index 8db72fb..0000000
--- a/files/vmmpy.py
+++ /dev/null
@@ -1,567 +0,0 @@
-# vmmpy.py
-#
-# Provides a convenient python interface for the memory process file system
-# virtual memory manager - vmm.dll / vmmpyc.pyc.
-#
-# Fast and convenient python access towards the native vmm.dll and in some
-# cases linked pcileech.dll libraries. This wrapper also provides for code
-# completion in some supported dev environments.
-#
-# https://github.com/ufrisk/
-#
-# (c) Ulf Frisk, 2018-2019
-# Author: Ulf Frisk, pcileech@frizk.net
-#
-
-from vmmpyc import *
-
-#------------------------------------------------------------------------------
-# VmmPy CONSTANTS BELOW:
-# NB! Only some unrelated contants are put here. Constants more closely related
-# to functionality is put close to the functionality itself.
-#------------------------------------------------------------------------------
-
-# NTSTATUS values. (Used/Returned by Write file plugin callbacks).
-VMMPY_STATUS_SUCCESS = 0x00000000
-VMMPY_STATUS_UNSUCCESSFUL = 0xC0000001
-VMMPY_STATUS_END_OF_FILE = 0xC0000011
-VMMPY_STATUS_FILE_INVALID = 0xC0000098
-
-# SYSTEM values - used to determine if a plugin is supported or not for
-# the current system that is being analyzed.
-VMMPY_SYSTEM_UNKNOWN_X64 = 0x0001
-VMMPY_SYSTEM_WINDOWS_X64 = 0x0002
-VMMPY_SYSTEM_UNKNOWN_X86 = 0x0003
-VMMPY_SYSTEM_WINDOWS_X86 = 0x0004
-
-# MEMORYMODEL values - used to determine if a plugin is supported or not
-# for a specific memory model.
-VMMPY_MEMORYMODEL_NA = 0x0000
-VMMPY_MEMORYMODEL_X86 = 0x0001
-VMMPY_MEMORYMODEL_X86PAE = 0x0002
-VMMPY_MEMORYMODEL_X64 = 0x0003
-
-# EVENT values - received by the notify callback function for specific events
-# occuring in the native plugin manager / vmm / memory process file system.
-VMMPY_PLUGIN_EVENT_VERBOSITYCHANGE = 0x01
-
-#------------------------------------------------------------------------------
-# VmmPy INITIALIZATION FUNCTIONALITY BELOW:
-#------------------------------------------------------------------------------
-
-def VmmPy_Close():
- """Close an initialized instance of VMM.DLL and clean up all allocated resources including plugins, linked PCILeech.dll and other memory resources.
-
- Keyword arguments:
- N/A
-
- Example:
- VmmPy_Close()
- """
- VMMPYC_Close()
-
-
-
-def VmmPy_Refresh():
- """Force refresh the internal state of the VMM.DLL - refreshing process listings and internal caches. NB! function may take a long time to execute!
-
- Keyword arguments:
- N/A
-
- Example:
- VmmPy_Refresh()
- """
- VMMPYC_Refresh(0)
-
-
-
-def VmmPy_Initialize(args, is_printf = True, is_verbose = False, is_verbose_extra = False, is_verbose_tlp = False, page_table_base = 0):
- """Initialize VmmPy and the Virtual Memory Manager VMM.DLL with arguments as
- in the argument list args. Important is the -device option and optionally
- -remote option as closer described in the MemProcFS and LeechCore projects.
-
- Keyword arguments:
- file_name -- str: memory dump file to load.
- is_printf -- bool: console output from vmm.dll is enabled.
- is_verbose -- bool: verbose level.
- is_verbose_extra -- bool: extra verbose level.
- is_verbose_tlp -- bool: show FPGA TLPs or similar - super verbose!
- page_table_base -- int: optional page directory base of the OS kernel or a x64 process.
-
- Example:
- VmmPy_Initialize(['c:\\temp\\dump.raw'])
- VmmPy_Initialize(['-device', 'dumpit','-remote', 'rpc://insecure:remote.example.com'])
- """
- if page_table_base > 0:
- args.append("-cr3")
- args.append(str(page_table_base))
- if is_printf:
- args.append("-printf")
- if is_verbose:
- args.append("-v")
- if is_verbose_extra:
- args.append("-vv")
- if is_verbose_tlp:
- args.append("-vvv")
- VMMPYC_Initialize(args)
-
-
-
-#------------------------------------------------------------------------------
-# VmmPy CONFIGURATION FUNCTIONALITY BELOW:
-#------------------------------------------------------------------------------
-
-VMMPY_OPT_DEVICE_FPGA_PROBE_MAXPAGES = 0x01 # RW
-VMMPY_OPT_DEVICE_FPGA_RX_FLUSH_LIMIT = 0x02 # RW
-VMMPY_OPT_DEVICE_FPGA_MAX_SIZE_RX = 0x03 # RW
-VMMPY_OPT_DEVICE_FPGA_MAX_SIZE_TX = 0x04 # RW
-VMMPY_OPT_DEVICE_FPGA_DELAY_PROBE_READ = 0x05 # RW - uS
-VMMPY_OPT_DEVICE_FPGA_DELAY_PROBE_WRITE = 0x06 # RW - uS
-VMMPY_OPT_DEVICE_FPGA_DELAY_WRITE = 0x07 # RW - uS
-VMMPY_OPT_DEVICE_FPGA_DELAY_READ = 0x08 # RW - uS
-VMMPY_OPT_DEVICE_FPGA_RETRY_ON_ERROR = 0x09 # RW
-VMMPY_OPT_DEVICE_FPGA_DEVICE_ID = 0x80 # R
-VMMPY_OPT_DEVICE_FPGA_FPGA_ID = 0x81 # R
-VMMPY_OPT_DEVICE_FPGA_VERSION_MAJOR = 0x82 # R
-VMMPY_OPT_DEVICE_FPGA_VERSION_MINOR = 0x83 # R
-
-VMMPY_OPT_CORE_PRINTF_ENABLE = 0x80000001 # RW
-VMMPY_OPT_CORE_VERBOSE = 0x80000002 # RW
-VMMPY_OPT_CORE_VERBOSE_EXTRA = 0x80000003 # RW
-VMMPY_OPT_CORE_VERBOSE_EXTRA_TLP = 0x80000004 # RW
-VMMPY_OPT_CORE_MAX_NATIVE_ADDRESS = 0x80000005 # R
-VMMPY_OPT_CORE_MAX_NATIVE_IOSIZE = 0x80000006 # R
-VMMPY_OPT_CORE_SYSTEM = 0x80000007 # R
-VMMPY_OPT_CORE_MEMORYMODEL = 0x80000008 # R
-
-VMMPY_OPT_CONFIG_IS_REFRESH_ENABLED = 0x40000001 # R - 1/0
-VMMPY_OPT_CONFIG_TICK_PERIOD = 0x40000002 # RW - base tick period in ms
-VMMPY_OPT_CONFIG_READCACHE_TICKS = 0x40000003 # RW - memory cache validity period (in ticks)
-VMMPY_OPT_CONFIG_TLBCACHE_TICKS = 0x40000004 # RW - page table (tlb) cache validity period (in ticks)
-VMMPY_OPT_CONFIG_PROCCACHE_TICKS_PARTIAL = 0x40000005 # RW - process refresh (partial) period (in ticks)
-VMMPY_OPT_CONFIG_PROCCACHE_TICKS_TOTAL = 0x40000006 # RW - process refresh (full) period (in ticks)
-VMMPY_OPT_CONFIG_VMM_VERSION_MAJOR = 0x40000007 # R
-VMMPY_OPT_CONFIG_VMM_VERSION_MINOR = 0x40000008 # R
-VMMPY_OPT_CONFIG_VMM_VERSION_REVISION = 0x40000009 # R
-VMMPY_OPT_CONFIG_STATISTICS_FUNCTIONCALL = 0x4000000A # RW - enable function call statistics (.status/statistics_fncall file)
-
-
-def VmmPy_ConfigGet(vmmpy_opt_id):
- """Retrieve a configuration setting given a VMMPY_OPT_* option.
-
- Keyword arguments:
- vmmpy_opt_id -- int: the configuration value to retrieve as defined by VMMPY_OPT_*.
- return -- int: configuration value. (Fail: -1).
-
- Example:
- VmmPy_ConfigGet(VMMPY_OPT_CORE_PRINTF_ENABLE) --> 1
- """
- return VMMPYC_ConfigGet(vmmpy_opt_id)
-
-
-
-def VmmPy_ConfigSet(vmmpy_opt_id, value):
- """Set a configuration setting given a VMMPY_OPT_* option.
-
- Keyword arguments:
- vmmpy_opt_id -- int: the configuration value to retrieve as defined by VMMPY_OPT_*.
- value -- int: value to set.
-
- Example:
- VmmPy_ConfigSet(VMMPY_OPT_CORE_PRINTF_ENABLE, 0)
- """
- VMMPYC_ConfigSet(vmmpy_opt_id, value)
-
-
-
-def VmmPy_GetVersion():
- """Retrieve the Version of the core functionality in the VMM.DLL.
-
- Example:
- VmmPy_GetVersion() -> 1.0.0
- """
- verMajor = VMMPYC_ConfigGet(VMMPY_OPT_CONFIG_VMM_VERSION_MAJOR)
- verMinor = VMMPYC_ConfigGet(VMMPY_OPT_CONFIG_VMM_VERSION_MINOR)
- verRevision = VMMPYC_ConfigGet(VMMPY_OPT_CONFIG_VMM_VERSION_REVISION)
- return str(verMajor) + '.' + str(verMinor) + '.' + str(verRevision)
-
-
-
-#------------------------------------------------------------------------------
-# VmmPy MEMORY ACCESS FUNCTIONALITY BELOW:
-#------------------------------------------------------------------------------
-
-VMMPY_FLAG_NOCACHE = 0x0001 # do not use the data cache (force reading from memory acquisition device)
-VMMPY_FLAG_ZEROPAD_ON_FAIL = 0x0002 # zero pad failed physical memory reads and report success if read within range of physical memory.
-
-
-
-def VmmPy_MemRead(pid, address, length, flags = 0):
- """Read memory given a pid, a (64-bit) address and length. Return result as bytes.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory. -1 when reading physical memory.
- address -- int: the address to read.
- length -- int: the number of bytes to read.
- flags -- int: optional flags as specified by VMMPY_FLAG* constants.
- return -- bytes: memory.
-
- Example:
- VmmPy_MemRead(-1, 0x1000, 4) --> b'\x00\x01\x02\x03'
- """
- return VMMPYC_MemRead(pid, address, length, flags)
-
-
-
-def VmmPy_MemReadScatter(pid, address_list, flags = 0):
- """Read page (4kB) sized & aligned memory given a pid and a list of (64-bit) addresses. Return result in list of dict.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory. -1 when reading physical memory.
- address_list -- list: a list of page (4kB/0x1000) aligned addresses.
- flags -- int: optional flags as specified by VMMPY_FLAG* constants.
- return -- list: of dicts with the result.
-
- Example:
- VmmPy_MemReadScatter(-1, [0x1000]) --> [{'addr': 4096, 'pa': 4096, 'data': b'\x00\x01\x02\x03\x04 ... ', 'size': 4096}]
- """
-
- return VMMPYC_MemReadScatter(pid, address_list, flags)
-
-
-
-def VmmPy_MemWrite(pid, address, bytes_data):
- """Write memory given a pid, a (64-bit) address and length. No return.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory. -1 when writing physical memory.
- address -- int: the address to write.
- bytes_data -- bytes: a bytes-like object.
-
- Example:
- VmmPy_MemWrite(0x666, 0x1000, b'\x00\x01\x02\x03')
- """
- VMMPYC_MemWrite(pid, address, bytes_data)
-
-
-
-def VmmPy_MemVirt2Phys(pid, address):
- """Translate a virtual address (va) to a physical address given a pid and return the result.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory.
- va -- int: the virtual address (va) to translate
- return -- int: the physical address (pa).
-
- Example:
- VmmPy_MemVirt2Phys(0x666, 0x00007ff74d5da000) --> 0x000000004d5da000
- """
- return VMMPYC_MemVirt2Phys(pid, address)
-
-
-
-#------------------------------------------------------------------------------
-# VmmPy GENERAL PROCESS / MEMORY MAP FUNCTIONALITY BELOW:
-#------------------------------------------------------------------------------
-
-def VmmPy_PidList():
- """Retrieve all process identifiers (pids) in the system and return them as a list.
-
- Keyword arguments:
- return -- list: pids.
-
- Example:
- VmmPy_PidList() --> [4, 76, 324, 392, 576, 588, ...]
- """
- return sorted(VMMPYC_PidList())
-
-
-
-def VmmPy_PidGetFromName(process_name):
- """Retrieve a pid from a process_name and return it.
- NB! if more processes do have the same name only one will be returned by
- this function. If important to find all then use VmmPy_PidList() instead.
-
- Keyword arguments:
- process_name -- str: name of a process to find.
- return -- int: pid number.
-
- Example:
- VmmPy_PidGetFromName() --> 4
- """
- return VMMPYC_PidGetFromName(process_name)
-
-
-
-def VmmPy_ProcessGetMemoryMap(pid, is_identify_modules = False):
- """Retrieve the memory map for a specific pid.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory.
- is_identify_modules -- bool: (optional) identify module names (slow).
- return -- list: of dict of memory map entries.
-
- Example:
- VmmPy_ProcessGetMemoryMap(4) --> [{'va': 2147352576, 'size': 4096, 'pages': 1, 'wow64': False, 'tag': '', 'flags-pte': 9223372036854775812, 'flags': 'srwx'}, ...]
- """
- return VMMPYC_ProcessGetMemoryMap(pid, is_identify_modules)
-
-
-
-def VmmPy_ProcessGetMemoryMapEntry(pid, va, is_identify_modules = False):
- """Retrieve a single memory map entry for a given pid and virtual address (va).
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory.
- va -- int: a virtual address inside the entry to retrieve.
- is_identify_modules -- bool: (optional) identify module names (slow).
- return -- dict: of memory map entries.
-
- Example:
- VmmPy_ProcessGetMemoryMapEntry(4, 0x7ffe0000) --> {'va': 2147352576, 'size': 4096, 'pages': 1, 'wow64': False, 'name': '', 'flags-pte': 9223372036854775812, 'flags': 'srwx'}
- """
- return VMMPYC_ProcessGetMemoryMapEntry(pid, va, is_identify_modules)
-
-
-
-def VmmPy_ProcessGetModuleMap(pid):
- """Retrieve the module map for a specific pid.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory.
- return -- list: of dict of module map information entries.
-
- Example:
- VmmPy_ProcessGetModuleMap(332) --> [{'va': 140718422491136, 'va-entry': 0, 'wow64': False, 'size': 1966080, 'name': 'ntdll.dll'}, ...]
- """
- return VMMPYC_ProcessGetModuleMap(pid)
-
-
-
-def VmmPy_ProcessGetModuleFromName(pid, module_name):
- """Retrieve the module map for a specific pid and module name.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory.
- module_name -- bool: name of the module to retrieve.
- return -- dict: of module information.
-
- Example:
- VmmPy_ProcessGetModuleMap(332, "ntdll.dll") --> {'va': 140718422491136, 'va-entry': 0, 'wow64': False, 'size': 1966080, 'name': 'ntdll.dll'}
- """
- return VMMPYC_ProcessGetModuleFromName(pid, module_name)
-
-
-
-def VmmPy_ProcessGetInformation(pid):
- """Retrieve process information for a specific pid and return as dict.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory.
- return -- dict: of process information.
-
- Example:
- VmmPy_ProcessGetInformation(332) --> {'pid': 8796, 'pa-dtb': 5798625280, 'pa-dtb-user': 6237978624, 'state': 0, 'tp-system': 2, 'usermode': True, 'name': 'cmd.exe', 'wow64': False, 'va-entry': 140700131683072, 'va-eprocess': 18446635809067693440, 'va-peb': 708313505792, 'va-peb32': 0}
- """
- return VMMPYC_ProcessGetInformation(pid)
-
-
-
-def VmmPy_ProcessListInformation():
- """Retrieve process information for all pids and return as dict of dict.
-
- Keyword arguments:
- return -- dict: dict of process information with pid as key.
-
- Example:
- VmmPy_ProcessListInformation() --> {4: {...}, ..., 322: {'pid': 8796, 'pa-dtb': 5798625280, 'pa-dtb-user': 6237978624, 'state': 0, 'tp-system': 2, 'usermode': True, 'name': 'cmd.exe', 'wow64': False, 'va-entry': 140700131683072, 'va-eprocess': 18446635809067693440, 'va-peb': 708313505792, 'va-peb32': 0}
- """
- pids = VmmPy_PidList()
- result = {}
- for pid in pids:
- result[pid] = VMMPYC_ProcessGetInformation(pid)
- return result
-
-
-
-#------------------------------------------------------------------------------
-# VmmPy WINDOWS SPECIFIC PROCESS FUNCTIONALITY BELOW:
-#------------------------------------------------------------------------------
-
-def VmmPy_ProcessGetEAT(pid, module_name):
- """Retrieve the export address table (EAT) for a specific pid and module name and return as list of dict.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory.
- module_name -- str: name of the module to retrieve.
- return -- list: of dict of EAT information.
-
- Example:
- VmmPy_ProcessGetEAT(332, "ntdll.dll") --> [{'i': 0, 'va': 140718385196671, 'offset': 585343, 'fn': 'AcquireSRWLockExclusive'}, ... ]
- """
- return VMMPYC_ProcessGetEAT(pid, module_name)
-
-
-
-def VmmPy_ProcessGetIAT(pid, module_name):
- """Retrieve the import address table (IAT) for a specific pid and module name and return as list of dict.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory.
- module_name -- str: name of the module to retrieve.
- return -- list: of dict of IAT information.
-
- Example:
- VmmPy_ProcessGetAT(332, "cmd.exe") --> [{'i': 0, 'va': 140718377374992, 'fn': 'setlocale', 'dll': 'msvcrt.dll'}, ... ]
- """
- return VMMPYC_ProcessGetIAT(pid, module_name)
-
-
-
-def VmmPy_ProcessGetDirectories(pid, module_name):
- """Retrieve the data directories for a specific pid and module name and return as list of dict.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory.
- module_name -- str: name of the module to retrieve.
- return -- list: of dict of data direcories information.
-
- Example:
- VmmPy_ProcessGetDirectories(332, "cmd.exe") --> [{'i': 0, 'size': 0, 'offset': 0, 'name': 'EXPORT'}, ... ]
- """
- return VMMPYC_ProcessGetDirectories(pid, module_name)
-
-
-
-def VmmPy_ProcessGetSections(pid, module_name):
- """Retrieve the sections for a specific pid and module name and return as list of dict.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory.
- module_name -- str: name of the module to retrieve.
- return -- list: of dict of section information.
-
- Example:
- VmmPy_ProcessGetSections(332, "cmd.exe") --> [{'i': 0, 'Characteristics': 1610612768, 'misc-PhysicalAddress': 183592, 'misc-VirtualSize': 183592, 'Name': '.text', 'NumberOfLinenumbers': 0, 'NumberOfRelocations': 0, 'PointerToLinenumbers': 0, 'PointerToRawData': 1024, 'PointerToRelocations': 0, 'SizeOfRawData': 183808, 'VirtualAddress': 4096}, ... ]
- """
- return VMMPYC_ProcessGetSections(pid, module_name)
-
-
-
-#------------------------------------------------------------------------------
-# VmmPy VFS (Virtual File System) FUNCTIONALITY BELOW:
-#------------------------------------------------------------------------------
-def VmmPy_VfsList(path):
- """Retrieve a Virtual File System directory listing a path and return it.
-
- Keyword arguments:
- path -- str: the directory path.
- return -- dict: of dict of file/directory names.
-
- Example:
- VmmPy_VfsList("/") --> {'pmem' : {'size': 247078670, 'f_isdir': False}, ...}
- """
- path = path.replace('/', '\\')
- return VMMPYC_VfsList(path)
-
-
-
-def VmmPy_VfsRead(path_file, length, offset = 0):
- """Read a Virtual File System file.
-
- Keyword arguments:
- path_file -- str: the file path including the file name.
- length -- int: the amount of bytes to read.
- offset -- int: start reading from this offset.
- return -- bytes: the read data.
-
- Example:
- VmmPy_VfsRead("/pmem", 0x1000, 0x10000000) --> b'000032040234023400 ...'
- """
- path_file = path_file.replace('/', '\\')
- return VMMPYC_VfsRead(path_file, length, offset)
-
-
-
-def VmmPy_VfsWrite(path_file, bytes_data, offset = 0):
- """Write to Virtual File System file.
-
- Keyword arguments:
- path_file -- str: the file path including the file name.
- bytes_data -- bytes: the data to write.
- offset -- int: start writing from this offset.
-
- Example:
- VmmPy_VfsWrite("/pmem", b'000000011122', 0x2000)
- """
- path_file = path_file.replace('/', '\\')
- VmmPy_VfsWrite(path_file, bytes_data, offset)
-
-
-#------------------------------------------------------------------------------
-# VmmPy WINDOWS ONLY FUNCTIONALITY BELOW:
-#------------------------------------------------------------------------------
-
-def VmmPy_WinGetThunkInfoEAT(pid, module_name, exported_function):
- """Retrieve information about a single export address table (EAT) entry. This may be useful for hooking.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory.
- module_name -- str: name of the module to retrieve.
- exported_function -- str: name of the exported function to retrieve.
- return -- dict: information about the EAT entry.
-
- Example:
- VmmPy_WinGetThunkInfoEAT(4, 'ntoskrnl.exe', 'KeGetCurrentIrql') --> {'vaFunction': 18446735288139539584, 'valueThunk': 1479808, 'vaNameFunction': 18446735288147899428, 'vaThunk': 18446735288147849312}
- """
- return VMMPYC_WinGetThunkInfoEAT(pid, module_name, exported_function)
-
-
-
-def VmmPy_WinGetThunkInfoIAT(pid, module_name, imported_module_name, imported_module_function):
- """Retrieve information about a single import address table (IAT) entry. This may be useful for hooking.
-
- Keyword arguments:
- pid -- int: the process identifier (pid) when reading process virtual memory.
- module_name -- str: name of the module to retrieve.
- imported_module_name -- str: name of the imported module to retrieve.
- imported_module_function -- str: name of the imported function to retrieve.
- return -- dict: information about the IAT entry.
-
- Example:
- VmmPy_WinGetThunkInfoIAT(4, 'ntoskrnl.exe', 'hal.dll', 'HalSendNMI') --> {'32': False, 'vaFunction': 18446735288149190896, 'vaNameFunction': 18446735288143568050, 'vaNameModule': 18446735288143568362, 'vaThunk': 18446735288143561136}
- """
- return VMMPYC_WinGetThunkInfoIAT(pid, module_name, imported_module_name, imported_module_function)
-
-
-
-def VmmPy_WinDecompressPage(va_compressed, len_compressed = 0):
- """Decompress a page stored in the MemCompression process in Windows 10.
-
- Keyword arguments:
- va_compressed -- int: the virtual address inside 'MemCompression' where the compressed buffer starts.
- len_compressed -- int: optional length of the compressed buffer (leave out for auto-detect).
- return -- dict: containing decompressed data and size of compressed buffer.
-
- Example:
- VmmPy_WinDecompressPage(0x00000210bfb40000) --> {'c': 456, 'b': b'...'}
- """
- return VMMPYC_WinMemCompression_DecompressPage(va_compressed, len_compressed)
-
-
-
-#------------------------------------------------------------------------------
-# VmmPy UTIL FUNCTIONALITY BELOW:
-#------------------------------------------------------------------------------
-
-def VmmPy_UtilFillHexAscii(data_bytes, cb_initial_offset = 0):
- """Fill a human readable hex ascii memory dump string given a bytes object.
-
- Keyword arguments:
- data_bytes -- bytes: binary data to convert.
- cb_initial_offset -- int: offset, must be max 0x1000 and multiple of 0x10.
- return -- str: human readable dump-data.
- """
- return VMMPYC_UtilFillHexAscii(data_bytes, cb_initial_offset)
-
-
diff --git a/files/vmmpy_example.py b/files/vmmpy_example.py
deleted file mode 100644
index 3b9a775..0000000
--- a/files/vmmpy_example.py
+++ /dev/null
@@ -1,428 +0,0 @@
-# vmmpy_example.py
-#
-# Example showcase file displaying how it is possible to interface the Memory
-# Process File System / Virtual Memory Manager - VMM.DLL / VmmPy / VmmPyC with
-# user created python programs.
-#
-# Requirement: Memory Dump file from Windows 7 x64 or later with a logged in
-# user that have the process 'explorer.exe' running.
-#
-# To start example run:
-# from vmmpy_example import *
-# VmmPy_Example("")
-# where is the file name and path of a
-# Windows dump file of a 64-bit Windows operating system - Windows 7 or later.
-#
-# To start example how to conveniently parse the PE header structs by using
-# the dissect.cstruct library and VmmPy please run the example:
-# from vmmpy_example import *
-# VmmPy_Example_ParsePE()
-#
-# https://github.com/ufrisk/
-#
-# (c) Ulf Frisk, 2018
-# Author: Ulf Frisk, pcileech@frizk.net
-#
-
-from vmmpy import *
-from io import BytesIO
-from dissect import cstruct
-
-
-# Examples:
-#
-# VmmPy_Example("c:\\temp\\win10.raw")
-# VmmPy_Example_ParsePE("c:\\temp\\win10.raw")
-
-def VmmPy_Example(dump_file_name):
- print("--------------------------------------------------------------------")
- print("Welcome to the VmmPy Example showcase / test cases. This will demo ")
- print("how it is possible to use VmmPy to access memory dump files in a ")
- print("convenient way. Please ensure that the VmmPy requirements about the ")
- print("python version (such as Python 3.6) is met before starting ... ")
-
- # INIITALIZE
- print("--------------------------------------------------------------------")
- print("Initialize VmmPy with the dump file specified. ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_Initialize()")
- VmmPy_Initialize(["-device", dump_file_name])
- print("SUCCESS: VmmPy_Initialize()")
-
- # GET CONFIG
- print("--------------------------------------------------------------------")
- print("Retrieve configuration value for: VMMPY_OPT_CORE_MAX_NATIVE_ADDRESS.")
- input("Press Enter to continue...")
- print("CALL: VmmPy_ConfigGet()")
- result = VmmPy_ConfigGet(VMMPY_OPT_CORE_MAX_NATIVE_ADDRESS)
- print("SUCCESS: VmmPy_ConfigGet()")
- print(result)
-
- # SET CONFIG
- print("--------------------------------------------------------------------")
- print("Set configuration value for: VMMPY_OPT_CORE_PRINTF_ENABLE. ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_ConfigSet()")
- VmmPy_ConfigSet(VMMPY_OPT_CORE_PRINTF_ENABLE, 1)
- print("SUCCESS: VmmPy_ConfigSet()")
-
- # MEM READ
- print("--------------------------------------------------------------------")
- print("Read 0x100 bytes of memory from the physical address 0x1000 ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_MemRead()")
- result = VmmPy_MemRead(-1, 0x1000, 0x100)
- print("SUCCESS: VmmPy_MemRead()")
- print(result)
-
- # MEM READ + FillHexAscii
- print("--------------------------------------------------------------------")
- print("Read 0x100 bytes of memory from the physical address 0x1000 ")
- input("Press Enter to continue...")
- print("CALL: VMMPYC_UtilFillHexAscii(VmmPy_MemRead())")
- result = VmmPy_UtilFillHexAscii(VmmPy_MemRead(-1, 0x1000, 0x100))
- print("SUCCESS: VMMPYC_UtilFillHexAscii(VmmPy_MemRead())")
- print(result)
-
- # MEM READ SCATTER
- print("--------------------------------------------------------------------")
- print("Read 2 non-contigious (scatter) memory from the physical addresses: ")
- print("0x1000 and 0x3000. ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_MemReadScatter()")
- result = VmmPy_MemReadScatter(-1, [0x1000, 0x3000])
- print("SUCCESS: VmmPy_MemReadScatter()")
- print(result)
-
- # PID
- print("--------------------------------------------------------------------")
- print("Retrieve the process identifier pid for the process 'explorer.exe'. ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_PidGetFromName()")
- result = VmmPy_PidGetFromName("explorer.exe")
- print("SUCCESS: VmmPy_PidGetFromName()")
- print(result)
- pid = result
-
- # PIDs
- print("--------------------------------------------------------------------")
- print("List the process identifier pids of the processes in the system. ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_PidList()")
- result = VMMPYC_PidList()
- print("SUCCESS: VmmPy_PidList()")
- print(result)
-
- # PROCESS INFORMATION GET
- print("--------------------------------------------------------------------")
- print("Get the process information about the earlier explorer.exe process. ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_ProcessGetInformation()")
- result = VmmPy_ProcessGetInformation(pid)
- print("SUCCESS: VmmPy_ProcessGetInformation()")
- print(result)
-
- # PROCESS INFORMATION LIST
- print("--------------------------------------------------------------------")
- print("Get the process information for all process in a dict by pid. ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_ProcessListInformation()")
- result = VmmPy_ProcessListInformation()
- print("SUCCESS: VmmPy_ProcessListInformation()")
- print(result)
-
- # MODULE INFORMATION
- print("--------------------------------------------------------------------")
- print("Get module information about the explorer.exe module in the process.")
- input("Press Enter to continue...")
- print("CALL: VmmPy_ProcessGetModuleFromName()")
- result = VmmPy_ProcessGetModuleFromName(pid, "explorer.exe")
- print("SUCCESS: VmmPy_ProcessGetModuleFromName()")
- print(result)
- va = result['va']
-
- # MEM MAP
- print("--------------------------------------------------------------------")
- print("Get the memory map of 'explorer.exe' by walking the page table. ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_ProcessGetMemoryMap()")
- result = VmmPy_ProcessGetMemoryMap(pid, True)
- print("SUCCESS: VmmPy_ProcessGetMemoryMap()")
- print(result)
-
- # MEM MAP ENTRY
- print("--------------------------------------------------------------------")
- print("Get the PE base of 'explorer.exe' in the 'explorer.exe' process. ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_ProcessGetMemoryMapEntry()")
- result = VmmPy_ProcessGetMemoryMapEntry(pid, va, True)
- print("SUCCESS: VmmPy_ProcessGetMemoryMapEntry()")
- print(result)
-
- # MEM VIRTUAL2PHYSICAL
- print("--------------------------------------------------------------------")
- print("Get physical address of the PE virtual address of 'explorer.exe'. ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_MemVirt2Phys()")
- result = VmmPy_MemVirt2Phys(pid, va)
- print("SUCCESS: VmmPy_MemVirt2Phys()")
- print(result)
-
- # MEM READ
- print("--------------------------------------------------------------------")
- print("Read 0x100 bytes of memory from 'explorer.exe' PE base. ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_MemRead()")
- result = VmmPy_UtilFillHexAscii(VmmPy_MemRead(pid, va, 0x100))
- print("SUCCESS: VmmPy_MemRead()")
- print(result)
-
- # PE EAT
- print("--------------------------------------------------------------------")
- print("Get the Export Address Table given 'explorer.exe'/'kernel32.dll' ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_ProcessGetEAT()")
- result = VmmPy_ProcessGetEAT(pid, "kernel32.dll")
- print("SUCCESS: VmmPy_ProcessGetEAT()")
- print(result)
-
- # PE IAT
- print("--------------------------------------------------------------------")
- print("Get the Import Address Table given 'explorer.exe'/'kernel32.dll' ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_ProcessGetIAT()")
- result = VmmPy_ProcessGetIAT(pid, "kernel32.dll")
- print("SUCCESS: VmmPy_ProcessGetIAT()")
- print(result)
-
- # PE DATA DIRECTORIES
- print("--------------------------------------------------------------------")
- print("Get the PE Data Directories from 'explorer.exe'/'kernel32.dll' ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_ProcessGetDirectories()")
- result = VmmPy_ProcessGetDirectories(pid, "kernel32.dll")
- print("SUCCESS: VmmPy_ProcessGetDirectories()")
- print(result)
-
- # PE SECTIONS
- print("--------------------------------------------------------------------")
- print("Get the PE Data Directories from 'explorer.exe'/'kernel32.dll' ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_ProcessGetSections()")
- result = VmmPy_ProcessGetSections(pid, "kernel32.dll")
- print("SUCCESS: VmmPy_ProcessGetSections()")
- print(result)
-
- # VFS LIST /
- print("--------------------------------------------------------------------")
- print("Retrieve the file list of the virtual file system from the root path")
- input("Press Enter to continue...")
- print("CALL: VmmPy_VfsList()")
- result = VmmPy_VfsList('/')
- print("SUCCESS: VmmPy_VfsList()")
- print(result)
-
- # VFS LIST /name
- print("--------------------------------------------------------------------")
- print("Retrieve the file list of the virtual file system from the name path")
- input("Press Enter to continue...")
- print("CALL: VmmPy_VfsList()")
- result = VmmPy_VfsList('/name')
- print("SUCCESS: VmmPy_VfsList()")
- print(result)
-
- # VFS READ
- print("--------------------------------------------------------------------")
- print("Read from a file in the virtual file system (/pmem at offset 0x1000)")
- input("Press Enter to continue...")
- print("CALL: VmmPy_VfsRead()")
- result = VmmPy_UtilFillHexAscii(VmmPy_VfsRead('/pmem', 0x100, 0x1000))
- print("SUCCESS: VmmPy_VfsRead()")
- print(result)
-
-
-
-PE_STRUCT_DEFINITIONS = """
- #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
- #define IMAGE_SIZEOF_SHORT_NAME 8
- typedef struct _IMAGE_DOS_HEADER
- {
- WORD e_magic;
- WORD e_cblp;
- WORD e_cp;
- WORD e_crlc;
- WORD e_cparhdr;
- WORD e_minalloc;
- WORD e_maxalloc;
- WORD e_ss;
- WORD e_sp;
- WORD e_csum;
- WORD e_ip;
- WORD e_cs;
- WORD e_lfarlc;
- WORD e_ovno;
- WORD e_res[4];
- WORD e_oemid;
- WORD e_oeminfo;
- WORD e_res2[10];
- LONG e_lfanew;
- } IMAGE_DOS_HEADER;
- typedef struct _IMAGE_FILE_HEADER {
- WORD Machine;
- WORD NumberOfSections;
- DWORD TimeDateStamp;
- DWORD PointerToSymbolTable;
- DWORD NumberOfSymbols;
- WORD SizeOfOptionalHeader;
- WORD Characteristics;
- } IMAGE_FILE_HEADER;
- typedef struct _IMAGE_DATA_DIRECTORY {
- ULONG VirtualAddress;
- ULONG Size;
- } IMAGE_DATA_DIRECTORY;
- typedef struct _IMAGE_OPTIONAL_HEADER {
- WORD Magic;
- BYTE MajorLinkerVersion;
- BYTE MinorLinkerVersion;
- DWORD SizeOfCode;
- DWORD SizeOfInitializedData;
- DWORD SizeOfUninitializedData;
- DWORD AddressOfEntryPoint;
- DWORD BaseOfCode;
- DWORD BaseOfData;
- DWORD ImageBase;
- DWORD SectionAlignment;
- DWORD FileAlignment;
- WORD MajorOperatingSystemVersion;
- WORD MinorOperatingSystemVersion;
- WORD MajorImageVersion;
- WORD MinorImageVersion;
- WORD MajorSubsystemVersion;
- WORD MinorSubsystemVersion;
- DWORD Win32VersionValue;
- DWORD SizeOfImage;
- DWORD SizeOfHeaders;
- DWORD CheckSum;
- WORD Subsystem;
- WORD DllCharacteristics;
- DWORD SizeOfStackReserve;
- DWORD SizeOfStackCommit;
- DWORD SizeOfHeapReserve;
- DWORD SizeOfHeapCommit;
- DWORD LoaderFlags;
- DWORD NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
- } IMAGE_OPTIONAL_HEADER;
- typedef struct _IMAGE_OPTIONAL_HEADER64 {
- WORD Magic;
- BYTE MajorLinkerVersion;
- BYTE MinorLinkerVersion;
- DWORD SizeOfCode;
- DWORD SizeOfInitializedData;
- DWORD SizeOfUninitializedData;
- DWORD AddressOfEntryPoint;
- DWORD BaseOfCode;
- ULONGLONG ImageBase;
- DWORD SectionAlignment;
- DWORD FileAlignment;
- WORD MajorOperatingSystemVersion;
- WORD MinorOperatingSystemVersion;
- WORD MajorImageVersion;
- WORD MinorImageVersion;
- WORD MajorSubsystemVersion;
- WORD MinorSubsystemVersion;
- DWORD Win32VersionValue;
- DWORD SizeOfImage;
- DWORD SizeOfHeaders;
- DWORD CheckSum;
- WORD Subsystem;
- WORD DllCharacteristics;
- ULONGLONG SizeOfStackReserve;
- ULONGLONG SizeOfStackCommit;
- ULONGLONG SizeOfHeapReserve;
- ULONGLONG SizeOfHeapCommit;
- DWORD LoaderFlags;
- DWORD NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
- } IMAGE_OPTIONAL_HEADER64;
- typedef struct _IMAGE_SECTION_HEADER {
- char Name[IMAGE_SIZEOF_SHORT_NAME];
- ULONG VirtualSize;
- ULONG VirtualAddress;
- ULONG SizeOfRawData;
- ULONG PointerToRawData;
- ULONG PointerToRelocations;
- ULONG PointerToLinenumbers;
- USHORT NumberOfRelocations;
- USHORT NumberOfLinenumbers;
- ULONG Characteristics;
- } IMAGE_SECTION_HEADER;
-"""
-
-
-
-def VmmPy_Example_ParsePE(dump_file_name):
- # INIITALIZE
- print("--------------------------------------------------------------------")
- print("Initialize VmmPy with the dump file specified. ")
- input("Press Enter to continue...")
- print("CALL: VmmPy_InitializeFile()")
- VmmPy_InitializeFile(dump_file_name)
- print("SUCCESS: VmmPy_InitializeFile()")
-
- #
- # EXAMPLE BELOW USE THE FOX-IT DISSECT CSTRUCT PYTHON MODULE TO PARSE THE
- # THE PE HEADER OF 'ntdll.dll' in 'explorer.exe'
- #
- print("--------------------------------------------------------------------")
- print("Parse the PE header of 'explorer.exe'/'ntdll.dll' by using a VmmPy ")
- print("custom version of the dissect.cstruct parsing library from fox-it. ")
- print("dissect.cstruct: https://github.com/fox-it/dissect.cstruct ")
- input("Press Enter to continue...")
-
- # Call VmmPy to retrieve the actual 0x1000 page containing the PE header.
- print("CALL: VmmPy*")
- mz_pid = VmmPy_PidGetFromName('explorer.exe')
- mz_va = VmmPy_ProcessGetModuleFromName(mz_pid, "ntdll.dll")['va']
- mz_bytes = VmmPy_MemRead(mz_pid, mz_va, 0x1000)
- print("SUCCESS: VmmPy*")
-
- # Create a stream for convenience
- mz_stream = BytesIO(mz_bytes)
-
- # Set up dissect.cstruct
- print("INITIALIZING dissect.cstruct and parsing PE header structures ... ")
- pestruct = cstruct.cstruct()
- pestruct.load(PE_STRUCT_DEFINITIONS)
-
- # Load the MZ stream into dissect.struct. NB! loading mz_bytes will work as
- # well but will not be as convenient since the 'file pointer' won't move on
- # struct reads automatically...
- struct_mz = pestruct.IMAGE_DOS_HEADER(mz_stream)
- if struct_mz.e_magic != 0x5a4d:
- print("MZ HEADER DOES NOT MATCH - ABORTING")
- return
- print(struct_mz)
- print(cstruct.dumpstruct(struct_mz, None, 0, False, True))
-
- # Seek towards the PE signature / magic value and check that it is correct.
- mz_stream.seek(struct_mz.e_lfanew)
- signature = pestruct.uint32(mz_stream)
- if signature != 0x4550:
- print("PE HEADER DOES NOT MATCH")
- return
-
- # Parse and display the PE file_header struct.
- struct_file_header = pestruct.IMAGE_FILE_HEADER(mz_stream)
- print(struct_file_header)
- print(cstruct.dumpstruct(struct_file_header, None, 0, False, True))
-
- # Parse and display the PE struct_optional_header struct.
- struct_optional_header = pestruct.IMAGE_OPTIONAL_HEADER64(mz_stream) if struct_file_header.Machine == 0x8664 else pestruct.IMAGE_OPTIONAL_HEADER(mz_stream)
- print(struct_optional_header)
- print(cstruct.dumpstruct(struct_optional_header, None, 0, False, True))
-
- # Parse and display the PE sections.
- struct_sections = [pestruct.IMAGE_SECTION_HEADER(mz_stream) for _ in range(struct_file_header.NumberOfSections)]
- for struct_section in struct_sections:
- print(cstruct.dumpstruct(struct_section, None, 0, False, True))
diff --git a/files/vmmpyc.pyd b/files/vmmpyc.pyd
deleted file mode 100644
index 66638a8..0000000
Binary files a/files/vmmpyc.pyd and /dev/null differ
diff --git a/files/vmmpycplugin.dll b/files/vmmpycplugin.dll
deleted file mode 100644
index 036470e..0000000
Binary files a/files/vmmpycplugin.dll and /dev/null differ
diff --git a/files/vmmpyplugin.py b/files/vmmpyplugin.py
deleted file mode 100644
index 9473050..0000000
--- a/files/vmmpyplugin.py
+++ /dev/null
@@ -1,355 +0,0 @@
-# VmmPyPlugin.py
-#
-# Provides plugin related functionality to the memory process file system and
-# the virtual memory manager in VMM.DLL. Functionality mainly consists of DLL
-# and Python callback functionality allowing for integration between the file
-# system native code base and any python modules.
-#
-# The VmmPyPlugin is responsible for providing List, Read, Write and Close
-# functionality towards the file system as well as loading any python modules
-# from the plugin sub-directory matching './plugins/m_*.py'.
-#
-# General API callback functionality is provided by the vmmpy module that may
-# be used in plugins, but also in ordinary stand-alone python for convenient
-# and easy vmm integration.
-#
-# https://github.com/ufrisk/
-#
-# (c) Ulf Frisk, 2018
-# Author: Ulf Frisk, pcileech@frizk.net
-#
-
-from vmmpy import *
-from vmmpycc import *
-
-VmmPyPlugin_fPrint = False # print statements enable.
-VmmPyPlugin_fPrintV = False # verbose print statements enable.
-VmmPyPlugin_fPrintVV = False # extra verbose print statements enable.
-VmmPyPlugin_fPrintVVV = False # super verbose print statements enable.
-
-#------------------------------------------------------------------------------
-# VmmPy DIRECTORY LISTING AND CALLBACK FUNCTIONALITY BELOW:
-#------------------------------------------------------------------------------
-
-"""
-Each file/directory is put as a dict inside the dict with the file/directory
-name as the key. The dict is documented below. Please note that list and dirs
-are a directory only attributes, while size, read, write are file only
-attributes.
-dict_file_directory['name'] = {
- # directory only attributes below:
- 'list':
- 'dirs':
- # file only attributes below:
- 'size':
- 'write':
- 'read':
-}
-
-The dicts are: VmmPy_RootDirectoryRoot and VmmPy_RootDirectoryProcess.
-
-Please note that the VmmPy_RootDirectoryProcess dict is shared amongst all
-processes. If process independant file listings are required please use the
-'list' function callback to generate dynamic directory listings per-process.
-
-Please also note that even though the directory listings are shared amongst
-all processes it's still possible to differentiate on file contents via the
-'read' and 'write' callback functions.
-"""
-
-
-
-def VmmPyPlugin_InternalInitialize():
- """Internal Use Only! - initialization function.
- """
- if 'VmmPyPlugin_IsInitialized' in globals():
- return
- global VmmPyPlugin_IsInitialized
- global VmmPyPlugin_RootDirectoryRoot
- global VmmPyPlugin_RootDirectoryProcess
- global VmmPyPlugin_TargetSystem
- global VmmPyPlugin_TargetMemoryModel
- VmmPyPlugin_IsInitialized = True
- VmmPyPlugin_RootDirectoryRoot = {}
- VmmPyPlugin_RootDirectoryProcess = {}
- VmmPyPlugin_TargetSystem = VmmPy_ConfigGet(VMMPY_OPT_CORE_SYSTEM)
- VmmPyPlugin_TargetMemoryModel = VmmPy_ConfigGet(VMMPY_OPT_CORE_MEMORYMODEL)
- VmmPyPlugin_InternalSetVerbosity();
- VmmPyPlugin_InternalInitializePlugins()
- VMMPYCC_CallbackRegister(
- VmmPyPlugin_InternalCallback_List,
- VmmPyPlugin_InternalCallback_Read,
- VmmPyPlugin_InternalCallback_Write,
- VmmPyPlugin_InternalCallback_Notify,
- VmmPyPlugin_InternalCallback_Close)
-
-
-
-def VmmPyPlugin_InternalInitializePlugins():
- """Internal Use Only! - initialization function - Load Plugins.
- """
- import os
- import glob
- import importlib
- global VmmPyPlugin_PluginModules
- path = os.path.dirname(__file__) + '/'
- plugin_files = glob.glob(path + 'plugins/pym_*/pym_*.py', recursive=True)
- plugin_names = set()
- for f in plugin_files:
- f_split = f.replace(path, '').replace('\\', '/').split('/')
- plugin_names.add(f_split[0] + '.' + f_split[1])
- VmmPyPlugin_PluginModules = []
- for e in plugin_names:
- try:
- module = importlib.import_module(e)
- module.Initialize(VmmPyPlugin_TargetSystem, VmmPyPlugin_TargetMemoryModel)
- VmmPyPlugin_PluginModules.append(module)
- if VmmPyPlugin_fPrintV:
- print("VmmPyPlugin: Loaded '" + e + "'")
- except Exception as e2:
- if VmmPyPlugin_fPrintV:
- print("VmmPyPlugin: Failed to load '" + e + "'")
- print("VmmPyPlugin_InternalInitializePlugins: Exception: " + str(e2))
-
-
-
-def VmmPyPlugin_InternalCallback_List(pid, path):
- """Internal Use Only!
- For a given path return list of dicts containing info for each entry.
-
- Keyword arguments:
- pid -- int: the pid (or None/False if root).
- path -- str: the path to retrieve.
- return -- list of dict containing the information.
- """
- try:
- dir_entry = VmmPyPlugin_RootDirectoryRoot if (pid == None or pid == False) else VmmPyPlugin_RootDirectoryProcess
- path_items = list(filter(None, path.split('/')))
- for e in path_items:
- if not e in dir_entry:
- return []
- if not 'list' in dir_entry[e]:
- return []
- if dir_entry[e]['list'] != None:
- dir_entry = dir_entry[e]['list'](pid, path)
- break
- else:
- dir_entry = dir_entry[e]['dirs']
- if dir_entry == None:
- return []
- result = []
- for k,v in dir_entry.items():
- result.append({'name': k,
- 'size': v['size'] if 'size' in v else 0,
- 'f_isdir': True if 'dirs' in v else False
- })
- return result
- except Exception as e:
- if VmmPyPlugin_fPrintV:
- print("VmmPyPlugin_InternalCallback_List: Exception: " + str(e))
- return []
-
-
-
-def VmmPyPlugin_InternalCallback_Read(pid, path, bytes_length, bytes_offset):
- """Internal Use Only!
- Read bytes from a given path/file.
-
- Keyword arguments:
- pid -- int: process identifier (PID), None/False for root.
- path -- str: the path/file to read.
- bytes_length -- int: number of bytes to read.
- bytes_offset -- int: offset of bytes to read.
- return -- bytes: the data read.
- """
- try:
- file_name, file_attr = VmmPyPlugin_FileRetrieve(pid, path)
- if file_attr['read'] == None:
- return b''
- if bytes_offset >= file_attr['size']:
- return b''
- if bytes_length + bytes_offset > file_attr['size']:
- bytes_length = file_attr['size'] - bytes_offset
- return file_attr['read'](pid, file_name, file_attr, bytes_length, bytes_offset)
- except Exception as e:
- if VmmPyPlugin_fPrintV:
- print("VmmPyPlugin_InternalCallback_Read: Exception: " + str(e))
- return None
-
-
-
-def VmmPyPlugin_InternalCallback_Write(pid, path, bytes_data, bytes_offset):
- """Internal Use Only!
- Write bytes to a given path/file.
-
- Keyword arguments:
- pid -- int: process identifier (PID), None/False for root.
- path -- str: the path/file to write.
- bytes_data -- bytes: the bytes to write.
- bytes_offset -- int: offset of bytes to write.
- return -- int: VMMPY_STATUS (NTSTATUS) value of the write operation.
- """
- try:
- file_name, file_attr = VmmPyPlugin_FileRetrieve(pid, path)
- bytes_length = len(bytes_data)
- if file_attr['write'] == None:
- return VMMPY_STATUS_END_OF_FILE
- if bytes_offset >= file_attr['size']:
- return VMMPY_STATUS_END_OF_FILE
- if bytes_length + bytes_offset > file_attr['size']:
- bytes_length = file_attr['size'] - bytes_offset
- return file_attr['write'](pid, file_name, file_attr, bytes_data, bytes_offset)
- except Exception as e:
- if VmmPyPlugin_fPrintV:
- print("VmmPyPlugin_InternalCallback_Write: Exception: " + str(e))
- return VMMPY_STATUS_FILE_INVALID
-
-
-
-def VmmPyPlugin_InternalSetVerbosity():
- """Internal Use Only!
- Set verbosity level variables
- """
- try:
- global VmmPyPlugin_fPrint, VmmPyPlugin_fPrintV, VmmPyPlugin_fPrintVV, VmmPyPlugin_fPrintVVV
- VmmPyPlugin_fPrint = VmmPy_ConfigGet(VMMPY_OPT_CORE_PRINTF_ENABLE) > 0
- VmmPyPlugin_fPrintV = VmmPyPlugin_fPrint and VmmPy_ConfigGet(VMMPY_OPT_CORE_VERBOSE) > 0
- VmmPyPlugin_fPrintVV = VmmPyPlugin_fPrint and VmmPy_ConfigGet(VMMPY_OPT_CORE_VERBOSE_EXTRA) > 0
- VmmPyPlugin_fPrintVVV = VmmPyPlugin_fPrint and VmmPy_ConfigGet(VMMPY_OPT_CORE_VERBOSE_EXTRA_TLP) > 0
- except Exception as e:
- if VmmPyPlugin_fPrintV:
- print("VmmPyPlugin_InternalSetVerbosity: Exception: " + str(e))
-
-
-
-def VmmPyPlugin_InternalCallback_Notify(fEvent, bytesData):
- """Internal Use Only!
- Receive notify events from the native plugin manager.
-
- Keyword arguments:
- fEvent -- int: the event id as given by VMMPY_PLUGIN_EVENT_*
- bytesData -- bytes: any bytes object (or None) related to the event.
- """
- if fEvent == VMMPY_PLUGIN_EVENT_VERBOSITYCHANGE:
- VmmPyPlugin_InternalSetVerbosity()
-
-
-
-def VmmPyPlugin_InternalCallback_Close():
- """Internal Use Only!
- Callback when closing down python interpreter.
- """
- print("VmmPyPlugin_InternalCallback_Close")
- return 0
-
-
-
-def VmmPyPlugin_FileRegister(pid, path, size, fn_read_callback, fn_write_callback = None, is_overwrite = False):
- """Register a file in the file listing database.
- NB! Required directories are automatically created if possible.
-
- Keyword arguments:
- pid -- int: process identifier (PID), None/False for root.
- path -- str: the path including the file name to register.
- size -- the file size.
- fn_read_callback = callback function for read operation.
- fn_write_callback = callback function for write operation.
- is_overwrite -- overwrise allowed?
- """
- dir_entry = VmmPyPlugin_RootDirectoryRoot if (pid == None or pid == False) else VmmPyPlugin_RootDirectoryProcess
- path_items = list(filter(None, path.split('/')))
- file = path_items.pop()
- for path_item in path_items:
- if not path_item in dir_entry:
- dir_entry[path_item] = {'list': None, 'dirs': {}}
- if dir_entry[path_item]['list'] != None:
- raise RuntimeError('VmmPyPlugin_FileRegister: cannot add file entry to sub-directory with dynamic listing.')
- dir_entry = dir_entry[path_item]['dirs']
- if not is_overwrite and file in dir_entry:
- raise RuntimeError('VmmPyPlugin_FileRegister: cannot overwrite existing file without is_overwrite flag set.')
- dir_entry[file] = {'size': size, 'read': fn_read_callback, 'write': fn_write_callback}
-
-
-
-def VmmPyPlugin_FileRegisterDirectory(pid, path, fn_list_callback = None, is_overwrite = False):
- """Register a directory in the file listing database.
- NB! Required directories are automatically created if possible.
-
- Keyword arguments:
- pid -- int: process identifier (PID), None/False for root.
- path -- the path including the file name to register.
- fn_list_callback = callback function for dynamic directory listing.
- is_overwrite -- overwrise allowed?
- """
- dir_entry = VmmPyPlugin_RootDirectoryRoot if (pid == None or pid == False) else VmmPyPlugin_RootDirectoryProcess
- path_items = list(filter(None, path.split('/')))
- dir_to_reg = path_items.pop()
- for path_item in path_items:
- if not path_item in dir_entry:
- dir_entry[path_item] = {'list': None, 'dirs': {}}
- if dir_entry[path_item]['list'] != None:
- raise RuntimeError('VmmPyPlugin_FileRegisterDirectory: cannot add directory entry to sub-directory with dynamic listing.')
- dir_entry = dir_entry[path_item]['dirs']
- if not is_overwrite and dir_to_reg in dir_entry:
- raise RuntimeError('VmmPyPlugin_FileRegisterDirectory: cannot overwrite existing directory without is_overwrite flag set.')
- dir_entry[dir_to_reg] = {'list': fn_list_callback, 'dirs': {}}
-
-
-
-def VmmPyPlugin_FileUnregister(pid, path):
- """Unregister a directory or file from the file listing database.
-
- Keyword arguments:
- pid -- int: process identifier (PID), None/False for root.
- path -- str: the path including the file name to register.
- """
- dir_entry = VmmPyPlugin_RootDirectoryRoot if (pid == None or pid == False) else VmmPyPlugin_RootDirectoryProcess
- path_items = list(filter(None, path.split('/')))
- entry = path_items.pop()
- for path_item in path_items:
- if not path_item in dir_entry:
- raise RuntimeError('VmmPyPlugin_FileUnregister: cannot remove non-existant directory/file.')
- dir_entry = dir_entry[path_item]['dirs']
- if not entry in dir_entry:
- raise RuntimeError('VmmPyPlugin_FileUnregister: cannot remove non-existant directory/file.')
- del dir_entry[entry]
-
-
-
-def VmmPyPlugin_FileRetrieve(pid, path):
- """Retrieve a file from the file listing database.
-
- Keyword arguments:
- pid -- int: process identifier (PID), None/False for root.
- path -- str: the path including the file name to register.
- pid -- int: process identifier (optional) to be forwarded to any dynamic list functions.
- return -- tuple: .
- """
- dir_entry = VmmPyPlugin_RootDirectoryRoot if (pid == None or pid == False) else VmmPyPlugin_RootDirectoryProcess
- path_items = list(filter(None, path.split('/')))
- entry = path_items.pop()
- dir_path = '/'.join(path_items)
- for path_item in path_items:
- if not path_item in dir_entry:
- raise RuntimeError('VmmPyPlugin_FileRetrieve: not found.')
- if dir_entry[path_item]['list'] != None:
- dir_entry = dir_entry[path_item]['list'](pid, dir_path)
- break
- else:
- dir_entry = dir_entry[path_item]['dirs']
- if entry in dir_entry:
- return entry, dir_entry[entry]
- raise RuntimeError('VmmPyPlugin_FileRetrieve: not found.')
-
-
-
-#------------------------------------------------------------------------------
-# Initialize the VmmPyPlugin system and register it with the native code VMM.
-#------------------------------------------------------------------------------
-
-try:
- VmmPyPlugin_InternalInitialize()
-except Exception as e:
- print(str(e))
diff --git a/m_vmemd/leechcore.h b/m_vmemd/leechcore.h
deleted file mode 100644
index a2da3e6..0000000
--- a/m_vmemd/leechcore.h
+++ /dev/null
@@ -1,466 +0,0 @@
-// leechcore.h : header file for the leechcore module - which purpose is to
-// expose low-level device physical memory functionality.
-//
-// This library is thread-safe in all functions with the notable exceptions of
-// the LeechCore_Open() and LeechCore_Close() functions. Some devices may allow
-// multi-threaded access while in reality most devices are single-threaded and
-// will control synchronization where necessary with locks.
-//
-// The library is initialized by calling LeechCore_Open with a LEECHCORE_CONFIG
-// struct containing the correct configuration paramters. Note that the version
-// and magic values must be set in addition to the szDevice configuration value
-// Also, it may be possible to optionally connect to a remote leechcore service
-// or instance over RPC by specifying a szRemote configuration value.
-//
-// ----------------------------------------------------------------------------
-//
-// Remote instance: szRemote configuration value. Connect to a remote leechcore
-// instance by specifying a configuration value in the szRemote parameter. If a
-// loaded already valid instance exists remotely this will be prioritized above
-// the value in szDevice. If the acquisition device is not yet loaded by the
-// remote instance the value in szDevice will be used. Normally, the connection
-// will take place as a mutually authenticated encrypted connection secured by
-// kerberos. If not possible or desirable the 'insecure' value may be specified
-// to disable authentication and security.
-// Syntax:
-// rpc://:: (port = optional, remote_spn = kerberos)
-// (SPN of remote service or 'insecure' )
-// Examples:
-// rpc://insecure:remotehost.example.com (connect insecure to remote host )
-// rpc://user@ad.domain.com:192.0.0.5 (connect secure to remote host )
-// rpc://insecure:127.0.0.0:6666 (connect insecure non-default port)
-//
-// ----------------------------------------------------------------------------
-//
-// Device to connect to: szDevice contains the device to capture memory from.
-// Supported memory acquisition devices are:
-// USB3380 : hardware, read/write, 32-bit (4GB) addressing only. Requires a
-// PCILeech flashed USB3380 device connected over USB and Google
-// Android WinUSB drivers to be installed. Download and install from:
-// http://developer.android.com/sdk/win-usb.html#download
-// Syntax:
-// USB3380
-// USB3380://USB2 (force USB2 connection speed)
-//
-// FPGA : hardware, read/write - requires a PCILeech FPGA flashed hardware
-// device as shown at: https://github.com/ufrisk/pcileech-fpga
-// Also requires the FTD3XX.DLL from ftdichip to be placed in the
-// same directory as the executable. Download from ftdichip at:
-// http://www.ftdichip.com/Drivers/D3XX/FTD3XXLibrary_v1.2.0.6.zip
-// Syntax:
-// FGPA
-// FPGA://[:[:]] (values are optional)
-//
-// SP605TCP : hardware, read/write - connect to a remote SP605 FPGA over the
-// network using the implementation created by @d_olex.
-// https://github.com/Cr4sh/s6_pcie_microblaze
-// Syntax:
-// SP605TCP://[:] (port is optional)
-//
-// RAWTCP : read/write - connect to a remote raw tcp device - such as HPE iLO
-// that have been patched to support DMA as per blog entry below:
-// https://www.synacktiv.com/posts/exploit/using-your-bmc-as-a-dma-device-plugging-pcileech-to-hpe-ilo-4.html
-// Syntax:
-// RAWTCP://[:] (port is optional)
-//
-// HvSavedState : read-only - connect to a Hyper-V saved state file. In order
-// to do so the .dll file 'vmsavedstatedumpprovider.dll' must be
-// placed in same directory as the executable file.
-//
-// PMEM : load the rekall winpmem driver into the kernel and connect to it
-// to acquire memory. The driver file 'winpmem_x64.sys' is found in
-// the Rekall directory after most recent version has been installed.
-// Copy 'winpmem_x64.sys' to the directory of leechcore.dll and run
-// executable as elevated admin using syntax below:
-// Syntax:
-// PMEM (use winpmem_x64.sys in directory of executable)
-// PMEM://
-//
-// TOTALMELTDOWN : read/write - requires a Windows 7 system vulnerable to the
-// "Total Meltdown" vulnerability - CVE-2018-1038.
-// Syntax:
-// TOTALMELTDOWN
-//
-// FILE : use dump file, either a raw linear memory dump or full crash dump.
-// Which format to use is auto-detected. If it looks like a full cash
-// dump that format will be used, otherwise it will be assumed that a
-// raw linear memory dump is to be used.
-// Syntax:
-// (no device-type prefix - just use the file name)
-// FILE://
-//
-// DumpIt : DumpIt is a "virtual" device. It's only possible to use the DumpIt
-// device if the main process containing LeechCore has been started
-// with DumpIt in LiveKD mode.
-// Example 1:
-// DumpIt.exe /LIVEKD /A MemProcFS.exe
-// Example 2:
-// DumpIt.exe /LIVEKD /A LeechSvc.exe /C "interactive insecure"
-// and then connect to remote service by:
-// MemProcFS.exe -remote rpc://insecure:192.168.x.x -device DumpIt
-//
-// EXISTING : Attach to existing already loaded configuration. This is done
-// instead of the default behaviour of closing any existing devices
-// and initializing the new requested device. If no existing device
-// exists the call to LeechCore_Open will fail.
-// Syntax:
-// EXISTING
-//
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 1.0
-//
-#ifndef __LEECHCORE_H__
-#define __LEECHCORE_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// WINDOWS / LINUX COMPATIBILITY BELOW:
-//-----------------------------------------------------------------------------
-
-#ifdef _WIN32
-#include
-typedef unsigned __int64 QWORD, *PQWORD;
-#define DLLEXPORT __declspec(dllexport)
-#endif /* _WIN32 */
-#ifdef LINUX
-#include
-#include
-typedef void VOID, *PVOID, *LPVOID;
-typedef void *HANDLE, **PHANDLE;
-typedef uint32_t BOOL, *PBOOL;
-typedef uint8_t BYTE, *PBYTE;
-typedef char CHAR, *PCHAR, *PSTR, *LPSTR;
-typedef uint16_t WORD, *PWORD, USHORT, *PUSHORT;
-typedef uint32_t DWORD, *PDWORD;
-typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64;
-#define MAX_PATH 260
-#define DLLEXPORT __attribute__((visibility("default")))
-#define _In_
-#define _Out_
-#define _In_z_
-#define _Inout_
-#define _In_opt_
-#define _Out_opt_
-#define _Out_writes_(x)
-#define _Check_return_opt_
-#define _Printf_format_string_
-#define _Inout_updates_bytes_(x)
-#define _In_reads_(cbDataIn)
-#define _Success_(return)
-#endif /* LINUX */
-
-//-----------------------------------------------------------------------------
-// GENERAL HEADER DEFINES BELOW:
-//-----------------------------------------------------------------------------
-
-#define MEM_IO_SCATTER_HEADER_MAGIC 0xffff6548
-#define MEM_IO_SCATTER_HEADER_VERSION 0x0003
-
-typedef struct tdMEM_IO_SCATTER_HEADER {
- DWORD magic; // magic
- WORD version; // version
- WORD Future1;
- ULONG64 qwA; // base address.
- DWORD cbMax; // bytes to read (DWORD boundry, max 0x1000); pb must have room for this.
- DWORD cb; // bytes read into result buffer.
- PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
- PVOID pvReserved1; // reserved for use by caller.
- PVOID pvReserved2; // reserved for use by caller.
- PVOID Future2[8];
-} MEM_IO_SCATTER_HEADER, *PMEM_IO_SCATTER_HEADER, **PPMEM_IO_SCATTER_HEADER;
-
-//-----------------------------------------------------------------------------
-// LEECHCORE INITIALIZATION / CLOSE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-typedef enum tdLEECHCORE_DEVICE {
- LEECHCORE_DEVICE_NA = 0,
- LEECHCORE_DEVICE_FILE = 1,
- LEECHCORE_DEVICE_PMEM = 2,
- LEECHCORE_DEVICE_FPGA = 3,
- LEECHCORE_DEVICE_SP605_TCP = 4,
- LEECHCORE_DEVICE_USB3380 = 5,
- LEECHCORE_DEVICE_TOTALMELTDOWN = 6,
- LEECHCORE_DEVICE_HVSAVEDSTATE = 7,
- LEECHCORE_DEVICE_RAWTCP = 8,
-} LEECHCORE_DEVICE;
-
-#define LEECHCORE_CONFIG_MAGIC 0xffff6549
-#define LEECHCORE_CONFIG_VERSION 0x0001
-
-#define LEECHCORE_CONFIG_FLAG_PRINTF 0x0001
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_1 0x0002
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_2 0x0004
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_3 0x0008
-#define LEECHCORE_CONFIG_FLAG_REMOTE_NO_COMPRESS 0x0010
-
-typedef struct tdLEECHCORE_CONFIG {
- DWORD magic; // set by caller.
- WORD version; // set by caller.
- WORD flags; // set by caller, updated by device.
- ULONG64 paMax; // set by caller, updated by device.
- ULONG64 cbMaxSizeMemIo; // set by caller, updated by device.
- ULONG64 paMaxNative; // set by device.
- LEECHCORE_DEVICE tpDevice; // set by device.
- BOOL fWritable; // set by device. (is device writable?)
- BOOL fVolatile; // set by device. (is device volatile / memory may change?)
- BOOL fVolatileMaxAddress; // set by device. (is max address volatile? - poll changes with LEECHCORE_OPT_MEMORYINFO_ADDR_MAX)
- BOOL fRemote; // set by device.
- WORD VersionMajor; // set by device.
- WORD VersionMinor; // set by device.
- WORD VersionRevision; // set by device.
- CHAR szDevice[MAX_PATH]; // set by caller.
- CHAR szRemote[MAX_PATH]; // set by caller.
- // optional 'printf' function pointer. if set to non null value 'printf'
- // calls will be redirected. useful when logging to files.
- _Check_return_opt_ int(*pfn_printf_opt)(_In_z_ _Printf_format_string_ char const* const _Format, ...); // set by caller.
-} LEECHCORE_CONFIG, *PLEECHCORE_CONFIG;
-
-typedef struct tdLEECHCORE_PAGESTAT_MINIMAL {
- HANDLE h;
- VOID(*pfnPageStatUpdate)(HANDLE h, ULONG64 pa, ULONG64 cPageSuccessAdd, ULONG64 cPageFailAdd);
-} LEECHCORE_PAGESTAT_MINIMAL, *PLEECHCORE_PAGESTAT_MINIMAL;
-
-/*
-* Open a connection to the target device.
-* -- pInformation
-* -- result
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Open(_Inout_ PLEECHCORE_CONFIG pConfig);
-
-/*
-* Clean up various device related stuff and deallocate memory buffers.
-*/
-DLLEXPORT VOID LeechCore_Close();
-
-
-
-//-----------------------------------------------------------------------------
-// LEECHCORE CORE READ AND WRITE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_FLAG_READ_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_VERIFY 0x02
-
-/*
-* Allocate a scatter buffer containing empty 0x1000-sized ppMEMs with address
-* set to zero. Caller is responsible for calling LocalFree(ppMEMs).
-* -- cMEMs
-* -- pppMEMs = pointer to receive ppMEMs on success.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_AllocScatterEmpty(_In_ DWORD cMEMs, _Out_ PPMEM_IO_SCATTER_HEADER *pppMEMs);
-
-/*
-* Read memory in various non-contigious locations specified by the items in the
-* phDMAs array. Result for each unit of work will be given individually. No upper
-* limit of number of items to read, but no performance boost will be given if
-* above hardware limit. Max size of each unit of work is one 4k page (4096 bytes).
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-*/
-DLLEXPORT VOID LeechCore_ReadScatter(_Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_Read(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_READ_RETRY
-* -- pPageStat = optional minimal statistic struct to update.
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_ReadEx(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb, _In_ DWORD flags, _In_opt_ PLEECHCORE_PAGESTAT_MINIMAL pPageStat);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Write(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_WRITE_*
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_WriteEx(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD flags);
-
-/*
-* Probe the memory of the target system to check whether it's readable or not.
-* Please note that not all devices support this natively.
-* -- pa = address to start probe from.
-* -- cPages = number of 4kB pages to probe.
-* -- pbResultMap = result map, 1 byte represents 1 page, 0 = fail, 1 = success.
-* (individual page elements in pbResultMap must be set to 0 [fail] on call
-* for probe to take place on individual page).
-* -- return = FALSE if not supported by underlying hardware, TRUE if supported.
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Probe(_In_ QWORD pa, _In_ DWORD cPages, _Inout_updates_bytes_(cPages) PBYTE pbResultMap);
-
-
-
-//-----------------------------------------------------------------------------
-// GET/SET DEVICE OPTIONS BELOW. SOME OPTIONS ARE GENERAL LEECHCORE OPTIONS
-// WHILE OTHER ARE DEVICE SPECIFIC. USE FUNCTIONS:
-// LeechCore_GetOption() AND LeechCore_GetOption() TO GET/SET OPTIONS.
-// FOR DEVICE-SPECIFIC OPTIONS PLEASE SEE INDIVIDUAL DEVICE FILES FOR MORE
-// DETAILED INFORMATION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE 0x80000002 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-
-#define LEECHCORE_OPT_CORE_VERSION_MAJOR 0x01000001 // R
-#define LEECHCORE_OPT_CORE_VERSION_MINOR 0x01000002 // R
-#define LEECHCORE_OPT_CORE_VERSION_REVISION 0x01000003 // R
-
-#define LEECHCORE_OPT_MEMORYINFO_VALID 0x02000001 // R
-#define LEECHCORE_OPT_MEMORYINFO_ADDR_MAX 0x02000002 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_32BIT 0x02000003 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_PAE 0x02000004 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MINOR 0x02000005 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MAJOR 0x02000006 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_DTB 0x02000007 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PFN 0x02000008 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsLoadedModuleList 0x02000009 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsActiveProcessHead 0x0200000a // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_MACHINE_IMAGE_TP 0x0200000b // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_NUM_PROCESSORS 0x0200000c // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_SYSTEMTIME 0x0200000d // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_UPTIME 0x0200000e // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELBASE 0x0200000f // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELHINT 0x02000010 // R
-
-#define LEECHCORE_OPT_FPGA_PROBE_MAXPAGES 0x03000001 // RW
-#define LEECHCORE_OPT_FPGA_RX_FLUSH_LIMIT 0x03000002 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_RX 0x03000003 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_TX 0x03000004 // RW
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_READ 0x03000005 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_WRITE 0x03000006 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_WRITE 0x03000007 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_READ 0x03000008 // RW - uS
-#define LEECHCORE_OPT_FPGA_RETRY_ON_ERROR 0x03000009 // RW
-#define LEECHCORE_OPT_FPGA_DEVICE_ID 0x03000080 // R
-#define LEECHCORE_OPT_FPGA_FPGA_ID 0x03000081 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MAJOR 0x03000082 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MINOR 0x03000083 // R
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- pqwValue = pointer to QWORD to receive option value.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_GetOption(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- qwValue
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_SetOption(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// TRANSFER DEVICE DEPENDANT COMMANDS OR DATA TO/FROM UNDERLYING DEVICES AND
-// PERFORM ACTIONS USING THE LeechCore_CommandData() FUNCTION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_COMMANDDATA_FPGA_WRITE_TLP 0x00000101 // R
-#define LEECHCORE_COMMANDDATA_FPGA_LISTEN_TLP 0x00000102 // R
-#define LEECHCORE_COMMANDDATA_STATISTICS_GET 0x80000100 // R
-
-#define LEECHCORE_STATISTICS_MAGIC 0xffff6550
-#define LEECHCORE_STATISTICS_VERSION 0x0001
-#define LEECHCORE_STATISTICS_ID_OPEN 0x00
-#define LEECHCORE_STATISTICS_ID_READSCATTER 0x01
-#define LEECHCORE_STATISTICS_ID_WRITE 0x02
-#define LEECHCORE_STATISTICS_ID_PROBE 0x03
-#define LEECHCORE_STATISTICS_ID_GETOPTION 0x04
-#define LEECHCORE_STATISTICS_ID_SETOPTION 0x05
-#define LEECHCORE_STATISTICS_ID_COMMANDDATA 0x06
-#define LEECHCORE_STATISTICS_ID_MAX 0x06
-
-static const LPSTR LEECHCORE_STATISTICS_NAME[] = {
- "LeechCore_Open",
- "LeechCore_ReadScatter",
- "LeechCore_Write",
- "LeechCore_Probe",
- "LeechCore_GetOption",
- "LeechCore_SetOption",
- "LeechCore_CommandData"
-};
-
-typedef struct tdLEECHCORE_STATISTICS {
- DWORD magic;
- WORD version;
- WORD Reserved0;
- DWORD Reserved1;
- QWORD qwFreq;
- struct {
- QWORD c;
- QWORD tm; // total time in qwFreq ticks
- } Call[0x10];
-} LEECHCORE_STATISTICS, *PLEECHCORE_STATISTICS;
-
-/*
-* Transfer device dependant commands/data to/from the underlying device and
-* perform device dependant actions.
-* -- fOption
-* -- cbDataIn
-* -- pbDataIn
-* -- pbDataOut
-* -- cbDataOut
-* -- pcbDataOut
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_CommandData(
- _In_ ULONG64 fOption,
- _In_reads_(cbDataIn) PBYTE pbDataIn,
- _In_ DWORD cbDataIn,
- _Out_writes_(cbDataOut) PBYTE pbDataOut,
- _In_ DWORD cbDataOut,
- _Out_ PDWORD pcbDataOut
-);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __LEECHCORE_H__ */
diff --git a/m_vmemd/m_vmemd.c b/m_vmemd/m_vmemd.c
deleted file mode 100644
index 8ded336..0000000
--- a/m_vmemd/m_vmemd.c
+++ /dev/null
@@ -1,151 +0,0 @@
-// m_vmemd.h : implementation related to the vmemd native plugin module for the
-// memory process file system.
-//
-// (c) Ulf Frisk, 2018
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include
-#include
-#include "vmmdll.h"
-
-VMMDLL_MEMORYMODEL_TP g_VMemD_TpMemoryModel = VMMDLL_MEMORYMODEL_NA;
-
-ULONG64 VMemD_GetBaseFromFileName(LPSTR sz)
-{
- if((strlen(sz) < 15) || (sz[0] != '0') || (sz[1] != 'x')) { return (ULONG64)-1; }
- return strtoull(sz, NULL, 16);
-}
-
-/*
-* Read : function as specified by the module manager. The module manager will
-* call into this callback function whenever a read shall occur from a "file".
-* -- ctx
-* -- pb
-* -- cb
-* -- pcbRead
-* -- cbOffset
-* -- return
-*/
-NTSTATUS VMemD_Read(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset)
-{
- BOOL result;
- ULONG64 cbMax, vaBase;
- VMMDLL_MEMMAP_ENTRY entry;
- // read memory from "vmemd" directory file
- vaBase = VMemD_GetBaseFromFileName(ctx->szPath);
- if(vaBase & 0xfff) { return VMMDLL_STATUS_FILE_INVALID; }
- result = VMMDLL_ProcessGetMemoryMapEntry(ctx->dwPID, &entry, vaBase, FALSE);
- if(!result) { return VMMDLL_STATUS_FILE_INVALID; }
- *pcbRead = 0;
- if(entry.AddrBase + (entry.cPages << 12) <= vaBase + cbOffset) { return VMMDLL_STATUS_END_OF_FILE; }
- cbMax = min((entry.AddrBase + (entry.cPages << 12)), (vaBase + cb + cbOffset)) - (vaBase - cbOffset); // min(entry_top_addr, request_top_addr) - request_start_addr
- result = VMMDLL_MemReadEx(ctx->dwPID, vaBase + cbOffset, pb, (DWORD)min(cb, cbMax), pcbRead, 0);
- return (result && *pcbRead) ? VMMDLL_STATUS_SUCCESS : VMMDLL_STATUS_END_OF_FILE;
-}
-
-/*
-* Write : function as specified by the module manager. The module manager will
-* call into this callback function whenever a write shall occur from a "file".
-* -- ctx
-* -- pb
-* -- cb
-* -- pcbWrite
-* -- cbOffset
-* -- return
-*/
-NTSTATUS VMemD_Write(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset)
-{
- BOOL result;
- ULONG64 cbMax, vaBase;
- VMMDLL_MEMMAP_ENTRY entry;
- // write memory from "vmemd" directory file
- vaBase = VMemD_GetBaseFromFileName(ctx->szPath);
- if(vaBase & 0xfff) { return VMMDLL_STATUS_FILE_INVALID; }
- result = VMMDLL_ProcessGetMemoryMapEntry(ctx->dwPID, &entry, vaBase, FALSE);
- if(!result) { return VMMDLL_STATUS_FILE_INVALID; }
- *pcbWrite = 0;
- if(entry.AddrBase + (entry.cPages << 12) <= vaBase + cbOffset) { return VMMDLL_STATUS_END_OF_FILE; }
- cbMax = min((entry.AddrBase + (entry.cPages << 12)), (vaBase + cb + cbOffset)) - (vaBase - cbOffset); // min(entry_top_addr, request_top_addr) - request_start_addr
- VMMDLL_MemWrite(ctx->dwPID, vaBase + cbOffset, pb, (DWORD)min(cb, cbMax));
- *pcbWrite = cb;
- return VMMDLL_STATUS_SUCCESS;
-}
-
-/*
-* List : function as specified by the module manager. The module manager will
-* call into this callback function whenever a list directory shall occur from
-* the given module.
-* -- ctx
-* -- pFileList
-* -- return
-*/
-BOOL VMemD_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
-{
- BOOL result;
- DWORD i;
- ULONG64 cEntries = 0;
- CHAR szBufferFileName[MAX_PATH];
- PVMMDLL_MEMMAP_ENTRY pMemMap;
- if(ctx->szPath[0]) {
- // only list in module root directory.
- // not root directory == error for this module.
- return FALSE;
- }
- // populate memory map directory
- result = VMMDLL_ProcessGetMemoryMap(ctx->dwPID, NULL, &cEntries, FALSE);
- if(!result) { return FALSE; }
- pMemMap = (PVMMDLL_MEMMAP_ENTRY)LocalAlloc(0, cEntries * sizeof(VMMDLL_MEMMAP_ENTRY));
- if(!pMemMap) { return FALSE; }
- result = VMMDLL_ProcessGetMemoryMap(ctx->dwPID, pMemMap, &cEntries, TRUE);
- if(!result) {
- LocalFree(pMemMap);
- return FALSE;
- }
- for(i = 0; i < cEntries; i++) {
- if(g_VMemD_TpMemoryModel == VMMDLL_MEMORYMODEL_X64) {
- sprintf_s(
- szBufferFileName,
- MAX_PATH - 1,
- "0x%016llx%s%s.vmem",
- pMemMap[i].AddrBase,
- pMemMap[i].szTag[0] ? "-" : "",
- pMemMap[i].szTag[0] ? pMemMap[i].szTag : "");
- } else if((g_VMemD_TpMemoryModel == VMMDLL_MEMORYMODEL_X86) || (g_VMemD_TpMemoryModel == VMMDLL_MEMORYMODEL_X86PAE)) {
- sprintf_s(
- szBufferFileName,
- MAX_PATH - 1,
- "0x%08x%s%s.vmem",
- (DWORD)pMemMap[i].AddrBase,
- pMemMap[i].szTag[0] ? "-" : "",
- pMemMap[i].szTag[0] ? pMemMap[i].szTag : "");
- }
- VMMDLL_VfsList_AddFile(pFileList, szBufferFileName, (pMemMap[i].cPages << 12));
- }
- LocalFree(pMemMap);
- return TRUE;
-}
-
-/*
-* Initialization function for the vmemd native plugin module.
-* It's important that the function is exported in the DLL and that it is
-* declared exactly as below. The plugin manager will call into this function
-* after the DLL is loaded. The DLL then must fill the appropriate information
-* into the supplied struct and call the pfnPluginManager_Register function to
-* register itself with the plugin manager.
-* -- pRegInfo
-*/
-__declspec(dllexport)
-VOID InitializeVmmPlugin(_In_ PVMMDLL_PLUGIN_REGINFO pRegInfo)
-{
- if((pRegInfo->magic != VMMDLL_PLUGIN_REGINFO_MAGIC) || (pRegInfo->wVersion != VMMDLL_PLUGIN_REGINFO_VERSION)) { return; }
- // Ensure that the plugin support the memory model that is used. The plugin
- // currently supports the 64-bit x64 and 32-bit x86 and x86-pae memory models.
- if(!((pRegInfo->tpMemoryModel == VMMDLL_MEMORYMODEL_X64) || (pRegInfo->tpMemoryModel == VMMDLL_MEMORYMODEL_X86) || (pRegInfo->tpMemoryModel == VMMDLL_MEMORYMODEL_X86PAE))) { return; }
- g_VMemD_TpMemoryModel = pRegInfo->tpMemoryModel;
- strcpy_s(pRegInfo->reg_info.szModuleName, 32, "vmemd"); // module name - 'vmemd'.
- pRegInfo->reg_info.fProcessModule = TRUE; // module shows in process directory.
- pRegInfo->reg_fn.pfnList = VMemD_List; // List function supported.
- pRegInfo->reg_fn.pfnRead = VMemD_Read; // Read function supported.
- pRegInfo->reg_fn.pfnWrite = VMemD_Write; // Write function supported.
- pRegInfo->pfnPluginManager_Register(pRegInfo); // Register with the plugin maanger.
-}
diff --git a/m_vmemd/m_vmemd.rc b/m_vmemd/m_vmemd.rc
deleted file mode 100644
index c26a624..0000000
Binary files a/m_vmemd/m_vmemd.rc and /dev/null differ
diff --git a/m_vmemd/m_vmemd.vcxproj b/m_vmemd/m_vmemd.vcxproj
deleted file mode 100644
index e46787f..0000000
--- a/m_vmemd/m_vmemd.vcxproj
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- 15.0
- {BC6D11FF-3B1E-480E-A1AB-AAE5868FE9B3}
- mvmemd
- 10.0.17763.0
-
-
-
- DynamicLibrary
- true
- v141
- Unicode
- false
-
-
- DynamicLibrary
- false
- v141
- true
- Unicode
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(SolutionDir)\files\plugins\
- $(SolutionDir)\files\temp\$(ProjectName)\
-
-
- $(SolutionDir)\files\plugins\
- $(SolutionDir)\files\temp\$(ProjectName)\
-
-
-
- Level3
- Disabled
- true
- true
-
-
- $(SolutionDir)\files\vmm.lib;%(AdditionalDependencies)
- $(OutDir)\..\lib\$(TargetName).lib
- $(OutDir)\..\lib\$(TargetName).pdb
-
-
-
-
-
-
- copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y
-copy $(SolutionDir)\files\vmmdll.h $(ProjectDir)\ /y
-
-
-
-
- Level3
- MaxSpeed
- true
- true
- true
- true
- MultiThreadedDLL
-
-
- true
- true
- $(SolutionDir)\files\vmm.lib;%(AdditionalDependencies)
- $(OutDir)\..\lib\$(TargetName).lib
- UseLinkTimeCodeGeneration
- $(OutDir)\..\lib\$(TargetName).pdb
-
-
-
-
-
-
- copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y
-copy $(SolutionDir)\files\vmmdll.h $(ProjectDir)\ /y
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/m_vmemd/m_vmemd.vcxproj.filters b/m_vmemd/m_vmemd.vcxproj.filters
deleted file mode 100644
index 0d96ffa..0000000
--- a/m_vmemd/m_vmemd.vcxproj.filters
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
- {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
-
-
- {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
- rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
-
-
- {1d09101e-f5a9-4468-b8c7-9ed1f353cbf8}
-
-
-
-
- Source Files
-
-
-
-
- Header Files\vmm
-
-
- Header Files\vmm
-
-
- Header Files
-
-
-
-
- Resource Files
-
-
-
\ No newline at end of file
diff --git a/m_vmemd/m_vmemd.vcxproj.user b/m_vmemd/m_vmemd.vcxproj.user
deleted file mode 100644
index be25078..0000000
--- a/m_vmemd/m_vmemd.vcxproj.user
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/m_vmemd/version.h b/m_vmemd/version.h
deleted file mode 100644
index f44c61a..0000000
--- a/m_vmemd/version.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#define STRINGIZE2(s) #s
-#define STRINGIZE(s) STRINGIZE2(s)
-
-#define VERSION_MAJOR 2
-#define VERSION_MINOR 0
-#define VERSION_REVISION 0
-#define VERSION_BUILD 0
-
-#define VER_FILE_DESCRIPTION_STR "The Memory Process File System : Plugin vmemd"
-#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
-#define VER_FILE_VERSION_STR STRINGIZE(VERSION_MAJOR) \
- "." STRINGIZE(VERSION_MINOR) \
- "." STRINGIZE(VERSION_REVISION) \
- "." STRINGIZE(VERSION_BUILD) \
-
-#define VER_COMPANY_NAME_STR ""
-#define VER_PRODUCTNAME_STR "m_vmemd"
-#define VER_PRODUCT_VERSION VER_FILE_VERSION
-#define VER_PRODUCT_VERSION_STR VER_FILE_VERSION_STR
-#define VER_ORIGINAL_FILENAME_STR VER_PRODUCTNAME_STR ".dll"
-#define VER_INTERNAL_NAME_STR VER_ORIGINAL_FILENAME_STR
-#define VER_COPYRIGHT_STR "Copyright (c) Ulf Frisk 2018-2019"
diff --git a/m_vmemd/vmmdll.h b/m_vmemd/vmmdll.h
deleted file mode 100644
index 353159a..0000000
--- a/m_vmemd/vmmdll.h
+++ /dev/null
@@ -1,550 +0,0 @@
-// vmmdll.h : header file to include in projects that use vmm.dll either as
-// stand anlone projects or as native plugins to vmm.dll.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 2.0
-//
-
-#include
-#include "leechcore.h"
-
-#ifndef __VMMDLL_H__
-#define __VMMDLL_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// INITIALIZATION FUNCTIONALITY BELOW:
-// Choose one way of initialzing the VMM / Memory Process File System.
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize VMM.DLL with command line parameters. For a more detailed info
-* about the parameters please see github wiki for Memory Process File System
-* and LeechCore. THIS IS THE PREFERED WAY OF INITIALIZING VMM.DLL
-* Important parameters are:
-* -vdll = show printf style outputs)
-* -v -vv -vvv = extra verbosity levels)
-* -device = device as on format for LeechCore - please see leechcore.h or
-* Github documentation for additional information. Some values
-* are: , fpga, usb3380, hvsavedstate, totalmeltdown, pmem
-* -remote = remote LeechCore instance - please see leechcore.h or Github
-* documentation for additional information.
-* -- argc
-* -- argv
-* -- return = success/fail
-*/
-_Success_(return)
-BOOL VMMDLL_Initialize(_In_ DWORD argc, _In_ LPSTR argv[]);
-
-/*
-* Close an initialized instance of VMM.DLL and clean up all allocated resources
-* including plugins, linked PCILeech.DLL and other memory resources.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_Close();
-
-
-
-//-----------------------------------------------------------------------------
-// CONFIGURATION SETTINGS BELOW:
-// Configure the memory process file system or the underlying memory
-// acquisition devices.
-//-----------------------------------------------------------------------------
-
-/*
-* Options used together with the functions: VMMDLL_GetOption & VMMDLL_SetOption
-* Options are defined with either: VMMDLL_OPT_* in this header file or as
-* MEMDEVICE_OPT_* in memdevice.h
-* For more detailed information check the sources for individual device types.
-*/
-#define VMMDLL_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define VMMDLL_OPT_CORE_VERBOSE 0x80000002 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
-#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
-#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
-#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
-
-#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
-#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
-#define VMMDLL_OPT_CONFIG_READCACHE_TICKS 0x40000003 // RW - memory cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_TLBCACHE_TICKS 0x40000004 // RW - page table (tlb) cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_PARTIAL 0x40000005 // RW - process refresh (partial) period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_TOTAL 0x40000006 // RW - process refresh (full) period (in ticks)
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MAJOR 0x40000007 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MINOR 0x40000008 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
-#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
-
-static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
-
-typedef enum tdVMMDLL_MEMORYMODEL_TP {
- VMMDLL_MEMORYMODEL_NA = 0,
- VMMDLL_MEMORYMODEL_X86 = 1,
- VMMDLL_MEMORYMODEL_X86PAE = 2,
- VMMDLL_MEMORYMODEL_X64 = 3
-} VMMDLL_MEMORYMODEL_TP;
-
-typedef enum tdVMMDLL_SYSTEM_TP {
- VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
- VMMDLL_SYSTEM_WINDOWS_X64 = 2,
- VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
- VMMDLL_SYSTEM_WINDOWS_X86 = 4
-} VMMDLL_SYSTEM_TP;
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- pqwValue = pointer to ULONG64 to receive option value.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- qwValue
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// VFS - VIRTUAL FILE SYSTEM FUNCTIONALITY BELOW:
-// This is the core of the memory process file system. All implementation and
-// analysis towards the file system is possible by using functionality below.
-//-----------------------------------------------------------------------------
-
-#define VMMDLL_STATUS_SUCCESS ((NTSTATUS)0x00000000L)
-#define VMMDLL_STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
-#define VMMDLL_STATUS_END_OF_FILE ((NTSTATUS)0xC0000011L)
-#define VMMDLL_STATUS_FILE_INVALID ((NTSTATUS)0xC0000098L)
-#define VMMDLL_STATUS_FILE_SYSTEM_LIMITATION ((NTSTATUS)0xC0000427L)
-
-typedef struct tdVMMDLL_VFS_FILELIST {
- VOID(*pfnAddFile) (_Inout_ HANDLE h, _In_ LPSTR szName, _In_ ULONG64 cb, _In_ PVOID pvReserved);
- VOID(*pfnAddDirectory)(_Inout_ HANDLE h, _In_ LPSTR szName, _In_ PVOID pvReserved);
- HANDLE h;
-} VMMDLL_VFS_FILELIST, *PVMMDLL_VFS_FILELIST;
-
-/*
-* Helper function macros for callbacks into the VMM_VFS_FILELIST structure.
-*/
-#define VMMDLL_VfsList_AddFile(pFileList, szName, cb) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddFile(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, cb, NULL); }
-#define VMMDLL_VfsList_AddDirectory(pFileList, szName) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddDirectory(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, NULL); }
-
-/*
-* List a directory of files in the memory process file system. Directories and
-* files will be listed by callbacks into functions supplied in the pFileList
-* parameter. If information of an individual file is needed it's neccessary
-* to list all files in its directory.
-* -- wcsPath
-* -- pFileList
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
-
-/*
-* Read select parts of a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbRead
-* -- cbOffset
-* -- return
-*
-*/
-NTSTATUS VMMDLL_VfsRead(_In_ LPCWSTR wcsFileName, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-
-/*
-* Write select parts to a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbWrite
-* -- cbOffset
-* -- return
-*/
-NTSTATUS VMMDLL_VfsWrite(_In_ LPCWSTR wcsFileName, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-
-/*
-* Utility functions for memory process file system read/write towards different
-* underlying data representations.
-*/
-NTSTATUS VMMDLL_UtilVfsReadFile_FromPBYTE(_In_ PBYTE pbFile, _In_ ULONG64 cbFile, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromQWORD(_In_ ULONG64 qwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromDWORD(_In_ DWORD dwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromBOOL(_In_ BOOL fValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_BOOL(_Inout_ PBOOL pfTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset, _In_ DWORD dwMinAllow);
-
-
-//-----------------------------------------------------------------------------
-// PLUGIN MANAGER FUNCTIONALITY BELOW:
-// Function and structures to initialize and use the memory process file system
-// plugin functionality. The plugin manager is started by a call to function:
-// VMM_VfsInitializePlugins. Each built-in plugin and external plugin of which
-// the DLL name matches m_*.dll will receive a call to its InitializeVmmPlugin
-// function. The plugin/module may decide to call pfnPluginManager_Register to
-// register plugins in the form of different names one or more times.
-// Example of registration function in a plugin DLL below:
-// 'VOID InitializeVmmPlugin(_In_ PVMM_PLUGIN_REGINFO pRegInfo)'
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize all potential plugins, both built-in and external, that maps into
-* the memory process file system. Please note that plugins are not loaded by
-* default - they have to be explicitly loaded by calling this function. They
-* will be unloaded on a general close of the vmm dll.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsInitializePlugins();
-
-#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
-#define VMMDLL_PLUGIN_CONTEXT_VERSION 2
-#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
-#define VMMDLL_PLUGIN_REGINFO_VERSION 3
-
-#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
-
-typedef struct tdVMMDLL_PLUGIN_CONTEXT {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- DWORD dwPID;
- PVOID pProcess;
- LPSTR szModule;
- LPSTR szPath;
- PVOID pvReserved1;
- PVOID pvReserved2;
-} VMMDLL_PLUGIN_CONTEXT, *PVMMDLL_PLUGIN_CONTEXT;
-
-typedef struct tdVMMDLL_PLUGIN_REGINFO {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel;
- VMMDLL_SYSTEM_TP tpSystem;
- HMODULE hDLL;
- HMODULE hReservedDll; // not for general use (only used for python).
- BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
- PVOID pvReserved1;
- PVOID pvReserved2;
- // general plugin registration info to be filled out by the plugin below:
- struct {
- CHAR szModuleName[32];
- BOOL fRootModule;
- BOOL fProcessModule;
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_info;
- // function plugin registration info to be filled out by the plugin below:
- struct {
- BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
- NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
- NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
- VOID(*pfnNotify)(_In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
- VOID(*pfnClose)();
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_fn;
-} VMMDLL_PLUGIN_REGINFO, *PVMMDLL_PLUGIN_REGINFO;
-
-//-----------------------------------------------------------------------------
-// VMM CORE FUNCTIONALITY BELOW:
-// Vmm core functaionlity such as read (and write) to both virtual and physical
-// memory. NB! writing will only work if the target is supported - i.e. not a
-// memory dump file...
-// To read physical memory specify dwPID as (DWORD)-1
-//-----------------------------------------------------------------------------
-
-// FLAG used to supress the default read cache in calls to VMM_MemReadEx()
-// which will lead to the read being fetched from the target system always.
-// Cached page tables (used for translating virtual2physical) are still used.
-#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
-#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
-
-/*
-* Read memory in various non-contigious locations specified by the pointers to
-* the items in the ppDMAs array. Result for each unit of work will be given
-* individually. No upper limit of number of items to read, but no performance
-* boost will be given if above hardware limit. Max size of each unit of work is
-* one 4k page (4096 bytes).
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-* -- pcpDMAsRead = optional count of number of successfully read ppDMAs.
-* -- flags = optional flags as given by VMM_FLAG_*
-* -- return = the number of successfully read items.
-*/
-DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs, _In_ DWORD flags);
-
-/*
-* Read a single 4096-byte page of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pbPage
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
-
-/*
-* Read a contigious arbitrary amount of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Read a contigious amount of memory and report the number of bytes read in pcbRead.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- pcbRead
-* -- flags = flags as in VMM_FLAG_*
-* -- return = success/fail. NB! reads may report as success even if 0 bytes are
-* read - it's recommended to verify pcbReadOpt parameter.
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
-
-/*
-* Write a contigious arbitrary amount of memory. Please note some virtual memory
-* such as pages of executables (such as DLLs) may be shared between different
-* virtual memory over different processes. As an example a write to kernel32.dll
-* in one process is likely to affect kernel32 in the whole system - in all
-* processes. Heaps and Stacks and other memory are usually safe to write to.
-* Please take care when writing to memory!
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = TRUE on success, FALSE on partial or zero write.
-*/
-_Success_(return)
-BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Translate a virtual address to a physical address by walking the page tables
-* of the specified process.
-* -- dwPID
-* -- qwVA
-* -- pqwPA
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
-
-
-
-//-----------------------------------------------------------------------------
-// VMM PROCESS FUNCTIONALITY BELOW:
-// Functionality below is mostly relating to Windows processes.
-//-----------------------------------------------------------------------------
-
-/*
-* Retrieve an active process given it's name. Please note that if multiple
-* processes with the same name exists only one will be returned. If required to
-* parse all processes with the same name please iterate over the PID list by
-* calling VMMDLL_PidList together with VMMDLL_ProcessGetInformation.
-* -- szProcName = process name (truncated max 15 chars) case insensitive.
-* -- pdwPID = pointer that will receive PID on success.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
-
-/*
-* List the PIDs in the system.
-* -- pPIDs = DWORD array of at least number of PIDs in system, or NULL.
-* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
-
-// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
-#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
-#define VMMDLL_MEMMAP_FLAG_PAGE_NS 0x0000000000000004
-#define VMMDLL_MEMMAP_FLAG_PAGE_NX 0x8000000000000000
-#define VMMDLL_MEMMAP_FLAG_PAGE_MASK 0x8000000000000006
-
-typedef struct tdVMMDLL_MEMMAP_ENTRY {
- ULONG64 AddrBase;
- ULONG64 cPages;
- ULONG64 fPage;
- BOOL fWoW64;
- CHAR szTag[32];
-} VMMDLL_MEMMAP_ENTRY, *PVMMDLL_MEMMAP_ENTRY;
-
-/*
-* Retrieve memory map entries from the specified process. Memory map entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries bytes.
-* If the pMemMapEntries is set to NULL the number of memory map entries will be
-* given in the pcMemMapEntries parameter.
-* -- dwPID
-* -- pMemMapEntries = buffer of minimum length sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries, or NULL.
-* -- pcMemMapEntries = pointer to number of memory map entries.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
-
-/*
-* Retrieve a single memory map entry given a virtual address within that entrys
-* range.
-* -- dwPID
-* -- pMemMapEntry
-* -- va = virtual address in the memory map entry to retrieve.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
-
-typedef struct tdVMMDLL_MODULEMAP_ENTRY {
- ULONG64 BaseAddress;
- ULONG64 EntryPoint;
- DWORD SizeOfImage;
- BOOL fWoW64;
- CHAR szName[32];
-} VMMDLL_MODULEMAP_ENTRY, *PVMMDLL_MODULEMAP_ENTRY;
-
-/*
-* Retrieve the module entries from the specified process. The module entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries bytes long. If the
-* pcModuleEntries is set to NULL the number of module entries will be given
-* in the pcModuleEntries parameter.
-* -- dwPID
-* -- pModuleEntries = buffer of minimum length sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries, or NULL.
-* -- pcModuleEntries = pointer to number of memory map entries.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
-
-/*
-* Retrieve a module (.exe or .dll or similar) given a module name.
-* -- dwPID
-* -- szModuleName
-* -- pModuleEntry
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
-
-#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
-#define VMMDLL_PROCESS_INFORMATION_VERSION 2
-
-typedef struct tdVMMDLL_PROCESS_INFORMATION {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
- VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
- BOOL fUserOnly; // only user mode pages listed
- DWORD dwPID;
- DWORD dwState;
- CHAR szName[16];
- ULONG64 paDTB;
- ULONG64 paDTB_UserOpt; // may not exist
- union {
- struct {
- ULONG64 vaEPROCESS;
- ULONG64 vaPEB;
- ULONG64 vaENTRY;
- BOOL fWow64;
- DWORD vaPEB32; // WoW64 only
- } win;
- } os;
-} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
-
-/*
-* Retrieve various process information from a PID. Process information such as
-* name, page directory bases and the process state may be retrieved.
-* -- dwPID
-* -- pProcessInformation = if null, size is given in *pcbProcessInfo
-* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
-
-typedef struct tdVMMDLL_EAT_ENTRY {
- ULONG64 vaFunction;
- DWORD vaFunctionOffset;
- CHAR szFunction[40];
-} VMMDLL_EAT_ENTRY, *PVMMDLL_EAT_ENTRY;
-
-typedef struct tdVMMDLL_IAT_ENTRY {
- ULONG64 vaFunction;
- CHAR szFunction[40];
- CHAR szModule[64];
-} VMMDLL_IAT_ENTRY, *PVMMDLL_IAT_ENTRY;
-
-/*
-* Retrieve information about: Data Directories, Sections, Export Address Table
-* and Import Address Table (IAT).
-* If the pData == NULL upon entry the number of entries of the pData array must
-* have in order to be able to hold the data is returned.
-* -- dwPID
-* -- szModule
-* -- pData
-* -- cData
-* -- pcData
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-
-
-
-//-----------------------------------------------------------------------------
-// VMM UTIL FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-/*
-* Fill a human readable hex ascii memory dump into the caller supplied sz buffer.
-* -- pb
-* -- cb
-* -- cbInitialOffset = offset, must be max 0x1000 and multiple of 0x10.
-* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
-* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
-*/
-_Success_(return)
-BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __VMMDLL_H__ */
diff --git a/vmm/leechcore.h b/vmm/leechcore.h
deleted file mode 100644
index 46af16a..0000000
--- a/vmm/leechcore.h
+++ /dev/null
@@ -1,471 +0,0 @@
-// leechcore.h : header file for the leechcore module - which purpose is to
-// expose low-level device physical memory functionality.
-//
-// This library is thread-safe in all functions with the notable exceptions of
-// the LeechCore_Open() and LeechCore_Close() functions. Some devices may allow
-// multi-threaded access while in reality most devices are single-threaded and
-// will control synchronization where necessary with locks.
-//
-// The library is initialized by calling LeechCore_Open with a LEECHCORE_CONFIG
-// struct containing the correct configuration paramters. Note that the version
-// and magic values must be set in addition to the szDevice configuration value
-// Also, it may be possible to optionally connect to a remote leechcore service
-// or instance over RPC by specifying a szRemote configuration value.
-//
-// ----------------------------------------------------------------------------
-//
-// Remote instance: szRemote configuration value. Connect to a remote leechcore
-// instance by specifying a configuration value in the szRemote parameter. If a
-// loaded already valid instance exists remotely this will be prioritized above
-// the value in szDevice. If the acquisition device is not yet loaded by the
-// remote instance the value in szDevice will be used. Normally, the connection
-// will take place as a mutually authenticated encrypted connection secured by
-// kerberos. If not possible or desirable the 'insecure' value may be specified
-// to disable authentication and security.
-// Syntax:
-// rpc://:: (port = optional, remote_spn = kerberos)
-// (SPN of remote service or 'insecure' )
-// Examples:
-// rpc://insecure:remotehost.example.com (connect insecure to remote host )
-// rpc://user@ad.domain.com:192.0.0.5 (connect secure to remote host )
-// rpc://insecure:127.0.0.0:6666 (connect insecure non-default port)
-//
-// ----------------------------------------------------------------------------
-//
-// Device to connect to: szDevice contains the device to capture memory from.
-// Supported memory acquisition devices are:
-// USB3380 : hardware, read/write, 32-bit (4GB) addressing only. Requires a
-// PCILeech flashed USB3380 device connected over USB and Google
-// Android WinUSB drivers to be installed. Download and install from:
-// http://developer.android.com/sdk/win-usb.html#download
-// Syntax:
-// USB3380
-// USB3380://USB2 (force USB2 connection speed)
-//
-// FPGA : hardware, read/write - requires a PCILeech FPGA flashed hardware
-// device as shown at: https://github.com/ufrisk/pcileech-fpga
-// Also requires the FTD3XX.DLL from ftdichip to be placed in the
-// same directory as the executable. Download from ftdichip at:
-// http://www.ftdichip.com/Drivers/D3XX/FTD3XXLibrary_v1.2.0.6.zip
-// Syntax:
-// FGPA
-// FPGA://[:[:]] (values are optional)
-//
-// SP605TCP : hardware, read/write - connect to a remote SP605 FPGA over the
-// network using the implementation created by @d_olex.
-// https://github.com/Cr4sh/s6_pcie_microblaze
-// Syntax:
-// SP605TCP://[:] (port is optional)
-//
-// RAWTCP : read/write - connect to a remote raw tcp device - such as HPE iLO
-// that have been patched to support DMA as per blog entry below:
-// https://www.synacktiv.com/posts/exploit/using-your-bmc-as-a-dma-device-plugging-pcileech-to-hpe-ilo-4.html
-// Syntax:
-// RAWTCP://[:] (port is optional)
-//
-// HvSavedState : read-only - connect to a Hyper-V saved state file. In order
-// to do so the .dll file 'vmsavedstatedumpprovider.dll' must be
-// placed in same directory as the executable file.
-//
-// PMEM : load the rekall winpmem driver into the kernel and connect to it
-// to acquire memory. The signed driver `.sys` file may be found at:
-// https://github.com/Velocidex/c-aff4/tree/master/tools/pmem/resources/winpmem
-// Download the driver file `att_winpmem_64.sys` and copy it to the
-// directory of leechcore.dll and run executable as elevated admin
-// using syntax below:
-// Syntax:
-// PMEM (use att_winpmem_64.sys in directory of executable)
-// PMEM://
-//
-// TOTALMELTDOWN : read/write - requires a Windows 7 system vulnerable to the
-// "Total Meltdown" vulnerability - CVE-2018-1038.
-// Syntax:
-// TOTALMELTDOWN
-//
-// FILE : use dump file, either a raw linear memory dump or full crash dump.
-// Which format to use is auto-detected. If it looks like a full cash
-// dump that format will be used, otherwise it will be assumed that a
-// raw linear memory dump is to be used.
-// Syntax:
-// (no device-type prefix - just use the file name)
-// FILE://
-//
-// DumpIt : DumpIt is a "virtual" device. It's only possible to use the DumpIt
-// device if the main process containing LeechCore has been started
-// with DumpIt in LiveKD mode.
-// Example 1:
-// DumpIt.exe /LIVEKD /A MemProcFS.exe
-// Example 2:
-// DumpIt.exe /LIVEKD /A LeechSvc.exe /C "interactive insecure"
-// and then connect to remote service by:
-// MemProcFS.exe -remote rpc://insecure:192.168.x.x -device DumpIt
-//
-// EXISTING : Attach to existing already loaded configuration. This is done
-// instead of the default behaviour of closing any existing devices
-// and initializing the new requested device. If no existing device
-// exists the call to LeechCore_Open will fail.
-// Syntax:
-// EXISTING
-//
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 1.1.0
-//
-#ifndef __LEECHCORE_H__
-#define __LEECHCORE_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// WINDOWS / LINUX COMPATIBILITY BELOW:
-//-----------------------------------------------------------------------------
-
-#ifdef _WIN32
-#include
-typedef unsigned __int64 QWORD, *PQWORD;
-#define DLLEXPORT __declspec(dllexport)
-#endif /* _WIN32 */
-#ifdef LINUX
-#include
-#include
-typedef void VOID, *PVOID, *LPVOID;
-typedef void *HANDLE, **PHANDLE;
-typedef uint32_t BOOL, *PBOOL;
-typedef uint8_t BYTE, *PBYTE;
-typedef char CHAR, *PCHAR, *PSTR, *LPSTR;
-typedef uint16_t WORD, *PWORD, USHORT, *PUSHORT;
-typedef uint32_t DWORD, *PDWORD;
-typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64;
-#define MAX_PATH 260
-#define DLLEXPORT __attribute__((visibility("default")))
-#define _In_
-#define _Out_
-#define _In_z_
-#define _Inout_
-#define _In_opt_
-#define _Out_opt_
-#define _Out_writes_(x)
-#define _Check_return_opt_
-#define _Printf_format_string_
-#define _Inout_updates_bytes_(x)
-#define _In_reads_(cbDataIn)
-#define _Out_writes_opt_(x)
-#define _Success_(return)
-#endif /* LINUX */
-
-//-----------------------------------------------------------------------------
-// GENERAL HEADER DEFINES BELOW:
-//-----------------------------------------------------------------------------
-
-#define MEM_IO_SCATTER_HEADER_MAGIC 0xffff6548
-#define MEM_IO_SCATTER_HEADER_VERSION 0x0003
-
-typedef struct tdMEM_IO_SCATTER_HEADER {
- DWORD magic; // magic
- WORD version; // version
- WORD Future1;
- ULONG64 qwA; // base address.
- DWORD cbMax; // bytes to read (DWORD boundry, max 0x1000); pb must have room for this.
- DWORD cb; // bytes read into result buffer.
- PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
- PVOID pvReserved1; // reserved for use by caller.
- PVOID pvReserved2; // reserved for use by caller.
- PVOID Future2[8];
-} MEM_IO_SCATTER_HEADER, *PMEM_IO_SCATTER_HEADER, **PPMEM_IO_SCATTER_HEADER;
-
-//-----------------------------------------------------------------------------
-// LEECHCORE INITIALIZATION / CLOSE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-typedef enum tdLEECHCORE_DEVICE {
- LEECHCORE_DEVICE_NA = 0,
- LEECHCORE_DEVICE_FILE = 1,
- LEECHCORE_DEVICE_PMEM = 2,
- LEECHCORE_DEVICE_FPGA = 3,
- LEECHCORE_DEVICE_SP605_TCP = 4,
- LEECHCORE_DEVICE_USB3380 = 5,
- LEECHCORE_DEVICE_TOTALMELTDOWN = 6,
- LEECHCORE_DEVICE_HVSAVEDSTATE = 7,
- LEECHCORE_DEVICE_RAWTCP = 8,
-} LEECHCORE_DEVICE;
-
-#define LEECHCORE_CONFIG_MAGIC 0xffff6549
-#define LEECHCORE_CONFIG_VERSION 0x0001
-
-#define LEECHCORE_CONFIG_FLAG_PRINTF 0x0001
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_1 0x0002
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_2 0x0004
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_3 0x0008
-#define LEECHCORE_CONFIG_FLAG_REMOTE_NO_COMPRESS 0x0010
-
-typedef struct tdLEECHCORE_CONFIG {
- DWORD magic; // set by caller.
- WORD version; // set by caller.
- WORD flags; // set by caller, updated by device.
- ULONG64 paMax; // set by caller, updated by device.
- ULONG64 cbMaxSizeMemIo; // set by caller, updated by device.
- ULONG64 paMaxNative; // set by device.
- LEECHCORE_DEVICE tpDevice; // set by device.
- BOOL fWritable; // set by device. (is device writable?)
- BOOL fVolatile; // set by device. (is device volatile / memory may change?)
- BOOL fVolatileMaxAddress; // set by device. (is max address volatile? - poll changes with LEECHCORE_OPT_MEMORYINFO_ADDR_MAX)
- BOOL fRemote; // set by device.
- WORD VersionMajor; // set by device.
- WORD VersionMinor; // set by device.
- WORD VersionRevision; // set by device.
- CHAR szDevice[MAX_PATH]; // set by caller.
- CHAR szRemote[MAX_PATH]; // set by caller.
- // optional 'printf' function pointer. if set to non null value 'printf'
- // calls will be redirected. useful when logging to files.
- _Check_return_opt_ int(*pfn_printf_opt)(_In_z_ _Printf_format_string_ char const* const _Format, ...); // set by caller.
-} LEECHCORE_CONFIG, *PLEECHCORE_CONFIG;
-
-typedef struct tdLEECHCORE_PAGESTAT_MINIMAL {
- HANDLE h;
- VOID(*pfnPageStatUpdate)(HANDLE h, ULONG64 pa, ULONG64 cPageSuccessAdd, ULONG64 cPageFailAdd);
-} LEECHCORE_PAGESTAT_MINIMAL, *PLEECHCORE_PAGESTAT_MINIMAL;
-
-/*
-* Open a connection to the target device. The LeechCore initialization may fail
-* if the underlying device cannot be opened or if the LeechCore is already
-* initialized. If already initialized please connect with device EXISTING or
-* call LeechCore_Close() before opening a new device.
-* -- pInformation
-* -- result
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Open(_Inout_ PLEECHCORE_CONFIG pConfig);
-
-/*
-* Clean up various device related stuff and deallocate memory buffers.
-*/
-DLLEXPORT VOID LeechCore_Close();
-
-
-
-//-----------------------------------------------------------------------------
-// LEECHCORE CORE READ AND WRITE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_FLAG_READ_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_VERIFY 0x02
-
-/*
-* Allocate a scatter buffer containing empty 0x1000-sized ppMEMs with address
-* set to zero. Caller is responsible for calling LocalFree(ppMEMs).
-* -- cMEMs
-* -- pppMEMs = pointer to receive ppMEMs on success.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_AllocScatterEmpty(_In_ DWORD cMEMs, _Out_ PPMEM_IO_SCATTER_HEADER *pppMEMs);
-
-/*
-* Read memory in various non-contigious locations specified by the items in the
-* phDMAs array. Result for each unit of work will be given individually. No upper
-* limit of number of items to read, but no performance boost will be given if
-* above hardware limit. Max size of each unit of work is one 4k page (4096 bytes).
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-*/
-DLLEXPORT VOID LeechCore_ReadScatter(_Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_Read(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_READ_RETRY
-* -- pPageStat = optional minimal statistic struct to update.
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_ReadEx(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb, _In_ DWORD flags, _In_opt_ PLEECHCORE_PAGESTAT_MINIMAL pPageStat);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Write(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_WRITE_*
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_WriteEx(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD flags);
-
-/*
-* Probe the memory of the target system to check whether it's readable or not.
-* Please note that not all devices support this natively.
-* -- pa = address to start probe from.
-* -- cPages = number of 4kB pages to probe.
-* -- pbResultMap = result map, 1 byte represents 1 page, 0 = fail, 1 = success.
-* (individual page elements in pbResultMap must be set to 0 [fail] on call
-* for probe to take place on individual page).
-* -- return = FALSE if not supported by underlying hardware, TRUE if supported.
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Probe(_In_ QWORD pa, _In_ DWORD cPages, _Inout_updates_bytes_(cPages) PBYTE pbResultMap);
-
-
-
-//-----------------------------------------------------------------------------
-// GET/SET DEVICE OPTIONS BELOW. SOME OPTIONS ARE GENERAL LEECHCORE OPTIONS
-// WHILE OTHER ARE DEVICE SPECIFIC. USE FUNCTIONS:
-// LeechCore_GetOption() AND LeechCore_GetOption() TO GET/SET OPTIONS.
-// FOR DEVICE-SPECIFIC OPTIONS PLEASE SEE INDIVIDUAL DEVICE FILES FOR MORE
-// DETAILED INFORMATION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE 0x80000002 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-
-#define LEECHCORE_OPT_CORE_VERSION_MAJOR 0x01000001 // R
-#define LEECHCORE_OPT_CORE_VERSION_MINOR 0x01000002 // R
-#define LEECHCORE_OPT_CORE_VERSION_REVISION 0x01000003 // R
-
-#define LEECHCORE_OPT_MEMORYINFO_VALID 0x02000001 // R
-#define LEECHCORE_OPT_MEMORYINFO_ADDR_MAX 0x02000002 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_32BIT 0x02000003 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_PAE 0x02000004 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MINOR 0x02000005 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MAJOR 0x02000006 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_DTB 0x02000007 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PFN 0x02000008 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsLoadedModuleList 0x02000009 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsActiveProcessHead 0x0200000a // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_MACHINE_IMAGE_TP 0x0200000b // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_NUM_PROCESSORS 0x0200000c // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_SYSTEMTIME 0x0200000d // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_UPTIME 0x0200000e // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELBASE 0x0200000f // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELHINT 0x02000010 // R
-
-#define LEECHCORE_OPT_FPGA_PROBE_MAXPAGES 0x03000001 // RW
-#define LEECHCORE_OPT_FPGA_RX_FLUSH_LIMIT 0x03000002 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_RX 0x03000003 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_TX 0x03000004 // RW
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_READ 0x03000005 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_WRITE 0x03000006 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_WRITE 0x03000007 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_READ 0x03000008 // RW - uS
-#define LEECHCORE_OPT_FPGA_RETRY_ON_ERROR 0x03000009 // RW
-#define LEECHCORE_OPT_FPGA_DEVICE_ID 0x03000080 // R
-#define LEECHCORE_OPT_FPGA_FPGA_ID 0x03000081 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MAJOR 0x03000082 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MINOR 0x03000083 // R
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- pqwValue = pointer to QWORD to receive option value.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_GetOption(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- qwValue
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_SetOption(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// TRANSFER DEVICE DEPENDANT COMMANDS OR DATA TO/FROM UNDERLYING DEVICES AND
-// PERFORM ACTIONS USING THE LeechCore_CommandData() FUNCTION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_COMMANDDATA_FPGA_WRITE_TLP 0x00000101 // R
-#define LEECHCORE_COMMANDDATA_FPGA_LISTEN_TLP 0x00000102 // R
-#define LEECHCORE_COMMANDDATA_STATISTICS_GET 0x80000100 // R
-
-#define LEECHCORE_STATISTICS_MAGIC 0xffff6550
-#define LEECHCORE_STATISTICS_VERSION 0x0001
-#define LEECHCORE_STATISTICS_ID_OPEN 0x00
-#define LEECHCORE_STATISTICS_ID_READSCATTER 0x01
-#define LEECHCORE_STATISTICS_ID_WRITE 0x02
-#define LEECHCORE_STATISTICS_ID_PROBE 0x03
-#define LEECHCORE_STATISTICS_ID_GETOPTION 0x04
-#define LEECHCORE_STATISTICS_ID_SETOPTION 0x05
-#define LEECHCORE_STATISTICS_ID_COMMANDDATA 0x06
-#define LEECHCORE_STATISTICS_ID_MAX 0x06
-
-static const LPSTR LEECHCORE_STATISTICS_NAME[] = {
- "LeechCore_Open",
- "LeechCore_ReadScatter",
- "LeechCore_Write",
- "LeechCore_Probe",
- "LeechCore_GetOption",
- "LeechCore_SetOption",
- "LeechCore_CommandData"
-};
-
-typedef struct tdLEECHCORE_STATISTICS {
- DWORD magic;
- WORD version;
- WORD Reserved0;
- DWORD Reserved1;
- QWORD qwFreq;
- struct {
- QWORD c;
- QWORD tm; // total time in qwFreq ticks
- } Call[0x10];
-} LEECHCORE_STATISTICS, *PLEECHCORE_STATISTICS;
-
-/*
-* Transfer device dependant commands/data to/from the underlying device and
-* perform device dependant actions.
-* -- fOption
-* -- cbDataIn
-* -- pbDataIn
-* -- pbDataOut
-* -- cbDataOut
-* -- pcbDataOut
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_CommandData(
- _In_ ULONG64 fOption,
- _In_reads_(cbDataIn) PBYTE pbDataIn,
- _In_ DWORD cbDataIn,
- _Out_writes_opt_(cbDataOut) PBYTE pbDataOut,
- _In_ DWORD cbDataOut,
- _Out_opt_ PDWORD pcbDataOut
-);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __LEECHCORE_H__ */
diff --git a/vmm/m_ldrmodules.c b/vmm/m_ldrmodules.c
deleted file mode 100644
index 9e46e32..0000000
--- a/vmm/m_ldrmodules.c
+++ /dev/null
@@ -1,416 +0,0 @@
-// m_ldrmodules.c : implementation of the ldrmodules built-in module.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include "m_ldrmodules.h"
-#include "pluginmanager.h"
-#include "vmm.h"
-#include "vmmproc.h"
-#include "vmmwin.h"
-#include "vmmvfs.h"
-#include "util.h"
-#include "pe.h"
-
-#define LDRMODULES_CACHE_TP_EAT 1
-#define LDRMODULES_CACHE_TP_IAT 2
-#define LDRMODULES_NUM_CACHE 8
-typedef struct tdOBLDRMODULES_CACHE_ENTRY {
- VMMOB ObHdr;
- CHAR szDll[32];
- DWORD tp;
- DWORD cb;
- BYTE pb[];
-} OBLDRMODULES_CACHE_ENTRY, *POBLDRMODULES_CACHE_ENTRY;
-
-
-#define LDRMODULES_MAX_IATEAT 0x10000
-
-/*
-* Retrieve a OBLDRMODULES_CACHE_ENTRY object for the Export Address Table (EAT).
-* CALLER DECREF: return
-* -- ctx
-* -- pModule
-* -- return
-*/
-POBLDRMODULES_CACHE_ENTRY LdrModule_GetEAT(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ PVMM_MODULEMAP_ENTRY pModule)
-{
- DWORD i, o, cEATs = 0;
- PVMMPROC_WINDOWS_EAT_ENTRY pEATs = NULL;
- POBLDRMODULES_CACHE_ENTRY pObCacheEntry = NULL;
- PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
- // 1: retrieve cache
- pObCacheEntry = VmmObContainer_GetOb(&pProcess->Plugin.ObCLdrModulesDisplayCache);
- if(pObCacheEntry && (pObCacheEntry->tp == LDRMODULES_CACHE_TP_EAT) && !_strnicmp(pObCacheEntry->szDll, pModule->szName, 32)) {
- return pObCacheEntry;
- }
- VmmOb_DECREF(pObCacheEntry);
- pObCacheEntry = NULL;
- // 2: retrieve exported functions
- pEATs = LocalAlloc(0, LDRMODULES_MAX_IATEAT * sizeof(VMMPROC_WINDOWS_EAT_ENTRY));
- if(!pEATs) { goto fail; }
- VmmWin_PE_LoadEAT_DisplayBuffer(ctx->pProcess, pModule, pEATs, LDRMODULES_MAX_IATEAT, &cEATs);
- if(!cEATs) { goto fail; }
- // 3: fill "display buffer"
- pObCacheEntry = VmmOb_Alloc('EA', LMEM_ZEROINIT, sizeof(OBLDRMODULES_CACHE_ENTRY) + (QWORD)cEATs * 64 + 1, NULL, NULL);
- if(!pObCacheEntry) { goto fail; }
- pObCacheEntry->tp = LDRMODULES_CACHE_TP_EAT;
- pObCacheEntry->cb = cEATs * 64 + 1;
- memcpy(pObCacheEntry->szDll, pModule->szName, 32);
- for(i = 0, o = 0; i < cEATs; i++) {
- o += snprintf(
- pObCacheEntry->pb + o,
- pObCacheEntry->cb - o,
- "%04x %016llx %-40.40s \n", // 64 bytes (chars) / line (function)
- (WORD)i,
- pModule->BaseAddress + pEATs[i].vaFunctionOffset,
- pEATs[i].szFunction
- );
- }
- pObCacheEntry->cb = o;
- LocalFree(pEATs);
- VmmObContainer_SetOb(&pProcess->Plugin.ObCLdrModulesDisplayCache, pObCacheEntry);
- return pObCacheEntry;
-fail:
- VmmOb_DECREF(pObCacheEntry);
- LocalFree(pEATs);
- return NULL;
-}
-
-/*
-* Retrieve a OBLDRMODULES_CACHE_ENTRY object for the Import Address Table (IAT).
-* CALLER DECREF: return
-* -- ctx
-* -- pModule
-* -- return
-*/
-POBLDRMODULES_CACHE_ENTRY LdrModule_GetIAT(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ PVMM_MODULEMAP_ENTRY pModule)
-{
- DWORD i, o, cIATs = 0;
- PVMMWIN_IAT_ENTRY pIATs = NULL;
- POBLDRMODULES_CACHE_ENTRY pObCacheEntry = NULL;
- PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
- // 1: retrieve cache
- pObCacheEntry = VmmObContainer_GetOb(&pProcess->Plugin.ObCLdrModulesDisplayCache);
- if(pObCacheEntry && (pObCacheEntry->tp == LDRMODULES_CACHE_TP_IAT) && !_strnicmp(pObCacheEntry->szDll, pModule->szName, 32)) {
- return pObCacheEntry;
- }
- VmmOb_DECREF(pObCacheEntry);
- pObCacheEntry = NULL;
- // 2: retrieve exported functions
- pIATs = LocalAlloc(0, LDRMODULES_MAX_IATEAT * sizeof(VMMWIN_IAT_ENTRY));
- if(!pIATs) { goto fail; }
- VmmWin_PE_LoadIAT_DisplayBuffer(ctx->pProcess, pModule, pIATs, LDRMODULES_MAX_IATEAT, &cIATs);
- if(!cIATs) { goto fail; }
- // 3: fill "display buffer"
- pObCacheEntry = VmmOb_Alloc('IA', LMEM_ZEROINIT, sizeof(OBLDRMODULES_CACHE_ENTRY) + (QWORD)cIATs * 128 + 1, NULL, NULL);
- if(!pObCacheEntry) { goto fail; }
- pObCacheEntry->tp = LDRMODULES_CACHE_TP_IAT;
- pObCacheEntry->cb = cIATs * 128 + 1;
- memcpy(pObCacheEntry->szDll, pModule->szName, 32);
- for(i = 0, o = 0; i < cIATs; i++) {
- o += snprintf(
- pObCacheEntry->pb + o,
- pObCacheEntry->cb - o,
- "%04x %016llx %-40.40s %-64.64s\n", // 128 bytes (chars) / line (function)
- (WORD)i,
- pIATs[i].vaFunction,
- pIATs[i].szFunction,
- pIATs[i].szModule
- );
- }
- pObCacheEntry->cb = o;
- LocalFree(pIATs);
- VmmObContainer_SetOb(&pProcess->Plugin.ObCLdrModulesDisplayCache, pObCacheEntry);
- return pObCacheEntry;
-fail:
- VmmOb_DECREF(pObCacheEntry);
- LocalFree(pIATs);
- return NULL;
-}
-
-/*
-* Helper write function - Write to a virtual memory backed "file".
-*/
-VOID LdrModules_Write_MemFile(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaMem, _In_ QWORD cbMem, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset)
-{
- if(cbMem <= cbOffset) { *pcbWrite = 0; return; }
- *pcbWrite = (DWORD)min(cb, cbMem - cbOffset);
- VmmWrite(pProcess, vaMem + cbOffset, pb, *pcbWrite);
-}
-
-/*
-* Helper write function - Write to the requested data directory file.
-*/
-VOID LdrModules_Write_DirectoriesD(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _In_ LPSTR szDirectory, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset)
-{
- DWORD i;
- IMAGE_DATA_DIRECTORY pDataDirectories[16];
- *pcbWrite = 0;
- for(i = 0; i < 16; i++) {
- if(!strcmp(szDirectory, PE_DATA_DIRECTORIES[i])) {
- VmmWin_PE_DIRECTORY_DisplayBuffer(pProcess, pModule, NULL, 0, NULL, pDataDirectories);
- LdrModules_Write_MemFile(pProcess, pModule->BaseAddress + pDataDirectories[i].VirtualAddress, pDataDirectories[i].Size, pb, cb, pcbWrite, cbOffset);
- }
- }
-}
-
-/*
-* Helper write function - Write to the requested section header file.
-*/
-VOID LdrModules_Write_SectionsD(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _In_ LPSTR szSection, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset)
-{
- IMAGE_SECTION_HEADER SectionHeader;
- if(!PE_SectionGetFromName(pProcess, pModule->BaseAddress, szSection, &SectionHeader)) { *pcbWrite = 0; return; }
- LdrModules_Write_MemFile(pProcess, pModule->BaseAddress + SectionHeader.VirtualAddress, SectionHeader.Misc.VirtualSize, pb, cb, pcbWrite, cbOffset);
-}
-
-/*
-* Write : function as specified by the module manager. The module manager will
-* call into this callback function whenever a write shall occur from a "file".
-* -- ctx
-* -- pb
-* -- cb
-* -- pcbWrite
-* -- cbOffset
-* -- return
-*/
-NTSTATUS LdrModules_Write(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset)
-{
- DWORD i;
- CHAR _szBuf[MAX_PATH] = { 0 };
- LPSTR szPath1, szPath2;
- PVMMOB_MODULEMAP pObModuleMap = NULL;
- PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
- *pcbWrite = 0;
- Util_PathSplit2(ctx->szPath, _szBuf, &szPath1, &szPath2);
- if(szPath1[0] && szPath2[0] && VmmProc_ModuleMapGet(pProcess, &pObModuleMap)) {
- for(i = 0; i < pObModuleMap->cMap; i++) {
- if(0 == strncmp(szPath1, pObModuleMap->pMap[i].szName, MAX_PATH)) {
- if(!_strnicmp(szPath2, "sectionsd\\", 10)) {
- LdrModules_Write_SectionsD(pProcess, pObModuleMap->pMap + i, szPath2 + 10, pb, cb, pcbWrite, cbOffset);
- }
- if(!_strnicmp(szPath2, "directoriesd\\", 13)) {
- LdrModules_Write_DirectoriesD(pProcess, pObModuleMap->pMap + i, szPath2 + 13, pb, cb, pcbWrite, cbOffset);
- }
- break;
- }
- }
- VmmOb_DECREF(pObModuleMap);
- }
- return VMM_STATUS_SUCCESS;
-}
-
-/*
-* Helper read function - Read a virtual memory backed "file".
-*/
-NTSTATUS LdrModules_Read_MemFile(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaMem, _In_ QWORD cbMem, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset)
-{
- if(cbMem <= cbOffset) { return VMM_STATUS_END_OF_FILE; }
- VmmReadEx(pProcess, vaMem + cbOffset, pb, (DWORD)min(cb, cbMem - cbOffset), pcbRead, 0);
- return *pcbRead ? VMMDLL_STATUS_SUCCESS : VMMDLL_STATUS_END_OF_FILE;
-}
-
-/*
-* Helper read function - Read the requested data directory file.
-*/
-NTSTATUS LdrModules_Read_DirectoriesD(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _In_ LPSTR szDirectory, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
-{
- DWORD i;
- IMAGE_DATA_DIRECTORY pDataDirectories[16];
- for(i = 0; i < 16; i++) {
- if(!strcmp(szDirectory, PE_DATA_DIRECTORIES[i])) {
- VmmWin_PE_DIRECTORY_DisplayBuffer(pProcess, pModule, NULL, 0, NULL, pDataDirectories);
- return LdrModules_Read_MemFile(pProcess, pModule->BaseAddress + pDataDirectories[i].VirtualAddress, pDataDirectories[i].Size, pb, cb, pcbRead, cbOffset);
- }
- }
- return VMMDLL_STATUS_FILE_INVALID;
-}
-
-/*
-* Helper read function - Read the requested section header file.
-*/
-NTSTATUS LdrModules_Read_SectionsD(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _In_ LPSTR szSection, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
-{
- IMAGE_SECTION_HEADER SectionHeader;
- if(!PE_SectionGetFromName(pProcess, pModule->BaseAddress, szSection, &SectionHeader)) { return VMMDLL_STATUS_FILE_INVALID; }
- return LdrModules_Read_MemFile(pProcess, pModule->BaseAddress + SectionHeader.VirtualAddress, SectionHeader.Misc.VirtualSize, pb, cb, pcbRead, cbOffset);
-}
-
-NTSTATUS LdrModules_Read_2(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ PVMMOB_MODULEMAP pObModuleMap, _In_ LPSTR szPath1, _In_ LPSTR szPath2, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
-{
- NTSTATUS nt;
- DWORD i, cbBuffer;
- BYTE pbBuffer[0x800];
- PVMM_MODULEMAP_ENTRY pModule;
- POBLDRMODULES_CACHE_ENTRY pObCacheEntry = NULL;
- PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
- for(i = 0; i < pObModuleMap->cMap; i++) {
- pModule = pObModuleMap->pMap + i;
- if(0 == strncmp(szPath1, pModule->szName, MAX_PATH)) {
- if(!_stricmp(szPath2, "base")) {
- return Util_VfsReadFile_FromQWORD(pModule->BaseAddress, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(szPath2, "entry")) {
- return Util_VfsReadFile_FromQWORD(pModule->EntryPoint, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(szPath2, "size")) {
- return Util_VfsReadFile_FromDWORD(pModule->SizeOfImage, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(szPath2, "directories")) {
- VmmWin_PE_DIRECTORY_DisplayBuffer(ctx->pProcess, pModule, pbBuffer, 0x400, &cbBuffer, NULL);
- return Util_VfsReadFile_FromPBYTE(pbBuffer, cbBuffer, pb, cb, pcbRead, cbOffset);
- }
- if(!_stricmp(szPath2, "export")) {
- pObCacheEntry = LdrModule_GetEAT(ctx, pModule);
- if(!pObCacheEntry) { return VMMDLL_STATUS_FILE_INVALID; }
- nt = Util_VfsReadFile_FromPBYTE(pObCacheEntry->pb, pObCacheEntry->cb, pb, cb, pcbRead, cbOffset);
- VmmOb_DECREF(pObCacheEntry);
- return nt;
- }
- if(!_stricmp(szPath2, "import")) {
- pObCacheEntry = LdrModule_GetIAT(ctx, pModule);
- if(!pObCacheEntry) { return VMMDLL_STATUS_FILE_INVALID; }
- nt = Util_VfsReadFile_FromPBYTE(pObCacheEntry->pb, pObCacheEntry->cb, pb, cb, pcbRead, cbOffset);
- VmmOb_DECREF(pObCacheEntry);
- return nt;
- }
- if(!_stricmp(szPath2, "sections")) {
- VmmWin_PE_SECTION_DisplayBuffer(ctx->pProcess, pModule, pbBuffer, 0x800, &cbBuffer, NULL, NULL);
- return Util_VfsReadFile_FromPBYTE(pbBuffer, cbBuffer, pb, cb, pcbRead, cbOffset);
- }
- if(!_strnicmp(szPath2, "sectionsd\\", 10)) {
- return LdrModules_Read_SectionsD(pProcess, pModule, szPath2 + 10, pb, cb, pcbRead, cbOffset);
- }
- if(!_strnicmp(szPath2, "directoriesd\\", 13)) {
- return LdrModules_Read_DirectoriesD(pProcess, pModule, szPath2 + 13, pb, cb, pcbRead, cbOffset);
- }
- return VMMDLL_STATUS_FILE_INVALID;
- }
- }
- return VMMDLL_STATUS_FILE_INVALID;
-}
-
-/*
-* Read : function as specified by the module manager. The module manager will
-* call into this callback function whenever a read shall occur from a "file".
-* -- ctx
-* -- pb
-* -- cb
-* -- pcbRead
-* -- cbOffset
-* -- return
-*/
-NTSTATUS LdrModules_Read(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
-{
- NTSTATUS nt;
- CHAR _szBuf[MAX_PATH] = { 0 };
- LPSTR szPath1, szPath2;
- PVMMOB_MODULEMAP pObModuleMap = NULL;
- Util_PathSplit2(ctx->szPath, _szBuf, &szPath1, &szPath2);
- *pcbRead = 0;
- if(szPath1[0] && szPath2[0] && VmmProc_ModuleMapGet((PVMM_PROCESS)ctx->pProcess, &pObModuleMap)) {
- nt = LdrModules_Read_2(ctx, pObModuleMap, szPath1, szPath2, pb, cb, pcbRead, cbOffset);
- VmmOb_DECREF(pObModuleMap);
- return nt;
- }
- return VMMDLL_STATUS_FILE_INVALID;
-}
-
-/*
-* List : function as specified by the module manager. The module manager will
-* call into this callback function whenever a list directory shall occur from
-* the given module.
-* -- ctx
-* -- pFileList
-* -- return
-*/
-BOOL LdrModules_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
-{
- DWORD c, i;
- CHAR _szBuf[MAX_PATH] = { 0 };
- LPSTR szPath1, szPath2;
- PVMMOB_MODULEMAP pObModuleMap = NULL;
- PVMM_MODULEMAP_ENTRY pModule = NULL;
- PIMAGE_SECTION_HEADER pSections = NULL;
- IMAGE_DATA_DIRECTORY pDataDirectories[16];
- PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
- if(!VmmProc_ModuleMapGet(pProcess, &pObModuleMap)) { goto fail; }
- // modules root directory -> add directory per DLL
- if(!ctx->szPath[0]) {
- for(i = 0; i < pObModuleMap->cMap; i++) {
- VMMDLL_VfsList_AddDirectory(pFileList, pObModuleMap->pMap[i].szName);
- }
- goto success;
- }
- // individual module directory -> list files
- Util_PathSplit2(ctx->szPath, _szBuf, &szPath1, &szPath2);
- for(i = 0; i < pObModuleMap->cMap; i++) {
- if(0 == strncmp(szPath1, pObModuleMap->pMap[i].szName, 32)) {
- pModule = pObModuleMap->pMap + i;
- break;
- }
- }
- if(!pModule) { goto fail; }
- // module-specific 'root' directory
- if(!szPath2[0]) {
- VmmWin_PE_SetSizeSectionIATEAT_DisplayBuffer(ctx->pProcess, pObModuleMap->pMap + i);
- VMMDLL_VfsList_AddFile(pFileList, "base", 16);
- VMMDLL_VfsList_AddFile(pFileList, "entry", 16);
- VMMDLL_VfsList_AddFile(pFileList, "size", 8);
- VMMDLL_VfsList_AddFile(pFileList, "directories", 864);
- VMMDLL_VfsList_AddFile(pFileList, "export", pObModuleMap->pMap[i].cbDisplayBufferEAT);
- VMMDLL_VfsList_AddFile(pFileList, "import", pObModuleMap->pMap[i].cbDisplayBufferIAT);
- VMMDLL_VfsList_AddFile(pFileList, "sections", pObModuleMap->pMap[i].cbDisplayBufferSections);
- VMMDLL_VfsList_AddDirectory(pFileList, "sectionsd");
- VMMDLL_VfsList_AddDirectory(pFileList, "directoriesd");
- goto success;
- }
- // module-specific 'sectiond' directory
- if(szPath2[0] && !strcmp(szPath2, "sectionsd")) {
- _szBuf[8] = 0;
- c = PE_SectionGetNumberOf(pProcess, pModule->BaseAddress);
- if(!(pSections = LocalAlloc(0, c * sizeof(IMAGE_SECTION_HEADER)))) { goto fail; }
- VmmWin_PE_SECTION_DisplayBuffer(pProcess, pModule, NULL, 0, NULL, &c, pSections);
- for(i = 0; i < c; i++) {
- *(PQWORD)_szBuf = *(PQWORD)pSections[i].Name;
- VMMDLL_VfsList_AddFile(pFileList, _szBuf, pSections[i].Misc.VirtualSize);
- }
- LocalFree(pSections);
- goto success;
- }
- // module-specific 'directoriesd' directory
- if(szPath2[0] && !strcmp(szPath2, "directoriesd")) {
- VmmWin_PE_DIRECTORY_DisplayBuffer(pProcess, pModule, NULL, 0, NULL, pDataDirectories);
- for(i = 0; i < 16; i++) {
- VMMDLL_VfsList_AddFile(pFileList, (LPSTR)PE_DATA_DIRECTORIES[i], pDataDirectories[i].Size);
- }
- goto success;
- }
-fail:
- VmmOb_DECREF(pObModuleMap);
- return FALSE;
-success:
- VmmOb_DECREF(pObModuleMap);
- return TRUE;
-}
-
-/*
-* Initialization function. The module manager shall call into this function
-* when the module shall be initialized. If the module wish to initialize it
-* shall call the supplied pfnPluginManager_Register function.
-* NB! the module does not have to register itself - for example if the target
-* operating system or architecture is unsupported.
-* -- pPluginRegInfo
-*/
-VOID M_LdrModules_Initialize(_Inout_ PVMMDLL_PLUGIN_REGINFO pRI)
-{
- if((pRI->magic != VMMDLL_PLUGIN_REGINFO_MAGIC) || (pRI->wVersion != VMMDLL_PLUGIN_REGINFO_VERSION)) { return; }
- if((pRI->tpSystem != VMM_SYSTEM_WINDOWS_X64) && (pRI->tpSystem != VMM_SYSTEM_WINDOWS_X86)) { return; }
- strcpy_s(pRI->reg_info.szModuleName, 32, "modules"); // module name
- pRI->reg_info.fProcessModule = TRUE; // module shows in process directory
- pRI->reg_fn.pfnList = LdrModules_List; // List function supported
- pRI->reg_fn.pfnRead = LdrModules_Read; // Read function supported
- pRI->reg_fn.pfnWrite = LdrModules_Write; // Write function supported
- pRI->pfnPluginManager_Register(pRI);
-}
diff --git a/vmm/m_ldrmodules.h b/vmm/m_ldrmodules.h
deleted file mode 100644
index 08d4044..0000000
--- a/vmm/m_ldrmodules.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// m_ldrmodules.h : definitions related to the ldrmodules built-in module.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __M_LDRMODULES_H__
-#define __M_LDRMODULES_H__
-#include
-#include "vmmdll.h"
-
-/*
-* Initialization function for the built-in ldrmodules module.
-* -- pPluginRegInfo
-*/
-VOID M_LdrModules_Initialize(_Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo);
-
-#endif /* __M_LDRMODULES_H__ */
diff --git a/vmm/m_status.c b/vmm/m_status.c
deleted file mode 100644
index 70b2302..0000000
--- a/vmm/m_status.c
+++ /dev/null
@@ -1,290 +0,0 @@
-// m_status.c : implementation of the .status built-in module.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-
-/*
-* The m_status module registers itself with the name '.status' with the plugin manager.
-*
-* The module showcases both a "root" "process" directory module as well as a
-* stateless module. It neither holds state in its "global" HandleModule context
-* nor in the per-process specific HandleProcess contexts.
-*
-* The module implements listing of directories as well as read and write.
-* Read/Write happens, if allowed, to various configuration and status settings
-* related to the VMM and Memory Process File System.
-*/
-
-#include "m_virt2phys.h"
-#include "pluginmanager.h"
-#include "util.h"
-#include "vmm.h"
-#include "vmmproc.h"
-#include "vmmvfs.h"
-#include "statistics.h"
-
-/*
-* Read : function as specified by the module manager. The module manager will
-* call into this callback function whenever a read shall occur from a "file".
-* -- ctx
-* -- pb
-* -- cb
-* -- pcbRead
-* -- cbOffset
-* -- return
-*/
-NTSTATUS MStatus_Read(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
-{
- PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
- DWORD cchBuffer;
- CHAR szBuffer[0x400];
- DWORD cbCallStatistics = 0;
- PBYTE pbCallStatistics = NULL;
- NTSTATUS nt;
- // "PROCESS"
- if(pProcess) {
- if(!_stricmp(ctx->szPath, "cache_file_enable")) {
- return Util_VfsReadFile_FromBOOL(!pProcess->fFileCacheDisabled, pb, cb, pcbRead, cbOffset);
- }
- }
- // "ROOT"
- if(!pProcess) {
- if(!_stricmp(ctx->szPath, "config_process_show_terminated")) {
- return Util_VfsReadFile_FromBOOL(ctxVmm->flags & VMM_FLAG_PROCESS_SHOW_TERMINATED, pb, cb, pcbRead, cbOffset);
- }
- if(!_stricmp(ctx->szPath, "config_cache_enable")) {
- return Util_VfsReadFile_FromBOOL(!(ctxVmm->flags & VMM_FLAG_NOCACHE), pb, cb, pcbRead, cbOffset);
- }
- if(!_stricmp(ctx->szPath, "config_statistics_fncall")) {
- return Util_VfsReadFile_FromBOOL(Statistics_CallGetEnabled(), pb, cb, pcbRead, cbOffset);
- }
- if(!_stricmp(ctx->szPath, "config_refresh_enable")) {
- return Util_VfsReadFile_FromBOOL(ctxVmm->ThreadProcCache.fEnabled, pb, cb, pcbRead, cbOffset);
- }
- if(!_stricmp(ctx->szPath, "config_refresh_tick_period_ms")) {
- return Util_VfsReadFile_FromDWORD(ctxVmm->ThreadProcCache.cMs_TickPeriod, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(ctx->szPath, "config_refresh_read")) {
- return Util_VfsReadFile_FromDWORD(ctxVmm->ThreadProcCache.cTick_Phys, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(ctx->szPath, "config_refresh_tlb")) {
- return Util_VfsReadFile_FromDWORD(ctxVmm->ThreadProcCache.cTick_TLB, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(ctx->szPath, "config_refresh_proc_partial")) {
- return Util_VfsReadFile_FromDWORD(ctxVmm->ThreadProcCache.cTick_ProcPartial, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(ctx->szPath, "config_refresh_proc_total")) {
- return Util_VfsReadFile_FromDWORD(ctxVmm->ThreadProcCache.cTick_ProcTotal, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(ctx->szPath, "statistics")) {
- cchBuffer = snprintf(szBuffer, 0x400,
- "VMM STATISTICS (4kB PAGES / COUNTS - HEXADECIMAL)\n" \
- "===================================================\n" \
- "PHYSICAL MEMORY READ CACHE HIT: %16llx\n" \
- "PHYSICAL MEMORY READ RETRIEVED: %16llx\n" \
- "PHYSICAL MEMORY READ FAILED: %16llx\n" \
- "PHYSICAL MEMORY WRITE: %16llx\n" \
- "TLB CACHE HIT: %16llx\n" \
- "TLB RETRIEVED: %16llx\n" \
- "TLB FAILED: %16llx\n" \
- "PHYSICAL MEMORY REFRESH: %16llx\n" \
- "TLB MEMORY REFRESH: %16llx\n" \
- "PROCESS PARTIAL REFRESH: %16llx\n" \
- "PROCESS FULL REFRESH: %16llx\n",
- ctxVmm->stat.cPhysCacheHit, ctxVmm->stat.cPhysReadSuccess, ctxVmm->stat.cPhysReadFail,
- ctxVmm->stat.cPhysWrite,
- ctxVmm->stat.cTlbCacheHit, ctxVmm->stat.cTlbReadSuccess, ctxVmm->stat.cTlbReadFail,
- ctxVmm->stat.cRefreshPhys, ctxVmm->stat.cRefreshTlb, ctxVmm->stat.cRefreshProcessPartial, ctxVmm->stat.cRefreshProcessFull
- );
- return Util_VfsReadFile_FromPBYTE(szBuffer, cchBuffer, pb, cb, pcbRead, cbOffset);
- }
- if(!_stricmp(ctx->szPath, "statistics_fncall")) {
- Statistics_CallToString(NULL, 0, &cbCallStatistics);
- pbCallStatistics = LocalAlloc(0, cbCallStatistics);
- if(!pbCallStatistics) { return VMMDLL_STATUS_FILE_INVALID; }
- Statistics_CallToString(pbCallStatistics, cbCallStatistics, &cbCallStatistics);
- nt = Util_VfsReadFile_FromPBYTE(pbCallStatistics, cbCallStatistics, pb, cb, pcbRead, cbOffset);
- LocalFree(pbCallStatistics);
- return nt;
- }
- if(!_stricmp(ctx->szPath, "config_printf_enable")) {
- return Util_VfsReadFile_FromBOOL(ctxMain->cfg.fVerboseDll, pb, cb, pcbRead, cbOffset);
- }
- if(!_stricmp(ctx->szPath, "config_printf_v")) {
- return Util_VfsReadFile_FromBOOL(ctxMain->cfg.fVerbose, pb, cb, pcbRead, cbOffset);
- }
- if(!_stricmp(ctx->szPath, "config_printf_vv")) {
- return Util_VfsReadFile_FromBOOL(ctxMain->cfg.fVerboseExtra, pb, cb, pcbRead, cbOffset);
- }
- if(!_stricmp(ctx->szPath, "config_printf_vvv")) {
- return Util_VfsReadFile_FromBOOL(ctxMain->cfg.fVerboseExtraTlp, pb, cb, pcbRead, cbOffset);
- }
- if(!_stricmp(ctx->szPath, "native_max_address")) {
- return Util_VfsReadFile_FromQWORD(ctxMain->dev.paMaxNative, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(ctx->szPath, "native_max_iosize")) {
- return Util_VfsReadFile_FromQWORD(ctxMain->dev.cbMaxSizeMemIo, pb, cb, pcbRead, cbOffset, FALSE);
- }
- }
- return VMMDLL_STATUS_FILE_INVALID;
-}
-
-NTSTATUS MStatus_Write_NotifyVerbosityChange(_In_ NTSTATUS nt)
-{
- if(nt == VMMDLL_STATUS_SUCCESS) {
- PluginManager_Notify(VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE, NULL, 0);
- }
- return nt;
-}
-
-/*
-* Write : function as specified by the module manager. The module manager will
-* call into this callback function whenever a write shall occur from a "file".
-* -- ctx
-* -- pb
-* -- cb
-* -- pcbWrite
-* -- cbOffset
-* -- return
-*/
-NTSTATUS MStatus_Write(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset)
-{
- PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
- NTSTATUS nt;
- BOOL fEnable = FALSE;
- // "PROCESS"
- if(pProcess) {
- if(!_stricmp(ctx->szPath, "cache_file_enable")) {
- if((cbOffset == 0) && (cb > 0)) {
- if(((PCHAR)pb)[0] == '1') { pProcess->fFileCacheDisabled = FALSE; }
- if(((PCHAR)pb)[0] == '0') { pProcess->fFileCacheDisabled = TRUE; }
- }
- *pcbWrite = cb;
- return VMMDLL_STATUS_SUCCESS;
- }
- }
- // "ROOT"
- if(!pProcess) {
-
- if(!_stricmp(ctx->szPath, "config_process_show_terminated")) {
- nt = Util_VfsWriteFile_BOOL(&fEnable, pb, cb, pcbWrite, cbOffset);
- if(nt == VMMDLL_STATUS_SUCCESS) {
- ctxVmm->flags &= ~VMM_FLAG_PROCESS_SHOW_TERMINATED;
- ctxVmm->flags |= fEnable ? VMM_FLAG_PROCESS_SHOW_TERMINATED : 0;
- VmmProc_RefreshProcesses(TRUE);
- }
- return nt;
- }
- if(!_stricmp(ctx->szPath, "config_cache_enable")) {
- nt = Util_VfsWriteFile_BOOL(&fEnable, pb, cb, pcbWrite, cbOffset);
- if(nt == VMMDLL_STATUS_SUCCESS) {
- ctxVmm->flags &= ~VMM_FLAG_NOCACHE;
- ctxVmm->flags |= fEnable ? 0 : VMM_FLAG_NOCACHE;
- }
- return nt;
- }
- if(!_stricmp(ctx->szPath, "config_statistics_fncall")) {
- nt = Util_VfsWriteFile_BOOL(&fEnable, pb, cb, pcbWrite, cbOffset);
- if(nt == VMMDLL_STATUS_SUCCESS) {
- Statistics_CallSetEnabled(fEnable);
- }
- return nt;
- }
- if(!_stricmp(ctx->szPath, "config_refresh_tick_period_ms")) {
- return Util_VfsWriteFile_DWORD(&ctxVmm->ThreadProcCache.cMs_TickPeriod, pb, cb, pcbWrite, cbOffset, 50);
- }
- if(!_stricmp(ctx->szPath, "config_refresh_read")) {
- return Util_VfsWriteFile_DWORD(&ctxVmm->ThreadProcCache.cTick_Phys, pb, cb, pcbWrite, cbOffset, 1);
- }
- if(!_stricmp(ctx->szPath, "config_refresh_tlb")) {
- return Util_VfsWriteFile_DWORD(&ctxVmm->ThreadProcCache.cTick_TLB, pb, cb, pcbWrite, cbOffset, 1);
- }
- if(!_stricmp(ctx->szPath, "config_refresh_proc_partial")) {
- return Util_VfsWriteFile_DWORD(&ctxVmm->ThreadProcCache.cTick_ProcPartial, pb, cb, pcbWrite, cbOffset, 1);
- }
- if(!_stricmp(ctx->szPath, "config_refresh_proc_total")) {
- return Util_VfsWriteFile_DWORD(&ctxVmm->ThreadProcCache.cTick_ProcTotal, pb, cb, pcbWrite, cbOffset, 1);
- }
- if(!_stricmp(ctx->szPath, "config_printf_enable")) {
- return MStatus_Write_NotifyVerbosityChange(
- Util_VfsWriteFile_BOOL(&ctxMain->cfg.fVerboseDll, pb, cb, pcbWrite, cbOffset));
- }
- if(!_stricmp(ctx->szPath, "config_printf_v")) {
- return MStatus_Write_NotifyVerbosityChange(
- Util_VfsWriteFile_BOOL(&ctxMain->cfg.fVerbose, pb, cb, pcbWrite, cbOffset));
- }
- if(!_stricmp(ctx->szPath, "config_printf_vv")) {
- return MStatus_Write_NotifyVerbosityChange(
- Util_VfsWriteFile_BOOL(&ctxMain->cfg.fVerboseExtra, pb, cb, pcbWrite, cbOffset));
- }
- if(!_stricmp(ctx->szPath, "config_printf_vvv")) {
- return MStatus_Write_NotifyVerbosityChange(
- Util_VfsWriteFile_BOOL(&ctxMain->cfg.fVerboseExtraTlp, pb, cb, pcbWrite, cbOffset));
- }
- }
- return VMMDLL_STATUS_FILE_INVALID;
-}
-
-/*
-* List : function as specified by the module manager. The module manager will
-* call into this callback function whenever a list directory shall occur from
-* the given module.
-* -- ctx
-* -- pFileList
-* -- return
-*/
-BOOL MStatus_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
-{
- DWORD cbCallStatistics = 0;
- PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
- // not module root directory -> fail!
- if(ctx->szPath[0]) { return FALSE; }
- // "root" view
- if(!ctx->pProcess) {
- VMMDLL_VfsList_AddFile(pFileList, "config_cache_enable", 1);
- VMMDLL_VfsList_AddFile(pFileList, "config_statistics_fncall", 1);
- VMMDLL_VfsList_AddFile(pFileList, "config_refresh_enable", 1);
- VMMDLL_VfsList_AddFile(pFileList, "config_refresh_tick_period_ms", 8);
- VMMDLL_VfsList_AddFile(pFileList, "config_refresh_read", 8);
- VMMDLL_VfsList_AddFile(pFileList, "config_refresh_tlb", 8);
- VMMDLL_VfsList_AddFile(pFileList, "config_refresh_proc_partial", 8);
- VMMDLL_VfsList_AddFile(pFileList, "config_refresh_proc_total", 8);
- VMMDLL_VfsList_AddFile(pFileList, "statistics", 0x283);
- VMMDLL_VfsList_AddFile(pFileList, "config_printf_enable", 1);
- VMMDLL_VfsList_AddFile(pFileList, "config_printf_v", 1);
- VMMDLL_VfsList_AddFile(pFileList, "config_printf_vv", 1);
- VMMDLL_VfsList_AddFile(pFileList, "config_printf_vvv", 1);
- VMMDLL_VfsList_AddFile(pFileList, "config_process_show_terminated", 1);
- VMMDLL_VfsList_AddFile(pFileList, "native_max_address", 16);
- VMMDLL_VfsList_AddFile(pFileList, "native_max_iosize", 16);
- Statistics_CallToString(NULL, 0, &cbCallStatistics);
- VMMDLL_VfsList_AddFile(pFileList, "statistics_fncall", cbCallStatistics);
- }
- // "process" view
- if(pProcess) {
- VMMDLL_VfsList_AddFile(pFileList, "cache_file_enable", 1);
- }
- return TRUE;
-}
-
-/*
-* Initialization function. The module manager shall call into this function
-* when the module shall be initialized. If the module wish to initialize it
-* shall call the supplied pfnPluginManager_Register function.
-* NB! the module does not have to register itself - for example if the target
-* operating system or architecture is unsupported.
-* -- pPluginRegInfo
-*/
-VOID M_Status_Initialize(_Inout_ PVMMDLL_PLUGIN_REGINFO pRI)
-{
- if((pRI->magic != VMMDLL_PLUGIN_REGINFO_MAGIC) || (pRI->wVersion != VMMDLL_PLUGIN_REGINFO_VERSION)) { return; }
- // .status module is always valid - no check against pPluginRegInfo->tpMemoryModel, tpSystem
- strcpy_s(pRI->reg_info.szModuleName, 32, ".status"); // module name
- pRI->reg_info.fRootModule = TRUE; // module shows in root directory
- pRI->reg_info.fProcessModule = TRUE; // module shows in process directory
- pRI->reg_fn.pfnList = MStatus_List; // List function supported
- pRI->reg_fn.pfnRead = MStatus_Read; // Read function supported
- pRI->reg_fn.pfnWrite = MStatus_Write; // Write function supported
- pRI->pfnPluginManager_Register(pRI);
-}
diff --git a/vmm/m_status.h b/vmm/m_status.h
deleted file mode 100644
index 3849ee7..0000000
--- a/vmm/m_status.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// m_status.h : definitions related to the .status built-in module.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __M_STATUS_H__
-#define __M_STATUS_H__
-#include
-#include "vmmdll.h"
-
-/*
-* Initialization function for the built-in virt2phys module.
-* -- pPluginRegInfo
-*/
-VOID M_Status_Initialize(_Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo);
-
-#endif /* __M_STATUS_H__ */
diff --git a/vmm/m_virt2phys.c b/vmm/m_virt2phys.c
deleted file mode 100644
index 6f3609b..0000000
--- a/vmm/m_virt2phys.c
+++ /dev/null
@@ -1,253 +0,0 @@
-// m_virt2phys.c : implementation of the virt2phys built-in module.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include "m_virt2phys.h"
-#include "pluginmanager.h"
-#include "util.h"
-#include "vmm.h"
-#include "vmmvfs.h"
-
-/*
-* Read : function as specified by the module manager. The module manager will
-* call into this callback function whenever a read shall occur from a "file".
-* -- ctx
-* -- pb
-* -- cb
-* -- pcbRead
-* -- cbOffset
-* -- return
-*/
-NTSTATUS Virt2Phys_Read(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
-{
- BYTE iPML = 0;
- DWORD cbBuffer;
- PBYTE pbSourceData;
- BYTE pbBuffer[0x1000];
- PVMMOB_MEM pObPT = NULL;
- PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
- VMM_VIRT2PHYS_INFORMATION Virt2PhysInfo = { 0 };
- Virt2PhysInfo.va = pProcess->pObProcessPersistent->Plugin.vaVirt2Phys;
- VmmVirt2PhysGetInformation(pProcess, &Virt2PhysInfo);
- if(!_stricmp(ctx->szPath, "virt")) {
- switch(ctxVmm->tpMemoryModel) {
- case VMM_MEMORYMODEL_X64:
- return Util_VfsReadFile_FromQWORD(Virt2PhysInfo.va, pb, cb, pcbRead, cbOffset, FALSE);
- break;
- case VMM_MEMORYMODEL_X86:
- case VMM_MEMORYMODEL_X86PAE:
- return Util_VfsReadFile_FromDWORD((DWORD)Virt2PhysInfo.va, pb, cb, pcbRead, cbOffset, FALSE);
- break;
- }
- }
- if(!_stricmp(ctx->szPath, "phys")) {
- return Util_VfsReadFile_FromQWORD(Virt2PhysInfo.pas[0], pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(ctx->szPath, "map")) {
- switch(ctxVmm->tpMemoryModel) {
- case VMM_MEMORYMODEL_X64:
- cbBuffer = snprintf(
- pbBuffer,
- 0x1000,
- "PML4 %016llx +%03x %016llx\n" \
- "PDPT %016llx +%03x %016llx\n" \
- "PD %016llx +%03x %016llx\n" \
- "PT %016llx +%03x %016llx\n" \
- "PAGE %016llx\n",
- Virt2PhysInfo.pas[4], Virt2PhysInfo.iPTEs[4] << 3, Virt2PhysInfo.PTEs[4],
- Virt2PhysInfo.pas[3], Virt2PhysInfo.iPTEs[3] << 3, Virt2PhysInfo.PTEs[3],
- Virt2PhysInfo.pas[2], Virt2PhysInfo.iPTEs[2] << 3, Virt2PhysInfo.PTEs[2],
- Virt2PhysInfo.pas[1], Virt2PhysInfo.iPTEs[1] << 3, Virt2PhysInfo.PTEs[1],
- Virt2PhysInfo.pas[0]
- );
- break;
- case VMM_MEMORYMODEL_X86PAE:
- cbBuffer = snprintf(
- pbBuffer,
- 0x1000,
- "PDPT %016llx +%03x %016llx\n" \
- "PD %016llx +%03x %016llx\n" \
- "PT %016llx +%03x %016llx\n" \
- "PAGE %016llx\n",
- Virt2PhysInfo.pas[3], Virt2PhysInfo.iPTEs[3] << 3, Virt2PhysInfo.PTEs[3],
- Virt2PhysInfo.pas[2], Virt2PhysInfo.iPTEs[2] << 3, Virt2PhysInfo.PTEs[2],
- Virt2PhysInfo.pas[1], Virt2PhysInfo.iPTEs[1] << 3, Virt2PhysInfo.PTEs[1],
- Virt2PhysInfo.pas[0]
- );
- break;
- case VMM_MEMORYMODEL_X86:
- cbBuffer = snprintf(
- pbBuffer,
- 0x1000,
- "PD %016llx +%03x %08x\n" \
- "PT %016llx +%03x %08x\n" \
- "PAGE %016llx\n",
- Virt2PhysInfo.pas[2], Virt2PhysInfo.iPTEs[2] << 2, (DWORD)Virt2PhysInfo.PTEs[2],
- Virt2PhysInfo.pas[1], Virt2PhysInfo.iPTEs[1] << 2, (DWORD)Virt2PhysInfo.PTEs[1],
- Virt2PhysInfo.pas[0]
- );
- break;
- }
- return Util_VfsReadFile_FromPBYTE(pbBuffer, cbBuffer, pb, cb, pcbRead, cbOffset);
- }
- // "page table" or data page
- if(!_stricmp(ctx->szPath, "pt_pml4")) { iPML = 4; }
- if(!_stricmp(ctx->szPath, "pt_pdpt")) { iPML = 3; }
- if(!_stricmp(ctx->szPath, "pt_pd")) { iPML = 2; }
- if(!_stricmp(ctx->szPath, "pt_pt")) { iPML = 1; }
- if((ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86) && (iPML > 2)) { return VMMDLL_STATUS_FILE_INVALID; }
- if((ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86PAE) && (iPML > 3)) { return VMMDLL_STATUS_FILE_INVALID; }
- ZeroMemory(pbBuffer, 0x1000);
- pbSourceData = pbBuffer;
- if(iPML && (Virt2PhysInfo.pas[iPML] & ~0xfff)) {
- pObPT = VmmTlbGetPageTable(Virt2PhysInfo.pas[iPML] & ~0xfff, FALSE);
- if(pObPT) {
- memcpy(pbSourceData, pObPT->pb, 0x1000);
- VmmOb_DECREF(pObPT);
- pObPT = NULL;
- }
- }
- if(!_stricmp(ctx->szPath, "page") && (Virt2PhysInfo.pas[0] & ~0xfff)) {
- VmmReadPhysicalPage(Virt2PhysInfo.pas[0] & ~0xfff, pbBuffer);
- }
- if(iPML || !_stricmp(ctx->szPath, "page")) {
- return Util_VfsReadFile_FromPBYTE(pbSourceData, 0x1000, pb, cb, pcbRead, cbOffset);
- }
- return VMMDLL_STATUS_FILE_INVALID;
-}
-
-/*
-* Write to the "virt" virtual file - update stored persistent address.
-* -- ctx
-* -- pb
-* -- cb
-* -- pcbWrite
-* -- cbOffset
-* -- return
-*/
-NTSTATUS Virt2Phys_WriteVA(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset)
-{
- PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
- BYTE pbBuffer[17];
- VMM_MEMORYMODEL_TP tp = ctxVmm->tpMemoryModel;
- if((tp == VMM_MEMORYMODEL_X64) && (cbOffset < 16)) {
- *pcbWrite = cb;
- snprintf(pbBuffer, 17, "%016llx", pProcess->pObProcessPersistent->Plugin.vaVirt2Phys);
- cb = (DWORD)min(16 - cbOffset, cb);
- memcpy(pbBuffer + cbOffset, pb, cb);
- pbBuffer[16] = 0;
- pProcess->pObProcessPersistent->Plugin.vaVirt2Phys = strtoull(pbBuffer, NULL, 16);
- } else if ((tp == VMM_MEMORYMODEL_X86) || (tp == VMM_MEMORYMODEL_X86PAE)) {
- *pcbWrite = cb;
- snprintf(pbBuffer, 9, "%08x", (DWORD)pProcess->pObProcessPersistent->Plugin.vaVirt2Phys);
- cb = (DWORD)min(8 - cbOffset, cb);
- memcpy(pbBuffer + cbOffset, pb, cb);
- pbBuffer[8] = 0;
- pProcess->pObProcessPersistent->Plugin.vaVirt2Phys = strtoul(pbBuffer, NULL, 16);
- } else {
- *pcbWrite = 0;
- }
- return VMMDLL_STATUS_SUCCESS;
-}
-
-/*
-* Write : function as specified by the module manager. The module manager will
-* call into this callback function whenever a write shall occur from a "file".
-* -- ctx
-* -- pb
-* -- cb
-* -- pcbWrite
-* -- cbOffset
-* -- return
-*/
-NTSTATUS Virt2Phys_Write(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset)
-{
- DWORD i;
- PVMM_PROCESS pProcess = (PVMM_PROCESS)ctx->pProcess;
- VMM_VIRT2PHYS_INFORMATION Virt2PhysInfo = { 0 };
- if(!_stricmp(ctx->szPath, "virt")) {
- return Virt2Phys_WriteVA(ctx, pb, cb, pcbWrite, cbOffset);
- }
- Virt2PhysInfo.va = pProcess->pObProcessPersistent->Plugin.vaVirt2Phys;
- VmmVirt2PhysGetInformation(pProcess, &Virt2PhysInfo);
- i = 0xff;
- if(!_stricmp(ctx->szPath, "pt_pml4")) { i = 4; }
- if(!_stricmp(ctx->szPath, "pt_pdpt")) { i = 3; }
- if(!_stricmp(ctx->szPath, "pt_pd")) { i = 2; }
- if(!_stricmp(ctx->szPath, "pt_pt")) { i = 1; }
- if(!_stricmp(ctx->szPath, "page")) { i = 0; }
- if(i > 4) { return VMMDLL_STATUS_FILE_INVALID; }
- if(Virt2PhysInfo.pas[i] < 0x1000) { return VMMDLL_STATUS_FILE_INVALID; }
- if(cbOffset > 0x1000) { return VMMDLL_STATUS_END_OF_FILE; }
- *pcbWrite = (DWORD)min(cb, 0x1000 - cbOffset);
- VmmWritePhysical(Virt2PhysInfo.pas[i] + cbOffset, pb, *pcbWrite);
- return *pcbWrite ? VMMDLL_STATUS_SUCCESS : VMMDLL_STATUS_END_OF_FILE;
-}
-
-/*
-* List : function as specified by the module manager. The module manager will
-* call into this callback function whenever a list directory shall occur from
-* the given module.
-* -- ctx
-* -- pFileList
-* -- return
-*/
-BOOL Virt2Phys_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
-{
- if(ctx->szPath[0]) {
- // only list in module root directory.
- // not root directory == error for this module.
- return FALSE;
- }
- switch(ctxVmm->tpMemoryModel) {
- case VMM_MEMORYMODEL_X64:
- VMMDLL_VfsList_AddFile(pFileList, "virt", 16);
- VMMDLL_VfsList_AddFile(pFileList, "phys", 16);
- VMMDLL_VfsList_AddFile(pFileList, "map", 198);
- VMMDLL_VfsList_AddFile(pFileList, "pt_pml4", 0x1000);
- VMMDLL_VfsList_AddFile(pFileList, "pt_pdpt", 0x1000);
- VMMDLL_VfsList_AddFile(pFileList, "pt_pd", 0x1000);
- VMMDLL_VfsList_AddFile(pFileList, "pt_pt", 0x1000);
- VMMDLL_VfsList_AddFile(pFileList, "page", 0x1000);
- break;
- case VMM_MEMORYMODEL_X86PAE:
- VMMDLL_VfsList_AddFile(pFileList, "virt", 8);
- VMMDLL_VfsList_AddFile(pFileList, "phys", 16);
- VMMDLL_VfsList_AddFile(pFileList, "map", 154);
- VMMDLL_VfsList_AddFile(pFileList, "pt_pdpt", 0x1000);
- VMMDLL_VfsList_AddFile(pFileList, "pt_pd", 0x1000);
- VMMDLL_VfsList_AddFile(pFileList, "pt_pt", 0x1000);
- VMMDLL_VfsList_AddFile(pFileList, "page", 0x1000);
- break;
- case VMM_MEMORYMODEL_X86:
- VMMDLL_VfsList_AddFile(pFileList, "virt", 8);
- VMMDLL_VfsList_AddFile(pFileList, "phys", 16);
- VMMDLL_VfsList_AddFile(pFileList, "map", 94);
- VMMDLL_VfsList_AddFile(pFileList, "pt_pd", 0x1000);
- VMMDLL_VfsList_AddFile(pFileList, "pt_pt", 0x1000);
- VMMDLL_VfsList_AddFile(pFileList, "page", 0x1000);
- break;
- }
- return TRUE;
-}
-
-/*
-* Initialization function. The module manager shall call into this function
-* when the module shall be initialized. If the module wish to initialize it
-* shall call the supplied pfnPluginManager_Register function.
-* NB! the module does not have to register itself - for example if the target
-* operating system or architecture is unsupported.
-* -- pPluginRegInfo
-*/
-VOID M_Virt2Phys_Initialize(_Inout_ PVMMDLL_PLUGIN_REGINFO pRI)
-{
- if((pRI->magic != VMMDLL_PLUGIN_REGINFO_MAGIC) || (pRI->wVersion != VMMDLL_PLUGIN_REGINFO_VERSION)) { return; }
- if(!((pRI->tpMemoryModel == VMM_MEMORYMODEL_X64) || (pRI->tpMemoryModel == VMM_MEMORYMODEL_X86) || (pRI->tpMemoryModel == VMM_MEMORYMODEL_X86PAE))) { return; }
- strcpy_s(pRI->reg_info.szModuleName, 32, "virt2phys"); // module name
- pRI->reg_info.fProcessModule = TRUE; // module shows in process directory
- pRI->reg_fn.pfnList = Virt2Phys_List; // List function supported
- pRI->reg_fn.pfnRead = Virt2Phys_Read; // Read function supported
- pRI->reg_fn.pfnWrite = Virt2Phys_Write; // Write function supported
- pRI->pfnPluginManager_Register(pRI);
-}
diff --git a/vmm/m_virt2phys.h b/vmm/m_virt2phys.h
deleted file mode 100644
index d77b0dc..0000000
--- a/vmm/m_virt2phys.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// m_virt2phys.h : definitions related to the virt2phys built-in module.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __M_VIRT2PHYS_H__
-#define __M_VIRT2PHYS_H__
-#include
-#include "vmmdll.h"
-
-/*
-* Initialization function for the built-in virt2phys module.
-* -- pPluginRegInfo
-*/
-VOID M_Virt2Phys_Initialize(_Inout_ PVMMDLL_PLUGIN_REGINFO pPluginRegInfo);
-
-#endif /* __M_VIRT2PHYS_H__ */
diff --git a/vmm/mm_x64.c b/vmm/mm_x64.c
deleted file mode 100644
index 64aad87..0000000
--- a/vmm/mm_x64.c
+++ /dev/null
@@ -1,466 +0,0 @@
-// mm_x64.c : implementation of the x64 / IA32e / long-mode paging / memory model.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include "vmm.h"
-#include "vmmproc.h"
-
-#define MMX64_MEMMAP_DISPLAYBUFFER_LINE_LENGTH 89
-
-/*
-* Tries to verify that a loaded page table is correct. If just a bit strange
-* bytes/ptes supplied in pb will be altered to look better.
-*/
-BOOL MmX64_TlbPageTableVerify(_Inout_ PBYTE pb, _In_ QWORD pa, _In_ BOOL fSelfRefReq)
-{
- DWORD i;
- QWORD *ptes, c = 0, pte;
- BOOL fSelfRef = FALSE;
- if(!pb) { return FALSE; }
- ptes = (PQWORD)pb;
- for(i = 0; i < 512; i++) {
- pte = *(ptes + i);
- if((pte & 0x01) && ((0x000fffffffffffff & pte) > ctxMain->dev.paMax)) {
- // A bad PTE, or memory allocated above the physical address max
- // limit. This may be just trash in the page table in which case
- // we clear this faulty entry. If too may bad PTEs are found this
- // is most probably not a page table - zero it out but let it
- // remain in cache to prevent performance degrading reloads...
- vmmprintfvv_fn("VMM: BAD PTE %016llx at PA: %016llx i: %i\n", *(ptes + i), pa, i);
- *(ptes + i) = (QWORD)0;
- c++;
- if(c > 16) { break; }
- }
- if(pa == (0x0000fffffffff000 & pte)) {
- fSelfRef = TRUE;
- }
- }
- if((c > 16) || (fSelfRefReq && !fSelfRef)) {
- if(ctxVmm) {
- vmmprintfvv_fn("VMM: BAD PT PAGE at PA: %016llx\n", pa);
- }
- ZeroMemory(pb, 4096);
- return FALSE;
- }
- return TRUE;
-}
-
-#define MMX64_TLB_SIZE_STAGEBUF 0x200
-
-typedef struct tdMMX64_TLB_SPIDER_STAGE_INTERNAL {
- QWORD c;
- PMEM_IO_SCATTER_HEADER ppMEMs[MMX64_TLB_SIZE_STAGEBUF];
- PVMMOB_MEM ppObMEMs[MMX64_TLB_SIZE_STAGEBUF];
-} MMX64_TLB_SPIDER_STAGE_INTERNAL, *PMMX64_TLB_SPIDER_STAGE_INTERNAL;
-
-VOID MmX64_TlbSpider_ReadToCache(PMMX64_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
-{
- QWORD i;
- LeechCore_ReadScatter(pTlbSpiderStage->ppMEMs, (DWORD)pTlbSpiderStage->c);
- for(i = 0; i < pTlbSpiderStage->c; i++) {
- MmX64_TlbPageTableVerify(pTlbSpiderStage->ppObMEMs[i]->h.pb, pTlbSpiderStage->ppObMEMs[i]->h.qwA, FALSE);
- VmmCacheReserveReturn(pTlbSpiderStage->ppObMEMs[i]);
- }
- pTlbSpiderStage->c = 0;
-}
-
-BOOL MmX64_TlbSpider_Stage(_In_ QWORD pa, _In_ BYTE iPML, _In_ BOOL fUserOnly, PMMX64_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
-{
- BOOL fSpiderComplete = TRUE;
- PVMMOB_MEM ptObMEM;
- QWORD i, pe;
- // 1: retrieve from cache, add to staging if not found
- ptObMEM = VmmCacheGet(VMM_CACHE_TAG_TLB, pa);
- if(!ptObMEM) {
- pTlbSpiderStage->ppObMEMs[pTlbSpiderStage->c] = VmmCacheReserve(VMM_CACHE_TAG_TLB);
- pTlbSpiderStage->ppMEMs[pTlbSpiderStage->c] = &pTlbSpiderStage->ppObMEMs[pTlbSpiderStage->c]->h;
- pTlbSpiderStage->ppMEMs[pTlbSpiderStage->c]->qwA = pa;
- pTlbSpiderStage->c++;
- if(pTlbSpiderStage->c == MMX64_TLB_SIZE_STAGEBUF) {
- MmX64_TlbSpider_ReadToCache(pTlbSpiderStage);
- }
- return FALSE;
- }
- // 2: walk trough all entries for PML4, PDPT, PD
- if(iPML == 1) {
- VmmOb_DECREF(ptObMEM);
- return TRUE;
- }
- for(i = 0; i < 512; i++) {
- pe = ptObMEM->pqw[i];
- if(!(pe & 0x01)) { continue; } // not valid
- if(pe & 0x80) { continue; } // not valid ptr to (PDPT || PD || PT)
- if(fUserOnly && !(pe & 0x04)) { continue; } // supervisor page when fUserOnly -> not valid
- fSpiderComplete = MmX64_TlbSpider_Stage(pe & 0x0000fffffffff000, iPML - 1, fUserOnly, pTlbSpiderStage) && fSpiderComplete;
- }
- VmmOb_DECREF(ptObMEM);
- return fSpiderComplete;
-}
-
-/*
-* Iterate over PML4, PTPT, PD (3 times in total) to first stage uncached pages
-* and then commit them to the cache.
-*/
-VOID MmX64_TlbSpider(_In_ PVMM_PROCESS pProcess)
-{
- DWORD i = 0;
- BOOL result = FALSE;
- PMMX64_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage;
- if(pProcess->fTlbSpiderDone) { return; }
- if(!(pTlbSpiderStage = (PMMX64_TLB_SPIDER_STAGE_INTERNAL)LocalAlloc(LMEM_ZEROINIT, sizeof(MMX64_TLB_SPIDER_STAGE_INTERNAL)))) { return; }
- while(!result && (i < 3)) {
- result = MmX64_TlbSpider_Stage(pProcess->paDTB, 4, pProcess->fUserOnly, pTlbSpiderStage);
- if(pTlbSpiderStage->c) {
- MmX64_TlbSpider_ReadToCache(pTlbSpiderStage);
- }
- i++;
- }
- LocalFree(pTlbSpiderStage);
- pProcess->fTlbSpiderDone = TRUE;
-}
-
-const QWORD MMX64_PAGETABLEMAP_PML_REGION_SIZE[5] = { 0, 12, 21, 30, 39 };
-
-VOID MmX64_MapInitialize_Index(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MEMMAP_ENTRY pMemMap, _In_ PDWORD pcMemMap, _In_ QWORD vaBase, _In_ BYTE iPML, _In_ QWORD PTEs[512], _In_ BOOL fSupervisorPML, _In_ QWORD paMax)
-{
- PVMMOB_MEM pObNextPT;
- QWORD i, pte, va;
- BOOL fUserOnly, fNextSupervisorPML;
- PVMM_MEMMAP_ENTRY pMemMapEntry = pMemMap + *pcMemMap - 1;
- if(!pProcess->fTlbSpiderDone) {
- VmmTlbSpider(pProcess);
- }
- fUserOnly = pProcess->fUserOnly;
- for(i = 0; i < 512; i++) {
- pte = PTEs[i];
- if(!(pte & 0x01)) { continue; }
- if((pte & 0x0000fffffffff000) > paMax) { continue; }
- if(fSupervisorPML) { pte = pte & 0xfffffffffffffffb; }
- if(fUserOnly && !(pte & 0x04)) { continue; }
- va = vaBase + (i << MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
- // maps page
- if((iPML == 1) || (pte & 0x80) /* PS */) {
- if(iPML == 4) { continue; } // not supported - PML4 cannot map page directly
- if((*pcMemMap == 0) ||
- (pMemMapEntry->fPage != (pte & VMM_MEMMAP_PAGE_MASK)) ||
- (va != pMemMapEntry->AddrBase + (pMemMapEntry->cPages << 12))) {
- if(*pcMemMap + 1 >= VMM_MEMMAP_ENTRIES_MAX) { return; }
- pMemMapEntry = pMemMap + *pcMemMap;
- pMemMapEntry->AddrBase = va;
- pMemMapEntry->fPage = pte & VMM_MEMMAP_PAGE_MASK;
- pMemMapEntry->cPages = 1ULL << (MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML] - 12);
- *pcMemMap = *pcMemMap + 1;
- if(*pcMemMap >= VMM_MEMMAP_ENTRIES_MAX - 1) {
- return;
- }
- continue;
- }
- pMemMapEntry->cPages += 1ULL << (MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML] - 12);
- continue;
- }
- // maps page table (PDPT, PD, PT)
- fNextSupervisorPML = !(pte & 0x04);
- pObNextPT = VmmTlbGetPageTable(pte & 0x0000fffffffff000, FALSE);
- if(!pObNextPT) { continue; }
- MmX64_MapInitialize_Index(pProcess, pMemMap, pcMemMap, va, iPML - 1, pObNextPT->pqw, fNextSupervisorPML, paMax);
- VmmOb_DECREF(pObNextPT);
- pMemMapEntry = pMemMap + *pcMemMap - 1;
- }
-}
-
-VOID MmX64_MapCloseObCallback(_In_ PVOID pVmmOb)
-{
- PVMMOB_MEMMAP pObMemMap = (PVMMOB_MEMMAP)pVmmOb;
- if(pObMemMap->pObDisplay) {
- VmmOb_DECREF(pObMemMap->pObDisplay);
- }
-}
-
-_Success_(return)
-BOOL MmX64_MapInitialize(_In_ PVMM_PROCESS pProcess)
-{
- QWORD i;
- DWORD cMemMap = 0;
- PVMMOB_MEM pObPML4;
- PVMM_MEMMAP_ENTRY pMemMap = NULL;
- PVMMOB_MEMMAP pObMemMap = NULL;
- // already existing?
- if(pProcess && pProcess->pObMemMap) {
- return pProcess->pObMemMap->fValid;
- }
- EnterCriticalSection(&pProcess->LockUpdate);
- if(pProcess && pProcess->pObMemMap) {
- LeaveCriticalSection(&pProcess->LockUpdate);
- return pProcess->pObMemMap->fValid;
- }
- // allocate temporary buffer and walk page tables
- pObPML4 = VmmTlbGetPageTable(pProcess->paDTB, FALSE);
- if(pObPML4) {
- pMemMap = (PVMM_MEMMAP_ENTRY)LocalAlloc(LMEM_ZEROINIT, VMM_MEMMAP_ENTRIES_MAX * sizeof(VMM_MEMMAP_ENTRY));
- if(pMemMap) {
- MmX64_MapInitialize_Index(pProcess, pMemMap, &cMemMap, 0, 4, pObPML4->pqw, FALSE, ctxMain->dev.paMax);
- for(i = 0; i < cMemMap; i++) { // fixup sign extension for kernel addresses
- if(pMemMap[i].AddrBase & 0x0000800000000000) {
- pMemMap[i].AddrBase |= 0xffff000000000000;
- }
- }
- }
- VmmOb_DECREF(pObPML4);
- }
- // allocate VmmOb depending on result
- pObMemMap = VmmOb_Alloc('MM', 0, sizeof(VMMOB_MEMMAP) + cMemMap * sizeof(VMM_MEMMAP_ENTRY), MmX64_MapCloseObCallback, NULL);
- if(!pObMemMap) {
- LeaveCriticalSection(&pProcess->LockUpdate);
- LocalFree(pMemMap);
- return FALSE;
- }
- pObMemMap->fValid = cMemMap > 0;
- pObMemMap->fTagModules = FALSE;
- pObMemMap->fTagScan = FALSE;
- pObMemMap->cMap = cMemMap;
- pObMemMap->cbDisplay = cMemMap * MMX64_MEMMAP_DISPLAYBUFFER_LINE_LENGTH;
- pObMemMap->pObDisplay = NULL;
- if(cMemMap > 0) {
- memcpy(pObMemMap->pMap, pMemMap, cMemMap * sizeof(VMM_MEMMAP_ENTRY));
- }
- LocalFree(pMemMap);
- pProcess->pObMemMap = pObMemMap;
- LeaveCriticalSection(&pProcess->LockUpdate);
- return pObMemMap->fValid;
-}
-
-/*
-* Map a tag into the sorted memory map in O(log2) operations. Supply only one of szTag or wszTag.
-* -- pProcess
-* -- vaBase
-* -- vaLimit = limit == vaBase + size (== top address in range +1)
-* -- szTag
-* -- wszTag
-* -- fWoW64
-* -- fOverwrite
-*/
-VOID MmX64_MapTag(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ QWORD vaLimit, _In_opt_ LPSTR szTag, _In_opt_ LPWSTR wszTag, _In_ BOOL fWoW64, _In_ BOOL fOverwrite)
-{
- // NB! update here may take placey without acquiring the process 'LockUpdate'
- // Data is not super important so it should be ok. Also, in many cases the
- // lock will already be acquired by MapGetEntries function.
- PVMM_MEMMAP_ENTRY pMap;
- QWORD i, lvl, cMap;
- if(!MmX64_MapInitialize(pProcess)) { return; }
- pMap = pProcess->pObMemMap->pMap;
- cMap = pProcess->pObMemMap->cMap;
- if(!pMap || !cMap) { return; }
- // 1: locate base
- lvl = 1;
- i = cMap >> lvl;
- while(TRUE) {
- lvl++;
- if((cMap >> lvl) == 0) {
- break;
- }
- if(pMap[i].AddrBase > vaBase) {
- i -= (cMap >> lvl);
- } else {
- i += (cMap >> lvl);
- }
- }
- // 2: scan back if needed
- while(i && (pMap[i].AddrBase > vaBase)) {
- i--;
- }
- // 3: fill in tag
- while((i < cMap) && (pMap[i].AddrBase + (pMap[i].cPages << 12) <= vaLimit)) {
- if((pMap[i].AddrBase >= vaBase) && (fOverwrite || !pMap[i].szTag[0])) {
- pMap[i].fWoW64 = fWoW64;
- if(wszTag) {
- snprintf(pMap[i].szTag, 31, "%S", wszTag);
- }
- if(szTag) {
- snprintf(pMap[i].szTag, 31, "%s", szTag);
- }
- }
- i++;
- }
-}
-
-_Success_(return)
-BOOL MmX64_MapGetEntries(_In_ PVMM_PROCESS pProcess, _In_ DWORD flags, _Out_ PVMMOB_MEMMAP *ppObMemMap)
-{
- DWORD i;
- PVMM_MODULEMAP_ENTRY pModule;
- PVMMOB_MODULEMAP pObModuleMap;
- if(!MmX64_MapInitialize(pProcess)) { return FALSE; }
- if((!pProcess->pObMemMap->fTagModules && (flags & VMM_MEMMAP_FLAG_MODULES)) || (!pProcess->pObMemMap->fTagScan && (flags & VMM_MEMMAP_FLAG_SCAN))) {
- EnterCriticalSection(&pProcess->LockUpdate);
- if(!pProcess->pObMemMap->fTagModules && (flags & VMM_MEMMAP_FLAG_MODULES)) {
- pProcess->pObMemMap->fTagModules = TRUE;
- if(VmmProc_ModuleMapGet(pProcess, &pObModuleMap)) {
- // update memory map with names
- for(i = 0; i < pObModuleMap->cMap; i++) {
- pModule = pObModuleMap->pMap + i;
- MmX64_MapTag(pProcess, pModule->BaseAddress, pModule->BaseAddress + pModule->SizeOfImage, pModule->szName, NULL, pModule->fWoW64, FALSE);
- }
- VmmOb_DECREF(pObModuleMap);
- }
- }
- if(!pProcess->pObMemMap->fTagScan && (flags & VMM_MEMMAP_FLAG_SCAN)) {
- pProcess->pObMemMap->fTagScan = TRUE;
- VmmProc_ScanTagsMemMap(pProcess);
- }
- LeaveCriticalSection(&pProcess->LockUpdate);
- }
- *ppObMemMap = VmmOb_INCREF(pProcess->pObMemMap);
- return TRUE;
-}
-
-_Success_(return)
-BOOL MmX64_MapGetDisplay(_In_ PVMM_PROCESS pProcess, _In_ DWORD flags, _Out_ PVMMOB_PDATA *ppObDisplay)
-{
- DWORD i, o = 0;
- PVMMOB_MEMMAP pObMemMap = NULL;
- PVMMOB_PDATA pObDisplay = NULL;
- // memory map display data already exists
- if(!MmX64_MapInitialize(pProcess)) { return FALSE; }
- if(pProcess->pObMemMap->pObDisplay) {
- *ppObDisplay = VmmOb_INCREF(pProcess->pObMemMap->pObDisplay);
- return TRUE;
- }
- // create new memory map display data
- EnterCriticalSection(&pProcess->LockUpdate);
- if(!pProcess->pObMemMap->pObDisplay) {
- if(MmX64_MapGetEntries(pProcess, flags, &pObMemMap)) {
- pObDisplay = VmmOb_Alloc('MD', LMEM_ZEROINIT, pObMemMap->cbDisplay, NULL, NULL);
- if(pObDisplay) {
- for(i = 0; i < pObMemMap->cMap; i++) {
- if(o + MMX64_MEMMAP_DISPLAYBUFFER_LINE_LENGTH > pObMemMap->cbDisplay) {
- vmmprintf_fn("ERROR: SHOULD NOT HAPPEN! LENGTH DIFFERS #1: %i %i\n", o + MMX64_MEMMAP_DISPLAYBUFFER_LINE_LENGTH, pObMemMap->cbDisplay);
- VmmOb_DECREF(pObDisplay);
- pObDisplay = NULL;
- goto fail;
- }
- o += snprintf(
- pObDisplay->pbData + o,
- pObMemMap->cbDisplay - o - MMX64_MEMMAP_DISPLAYBUFFER_LINE_LENGTH,
- "%04x %8x %016llx-%016llx %sr%s%s%s%-32s\n",
- i,
- (DWORD)pObMemMap->pMap[i].cPages,
- pObMemMap->pMap[i].AddrBase,
- pObMemMap->pMap[i].AddrBase + (pObMemMap->pMap[i].cPages << 12) - 1,
- pObMemMap->pMap[i].fPage & VMM_MEMMAP_PAGE_NS ? "-" : "s",
- pObMemMap->pMap[i].fPage & VMM_MEMMAP_PAGE_W ? "w" : "-",
- pObMemMap->pMap[i].fPage & VMM_MEMMAP_PAGE_NX ? "-" : "x",
- pObMemMap->pMap[i].szTag[0] ? (pObMemMap->pMap[i].fWoW64 ? " 32 " : " ") : " ",
- pObMemMap->pMap[i].szTag
- );
- }
- if(o != pObMemMap->cbDisplay) {
- vmmprintf_fn("ERROR: SHOULD NOT HAPPEN! LENGTH DIFFERS #2: %i %i\n", o, pObMemMap->cbDisplay);
- VmmOb_DECREF(pObDisplay);
- pObDisplay = NULL;
- goto fail;
- }
- }
- }
- pProcess->pObMemMap->pObDisplay = pObDisplay;
- }
-fail:
- VmmOb_DECREF(pObMemMap);
- LeaveCriticalSection(&pProcess->LockUpdate);
- if(pProcess->pObMemMap->pObDisplay) {
- *ppObDisplay = VmmOb_INCREF(pProcess->pObMemMap->pObDisplay);
- return TRUE;
- }
- return FALSE;
-}
-
-_Success_(return)
-BOOL MmX64_Virt2Phys(_In_ QWORD paPT, _In_ BOOL fUserOnly, _In_ BYTE iPML, _In_ QWORD va, _Out_ PQWORD ppa)
-{
- QWORD pte, i, qwMask;
- PVMMOB_MEM pObPTEs;
- if(iPML == (BYTE)-1) { iPML = 4; }
- pObPTEs = VmmTlbGetPageTable(paPT & 0x0000fffffffff000, FALSE);
- if(!pObPTEs) { return FALSE; }
- i = 0x1ff & (va >> MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
- pte = pObPTEs->pqw[i];
- VmmOb_DECREF(pObPTEs);
- if(!(pte & 0x01)) { return FALSE; } // NOT VALID
- if(fUserOnly && !(pte & 0x04)) { return FALSE; } // SUPERVISOR PAGE & USER MODE REQ
- if(pte & 0x000f000000000000) { return FALSE; } // RESERVED
- if((iPML == 1) || (pte & 0x80) /* PS */) {
- if(iPML == 4) { return FALSE; } // NO SUPPORT IN PML4
- qwMask = 0xffffffffffffffff << MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML];
- *ppa = pte & 0x0000fffffffff000 & qwMask; // MASK AWAY BITS FOR 4kB/2MB/1GB PAGES
- qwMask = qwMask ^ 0xffffffffffffffff;
- *ppa = *ppa | (qwMask & va); // FILL LOWER ADDRESS BITS
- return TRUE;
- }
- return MmX64_Virt2Phys(pte, fUserOnly, iPML - 1, va, ppa);
-}
-
-VOID MmX64_Virt2PhysGetInformation_DoWork(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo, _In_ BYTE iPML, _In_ QWORD PTEs[512])
-{
- QWORD pte, i, qwMask;
- PVMMOB_MEM pObNextPT;
- i = 0x1ff & (pVirt2PhysInfo->va >> MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
- pte = PTEs[i];
- pVirt2PhysInfo->iPTEs[iPML] = (WORD)i;
- pVirt2PhysInfo->PTEs[iPML] = pte;
- if(!(pte & 0x01)) { return; } // NOT VALID
- if(pProcess->fUserOnly && !(pte & 0x04)) { return; } // SUPERVISOR PAGE & USER MODE REQ
- if(pte & 0x000f000000000000) { return; } // RESERVED
- if((iPML == 1) || (pte & 0x80) /* PS */) {
- if(iPML == 4) { return; } // NO SUPPORT IN PML4
- qwMask = 0xffffffffffffffff << MMX64_PAGETABLEMAP_PML_REGION_SIZE[iPML];
- pVirt2PhysInfo->pas[0] = pte & 0x0000fffffffff000 & qwMask; // MASK AWAY BITS FOR 4kB/2MB/1GB PAGES
- qwMask = qwMask ^ 0xffffffffffffffff;
- pVirt2PhysInfo->pas[0] = pVirt2PhysInfo->pas[0] | (qwMask & pVirt2PhysInfo->va); // FILL LOWER ADDRESS BITS
- return;
- }
- pObNextPT = VmmTlbGetPageTable(pte & 0x0000fffffffff000, FALSE);
- if(!pObNextPT) { return; }
- pVirt2PhysInfo->pas[iPML - 1] = pte & 0x0000fffffffff000;
- MmX64_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, iPML - 1, pObNextPT->pqw);
- VmmOb_DECREF(pObNextPT);
-}
-
-VOID MmX64_Virt2PhysGetInformation(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo)
-{
- QWORD va;
- PVMMOB_MEM pObPML4;
- va = pVirt2PhysInfo->va;
- ZeroMemory(pVirt2PhysInfo, sizeof(VMM_VIRT2PHYS_INFORMATION));
- pVirt2PhysInfo->tpMemoryModel = VMM_MEMORYMODEL_X64;
- pVirt2PhysInfo->va = va;
- pVirt2PhysInfo->pas[4] = pProcess->paDTB;
- pObPML4 = VmmTlbGetPageTable(pProcess->paDTB, FALSE);
- if(!pObPML4) { return; }
- MmX64_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, 4, pObPML4->pqw);
- VmmOb_DECREF(pObPML4);
-}
-
-VOID MmX64_Close()
-{
- ctxVmm->f32 = FALSE;
- ctxVmm->tpMemoryModel = VMM_MEMORYMODEL_NA;
- ZeroMemory(&ctxVmm->fnMemoryModel, sizeof(VMM_MEMORYMODEL_FUNCTIONS));
-}
-
-VOID MmX64_Initialize()
-{
- if(ctxVmm->fnMemoryModel.pfnClose) {
- ctxVmm->fnMemoryModel.pfnClose();
- }
- ctxVmm->fnMemoryModel.pfnClose = MmX64_Close;
- ctxVmm->fnMemoryModel.pfnVirt2Phys = MmX64_Virt2Phys;
- ctxVmm->fnMemoryModel.pfnVirt2PhysGetInformation = MmX64_Virt2PhysGetInformation;
- ctxVmm->fnMemoryModel.pfnMapInitialize = MmX64_MapInitialize;
- ctxVmm->fnMemoryModel.pfnMapTag = MmX64_MapTag;
- ctxVmm->fnMemoryModel.pfnMapGetEntries = MmX64_MapGetEntries;
- ctxVmm->fnMemoryModel.pfnMapGetDisplay = MmX64_MapGetDisplay;
- ctxVmm->fnMemoryModel.pfnTlbSpider = MmX64_TlbSpider;
- ctxVmm->fnMemoryModel.pfnTlbPageTableVerify = MmX64_TlbPageTableVerify;
- ctxVmm->tpMemoryModel = VMM_MEMORYMODEL_X64;
- ctxVmm->f32 = FALSE;
-}
diff --git a/vmm/mm_x64.h b/vmm/mm_x64.h
deleted file mode 100644
index e2e1126..0000000
--- a/vmm/mm_x64.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// mm_x64.h : definitions related to the x64 / IA32e / long-mode paging / memory model.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __MM_X64_H__
-#define __MM_X64_H__
-#include "vmm.h"
-
-/*
-* Initialize the X64 / IA32e / Long-Mode paging / memory model.
-* If a previous memory model exists that memory model is first closed before
-* the new X64 memory model is initialized.
-*/
-VOID MmX64_Initialize();
-
-#endif /* __MM_X64_H__ */
diff --git a/vmm/mm_x64_winpaged.c b/vmm/mm_x64_winpaged.c
deleted file mode 100644
index 3d204ad..0000000
--- a/vmm/mm_x64_winpaged.c
+++ /dev/null
@@ -1,54 +0,0 @@
-// mm_x64_winpaged.c : implementation related to the x64 windows paging subsystem
-// (including paged out virtual/compressed virtual memory).
-//
-// (c) Ulf Frisk, 2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include "mm_x64_winpaged.h"
-
-#define COMPRESS_ALGORITHM_INVALID 0
-#define COMPRESS_ALGORITHM_NULL 1
-#define COMPRESS_ALGORITHM_MSZIP 2
-#define COMPRESS_ALGORITHM_XPRESS 3
-#define COMPRESS_ALGORITHM_XPRESS_HUFF 4
-#define COMPRESS_ALGORITHM_LZMS 5
-#define COMPRESS_ALGORITHM_MAX 6
-#define COMPRESS_RAW (1 << 29)
-
-_Success_(return)
-BOOL MmX64WinPaged_MemCompression_DecompressPage(_In_ QWORD vaCompressedData, _In_opt_ DWORD cbCompressedData, _Out_writes_(4096) PBYTE pbDecompressedPage, _Out_opt_ PDWORD pcbCompressedData)
-{
- BOOL result = FALSE;
- DWORD i, cbReadCompressedData = 0, cbDecompressed = 0;
- BYTE pbCompressed[0x1000] = { 0 };
- PVMM_PROCESS pObProcess = NULL;
- if(pcbCompressedData) { *pcbCompressedData = 0; }
- if(!ctxVmm->fn.RtlDecompressBuffer) { return FALSE; }
- if(cbCompressedData > 0x1000) { return FALSE; }
- if(!ctxVmm->kernel.dwPidMemCompression) { return FALSE; }
- if(!(pObProcess = VmmProcessGet(ctxVmm->kernel.dwPidMemCompression))) { return FALSE; }
- // buffer size specified - use value!
- if(cbCompressedData) {
- result =
- VmmRead(pObProcess, vaCompressedData, pbCompressed, cbCompressedData) &&
- (VMM_STATUS_SUCCESS == ctxVmm->fn.RtlDecompressBuffer(COMPRESS_ALGORITHM_XPRESS, pbDecompressedPage, 0x1000, pbCompressed, cbCompressedData, &cbDecompressed)) &&
- (cbDecompressed == 0x1000);
- VmmOb_DECREF(pObProcess); pObProcess = NULL;
- if(pcbCompressedData) { *pcbCompressedData = cbCompressedData; }
- return result;
- }
- // buffer not specified - try auto-detect!
- VmmReadEx(pObProcess, vaCompressedData, pbCompressed, 0x1000, &cbReadCompressedData, VMM_FLAG_ZEROPAD_ON_FAIL);
- VmmOb_DECREF(pObProcess); pObProcess = NULL;
- if(cbReadCompressedData < 0x10) { return FALSE; }
- for(i = 0x10; i < 0x1000; i++) {
- result =
- (VMM_STATUS_SUCCESS == ctxVmm->fn.RtlDecompressBuffer(COMPRESS_ALGORITHM_XPRESS, pbDecompressedPage, 0x1000, pbCompressed, i, &cbDecompressed)) &&
- (cbDecompressed == 0x1000);
- if(result) {
- if(pcbCompressedData) { *pcbCompressedData = i; }
- return TRUE;
- }
- }
- return FALSE;
-}
diff --git a/vmm/mm_x64_winpaged.h b/vmm/mm_x64_winpaged.h
deleted file mode 100644
index 4b387ea..0000000
--- a/vmm/mm_x64_winpaged.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// mm_x64_winpaged.h : definitions related to the x64 windows paging subsystem
-// (including paged out virtual/compressed virtual memory).
-//
-// (c) Ulf Frisk, 2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __MM_X64_WINPAGED_H__
-#define __MM_X64_WINPAGED_H__
-#include "vmm.h"
-
-/*
-* Decompress compressed memory page stored in the MemCompression process.
-* -- vaCompressedData = virtual address in 'MemCompression' to decompress.
-* -- cbCompressedData = length of compressed data in 'MemCompression' to decompress.
-* -- pbDecompressedPage
-* -- return
-*/
-_Success_(return)
-BOOL MmX64WinPaged_MemCompression_DecompressPage(
- _In_ QWORD vaCompressedData,
- _In_opt_ DWORD cbCompressedData,
- _Out_writes_(4096) PBYTE pbDecompressedPage,
- _Out_opt_ PDWORD pcbCompressedData
-);
-
-#endif /* __MM_X64_WINPAGED_H__ */
diff --git a/vmm/mm_x86.c b/vmm/mm_x86.c
deleted file mode 100644
index 432a44b..0000000
--- a/vmm/mm_x86.c
+++ /dev/null
@@ -1,398 +0,0 @@
-// mm_x86.c : implementation of the x86 32-bit protected mode memory model.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include "vmm.h"
-#include "vmmproc.h"
-
-#define MMX86_MEMMAP_DISPLAYBUFFER_LINE_LENGTH 70
-
-/*
-* Tries to verify that a loaded page table is correct. If just a bit strange
-* bytes/ptes supplied in pb will be altered to look better.
-*/
-BOOL MmX86_TlbPageTableVerify(_Inout_ PBYTE pb, _In_ QWORD pa, _In_ BOOL fSelfRefReq)
-{
- return TRUE;
-}
-
-#define VMMX64_TLB_SIZE_STAGEBUF 0x400
-
-typedef struct tdMMX86_TLB_SPIDER_STAGE_INTERNAL {
- QWORD c;
- PMEM_IO_SCATTER_HEADER ppMEMs[VMMX64_TLB_SIZE_STAGEBUF];
- PVMMOB_MEM ppObMEMs[VMMX64_TLB_SIZE_STAGEBUF];
-} MMX86_TLB_SPIDER_STAGE_INTERNAL, *PMMX86_TLB_SPIDER_STAGE_INTERNAL;
-
-VOID MmX86_TlbSpider_ReadToCache(PMMX86_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
-{
- QWORD i;
- LeechCore_ReadScatter(pTlbSpiderStage->ppMEMs, (DWORD)pTlbSpiderStage->c);
- for(i = 0; i < pTlbSpiderStage->c; i++) {
- MmX86_TlbPageTableVerify(pTlbSpiderStage->ppObMEMs[i]->h.pb, pTlbSpiderStage->ppObMEMs[i]->h.qwA, FALSE);
- VmmCacheReserveReturn(pTlbSpiderStage->ppObMEMs[i]);
- }
- pTlbSpiderStage->c = 0;
-}
-
-/*
-* Iterate over the PD to retrieve uncached PT pages and then commit them to the cache.
-*/
-VOID MmX86_TlbSpider(_In_ PVMM_PROCESS pProcess)
-{
- PMMX86_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage = NULL;
- PVMMOB_MEM pObPD = NULL;
- DWORD i, pte;
- if(pProcess->fTlbSpiderDone) { return; }
- if(!(pTlbSpiderStage = (PMMX86_TLB_SPIDER_STAGE_INTERNAL)LocalAlloc(LMEM_ZEROINIT, sizeof(MMX86_TLB_SPIDER_STAGE_INTERNAL)))) { return; }
- pObPD = VmmTlbGetPageTable(pProcess->paDTB & 0xfffff000, FALSE);
- if(!pObPD) { goto fail; }
- for(i = 0; i < 1024; i++) {
- pte = pObPD->pdw[i];
- if(!(pte & 0x01)) { continue; } // not valid
- if(pte & 0x80) { continue; } // not valid ptr to PT
- if(pProcess->fUserOnly && !(pte & 0x04)) { continue; } // supervisor page when fUserOnly -> not valid
- if(!VmmCacheExists(VMM_CACHE_TAG_TLB, pte & 0xfffff000)) {
- pTlbSpiderStage->ppObMEMs[pTlbSpiderStage->c] = VmmCacheReserve(VMM_CACHE_TAG_TLB);
- pTlbSpiderStage->ppMEMs[pTlbSpiderStage->c] = &pTlbSpiderStage->ppObMEMs[pTlbSpiderStage->c]->h;
- pTlbSpiderStage->ppMEMs[pTlbSpiderStage->c]->qwA = pte & 0xfffff000;
- pTlbSpiderStage->c++;
- }
- }
- MmX86_TlbSpider_ReadToCache(pTlbSpiderStage);
- pProcess->fTlbSpiderDone = TRUE;
-fail:
- LocalFree(pTlbSpiderStage);
- VmmOb_DECREF(pObPD);
-}
-
-const QWORD MMX86_PAGETABLEMAP_PML_REGION_SIZE[3] = { 0, 12, 22 };
-
-VOID MmX86_MapInitialize_Index(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MEMMAP_ENTRY pMemMap, _In_ PDWORD pcMemMap, _In_ DWORD vaBase, _In_ BYTE iPML, _In_ DWORD PTEs[1024], _In_ BOOL fSupervisorPML, _In_ QWORD paMax)
-{
- PVMMOB_MEM pObNextPT;
- DWORD i, va, pte;
- BOOL fUserOnly, fNextSupervisorPML;
- PVMM_MEMMAP_ENTRY pMemMapEntry = pMemMap + *pcMemMap - 1;
- fUserOnly = pProcess->fUserOnly;
- for(i = 0; i < 1024; i++) {
- pte = PTEs[i];
- if(!(pte & 0x01)) { continue; }
- if((pte & 0xfffff000) > paMax) { continue; }
- if(fSupervisorPML) { pte = pte & 0xfffffffb; }
- if(fUserOnly && !(pte & 0x04)) { continue; }
- va = vaBase + (i << MMX86_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
- if((iPML == 1) || (pte & 0x80) /* PS */) {
- if((*pcMemMap == 0) ||
- (pMemMapEntry->fPage != (pte & VMM_MEMMAP_PAGE_MASK)) ||
- (va != pMemMapEntry->AddrBase + (pMemMapEntry->cPages << 12))) {
- if(*pcMemMap + 1 >= VMM_MEMMAP_ENTRIES_MAX) { return; }
- pMemMapEntry = pMemMap + *pcMemMap;
- pMemMapEntry->AddrBase = va;
- pMemMapEntry->fPage = pte & VMM_MEMMAP_PAGE_MASK;
- pMemMapEntry->cPages = 1ULL << (MMX86_PAGETABLEMAP_PML_REGION_SIZE[iPML] - 12);
- *pcMemMap = *pcMemMap + 1;
- if(*pcMemMap >= VMM_MEMMAP_ENTRIES_MAX - 1) { return; }
- continue;
- }
- pMemMapEntry->cPages += 1ULL << (MMX86_PAGETABLEMAP_PML_REGION_SIZE[iPML] - 12);
- continue;
- }
- // maps page table
- fNextSupervisorPML = !(pte & 0x04);
- pObNextPT = VmmTlbGetPageTable(pte & 0xfffff000, FALSE);
- if(!pObNextPT) { continue; }
- MmX86_MapInitialize_Index(pProcess, pMemMap, pcMemMap, va, 1, pObNextPT->pdw, fNextSupervisorPML, paMax);
- VmmOb_DECREF(pObNextPT);
- pMemMapEntry = pMemMap + *pcMemMap - 1;
- }
-}
-
-VOID MmX86_MapCloseObCallback(_In_ PVOID pVmmOb)
-{
- PVMMOB_MEMMAP pObMemMap = (PVMMOB_MEMMAP)pVmmOb;
- if(pObMemMap->pObDisplay) {
- VmmOb_DECREF(pObMemMap->pObDisplay);
- }
-}
-
-_Success_(return)
-BOOL MmX86_MapInitialize(_In_ PVMM_PROCESS pProcess)
-{
- PVMMOB_MEM pObPD;
- DWORD cMemMap = 0;
- PVMM_MEMMAP_ENTRY pMemMap = NULL;
- PVMMOB_MEMMAP pObMemMap = NULL;
- // already existing?
- if(pProcess && pProcess->pObMemMap) {
- return pProcess->pObMemMap->fValid;
- }
- EnterCriticalSection(&pProcess->LockUpdate);
- if(pProcess && pProcess->pObMemMap) {
- LeaveCriticalSection(&pProcess->LockUpdate);
- return pProcess->pObMemMap->fValid;
- }
- // allocate temporary buffer and walk page tables
- VmmTlbSpider(pProcess);
- pObPD = VmmTlbGetPageTable(pProcess->paDTB & 0xfffff000, FALSE);
- if(pObPD) {
- pMemMap = (PVMM_MEMMAP_ENTRY)LocalAlloc(LMEM_ZEROINIT, VMM_MEMMAP_ENTRIES_MAX * sizeof(VMM_MEMMAP_ENTRY));
- if(pMemMap) {
- MmX86_MapInitialize_Index(pProcess, pMemMap, &cMemMap, 0, 2, pObPD->pdw, FALSE, ctxMain->dev.paMax);
- }
- VmmOb_DECREF(pObPD);
- }
- // allocate VmmOb depending on result
- pObMemMap = VmmOb_Alloc('MM', 0, sizeof(VMMOB_MEMMAP) + cMemMap * sizeof(VMM_MEMMAP_ENTRY), MmX86_MapCloseObCallback, NULL);
- if(!pObMemMap) {
- LeaveCriticalSection(&pProcess->LockUpdate);
- LocalFree(pMemMap);
- return FALSE;
- }
- pObMemMap->fValid = cMemMap > 0;
- pObMemMap->fTagModules = FALSE;
- pObMemMap->fTagScan = FALSE;
- pObMemMap->cMap = cMemMap;
- pObMemMap->cbDisplay = cMemMap * MMX86_MEMMAP_DISPLAYBUFFER_LINE_LENGTH;
- pObMemMap->pObDisplay = NULL;
- if(cMemMap > 0) {
- memcpy(pObMemMap->pMap, pMemMap, cMemMap * sizeof(VMM_MEMMAP_ENTRY));
- }
- LocalFree(pMemMap);
- pProcess->pObMemMap = pObMemMap;
- LeaveCriticalSection(&pProcess->LockUpdate);
- return pObMemMap->fValid;
-}
-
-/*
-* Map a tag into the sorted memory map in O(log2) operations. Supply only one of szTag or wszTag.
-* -- pProcess
-* -- vaBase
-* -- vaLimit = limit == vaBase + size (== top address in range +1)
-* -- szTag
-* -- wszTag
-* -- fWoW64
-* -- fOverwrite
-*/
-VOID MmX86_MapTag(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ QWORD vaLimit, _In_opt_ LPSTR szTag, _In_opt_ LPWSTR wszTag, _In_ BOOL fWoW64, _In_ BOOL fOverwrite)
-{
- // NB! update here may take placey without acquiring the process 'LockUpdate'
- // Data is not super important so it should be ok. Also, in many cases the
- // lock will already be acquired by MapGetEntries function.
- PVMM_MEMMAP_ENTRY pMap;
- QWORD i, lvl, cMap;
- if(!MmX86_MapInitialize(pProcess)) { return; }
- if((vaBase > 0xffffffff) || (vaLimit > 0xffffffff)) { return; }
- pMap = pProcess->pObMemMap->pMap;
- cMap = pProcess->pObMemMap->cMap;
- if(!pMap || !cMap) { return; }
- // 1: locate base
- lvl = 1;
- i = cMap >> lvl;
- while(TRUE) {
- lvl++;
- if((cMap >> lvl) == 0) {
- break;
- }
- if(pMap[i].AddrBase > vaBase) {
- i -= (cMap >> lvl);
- } else {
- i += (cMap >> lvl);
- }
- }
- // 2: scan back if needed
- while(i && (pMap[i].AddrBase > vaBase)) {
- i--;
- }
- // 3: fill in tag
- while((i < cMap) && (pMap[i].AddrBase + (pMap[i].cPages << 12) <= vaLimit)) {
- if((pMap[i].AddrBase >= vaBase) && (fOverwrite || !pMap[i].szTag[0])) {
- if(wszTag) {
- snprintf(pMap[i].szTag, 31, "%S", wszTag);
- }
- if(szTag) {
- snprintf(pMap[i].szTag, 31, "%s", szTag);
- }
- }
- i++;
- }
-}
-
-_Success_(return)
-BOOL MmX86_MapGetEntries(_In_ PVMM_PROCESS pProcess, _In_ DWORD flags, _Out_ PVMMOB_MEMMAP *ppObMemMap)
-{
- DWORD i;
- PVMM_MODULEMAP_ENTRY pModule;
- PVMMOB_MODULEMAP pObModuleMap;
- if(!MmX86_MapInitialize(pProcess)) { return FALSE; }
- if((!pProcess->pObMemMap->fTagModules && (flags & VMM_MEMMAP_FLAG_MODULES)) || (!pProcess->pObMemMap->fTagScan && (flags & VMM_MEMMAP_FLAG_SCAN))) {
- EnterCriticalSection(&pProcess->LockUpdate);
- if(!pProcess->pObMemMap->fTagModules && (flags & VMM_MEMMAP_FLAG_MODULES)) {
- pProcess->pObMemMap->fTagModules = TRUE;
- if(VmmProc_ModuleMapGet(pProcess, &pObModuleMap)) {
- // update memory map with names
- for(i = 0; i < pObModuleMap->cMap; i++) {
- pModule = pObModuleMap->pMap + i;
- MmX86_MapTag(pProcess, pModule->BaseAddress, pModule->BaseAddress + pModule->SizeOfImage, pModule->szName, NULL, FALSE, FALSE);
- }
- VmmOb_DECREF(pObModuleMap);
- }
- }
- if(!pProcess->pObMemMap->fTagScan && (flags & VMM_MEMMAP_FLAG_SCAN)) {
- pProcess->pObMemMap->fTagScan = TRUE;
- VmmProc_ScanTagsMemMap(pProcess);
- }
- LeaveCriticalSection(&pProcess->LockUpdate);
- }
- *ppObMemMap = VmmOb_INCREF(pProcess->pObMemMap);
- return TRUE;
-}
-
-_Success_(return)
-BOOL MmX86_MapGetDisplay(_In_ PVMM_PROCESS pProcess, _In_ DWORD flags, _Out_ PVMMOB_PDATA *ppObDisplay)
-{
- DWORD i, o = 0;
- PVMMOB_MEMMAP pObMemMap = NULL;
- PVMMOB_PDATA pObDisplay = NULL;
- // memory map display data already exists
- if(!MmX86_MapInitialize(pProcess)) { return FALSE; }
- if(pProcess->pObMemMap->pObDisplay) {
- *ppObDisplay = VmmOb_INCREF(pProcess->pObMemMap->pObDisplay);
- return TRUE;
- }
- // create new memory map display data
- EnterCriticalSection(&pProcess->LockUpdate);
- if(!pProcess->pObMemMap->pObDisplay) {
- if(MmX86_MapGetEntries(pProcess, flags, &pObMemMap)) {
- pObDisplay = VmmOb_Alloc('MD', LMEM_ZEROINIT, pObMemMap->cbDisplay, NULL, NULL);
- if(pObDisplay) {
- for(i = 0; i < pObMemMap->cMap; i++) {
- if(o + MMX86_MEMMAP_DISPLAYBUFFER_LINE_LENGTH > pObMemMap->cbDisplay) {
- vmmprintf_fn("ERROR: SHOULD NOT HAPPEN! LENGTH DIFFERS #1: %i %i\n", o + MMX86_MEMMAP_DISPLAYBUFFER_LINE_LENGTH, pObMemMap->cbDisplay);
- VmmOb_DECREF(pObDisplay);
- pObDisplay = NULL;
- goto fail;
- }
- o += snprintf(
- pObDisplay->pbData + o,
- pObMemMap->cbDisplay - o - MMX86_MEMMAP_DISPLAYBUFFER_LINE_LENGTH,
- "%04x %8x %08x-%08x %sr%sx %-32s\n",
- i,
- (DWORD)pObMemMap->pMap[i].cPages,
- (DWORD)pObMemMap->pMap[i].AddrBase,
- (DWORD)(pObMemMap->pMap[i].AddrBase + (pObMemMap->pMap[i].cPages << 12) - 1),
- pObMemMap->pMap[i].fPage & VMM_MEMMAP_PAGE_NS ? "-" : "s",
- pObMemMap->pMap[i].fPage & VMM_MEMMAP_PAGE_W ? "w" : "-",
- pObMemMap->pMap[i].szTag
- );
- }
- if(o != pObMemMap->cbDisplay) {
- vmmprintf_fn("ERROR: SHOULD NOT HAPPEN! LENGTH DIFFERS #2: %i %i\n", o, pObMemMap->cbDisplay);
- VmmOb_DECREF(pObDisplay);
- pObDisplay = NULL;
- goto fail;
- }
- }
- }
- pProcess->pObMemMap->pObDisplay = pObDisplay;
- }
-fail:
- VmmOb_DECREF(pObMemMap);
- LeaveCriticalSection(&pProcess->LockUpdate);
- if(pProcess->pObMemMap->pObDisplay) {
- *ppObDisplay = VmmOb_INCREF(pProcess->pObMemMap->pObDisplay);
- return TRUE;
- }
- return FALSE;
-}
-
-_Success_(return)
-BOOL MmX86_Virt2Phys(_In_ QWORD paPT, _In_ BOOL fUserOnly, _In_ BYTE iPML, _In_ QWORD va, _Out_ PQWORD ppa)
-{
- DWORD pte, i;
- PVMMOB_MEM pObPTEs;
- //PBYTE pbPTEs;
- if(va > 0xffffffff) { return FALSE; }
- if(paPT > 0xffffffff) { return FALSE; }
- if(iPML == (BYTE)-1) { iPML = 2; }
- pObPTEs = VmmTlbGetPageTable(paPT & 0xfffff000, FALSE);
- if(!pObPTEs) { return FALSE; }
- i = 0x3ff & (va >> MMX86_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
- pte = pObPTEs->pdw[i];
- VmmOb_DECREF(pObPTEs);
- if(!(pte & 0x01)) { return FALSE; } // NOT VALID
- if(fUserOnly && !(pte & 0x04)) { return FALSE; } // SUPERVISOR PAGE & USER MODE REQ
- if((iPML == 2) && !(pte & 0x80) /* PS */) {
- return MmX86_Virt2Phys(pte, fUserOnly, 1, va, ppa);
- }
- if(iPML == 1) { // 4kB PAGE
- *ppa = pte & 0xfffff000;
- return TRUE;
- }
- // 4MB PAGE
- if(pte & 0x003e0000) { return FALSE; } // RESERVED
- *ppa = (((QWORD)(pte & 0x0001e000)) << (32 - 13)) + (pte & 0xffc00000) + (va & 0x003ff000);
- return TRUE;
-}
-
-VOID MmX86_Virt2PhysGetInformation_DoWork(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo, _In_ BYTE iPML, _In_ QWORD paPT)
-{
- PVMMOB_MEM pObPTEs;
- DWORD pte, i;
- pObPTEs = VmmTlbGetPageTable(paPT, FALSE);
- if(!pObPTEs) { return; }
- i = 0x3ff & (pVirt2PhysInfo->va >> MMX86_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
- pte = pObPTEs->pdw[i];
- VmmOb_DECREF(pObPTEs);
- pVirt2PhysInfo->pas[iPML] = paPT;
- pVirt2PhysInfo->iPTEs[iPML] = (WORD)i;
- pVirt2PhysInfo->PTEs[iPML] = pte;
- if(!(pte & 0x01)) { return; } // NOT VALID
- if(pProcess->fUserOnly && !(pte & 0x04)) { return; } // SUPERVISOR PAGE & USER MODE REQ
- if(iPML == 1) { // 4kB page
- pVirt2PhysInfo->pas[0] = pte & 0xfffff000;
- return;
- }
- if(pte & 0x80) { // 4MB page
- if(pte & 0x003e0000) { return; } // RESERVED
- pVirt2PhysInfo->pas[0] = (pte & 0xffc00000) + (((QWORD)(pte & 0x0001e000)) << (32 - 13));
- return;
- }
- MmX86_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, 1, pte & 0xffff000); // PDE
-}
-
-VOID MmX86_Virt2PhysGetInformation(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo)
-{
- QWORD va;
- if(pVirt2PhysInfo->va > 0xffffffff) { return; }
- va = pVirt2PhysInfo->va;
- ZeroMemory(pVirt2PhysInfo, sizeof(VMM_VIRT2PHYS_INFORMATION));
- pVirt2PhysInfo->tpMemoryModel = VMM_MEMORYMODEL_X86;
- pVirt2PhysInfo->va = va;
- MmX86_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, 2, pProcess->paDTB & 0xfffff000);
-}
-
-VOID MmX86_Close()
-{
- ctxVmm->f32 = FALSE;
- ctxVmm->tpMemoryModel = VMM_MEMORYMODEL_NA;
- ZeroMemory(&ctxVmm->fnMemoryModel, sizeof(VMM_MEMORYMODEL_FUNCTIONS));
-}
-
-VOID MmX86_Initialize()
-{
- if(ctxVmm->fnMemoryModel.pfnClose) {
- ctxVmm->fnMemoryModel.pfnClose();
- }
- ctxVmm->fnMemoryModel.pfnClose = MmX86_Close;
- ctxVmm->fnMemoryModel.pfnVirt2Phys = MmX86_Virt2Phys;
- ctxVmm->fnMemoryModel.pfnVirt2PhysGetInformation = MmX86_Virt2PhysGetInformation;
- ctxVmm->fnMemoryModel.pfnMapTag = MmX86_MapTag;
- ctxVmm->fnMemoryModel.pfnMapGetEntries = MmX86_MapGetEntries;
- ctxVmm->fnMemoryModel.pfnMapGetDisplay = MmX86_MapGetDisplay;
- ctxVmm->fnMemoryModel.pfnTlbSpider = MmX86_TlbSpider;
- ctxVmm->fnMemoryModel.pfnTlbPageTableVerify = MmX86_TlbPageTableVerify;
- ctxVmm->tpMemoryModel = VMM_MEMORYMODEL_X86;
- ctxVmm->f32 = TRUE;
-}
diff --git a/vmm/mm_x86.h b/vmm/mm_x86.h
deleted file mode 100644
index a47962a..0000000
--- a/vmm/mm_x86.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// mm_x86.h : definitions related to the x86 32-bit protected mode memory model.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __MM_X86_H__
-#define __MM_X86_H__
-#include "vmm.h"
-
-/*
-* Initialize the X86 32-bit protected mode memory model.
-* If a previous memory model exists that memory model is first closed before
-* the new X86 memory model is initialized.
-*/
-VOID MmX86_Initialize();
-
-#endif /* __MM_X86_H__ */
diff --git a/vmm/mm_x86pae.c b/vmm/mm_x86pae.c
deleted file mode 100644
index bd7b01c..0000000
--- a/vmm/mm_x86pae.c
+++ /dev/null
@@ -1,479 +0,0 @@
-// mm_x86pae.c : implementation of the x86 PAE (Physical Address Extension) 32-bit protected mode memory model.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include "vmm.h"
-#include "vmmproc.h"
-
-#define MMX86PAE_MEMMAP_DISPLAYBUFFER_LINE_LENGTH 70
-
-/*
-* Tries to verify that a loaded page table is correct. If just a bit strange
-* bytes/ptes supplied in pb will be altered to look better.
-*/
-BOOL MmX86PAE_TlbPageTableVerify(_Inout_ PBYTE pb, _In_ QWORD pa, _In_ BOOL fSelfRefReq)
-{
- return TRUE;
-}
-
-#define VMMX64_TLB_SIZE_STAGEBUF 0x200
-
-typedef struct tdMMX86PAE_TLB_SPIDER_STAGE_INTERNAL {
- QWORD c;
- PMEM_IO_SCATTER_HEADER ppMEMs[VMMX64_TLB_SIZE_STAGEBUF];
- PVMMOB_MEM ppObMEMs[VMMX64_TLB_SIZE_STAGEBUF];
-} MMX86PAE_TLB_SPIDER_STAGE_INTERNAL, *PMMX86PAE_TLB_SPIDER_STAGE_INTERNAL;
-
-VOID MmX86PAE_TlbSpider_ReadToCache(PMMX86PAE_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
-{
- QWORD i;
- LeechCore_ReadScatter(pTlbSpiderStage->ppMEMs, (DWORD)pTlbSpiderStage->c);
- for(i = 0; i < pTlbSpiderStage->c; i++) {
- MmX86PAE_TlbPageTableVerify(pTlbSpiderStage->ppObMEMs[i]->h.pb, pTlbSpiderStage->ppObMEMs[i]->h.qwA, FALSE);
- VmmCacheReserveReturn(pTlbSpiderStage->ppObMEMs[i]);
- }
- pTlbSpiderStage->c = 0;
-}
-
-BOOL MmX86PAE_TlbSpider_PD_PT(_In_ QWORD pa, _In_ BYTE iPML, _In_ BOOL fUserOnly, PMMX86PAE_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
-{
- BOOL fSpiderComplete = TRUE;
- PVMMOB_MEM pObPT;
- QWORD i, pte;
- // 1: retrieve from cache, add to staging if not found
- pObPT = VmmCacheGet(VMM_CACHE_TAG_TLB, pa);
- if(!pObPT) {
- pTlbSpiderStage->ppObMEMs[pTlbSpiderStage->c] = VmmCacheReserve(VMM_CACHE_TAG_TLB);
- pTlbSpiderStage->ppMEMs[pTlbSpiderStage->c] = &pTlbSpiderStage->ppObMEMs[pTlbSpiderStage->c]->h;
- pTlbSpiderStage->ppMEMs[pTlbSpiderStage->c]->qwA = pa;
- pTlbSpiderStage->c++;
- if(pTlbSpiderStage->c == VMMX64_TLB_SIZE_STAGEBUF) {
- MmX86PAE_TlbSpider_ReadToCache(pTlbSpiderStage);
- }
- return FALSE;
- }
- if(iPML == 1) {
- VmmOb_DECREF(pObPT);
- return TRUE;
- }
- // 2: walk trough all entries for PD
- for(i = 0; i < 512; i++) {
- pte = pObPT->pqw[i];
- if(!(pte & 0x01)) { continue; } // not valid
- if(pte & 0x80) { continue; } // not valid ptr to PT
- if(fUserOnly && !(pte & 0x04)) { continue; } // supervisor page when fUserOnly -> not valid
- fSpiderComplete = MmX86PAE_TlbSpider_PD_PT(pte & 0x0000fffffffff000, 1, fUserOnly, pTlbSpiderStage) && fSpiderComplete;
- }
- VmmOb_DECREF(pObPT);
- return fSpiderComplete;
-}
-
-BOOL MmX86PAE_TlbSpider_PDPT(_In_ QWORD paDTB, _In_ BOOL fUserOnly, PMMX86PAE_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage)
-{
- BOOL fSpiderComplete = TRUE;
- PVMMOB_MEM pObPDPT;
- PBYTE pbPDPT;
- QWORD i, pte;
- // 1: retrieve PDPT
- pObPDPT = VmmTlbGetPageTable(paDTB & 0xfffff000, FALSE);
- if(!pObPDPT) { return FALSE; }
- pbPDPT = pObPDPT->pb + (paDTB & 0xfe0);
- // 2: walk through all four (4) PDPTEs
- for(i = 0; i < 0x20; i += 8) {
- pte = *(PQWORD)(pbPDPT + i);
- if(!(pte & 0x01)) { continue; } // not valid
- if(pte & 0xffff0000000001e6) { continue; } // RESERVED BITS IN PDPTE
- fSpiderComplete = MmX86PAE_TlbSpider_PD_PT(pte & 0x0000fffffffff000, 2, fUserOnly, pTlbSpiderStage) && fSpiderComplete;
- }
- VmmOb_DECREF(pObPDPT);
- return fSpiderComplete;
-}
-
-/*
-* Iterate over PTPT, PD (3 times in total) to first stage uncached pages
-* and then commit them to the cache.
-*/
-VOID MmX86PAE_TlbSpider(_In_ PVMM_PROCESS pProcess)
-{
- DWORD i = 0;
- BOOL result = FALSE;
- PMMX86PAE_TLB_SPIDER_STAGE_INTERNAL pTlbSpiderStage;
- if(pProcess->fTlbSpiderDone) { return; }
- if(!(pTlbSpiderStage = (PMMX86PAE_TLB_SPIDER_STAGE_INTERNAL)LocalAlloc(LMEM_ZEROINIT, sizeof(MMX86PAE_TLB_SPIDER_STAGE_INTERNAL)))) { return; }
- while(!result && (i < 3)) {
- result = MmX86PAE_TlbSpider_PDPT(pProcess->paDTB, pProcess->fUserOnly, pTlbSpiderStage);
- if(pTlbSpiderStage->c) {
- MmX86PAE_TlbSpider_ReadToCache(pTlbSpiderStage);
- }
- i++;
- }
- LocalFree(pTlbSpiderStage);
- pProcess->fTlbSpiderDone = TRUE;
-}
-
-const QWORD MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[4] = { 0, 12, 21, 30 };
-
-VOID MmX86PAE_MapInitialize_Index(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MEMMAP_ENTRY pMemMap, _In_ PDWORD pcMemMap, _In_ DWORD vaBase, _In_ BYTE iPML, _In_ QWORD PTEs[512], _In_ BOOL fSupervisorPML, _In_ QWORD paMax)
-{
- PVMMOB_MEM pObNextPT;
- DWORD i, va;
- QWORD pte;
- BOOL fUserOnly, fNextSupervisorPML;
- PVMM_MEMMAP_ENTRY pMemMapEntry = pMemMap + *pcMemMap - 1;
- fUserOnly = pProcess->fUserOnly;
- for(i = 0; i < 512; i++) {
- if((iPML == 3) && (i > 3)) { break; } // MAX 4 ENTRIES IN PDPT
- pte = PTEs[i];
- if(!(pte & 0x01)) { continue; }
- if((pte & 0x0000fffffffff000) > paMax) { continue; }
- if(iPML == 3) {
- // PDPT: (iPML = 3)
- if(pte & 0xffff0000000001e6) { continue; } // RESERVED BITS IN PDPTE
- va = i * 0x40000000;
- } else {
- // PT or PD: (iPML = 1..2)
- if(fSupervisorPML) { pte = pte & 0xfffffffffffffffb; }
- if(fUserOnly && !(pte & 0x04)) { continue; }
- va = vaBase + (i << MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
- // maps page
- if((iPML == 1) || (pte & 0x80) /* PS */) {
- if((*pcMemMap == 0) ||
- (pMemMapEntry->fPage != (pte & VMM_MEMMAP_PAGE_MASK)) ||
- (va != pMemMapEntry->AddrBase + (pMemMapEntry->cPages << 12))) {
- if(*pcMemMap + 1 >= VMM_MEMMAP_ENTRIES_MAX) { return; }
- pMemMapEntry = pMemMap + *pcMemMap;
- pMemMapEntry->AddrBase = va;
- pMemMapEntry->fPage = pte & VMM_MEMMAP_PAGE_MASK;
- pMemMapEntry->cPages = 1ULL << (MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML] - 12);
- *pcMemMap = *pcMemMap + 1;
- if(*pcMemMap >= VMM_MEMMAP_ENTRIES_MAX - 1) { return; }
- continue;
- }
- pMemMapEntry->cPages += 1ULL << (MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML] - 12);
- continue;
- }
- }
- // maps page table (PD, PT)
- fNextSupervisorPML = (iPML != 3) && !(pte & 0x04);
- pObNextPT = VmmTlbGetPageTable(pte & 0x0000fffffffff000, FALSE);
- if(!pObNextPT) { continue; }
- MmX86PAE_MapInitialize_Index(pProcess, pMemMap, pcMemMap, va, iPML - 1, pObNextPT->pqw, fNextSupervisorPML, paMax);
- VmmOb_DECREF(pObNextPT);
- pMemMapEntry = pMemMap + *pcMemMap - 1;
- }
-}
-
-VOID MmX86PAE_MapCloseObCallback(_In_ PVOID pVmmOb)
-{
- PVMMOB_MEMMAP pObMemMap = (PVMMOB_MEMMAP)pVmmOb;
- if(pObMemMap->pObDisplay) {
- VmmOb_DECREF(pObMemMap->pObDisplay);
- }
-}
-
-_Success_(return)
-BOOL MmX86PAE_MapInitialize(_In_ PVMM_PROCESS pProcess)
-{
- DWORD cMemMap = 0;
- PBYTE pbPDPT;
- PVMMOB_MEM pObPDPT;
- PVMM_MEMMAP_ENTRY pMemMap = NULL;
- PVMMOB_MEMMAP pObMemMap = NULL;
- // already existing?
- if(pProcess && pProcess->pObMemMap) {
- return pProcess->pObMemMap->fValid;
- }
- EnterCriticalSection(&pProcess->LockUpdate);
- if(pProcess && pProcess->pObMemMap) {
- LeaveCriticalSection(&pProcess->LockUpdate);
- return pProcess->pObMemMap->fValid;
- }
- // allocate temporary buffer and walk page tables
- VmmTlbSpider(pProcess);
- pObPDPT = VmmTlbGetPageTable(pProcess->paDTB & 0xfffff000, FALSE);
- if(pObPDPT) {
- pMemMap = (PVMM_MEMMAP_ENTRY)LocalAlloc(LMEM_ZEROINIT, VMM_MEMMAP_ENTRIES_MAX * sizeof(VMM_MEMMAP_ENTRY));
- if(pMemMap) {
- pbPDPT = pObPDPT->pb + (pProcess->paDTB & 0xfe0); // ADJUST PDPT TO 32-BYTE BOUNDARY
- MmX86PAE_MapInitialize_Index(pProcess, pMemMap, &cMemMap, 0, 3, (PQWORD)pbPDPT, FALSE, ctxMain->dev.paMax);
- }
- VmmOb_DECREF(pObPDPT);
- }
- // allocate VmmOb depending on result
- pObMemMap = VmmOb_Alloc('MM', 0, sizeof(VMMOB_MEMMAP) + cMemMap * sizeof(VMM_MEMMAP_ENTRY), MmX86PAE_MapCloseObCallback, NULL);
- if(!pObMemMap) {
- LeaveCriticalSection(&pProcess->LockUpdate);
- LocalFree(pMemMap);
- return FALSE;
- }
- pObMemMap->fValid = cMemMap > 0;
- pObMemMap->fTagModules = FALSE;
- pObMemMap->fTagScan = FALSE;
- pObMemMap->cMap = cMemMap;
- pObMemMap->cbDisplay = cMemMap * MMX86PAE_MEMMAP_DISPLAYBUFFER_LINE_LENGTH;
- pObMemMap->pObDisplay = NULL;
- if(cMemMap > 0) {
- memcpy(pObMemMap->pMap, pMemMap, cMemMap * sizeof(VMM_MEMMAP_ENTRY));
- }
- LocalFree(pMemMap);
- pProcess->pObMemMap = pObMemMap;
- LeaveCriticalSection(&pProcess->LockUpdate);
- return pObMemMap->fValid;
-}
-
-/*
-* Map a tag into the sorted memory map in O(log2) operations. Supply only one of szTag or wszTag.
-* -- pProcess
-* -- vaBase
-* -- vaLimit = limit == vaBase + size (== top address in range +1)
-* -- szTag
-* -- wszTag
-* -- fWoW64
-* -- fOverwrite
-*/
-VOID MmX86PAE_MapTag(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ QWORD vaLimit, _In_opt_ LPSTR szTag, _In_opt_ LPWSTR wszTag, _In_ BOOL fWoW64, _In_ BOOL fOverwrite)
-{
- // NB! update here may take placey without acquiring the process 'LockUpdate'
- // Data is not super important so it should be ok. Also, in many cases the
- // lock will already be acquired by MapGetEntries function.
- PVMM_MEMMAP_ENTRY pMap;
- QWORD i, lvl, cMap;
- if(!MmX86PAE_MapInitialize(pProcess)) { return; }
- if((vaBase > 0xffffffff) || (vaLimit > 0xffffffff)) { return; }
- pMap = pProcess->pObMemMap->pMap;
- cMap = pProcess->pObMemMap->cMap;
- if(!pMap || !cMap) { return; }
- // 1: locate base
- lvl = 1;
- i = cMap >> lvl;
- while(TRUE) {
- lvl++;
- if((cMap >> lvl) == 0) {
- break;
- }
- if(pMap[i].AddrBase > vaBase) {
- i -= (cMap >> lvl);
- } else {
- i += (cMap >> lvl);
- }
- }
- // 2: scan back if needed
- while(i && (pMap[i].AddrBase > vaBase)) {
- i--;
- }
- // 3: fill in tag
- while((i < cMap) && (pMap[i].AddrBase + (pMap[i].cPages << 12) <= vaLimit)) {
- if((pMap[i].AddrBase >= vaBase) && (fOverwrite || !pMap[i].szTag[0])) {
- if(wszTag) {
- snprintf(pMap[i].szTag, 31, "%S", wszTag);
- }
- if(szTag) {
- snprintf(pMap[i].szTag, 31, "%s", szTag);
- }
- }
- i++;
- }
-}
-
-_Success_(return)
-BOOL MmX86PAE_MapGetEntries(_In_ PVMM_PROCESS pProcess, _In_ DWORD flags, _Out_ PVMMOB_MEMMAP *ppObMemMap)
-{
- DWORD i;
- PVMM_MODULEMAP_ENTRY pModule;
- PVMMOB_MODULEMAP pObModuleMap;
- if(!MmX86PAE_MapInitialize(pProcess)) { return FALSE; }
- if((!pProcess->pObMemMap->fTagModules && (flags & VMM_MEMMAP_FLAG_MODULES)) || (!pProcess->pObMemMap->fTagScan && (flags & VMM_MEMMAP_FLAG_SCAN))) {
- EnterCriticalSection(&pProcess->LockUpdate);
- if(!pProcess->pObMemMap->fTagModules && (flags & VMM_MEMMAP_FLAG_MODULES)) {
- pProcess->pObMemMap->fTagModules = TRUE;
- if(VmmProc_ModuleMapGet(pProcess, &pObModuleMap)) {
- // update memory map with names
- for(i = 0; i < pObModuleMap->cMap; i++) {
- pModule = pObModuleMap->pMap + i;
- MmX86PAE_MapTag(pProcess, pModule->BaseAddress, pModule->BaseAddress + pModule->SizeOfImage, pModule->szName, NULL, FALSE, FALSE);
- }
- VmmOb_DECREF(pObModuleMap);
- }
- }
- if(!pProcess->pObMemMap->fTagScan && (flags & VMM_MEMMAP_FLAG_SCAN)) {
- pProcess->pObMemMap->fTagScan = TRUE;
- VmmProc_ScanTagsMemMap(pProcess);
- }
- LeaveCriticalSection(&pProcess->LockUpdate);
- }
- *ppObMemMap = VmmOb_INCREF(pProcess->pObMemMap);
- return TRUE;
-}
-
-_Success_(return)
-BOOL MmX86PAE_MapGetDisplay(_In_ PVMM_PROCESS pProcess, _In_ DWORD flags, _Out_ PVMMOB_PDATA *ppObDisplay)
-{
- DWORD i, o = 0;
- PVMMOB_MEMMAP pObMemMap = NULL;
- PVMMOB_PDATA pObDisplay = NULL;
- // memory map display data already exists
- if(!MmX86PAE_MapInitialize(pProcess)) { return FALSE; }
- if(pProcess->pObMemMap->pObDisplay) {
- *ppObDisplay = VmmOb_INCREF(pProcess->pObMemMap->pObDisplay);
- return TRUE;
- }
- // create new memory map display data
- EnterCriticalSection(&pProcess->LockUpdate);
- if(!pProcess->pObMemMap->pObDisplay) {
- if(MmX86PAE_MapGetEntries(pProcess, flags, &pObMemMap)) {
- pObDisplay = VmmOb_Alloc('MD', LMEM_ZEROINIT, pObMemMap->cbDisplay, NULL, NULL);
- if(pObDisplay) {
- for(i = 0; i < pObMemMap->cMap; i++) {
- if(o + MMX86PAE_MEMMAP_DISPLAYBUFFER_LINE_LENGTH > pObMemMap->cbDisplay) {
- vmmprintf_fn("ERROR: SHOULD NOT HAPPEN! LENGTH DIFFERS #1: %i %i\n", o + MMX86PAE_MEMMAP_DISPLAYBUFFER_LINE_LENGTH, pObMemMap->cbDisplay);
- VmmOb_DECREF(pObDisplay);
- pObDisplay = NULL;
- goto fail;
- }
- o += snprintf(
- pObDisplay->pbData + o,
- pObMemMap->cbDisplay - o - MMX86PAE_MEMMAP_DISPLAYBUFFER_LINE_LENGTH,
- "%04x %8x %08x-%08x %sr%s%s %-32s\n",
- i,
- (DWORD)pObMemMap->pMap[i].cPages,
- (DWORD)pObMemMap->pMap[i].AddrBase,
- (DWORD)(pObMemMap->pMap[i].AddrBase + (pObMemMap->pMap[i].cPages << 12) - 1),
- pObMemMap->pMap[i].fPage & VMM_MEMMAP_PAGE_NS ? "-" : "s",
- pObMemMap->pMap[i].fPage & VMM_MEMMAP_PAGE_W ? "w" : "-",
- pObMemMap->pMap[i].fPage & VMM_MEMMAP_PAGE_NX ? "-" : "x",
- pObMemMap->pMap[i].szTag
- );
- }
- if(o != pObMemMap->cbDisplay) {
- vmmprintf_fn("ERROR: SHOULD NOT HAPPEN! LENGTH DIFFERS #2: %i %i\n", o, pObMemMap->cbDisplay);
- VmmOb_DECREF(pObDisplay);
- pObDisplay = NULL;
- goto fail;
- }
- }
- }
- pProcess->pObMemMap->pObDisplay = pObDisplay;
- }
-fail:
- VmmOb_DECREF(pObMemMap);
- LeaveCriticalSection(&pProcess->LockUpdate);
- if(pProcess->pObMemMap->pObDisplay) {
- *ppObDisplay = VmmOb_INCREF(pProcess->pObMemMap->pObDisplay);
- return TRUE;
- }
- return FALSE;
-}
-
-_Success_(return)
-BOOL MmX86PAE_Virt2Phys(_In_ QWORD paPT, _In_ BOOL fUserOnly, _In_ BYTE iPML, _In_ QWORD va, _Out_ PQWORD ppa)
-{
- PBYTE pbPTEs;
- QWORD pte, i, qwMask;
- PVMMOB_MEM pObPTEs;
- if(va > 0xffffffff) { return FALSE; }
- if(iPML == (BYTE)-1) { iPML = 3; }
- pObPTEs = VmmTlbGetPageTable(paPT & 0x0000fffffffff000, FALSE);
- if(!pObPTEs) { return FALSE; }
- i = 0x1ff & (va >> MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
- if(iPML == 3) {
- // PDPT
- if(i > 3) { // MAX 4 ENTRIES IN PDPT
- VmmOb_DECREF(pObPTEs);
- return FALSE;
- }
- pbPTEs = pObPTEs->pb + (paPT & 0xfe0); // ADJUST PDPT TO 32-BYTE BOUNDARY
- pte = ((PQWORD)pbPTEs)[i];
- VmmOb_DECREF(pObPTEs);
- if(!(pte & 0x01)) { return FALSE; } // NOT VALID
- if(pte & 0xffff0000000001e6) { return FALSE; } // RESERVED BITS IN PDPTE
- return MmX86PAE_Virt2Phys(pte, fUserOnly, 2, va, ppa);
- }
- // PT or PD
- pte = pObPTEs->pqw[i];
- VmmOb_DECREF(pObPTEs);
- if(!(pte & 0x01)) { return FALSE; } // NOT VALID
- if(fUserOnly && !(pte & 0x04)) { return FALSE; } // SUPERVISOR PAGE & USER MODE REQ
- if(pte & 0x000f000000000000) { return FALSE; } // RESERVED
- if((iPML == 1) || (pte & 0x80) /* PS */) {
- qwMask = 0xffffffffffffffff << MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML];
- *ppa = pte & 0x0000fffffffff000 & qwMask; // MASK AWAY BITS FOR 4kB/2MB/1GB PAGES
- qwMask = qwMask ^ 0xffffffffffffffff;
- *ppa = *ppa | (qwMask & va); // FILL LOWER ADDRESS BITS
- return TRUE;
- }
- return MmX86PAE_Virt2Phys(pte, fUserOnly, 1, va, ppa);
-}
-
-VOID MmX86PAE_Virt2PhysGetInformation_DoWork(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo, _In_ BYTE iPML, _In_ QWORD PTEs[512])
-{
- QWORD pte, i, qwMask;
- PVMMOB_MEM pObNextPT;
- i = 0x1ff & (pVirt2PhysInfo->va >> MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML]);
- if((iPML == 3) && (i > 3)) { return; } // MAX 4 ENTRIES IN PDPT
- pte = PTEs[i];
- pVirt2PhysInfo->iPTEs[iPML] = (WORD)i;
- pVirt2PhysInfo->PTEs[iPML] = pte;
- if(!(pte & 0x01)) { return; } // NOT VALID
- if(iPML == 3) {
- // PDPT: (iPML = 3)
- if(pte & 0xffff0000000001e6) { return; } // RESERVED BITS IN PDPTE
- } else {
- // PT or PD: (iPML = 1..2)
- if(pProcess->fUserOnly && !(pte & 0x04)) { return; } // SUPERVISOR PAGE & USER MODE REQ
- if(pte & 0x000f000000000000) { return; } // RESERVED
- if((iPML == 1) || (pte & 0x80) /* PS */) {
- qwMask = 0xffffffffffffffff << MMX86PAE_PAGETABLEMAP_PML_REGION_SIZE[iPML];
- pVirt2PhysInfo->pas[0] = pte & 0x0000fffffffff000 & qwMask; // MASK AWAY BITS FOR 4kB/2MB PAGES
- qwMask = qwMask ^ 0xffffffffffffffff;
- pVirt2PhysInfo->pas[0] = pVirt2PhysInfo->pas[0] | (qwMask & pVirt2PhysInfo->va); // FILL LOWER ADDRESS BITS
- return;
- }
- }
- pObNextPT = VmmTlbGetPageTable(pte & 0x0000fffffffff000, FALSE);
- if(!pObNextPT) { return; }
- pVirt2PhysInfo->pas[iPML - 1] = pte & 0x0000fffffffff000;
- MmX86PAE_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, iPML - 1, pObNextPT->pqw);
- VmmOb_DECREF(pObNextPT);
-}
-
-VOID MmX86PAE_Virt2PhysGetInformation(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo)
-{
- QWORD va;
- PVMMOB_MEM pObPML4;
- if(pVirt2PhysInfo->va > 0xffffffff) { return; }
- va = pVirt2PhysInfo->va;
- ZeroMemory(pVirt2PhysInfo, sizeof(VMM_VIRT2PHYS_INFORMATION));
- pVirt2PhysInfo->tpMemoryModel = VMM_MEMORYMODEL_X86PAE;
- pVirt2PhysInfo->va = va;
- pVirt2PhysInfo->pas[3] = pProcess->paDTB;
- pObPML4 = VmmTlbGetPageTable(pProcess->paDTB & 0xfffff000, FALSE);
- if(!pObPML4) { return; }
- MmX86PAE_Virt2PhysGetInformation_DoWork(pProcess, pVirt2PhysInfo, 3, (PQWORD)(pObPML4->pb + (pProcess->paDTB & 0xfe0)));
- VmmOb_DECREF(pObPML4);
-}
-
-VOID MmX86PAE_Close()
-{
- ctxVmm->f32 = FALSE;
- ctxVmm->tpMemoryModel = VMM_MEMORYMODEL_NA;
- ZeroMemory(&ctxVmm->fnMemoryModel, sizeof(VMM_MEMORYMODEL_FUNCTIONS));
-}
-
-VOID MmX86PAE_Initialize()
-{
- if(ctxVmm->fnMemoryModel.pfnClose) {
- ctxVmm->fnMemoryModel.pfnClose();
- }
- ctxVmm->fnMemoryModel.pfnClose = MmX86PAE_Close;
- ctxVmm->fnMemoryModel.pfnVirt2Phys = MmX86PAE_Virt2Phys;
- ctxVmm->fnMemoryModel.pfnVirt2PhysGetInformation = MmX86PAE_Virt2PhysGetInformation;
- ctxVmm->fnMemoryModel.pfnMapInitialize = MmX86PAE_MapInitialize;
- ctxVmm->fnMemoryModel.pfnMapTag = MmX86PAE_MapTag;
- ctxVmm->fnMemoryModel.pfnMapGetEntries = MmX86PAE_MapGetEntries;
- ctxVmm->fnMemoryModel.pfnMapGetDisplay = MmX86PAE_MapGetDisplay;
- ctxVmm->fnMemoryModel.pfnTlbSpider = MmX86PAE_TlbSpider;
- ctxVmm->fnMemoryModel.pfnTlbPageTableVerify = MmX86PAE_TlbPageTableVerify;
- ctxVmm->tpMemoryModel = VMM_MEMORYMODEL_X86PAE;
- ctxVmm->f32 = TRUE;
-}
diff --git a/vmm/mm_x86pae.h b/vmm/mm_x86pae.h
deleted file mode 100644
index 5d0dc16..0000000
--- a/vmm/mm_x86pae.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// mm_x86pae.h : definitions related to the x86 PAE (Physical Address Extension) 32-bit protected mode memory model.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __MM_X86PAE_H__
-#define __MM_X86PAE_H__
-#include "vmm.h"
-
-/*
-* Initialize the X86 PAE 32-bit protected mode memory model.
-* If a previous memory model exists that memory model is first closed before
-* the new X86 PAE memory model is initialized.
-*/
-VOID MmX86PAE_Initialize();
-
-#endif /* __MM_X86PAE_H__ */
diff --git a/vmm/pe.c b/vmm/pe.c
deleted file mode 100644
index 6e9c56c..0000000
--- a/vmm/pe.c
+++ /dev/null
@@ -1,327 +0,0 @@
-// pe.c : implementation related to parsing of portable executable (PE) images
-// in virtual address space. This may mostly (but not exclusively) be
-// used by Windows functionality.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include "vmm.h"
-#include "pe.h"
-
-PIMAGE_NT_HEADERS PE_HeaderGetVerify(_In_ PVMM_PROCESS pProcess, _In_opt_ QWORD vaModuleBase, _Inout_ PBYTE pbModuleHeader, _Out_opt_ PBOOL pfHdr32)
-{
- PIMAGE_DOS_HEADER dosHeader;
- PIMAGE_NT_HEADERS ntHeader;
- if(pfHdr32) { *pfHdr32 = FALSE; }
- if(vaModuleBase) {
- if(!VmmReadPage(pProcess, vaModuleBase, pbModuleHeader)) { return NULL; }
- }
- dosHeader = (PIMAGE_DOS_HEADER)pbModuleHeader; // dos header.
- if(!dosHeader || dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { return NULL; }
- if(dosHeader->e_lfanew > 0x800) { return NULL; }
- ntHeader = (PIMAGE_NT_HEADERS)(pbModuleHeader + dosHeader->e_lfanew); // nt header
- if(!ntHeader || ntHeader->Signature != IMAGE_NT_SIGNATURE) { return NULL; }
- if((ntHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) && (ntHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)) { return NULL; }
- if(pfHdr32) { *pfHdr32 = (ntHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC); }
- return ntHeader;
-}
-
-QWORD PE_GetSize(_In_ PVMM_PROCESS pProcess, _In_opt_ QWORD vaModuleBase)
-{
- BYTE pbHeader[0x1000] = { 0 };
- PIMAGE_NT_HEADERS ntHeader;
- DWORD cbSize;
- BOOL f32;
- ntHeader = PE_HeaderGetVerify(pProcess, vaModuleBase, pbHeader, &f32);
- cbSize = f32 ?
- ((PIMAGE_NT_HEADERS32)ntHeader)->OptionalHeader.SizeOfImage :
- ((PIMAGE_NT_HEADERS64)ntHeader)->OptionalHeader.SizeOfImage;
- if(cbSize > 0x02000000) { cbSize = 0; }
- return cbSize;
-}
-
-_Success_(return)
-BOOL PE_GetThunkInfoIAT(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ LPSTR szImportModuleName, _In_ LPSTR szImportProcName, _Out_ PPE_THUNKINFO_IAT pThunkInfoIAT)
-{
- BYTE pbModuleHeader[0x1000] = { 0 };
- PIMAGE_NT_HEADERS64 ntHeader64;
- PIMAGE_NT_HEADERS32 ntHeader32;
- QWORD i, oImportDirectory;
- PIMAGE_IMPORT_DESCRIPTOR pIID;
- PQWORD pIAT64, pHNA64;
- PDWORD pIAT32, pHNA32;
- DWORD cbModule, cbRead;
- PBYTE pbModule = NULL;
- BOOL f32, fFnName;
- DWORD c, j;
- LPSTR szNameFunction, szNameModule;
- // load both 32/64 bit ntHeader (only one will be valid)
- if(!(ntHeader64 = PE_HeaderGetVerify(pProcess, vaModuleBase, pbModuleHeader, &f32))) { goto fail; }
- ntHeader32 = (PIMAGE_NT_HEADERS32)ntHeader64;
- cbModule = f32 ?
- ntHeader32->OptionalHeader.SizeOfImage :
- ntHeader64->OptionalHeader.SizeOfImage;
- if(cbModule > 0x02000000) { goto fail; }
- oImportDirectory = f32 ?
- ntHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress :
- ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
- if(!oImportDirectory || (oImportDirectory >= cbModule)) { goto fail; }
- if(!(pbModule = LocalAlloc(LMEM_ZEROINIT, cbModule))) { goto fail; }
- VmmReadEx(pProcess, vaModuleBase, pbModule, cbModule, &cbRead, VMM_FLAG_ZEROPAD_ON_FAIL);
- if(cbRead <= 0x2000) { goto fail; }
- // Walk imported modules / functions
- pIID = (PIMAGE_IMPORT_DESCRIPTOR)(pbModule + oImportDirectory);
- i = 0, c = 0;
- while((oImportDirectory + (i + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR) < cbModule) && pIID[i].FirstThunk) {
- if(pIID[i].Name > cbModule - 64) { i++; continue; }
- if(f32) {
- // 32-bit PE
- j = 0;
- pIAT32 = (PDWORD)(pbModule + pIID[i].FirstThunk);
- pHNA32 = (PDWORD)(pbModule + pIID[i].OriginalFirstThunk);
- while(TRUE) {
- if((QWORD)(pIAT32 + j) + sizeof(DWORD) - (QWORD)pbModule > cbModule) { break; }
- if((QWORD)(pHNA32 + j) + sizeof(DWORD) - (QWORD)pbModule > cbModule) { break; }
- if(!pIAT32[j]) { break; }
- if(!pHNA32[j]) { break; }
- fFnName = (pHNA32[j] < cbModule - 40);
- szNameFunction = (LPSTR)(pbModule + pHNA32[j] + 2);
- szNameModule = (LPSTR)(pbModule + pIID[i].Name);
- if(fFnName && !strcmp(szNameFunction, szImportProcName) && !_stricmp(szNameModule, szImportModuleName)) {
- pThunkInfoIAT->fValid = TRUE;
- pThunkInfoIAT->f32 = TRUE;
- pThunkInfoIAT->vaThunk = vaModuleBase + pIID[i].FirstThunk + sizeof(DWORD) * j;
- pThunkInfoIAT->vaFunction = pIAT32[j];
- pThunkInfoIAT->vaNameFunction = vaModuleBase + pHNA32[j] + 2;
- pThunkInfoIAT->vaNameModule = vaModuleBase + pIID[i].Name;
- LocalFree(pbModule);
- return TRUE;
- }
- c++;
- j++;
- }
- } else {
- // 64-bit PE
- j = 0;
- pIAT64 = (PQWORD)(pbModule + pIID[i].FirstThunk);
- pHNA64 = (PQWORD)(pbModule + pIID[i].OriginalFirstThunk);
- while(TRUE) {
- if((QWORD)(pIAT64 + j) + sizeof(QWORD) - (QWORD)pbModule > cbModule) { break; }
- if((QWORD)(pHNA64 + j) + sizeof(QWORD) - (QWORD)pbModule > cbModule) { break; }
- if(!pIAT64[j]) { break; }
- if(!pHNA64[j]) { break; }
- fFnName = (pHNA64[j] < cbModule - 40);
- szNameFunction = (LPSTR)(pbModule + pHNA64[j] + 2);
- szNameModule = (LPSTR)(pbModule + pIID[i].Name);
- if(fFnName && !strcmp(szNameFunction, szImportProcName) && !_stricmp(szNameModule, szImportModuleName)) {
- pThunkInfoIAT->fValid = TRUE;
- pThunkInfoIAT->f32 = FALSE;
- pThunkInfoIAT->vaThunk = vaModuleBase + pIID[i].FirstThunk + sizeof(QWORD) * j;
- pThunkInfoIAT->vaFunction = pIAT64[j];
- pThunkInfoIAT->vaNameFunction = vaModuleBase + pHNA64[j] + 2;
- pThunkInfoIAT->vaNameModule = vaModuleBase + pIID[i].Name;
- LocalFree(pbModule);
- return TRUE;
- }
- c++;
- j++;
- }
- }
- i++;
- }
-fail:
- LocalFree(pbModule);
- return FALSE;
-}
-
-_Success_(return)
-BOOL PE_GetThunkInfoEAT(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ LPSTR szProcName, _Out_ PPE_THUNKINFO_EAT pThunkInfoEAT)
-{
- BYTE pbModuleHeader[0x1000] = { 0 };
- PIMAGE_NT_HEADERS32 ntHeader32;
- PIMAGE_NT_HEADERS64 ntHeader64;
- PDWORD pdwRVAAddrNames, pdwRVAAddrFunctions;
- PWORD pwNameOrdinals;
- DWORD i, cbProcName, cbExportDirectoryOffset, cbRead = 0;
- LPSTR sz;
- QWORD vaExportDirectory;
- DWORD cbExportDirectory;
- PBYTE pbExportDirectory = NULL;
- QWORD vaRVAAddrNames, vaNameOrdinals, vaRVAAddrFunctions;
- BOOL f32;
- if(!(ntHeader64 = PE_HeaderGetVerify(pProcess, vaModuleBase, pbModuleHeader, &f32))) { goto cleanup; }
- if(f32) { // 32-bit PE
- ntHeader32 = (PIMAGE_NT_HEADERS32)ntHeader64;
- vaExportDirectory = vaModuleBase + ntHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- cbExportDirectory = ntHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
- } else { // 64-bit PE
- vaExportDirectory = vaModuleBase + ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- cbExportDirectory = ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
- }
- if((cbExportDirectory < sizeof(IMAGE_EXPORT_DIRECTORY)) || (cbExportDirectory > 0x01000000) || (vaExportDirectory == vaModuleBase) || (vaExportDirectory > vaModuleBase + 0x80000000)) { goto cleanup; }
- if(!(pbExportDirectory = LocalAlloc(0, cbExportDirectory))) { goto cleanup; }
- VmmReadEx(pProcess, vaExportDirectory, pbExportDirectory, cbExportDirectory, &cbRead, VMM_FLAG_ZEROPAD_ON_FAIL);
- if(!cbRead) { goto cleanup; }
- PIMAGE_EXPORT_DIRECTORY exp = (PIMAGE_EXPORT_DIRECTORY)pbExportDirectory;
- if(!exp || !exp->NumberOfNames || !exp->AddressOfNames) { goto cleanup; }
- vaRVAAddrNames = vaModuleBase + exp->AddressOfNames;
- vaNameOrdinals = vaModuleBase + exp->AddressOfNameOrdinals;
- vaRVAAddrFunctions = vaModuleBase + exp->AddressOfFunctions;
- if((vaRVAAddrNames < vaExportDirectory) || (vaRVAAddrNames > vaExportDirectory + cbExportDirectory - exp->NumberOfNames * sizeof(DWORD))) { goto cleanup; }
- if((vaNameOrdinals < vaExportDirectory) || (vaNameOrdinals > vaExportDirectory + cbExportDirectory - exp->NumberOfNames * sizeof(WORD))) { goto cleanup; }
- if((vaRVAAddrFunctions < vaExportDirectory) || (vaRVAAddrFunctions > vaExportDirectory + cbExportDirectory - exp->NumberOfNames * sizeof(DWORD))) { goto cleanup; }
- cbProcName = (DWORD)strnlen_s(szProcName, MAX_PATH) + 1;
- cbExportDirectoryOffset = (DWORD)(vaExportDirectory - vaModuleBase);
- pdwRVAAddrNames = (PDWORD)(pbExportDirectory + exp->AddressOfNames - cbExportDirectoryOffset);
- pwNameOrdinals = (PWORD)(pbExportDirectory + exp->AddressOfNameOrdinals - cbExportDirectoryOffset);
- pdwRVAAddrFunctions = (PDWORD)(pbExportDirectory + exp->AddressOfFunctions - cbExportDirectoryOffset);
- for(i = 0; i < exp->NumberOfNames; i++) {
- if(pdwRVAAddrNames[i] - cbExportDirectoryOffset + cbProcName > cbExportDirectory) { continue; }
- sz = (LPSTR)(pbExportDirectory + pdwRVAAddrNames[i] - cbExportDirectoryOffset);
- if(0 == memcmp(sz, szProcName, cbProcName)) {
- if(pwNameOrdinals[i] >= exp->NumberOfFunctions) { goto cleanup; }
- pThunkInfoEAT->fValid = TRUE;
- pThunkInfoEAT->vaFunction = (QWORD)(vaModuleBase + pdwRVAAddrFunctions[pwNameOrdinals[i]]);
- pThunkInfoEAT->valueThunk = pdwRVAAddrFunctions[pwNameOrdinals[i]];
- pThunkInfoEAT->vaThunk = vaExportDirectory + exp->AddressOfFunctions - cbExportDirectoryOffset + sizeof(DWORD) * pwNameOrdinals[i];
- pThunkInfoEAT->vaNameFunction = vaExportDirectory + pdwRVAAddrNames[i] - cbExportDirectoryOffset;
- LocalFree(pbExportDirectory);
- return TRUE;
- }
- }
-cleanup:
- LocalFree(pbExportDirectory);
- return FALSE;
-}
-
-QWORD PE_GetProcAddress(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ LPSTR lpProcName)
-{
- PE_THUNKINFO_EAT oThunkInfoEAT = { 0 };
- PE_GetThunkInfoEAT(pProcess, vaModuleBase, lpProcName, &oThunkInfoEAT);
- return oThunkInfoEAT.vaFunction;
-}
-
-WORD PE_SectionGetNumberOfEx(_In_ PVMM_PROCESS pProcess, _In_opt_ QWORD vaModuleBase, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt)
-{
- BOOL f32;
- BYTE pbModuleHeader[0x1000] = { 0 };
- WORD cSections;
- PIMAGE_NT_HEADERS ntHeader;
- // load nt header either by using optionally supplied module header or by fetching from memory.
- ntHeader = pbModuleHeaderOpt ? PE_HeaderGetVerify(pProcess, 0, pbModuleHeaderOpt, &f32) : PE_HeaderGetVerify(pProcess, vaModuleBase, pbModuleHeader, &f32);
- if(!ntHeader) { return 0; }
- cSections = f32 ? ((PIMAGE_NT_HEADERS32)ntHeader)->FileHeader.NumberOfSections : ((PIMAGE_NT_HEADERS64)ntHeader)->FileHeader.NumberOfSections;
- if(cSections > 0x40) { return 0; }
- return cSections;
-}
-
-_Success_(return)
-BOOL PE_SectionGetFromName(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ LPSTR szSectionName, _Out_ PIMAGE_SECTION_HEADER pSection)
-{
- BOOL f32;
- BYTE pbModuleHeader[0x1000] = { 0 };
- PIMAGE_NT_HEADERS ntHeader;
- PIMAGE_SECTION_HEADER pSectionBase;
- DWORD i, cSections;
- if(!(ntHeader = PE_HeaderGetVerify(pProcess, vaModuleBase, pbModuleHeader, &f32))) { return FALSE; }
- pSectionBase = f32 ?
- (PIMAGE_SECTION_HEADER)((QWORD)ntHeader + sizeof(IMAGE_NT_HEADERS32)) :
- (PIMAGE_SECTION_HEADER)((QWORD)ntHeader + sizeof(IMAGE_NT_HEADERS64));
- cSections = (DWORD)(((QWORD)pbModuleHeader + 0x1000 - (QWORD)pSectionBase) / sizeof(IMAGE_SECTION_HEADER)); // max section headers possible in 0x1000 module header buffer
- cSections = (DWORD)min(cSections, ntHeader->FileHeader.NumberOfSections); // FileHeader is the same in both 32/64-bit versions of struct
- for(i = 0; i < cSections; i++) {
- if(!strncmp((pSectionBase + i)->Name, szSectionName, 8)) {
- memcpy(pSection, pSectionBase + i, sizeof(IMAGE_SECTION_HEADER));
- return TRUE;
- }
- }
- return FALSE;
-}
-
-DWORD PE_IatGetNumberOfEx(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt)
-{
- BOOL f32;
- BYTE pbModuleHeader[0x1000] = { 0 };
- PIMAGE_NT_HEADERS ntHeader;
- DWORD cbImportDirectory, cbImportAddressTable, cIatEntries, cModules;
- // load nt header either by using optionally supplied module header or by fetching from memory.
- ntHeader = pbModuleHeaderOpt ? PE_HeaderGetVerify(pProcess, 0, pbModuleHeaderOpt, &f32) : PE_HeaderGetVerify(pProcess, vaModuleBase, pbModuleHeader, &f32);
- if(!ntHeader) { return 0; }
- // Calculate the number of functions in the import address table (IAT).
- // Number of functions = # IAT entries - # Imported modules
- cbImportDirectory = f32 ?
- ((PIMAGE_NT_HEADERS32)ntHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size :
- ((PIMAGE_NT_HEADERS64)ntHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
- cbImportAddressTable = f32 ?
- ((PIMAGE_NT_HEADERS32)ntHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size :
- ((PIMAGE_NT_HEADERS64)ntHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
- cIatEntries = cbImportAddressTable / (f32 ? sizeof(DWORD) : sizeof(QWORD));
- cModules = cbImportDirectory / sizeof(IMAGE_IMPORT_DESCRIPTOR);
- return cIatEntries - cModules;
-}
-
-DWORD PE_EatGetNumberOfEx(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt)
-{
- BOOL f32;
- BYTE pbModuleHeader[0x1000] = { 0 };
- PIMAGE_NT_HEADERS ntHeader;
- QWORD va, vaExportDirectory;
- IMAGE_EXPORT_DIRECTORY hdrExportDirectory;
- // load both 32/64 bit ntHeader unless already supplied in parameter (only one of 32/64 bit hdr will be valid)
- // load nt header either by using optionally supplied module header or by fetching from memory.
- ntHeader = pbModuleHeaderOpt ? PE_HeaderGetVerify(pProcess, 0, pbModuleHeaderOpt, &f32) : PE_HeaderGetVerify(pProcess, vaModuleBase, pbModuleHeader, &f32);
- if(!ntHeader) { return 0; }
- // Calculate the number of functions in the export address table (EAT).
- va = f32 ?
- ((PIMAGE_NT_HEADERS32)ntHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress :
- ((PIMAGE_NT_HEADERS64)ntHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- vaExportDirectory = va ? vaModuleBase + va : 0;
- if(vaExportDirectory && VmmRead(pProcess, vaExportDirectory, (PBYTE)&hdrExportDirectory, sizeof(IMAGE_EXPORT_DIRECTORY)) && (hdrExportDirectory.NumberOfNames < 0x00010000)) {
- return hdrExportDirectory.NumberOfNames;
- }
- return 0;
-}
-
-_Success_(return)
-BOOL PE_GetModuleNameEx(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ BOOL fOnFailDummyName, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt, _Out_writes_(cszModuleName) PCHAR szModuleName, _In_ DWORD cszModuleName, _Out_opt_ PDWORD pdwSize)
-{
- BOOL f32;
- BYTE pbModuleHeader[0x1000] = { 0 };
- PIMAGE_NT_HEADERS ntHeader;
- PIMAGE_NT_HEADERS64 ntHeader64;
- PIMAGE_NT_HEADERS32 ntHeader32;
- PIMAGE_EXPORT_DIRECTORY exp;
- QWORD vaExportDirectory;
- DWORD cbImageSize, cbExportDirectory;
- BYTE pbExportDirectory[sizeof(IMAGE_EXPORT_DIRECTORY)];
- // load both 32/64 bit ntHeader unless already supplied in parameter (only one of 32/64 bit hdr will be valid)
- // load nt header either by using optionally supplied module header or by fetching from memory.
- ntHeader = pbModuleHeaderOpt ? PE_HeaderGetVerify(pProcess, 0, pbModuleHeaderOpt, &f32) : PE_HeaderGetVerify(pProcess, vaModuleBase, pbModuleHeader, &f32);
- if(!ntHeader) { return FALSE; }
- if(!f32) { // 64-bit PE
- ntHeader64 = (PIMAGE_NT_HEADERS64)ntHeader;
- if(pdwSize) { *pdwSize = ntHeader64->OptionalHeader.SizeOfImage; }
- vaExportDirectory = vaModuleBase + ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- cbExportDirectory = ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
- cbImageSize = ntHeader64->OptionalHeader.SizeOfImage;
- } else { // 32-bit PE
- ntHeader32 = (PIMAGE_NT_HEADERS32)ntHeader;
- if(pdwSize) { *pdwSize = ntHeader32->OptionalHeader.SizeOfImage; }
- vaExportDirectory = vaModuleBase + ntHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- cbExportDirectory = ntHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
- cbImageSize = ntHeader32->OptionalHeader.SizeOfImage;
- }
- if((cbExportDirectory < sizeof(IMAGE_EXPORT_DIRECTORY)) || (vaExportDirectory == vaModuleBase) || (cbExportDirectory > cbImageSize)) { goto fail; }
- if(!VmmRead(pProcess, vaExportDirectory, pbExportDirectory, sizeof(IMAGE_EXPORT_DIRECTORY))) { goto fail; }
- exp = (PIMAGE_EXPORT_DIRECTORY)pbExportDirectory;
- if(!exp || !exp->Name || exp->Name > cbImageSize) { goto fail; }
- szModuleName[cszModuleName - 1] = 0;
- if(!VmmRead(pProcess, vaModuleBase + exp->Name, szModuleName, cszModuleName - 1)) { goto fail; }
- return TRUE;
-fail:
- if(fOnFailDummyName) {
- memcpy(szModuleName, "UNKNOWN", 8);
- return TRUE;
- }
- return FALSE;
-}
diff --git a/vmm/pe.h b/vmm/pe.h
deleted file mode 100644
index 5912892..0000000
--- a/vmm/pe.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// pe.h : definitions related to parsing of portable executable (PE) images in
-// virtual address space. This may mostly (but not exclusively) be used
-// by Windows functionality.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __PE_H__
-#define __PE_H__
-#include "vmm.h"
-
-#define CONTAINING_RECORD32(address, type, field) ((DWORD)( \
- (DWORD)(QWORD)(address) - \
- (DWORD)(QWORD)(&((type *)0)->field)))
-
-static const LPCSTR PE_DATA_DIRECTORIES[16] = { "EXPORT", "IMPORT", "RESOURCE", "EXCEPTION", "SECURITY", "BASERELOC", "DEBUG", "ARCHITECTURE", "GLOBALPTR", "TLS", "LOAD_CONFIG", "BOUND_IMPORT", "IAT", "DELAY_IMPORT", "COM_DESCRIPTOR", "RESERVED" };
-
-typedef struct tdPE_THUNKINFO_IAT {
- BOOL fValid;
- BOOL f32; // if TRUE fn is a 32-bit/4-byte entry, otherwise 64-bit/8-byte entry.
- ULONG64 vaThunk; // address of import address table 'thunk'.
- ULONG64 vaFunction; // value if import address table 'thunk' == address of imported function.
- ULONG64 vaNameModule; // address of name string for imported module.
- ULONG64 vaNameFunction; // address of name string for imported function.
-} PE_THUNKINFO_IAT, *PPE_THUNKINFO_IAT;
-
-typedef struct tdPE_THUNKINFO_EAT {
- BOOL fValid;
- DWORD valueThunk; // value of export address table 'thunk'.
- ULONG64 vaThunk; // address of import address table 'thunk'.
- ULONG64 vaNameFunction; // address of name string for exported function.
- ULONG64 vaFunction; // address of exported function (module base + value parameter).
-} PE_THUNKINFO_EAT, *PPE_THUNKINFO_EAT;
-
-/*
-* Retrieve the size of the module given its base.
-* -- pProcess
-* -- vaModuleBase = PE module base address.
-* -- return = success: size of module. fail: 0.
-*/
-QWORD PE_GetSize(_In_ PVMM_PROCESS pProcess, _In_opt_ QWORD vaModuleBase);
-
-/*
-* Lookup the virtual address of an exported function or symbol in the module supplied.
-* Similar to Windows 'GetProcAddress'.
-* -- pProcess
-* -- vaModuleBase = PE module base address.
-* -- return = success: virtual address of function / symbol. fail: 0.
-*/
-QWORD PE_GetProcAddress(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ LPSTR lpProcName);
-
-/*
-* Lookup the virtual address of an exported function or symbol in the module supplied
-* among with additional information returned in the pThunkInfoEAT struct.
-* -- pProcess
-* -- vaModuleBase = PE module base address.
-* -- szProcName
-* -- pThunkInfoEAT
-* -- return
-*/
-_Success_(return)
-BOOL PE_GetThunkInfoEAT(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ LPSTR szProcName, _Out_ PPE_THUNKINFO_EAT pThunkInfoEAT);
-
-/*
-* Retrieve an import address table (IAT) entry for a specific function.
-* This may be useful for IAT patching functionality.
-* -- pProcess
-* -- vaModuleBase
-* -- szImportModuleName
-* -- szImportProcName
-* -- pThunkInfoIAT
-* -- return
-*/
-_Success_(return)
-BOOL PE_GetThunkInfoIAT(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ LPSTR szImportModuleName, _In_ LPSTR szImportProcName, _Out_ PPE_THUNKINFO_IAT pThunkInfoIAT);
-
-/*
-* Retrieve the module name and optionally the module size.
-* -- pProcess
-* -- vaModuleBase
-* -- fOnFailDummyName
-* -- pbModuleHeaderOpt
-* -- szModuleName
-* -- cszModuleName
-* -- pdwSize
-* -- return
-*/
-_Success_(return)
-BOOL PE_GetModuleNameEx(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ BOOL fOnFailDummyName, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt, _Out_writes_(cszModuleName) PCHAR szModuleName, _In_ DWORD cszModuleName, _Out_opt_ PDWORD pdwSize);
-_Success_(return)
-inline BOOL PE_GetModuleName(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _Out_writes_(cszModuleName) PCHAR szModuleName, _In_ DWORD cszModuleName)
-{
- return PE_GetModuleNameEx(pProcess, vaModuleBase, FALSE, NULL, szModuleName, cszModuleName, NULL);
-}
-
-/*
-* Retrieve the number of sections in the module given by either the module base
-* virtual address or a pre-retrieved pbModuleHeader of size 0x1000.
-* -- pProcess
-* -- vaModuleBase = PE module base address (unless pbModuleHeaderOpt is specified)
-* -- pbModuleHeaderOpt = Optional buffer containing module header (MZ) page.
-* -- return = success: number of sections. fail: 0.
-*/
-WORD PE_SectionGetNumberOfEx(_In_ PVMM_PROCESS pProcess, _In_opt_ QWORD vaModuleBase, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt);
-inline WORD PE_SectionGetNumberOf(_In_ PVMM_PROCESS pProcess, _In_opt_ QWORD vaModuleBase)
-{
- return PE_SectionGetNumberOfEx(pProcess, vaModuleBase, NULL);
-}
-
-/*
-* Retrieve a single section header given its name.
-* -- pProcess
-* -- vaModuleBase
-* -- szSectionName
-* -- pSection
-* -- return
-*/
-_Success_(return)
-BOOL PE_SectionGetFromName(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_ LPSTR szSectionName, _Out_ PIMAGE_SECTION_HEADER pSection);
-
-/*
-* Retrieve the number of export address table (EAT) entries - i.e. the number
-* of functions that the module is exporting.
-* -- pProcess
-* -- vaModuleBase = PE module base address (unless pbModuleHeaderOpt is specified)
-* -- pbModuleHaderOpt = Optional buffer containing module header (MZ) page.
-* -- return = success: number of entries. fail: 0.
-*/
-DWORD PE_EatGetNumberOfEx(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt);
-inline DWORD PE_EatGetNumberOf(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase)
-{
- return PE_EatGetNumberOfEx(pProcess, vaModuleBase, NULL);
-}
-
-/*
-* Retrieve the number of import address table (IAT) entries - i.e. the number
-* of functions that the module is importing.
-* -- pProcess
-* -- vaModuleBase = PE module base address (unless pbModuleHeaderOpt is specified)
-* -- pbModuleHaderOpt = Optional buffer containing module header (MZ) page.
-* -- return = success: number of entries. fail: 0.
-*/
-DWORD PE_IatGetNumberOfEx(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase, _In_reads_opt_(0x1000) PBYTE pbModuleHeaderOpt);
-inline DWORD PE_IatGetNumberOf(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaModuleBase)
-{
- return PE_IatGetNumberOfEx(pProcess, vaModuleBase, NULL);
-}
-
-#endif /* __PE_H__ */
diff --git a/vmm/pluginmanager.c b/vmm/pluginmanager.c
deleted file mode 100644
index d0a15a4..0000000
--- a/vmm/pluginmanager.c
+++ /dev/null
@@ -1,350 +0,0 @@
-// pluginmanager.h : implementation of the plugin manager for memory process file system plugins.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include "pluginmanager.h"
-#include "statistics.h"
-#include "util.h"
-#include "vmm.h"
-#include "vmmdll.h"
-#include "m_ldrmodules.h"
-#include "m_status.h"
-#include "m_virt2phys.h"
-
-//
-// This file contains functionality related to keeping track of plugins, both
-// internal built-in ones and loadable plugins in the form of compliant DLLs.
-//
-// The functionality and data structures are at this moment single-threaded in
-// this implementation and should be protected by a lock (ctxVmm->MasterLock).
-//
-// Core module calls are: List, Read, Write.
-// Other module calls are: Notify and Close.
-//
-// In general, a pointer to a stored-away module specific handle is given in
-// every call together with a plugin/process specific pointer to a handle.
-// The plugin/process specific handle is stored per module, per PID.
-//
-// A pProcess struct (if applicable) and a PID is also given in each call
-// together with the module name and path.
-//
-
-// ----------------------------------------------------------------------------
-// MODULES CORE FUNCTIONALITY - DEFINES BELOW:
-// ----------------------------------------------------------------------------
-
-typedef struct tdPLUGIN_LISTENTRY {
- struct tdPLUGIN_LISTENTRY *FLink;
- HMODULE hDLL;
- CHAR szModuleName[32];
- BOOL fRootModule;
- BOOL fProcessModule;
- BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
- NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset);
- NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset);
- VOID(*pfnNotify)(_In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
- VOID(*pfnClose)();
-} PLUGIN_LISTENTRY, *PPLUGIN_LISTENTRY;
-
-// ----------------------------------------------------------------------------
-// MODULES CORE FUNCTIONALITY - IMPLEMENTATION BELOW:
-// ----------------------------------------------------------------------------
-
-VOID PluginManager_ContextInitialize(_Out_ PVMMDLL_PLUGIN_CONTEXT ctx, PPLUGIN_LISTENTRY pModule, _In_opt_ PVMM_PROCESS pProcess, _In_ LPSTR szPath)
-{
- ctx->magic = VMMDLL_PLUGIN_CONTEXT_MAGIC;
- ctx->wVersion = VMMDLL_PLUGIN_CONTEXT_VERSION;
- ctx->wSize = sizeof(VMMDLL_PLUGIN_CONTEXT);
- ctx->dwPID = (pProcess ? pProcess->dwPID : (DWORD)-1);
- ctx->pProcess = pModule->hDLL ? NULL : pProcess;
- ctx->szModule = pModule->szModuleName;
- ctx->szPath = szPath;
-}
-
-VOID PluginManager_ListAll(_In_opt_ PVMM_PROCESS pProcess, _Inout_ PHANDLE pFileList)
-{
- PPLUGIN_LISTENTRY pModule = (PPLUGIN_LISTENTRY)ctxVmm->pVmmVfsModuleList;
- while(pModule) {
- if((pProcess && pModule->fProcessModule) || (!pProcess && pModule->fRootModule)) {
- VMMDLL_VfsList_AddDirectory(pFileList, pModule->szModuleName);
- }
- pModule = pModule->FLink;
- }
-}
-
-BOOL PluginManager_List(_In_opt_ PVMM_PROCESS pProcess, _In_ LPSTR szModule, _In_ LPSTR szPath, _Inout_ PHANDLE pFileList)
-{
- QWORD tmStart = Statistics_CallStart();
- BOOL result;
- VMMDLL_PLUGIN_CONTEXT ctx;
- PPLUGIN_LISTENTRY pModule = (PPLUGIN_LISTENTRY)ctxVmm->pVmmVfsModuleList;
- while(pModule) {
- if(!((pProcess && pModule->fProcessModule) || (!pProcess && pModule->fRootModule))) {
- pModule = pModule->FLink;
- continue;
- }
- if(pModule->pfnList && !_stricmp(szModule, pModule->szModuleName)) {
- PluginManager_ContextInitialize(&ctx, pModule, pProcess, (szPath ? szPath : ""));
- result = pModule->pfnList(&ctx, pFileList);
- Statistics_CallEnd(STATISTICS_ID_PluginManager_List, tmStart);
- return result;
- }
- pModule = pModule->FLink;
- }
- Statistics_CallEnd(STATISTICS_ID_PluginManager_List, tmStart);
- return FALSE;
-}
-
-NTSTATUS PluginManager_Read(_In_opt_ PVMM_PROCESS pProcess, _In_ LPSTR szModule, _In_ LPSTR szPath, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
-{
- QWORD tmStart = Statistics_CallStart();
- NTSTATUS nt;
- VMMDLL_PLUGIN_CONTEXT ctx;
- PPLUGIN_LISTENTRY pModule = (PPLUGIN_LISTENTRY)ctxVmm->pVmmVfsModuleList;
- while(pModule) {
- if(!((pProcess && pModule->fProcessModule) || (!pProcess && pModule->fRootModule))) {
- pModule = pModule->FLink;
- continue;
- }
- if(pModule->pfnRead && !_stricmp(szModule, pModule->szModuleName)) {
- PluginManager_ContextInitialize(&ctx, pModule, pProcess, (szPath ? szPath : ""));
- nt = pModule->pfnRead(&ctx, pb, cb, pcbRead, cbOffset);
- Statistics_CallEnd(STATISTICS_ID_PluginManager_Read, tmStart);
- return nt;
- }
- pModule = pModule->FLink;
- }
- Statistics_CallEnd(STATISTICS_ID_PluginManager_Read, tmStart);
- return VMMDLL_STATUS_FILE_INVALID;
-}
-
-NTSTATUS PluginManager_Write(_In_opt_ PVMM_PROCESS pProcess, _In_ LPSTR szModule, _In_ LPSTR szPath, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset)
-{
- QWORD tmStart = Statistics_CallStart();
- NTSTATUS nt;
- VMMDLL_PLUGIN_CONTEXT ctx;
- PPLUGIN_LISTENTRY pModule = (PPLUGIN_LISTENTRY)ctxVmm->pVmmVfsModuleList;
- while(pModule) {
- if(!((pProcess && pModule->fProcessModule) || (!pProcess && pModule->fRootModule))) {
- pModule = pModule->FLink;
- continue;
- }
- if(pModule->pfnWrite && !_stricmp(szModule, pModule->szModuleName)) {
- PluginManager_ContextInitialize(&ctx, pModule, pProcess, (szPath ? szPath : ""));
- nt = pModule->pfnWrite(&ctx, pb, cb, pcbWrite, cbOffset);
- Statistics_CallEnd(STATISTICS_ID_PluginManager_Write, tmStart);
- return nt;
- }
- pModule = pModule->FLink;
- }
- Statistics_CallEnd(STATISTICS_ID_PluginManager_Write, tmStart);
- return VMMDLL_STATUS_FILE_INVALID;
-}
-
-BOOL PluginManager_Notify(_In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent)
-{
- QWORD tmStart = Statistics_CallStart();
- PPLUGIN_LISTENTRY pModule = (PPLUGIN_LISTENTRY)ctxVmm->pVmmVfsModuleList;
- while(pModule) {
- if(pModule->pfnNotify) {
- pModule->pfnNotify(fEvent, pvEvent, cbEvent);
- }
- pModule = pModule->FLink;
- }
- Statistics_CallEnd(STATISTICS_ID_PluginManager_Notify, tmStart);
- return TRUE;
-}
-
-BOOL PluginManager_ModuleExists(_In_opt_ HMODULE hDLL, _In_opt_ LPSTR szModule) {
- PPLUGIN_LISTENTRY pModule = (PPLUGIN_LISTENTRY)ctxVmm->pVmmVfsModuleList;
- while(pModule) {
- if(hDLL && (hDLL == pModule->hDLL)) { return TRUE; }
- if(szModule && !_stricmp(szModule, pModule->szModuleName)) { return TRUE; }
- pModule = pModule->FLink;
- }
- return FALSE;
-}
-
-BOOL PluginManager_Register(_In_ PVMMDLL_PLUGIN_REGINFO pRegInfo)
-{
- const LPSTR RESERVED_NAMES[] = { "name", "pid", "pmem", "map", "pml4", "vmem", "pml4-user", "win-eprocess", "win-entry", "win-peb", "win-peb32", "win-modules" };
- PPLUGIN_LISTENTRY pModule;
- DWORD i;
- // 1: tests if module is valid
- if(!pRegInfo || (pRegInfo->magic != VMMDLL_PLUGIN_REGINFO_MAGIC) || (pRegInfo->wVersion > VMMDLL_PLUGIN_REGINFO_VERSION)) { return FALSE; }
- if(!pRegInfo->reg_fn.pfnList || !pRegInfo->reg_info.szModuleName[0] || (strlen(pRegInfo->reg_info.szModuleName) > 31)) { return FALSE; }
- if(PluginManager_ModuleExists(NULL, pRegInfo->reg_info.szModuleName)) { return FALSE; }
- pModule = (PPLUGIN_LISTENTRY)LocalAlloc(LMEM_ZEROINIT, sizeof(PLUGIN_LISTENTRY));
- if(!pModule) { return FALSE; }
- if(!pRegInfo->reg_info.fRootModule && !pRegInfo->reg_info.fProcessModule) { return FALSE; }
- for(i = 0; i < (sizeof(RESERVED_NAMES) / sizeof(LPSTR)); i++) {
- if(!strcmp(pRegInfo->reg_info.szModuleName, RESERVED_NAMES[i])) { return FALSE; }
- }
- // 2: register module
- pModule->hDLL = pRegInfo->hDLL;
- strncpy_s(pModule->szModuleName, 32, pRegInfo->reg_info.szModuleName, 32);
- pModule->fRootModule = pRegInfo->reg_info.fRootModule;
- pModule->fProcessModule = pRegInfo->reg_info.fProcessModule;
- pModule->pfnList = pRegInfo->reg_fn.pfnList;
- pModule->pfnRead = pRegInfo->reg_fn.pfnRead;
- pModule->pfnWrite = pRegInfo->reg_fn.pfnWrite;
- pModule->pfnNotify = pRegInfo->reg_fn.pfnNotify;
- pModule->pfnClose = pRegInfo->reg_fn.pfnClose;
- vmmprintfv("PluginManager: Loaded %s module '%s'.\n", (pModule->hDLL ? "native" : "built-in"), pModule->szModuleName);
- pModule->FLink = (PPLUGIN_LISTENTRY)ctxVmm->pVmmVfsModuleList;
- ctxVmm->pVmmVfsModuleList = pModule;
- return TRUE;
-}
-
-VOID PluginManager_Close()
-{
- PPLUGIN_LISTENTRY pm;
- while((pm = (PPLUGIN_LISTENTRY)ctxVmm->pVmmVfsModuleList)) {
- // 1: Detach current module list entry from list
- ctxVmm->pVmmVfsModuleList = pm->FLink;
- // 2: Close module callback
- if(pm->pfnClose) {
- pm->pfnClose();
- }
- // 3: FreeLibrary (if last module belonging to specific Library)
- if(pm->hDLL && !PluginManager_ModuleExists(pm->hDLL, NULL)) { FreeLibrary(pm->hDLL); }
- // 4: LocalFree this ListEntry
- LocalFree(pm);
- }
-}
-
-VOID PluginManager_Initialize_RegInfoInit(_Out_ PVMMDLL_PLUGIN_REGINFO pRI, _In_opt_ HMODULE hDLL)
-{
- ZeroMemory(pRI, sizeof(VMMDLL_PLUGIN_REGINFO));
- pRI->magic = VMMDLL_PLUGIN_REGINFO_MAGIC;
- pRI->wVersion = VMMDLL_PLUGIN_REGINFO_VERSION;
- pRI->wSize = sizeof(VMMDLL_PLUGIN_REGINFO);
- pRI->hDLL = hDLL;
- pRI->tpMemoryModel = ctxVmm->tpMemoryModel;
- pRI->tpSystem = ctxVmm->tpSystem;
- pRI->pfnPluginManager_Register = PluginManager_Register;
-}
-
-VOID PluginManager_Initialize_Python()
-{
- VMMDLL_PLUGIN_REGINFO ri;
- CHAR szPythonPath[MAX_PATH];
- HMODULE hDllPython = NULL, hDllPyPlugin = NULL;
- VOID(*pfnInitializeVmmPlugin)(_In_ PVMMDLL_PLUGIN_REGINFO pRegInfo);
- // 1: Locate Python by trying user-defined path
- if(ctxMain->cfg.szPythonPath[0]) {
- ZeroMemory(szPythonPath, _countof(szPythonPath));
- strcpy_s(szPythonPath, _countof(szPythonPath), ctxMain->cfg.szPythonPath);
- strcat_s(szPythonPath, _countof(szPythonPath), "\\python36.dll");
- hDllPython = LoadLibraryExA(szPythonPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
- if(!hDllPython) {
- ZeroMemory(ctxMain->cfg.szPythonPath, _countof(ctxMain->cfg.szPythonPath));
- vmmprintf("PluginManager: Python initialization failed. Python 3.6 not found on user specified path.\n");
- return;
- }
- }
- // 2: Try locate Python by checking the python36 sub-directory relative to the current executable (.exe).
- if(0 == ctxMain->cfg.szPythonPath[0]) {
- ZeroMemory(szPythonPath, _countof(szPythonPath));
- Util_GetPathDll(szPythonPath, NULL);
- strcat_s(szPythonPath, _countof(szPythonPath), "python36\\python36.dll");
- hDllPython = LoadLibraryExA(szPythonPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
- if(hDllPython) {
- Util_GetPathDll(ctxMain->cfg.szPythonPath, NULL);
- strcat_s(ctxMain->cfg.szPythonPath, _countof(ctxMain->cfg.szPythonPath), "python36\\");
- }
- }
- // 3: Try locate Python by loading from the current path.
- if(0 == ctxMain->cfg.szPythonPath[0]) {
- hDllPython = LoadLibraryA("python36.dll");
- if(hDllPython) {
- Util_GetPathDll(ctxMain->cfg.szPythonPath, hDllPython);
- }
- }
- // 4: Python is not found?
- if(0 == ctxMain->cfg.szPythonPath[0]) {
- vmmprintf("PluginManager: Python initialization failed. Python 3.6 not found.\n");
- goto fail;
- }
- // 5: process 'special status' python plugin manager.
- hDllPyPlugin = LoadLibraryA("vmmpycplugin.dll");
- if(!hDllPyPlugin) {
- vmmprintf("PluginManager: Python plugin manager failed to load.\n");
- goto fail;
- }
- pfnInitializeVmmPlugin = (VOID(*)(PVMMDLL_PLUGIN_REGINFO))GetProcAddress(hDllPyPlugin, "InitializeVmmPlugin");
- if(!pfnInitializeVmmPlugin) {
- vmmprintf("PluginManager: Python plugin manager failed to load due to corrupt DLL.\n");
- goto fail;
- }
- PluginManager_Initialize_RegInfoInit(&ri, hDllPyPlugin);
- ri.hReservedDll = hDllPython;
- pfnInitializeVmmPlugin(&ri);
- if(!PluginManager_ModuleExists(hDllPyPlugin, NULL)) {
- vmmprintf("PluginManager: Python plugin manager failed to load due to internal error.\n");
- return;
- }
- vmmprintfv("PluginManager: Python plugin loaded.\n");
- if(hDllPython) { FreeLibrary(hDllPython); }
- return;
-fail:
- if(hDllPyPlugin) { FreeLibrary(hDllPyPlugin); }
- if(hDllPython) { FreeLibrary(hDllPython); }
-}
-
-BOOL PluginManager_Initialize()
-{
- VMMDLL_PLUGIN_REGINFO ri;
- CHAR szPath[MAX_PATH];
- DWORD cchPathBase;
- HANDLE hFindFile;
- WIN32_FIND_DATAA FindData;
- HMODULE hDLL;
- VOID(*pfnInitializeVmmPlugin)(_In_ PVMMDLL_PLUGIN_REGINFO pRegInfo);
- if(ctxVmm->pVmmVfsModuleList) { return FALSE; } // already initialized
- ZeroMemory(&ri, sizeof(VMMDLL_PLUGIN_REGINFO));
- // 1: process built-in modules
- EnterCriticalSection(&ctxVmm->MasterLock);
- PluginManager_Initialize_RegInfoInit(&ri, NULL);
- M_Virt2Phys_Initialize(&ri);
- PluginManager_Initialize_RegInfoInit(&ri, NULL);
- M_LdrModules_Initialize(&ri);
- PluginManager_Initialize_RegInfoInit(&ri, NULL);
- M_Status_Initialize(&ri);
- // 2: process dll modules
- Util_GetPathDll(szPath, NULL);
- cchPathBase = (DWORD)strnlen(szPath, _countof(szPath) - 1);
- strcat_s(szPath, _countof(szPath), "plugins\\m_*.dll");
- hFindFile = FindFirstFileA(szPath, &FindData);
- if(hFindFile != INVALID_HANDLE_VALUE) {
- do {
- szPath[cchPathBase] = '\0';
- strcat_s(szPath, _countof(szPath), "plugins\\");
- strcat_s(szPath, _countof(szPath), FindData.cFileName);
- hDLL = LoadLibraryExA(szPath, 0, 0);
- if(!hDLL) {
- vmmprintfvv("PluginManager: FAIL: Load DLL: '%s' - missing dependencies?\n", FindData.cFileName);
- continue;
- }
- vmmprintfvv("PluginManager: Load DLL: '%s'\n", FindData.cFileName);
- pfnInitializeVmmPlugin = (VOID(*)(PVMMDLL_PLUGIN_REGINFO))GetProcAddress(hDLL, "InitializeVmmPlugin");
- if(!pfnInitializeVmmPlugin) {
- vmmprintfvv("PluginManager: UnLoad DLL: '%s' - Plugin Entry Point not found.\n", FindData.cFileName);
- FreeLibrary(hDLL);
- continue;
- }
- PluginManager_Initialize_RegInfoInit(&ri, hDLL);
- pfnInitializeVmmPlugin(&ri);
- if(!PluginManager_ModuleExists(hDLL, NULL)) {
- vmmprintfvv("PluginManager: UnLoad DLL: '%s' - not registered with plugin manager.\n", FindData.cFileName);
- FreeLibrary(hDLL);
- continue;
- }
- } while(FindNextFileA(hFindFile, &FindData));
- }
- // 3: process 'special status' python plugin manager.
- PluginManager_Initialize_Python();
- LeaveCriticalSection(&ctxVmm->MasterLock);
- return TRUE;
-}
diff --git a/vmm/pluginmanager.h b/vmm/pluginmanager.h
deleted file mode 100644
index 5002385..0000000
--- a/vmm/pluginmanager.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// pluginmanager.h : definitions for the plugin manager for memory process file system plugins.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __PLUGINMANAGER_H__
-#define __PLUGINMANAGER_H__
-
-#include
-#include "vmm.h"
-
-/*
-* Initialize built-in and external modules.
-*/
-BOOL PluginManager_Initialize();
-
-/*
-* Close built-in and external modules, free their resources and unload loaded
-* DLLs from memory.
-*/
-VOID PluginManager_Close();
-
-/*
-* Enumerate modules in a process directory (insert directories of module names).
-* -- pProcess
-* -- pFileList
-*/
-VOID PluginManager_ListAll(_In_opt_ PVMM_PROCESS pProcess, _Inout_ PHANDLE pFileList);
-
-/*
-* Send a List command down the module chain to the appropriate module.
-* -- pProcess
-* -- szModule
-* -- szPath
-* -- pFileList
-* -- return
-*/
-BOOL PluginManager_List(_In_opt_ PVMM_PROCESS pProcess, _In_ LPSTR szModule, _In_ LPSTR szPath, _Inout_ PHANDLE pFileList);
-
-/*
-* Send a Read command down the module chain to the appropriate module.
-* -- pProcess
-* -- szModule
-* -- szPath
-* -- pb
-* -- cb
-* -- pcbRead
-* -- cbOffset
-* -- return
-*/
-NTSTATUS PluginManager_Read(_In_opt_ PVMM_PROCESS pProcess, _In_ LPSTR szModule, _In_ LPSTR szPath, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset);
-
-/*
-* Send a Write command down the module chain to the appropriate module.
-* -- pProcess
-* -- szModule
-* -- szPath
-* -- pb
-* -- cb
-* -- pcbWrite
-* -- cbOffset
-* -- return
-*/
-NTSTATUS PluginManager_Write(_In_opt_ PVMM_PROCESS pProcess, _In_ LPSTR szModule, _In_ LPSTR szPath, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset);
-
-/*
-* Send a notification event to plugins that registered to receive notifications.
-* Officially supported events are listed in vmmdll.h!VMMDLL_PLUGIN_EVENT_*
-* -- fEvent = the event to send.
-* -- pvEvent = optional binary object related to the event.
-* -- cbEvent = length in bytes of pvEvent (if any).
-* -- return = (always return TRUE).
-*/
-BOOL PluginManager_Notify(_In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
-
-#endif /* __PLUGINMANAGER_H__ */
diff --git a/vmm/resource.h b/vmm/resource.h
deleted file mode 100644
index c78e35f..0000000
--- a/vmm/resource.h
+++ /dev/null
@@ -1,14 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by vmm.rc
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 101
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1001
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
diff --git a/vmm/statistics.c b/vmm/statistics.c
deleted file mode 100644
index 44164da..0000000
--- a/vmm/statistics.c
+++ /dev/null
@@ -1,328 +0,0 @@
-// statistics.c : implementation of statistics related functionality.
-//
-// (c) Ulf Frisk, 2016-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include "statistics.h"
-#include "vmm.h"
-
-// ----------------------------------------------------------------------------
-// PAGE READ STATISTICAL FUNCTIONALITY BELOW:
-// ----------------------------------------------------------------------------
-
-VOID _PageStatPrintMemMap(_Inout_ PPAGE_STATISTICS ps)
-{
- QWORD i, qwAddrEnd;
- if(!ps->i.fIsFirstPrintCompleted) {
- printf(" Memory Map: \n START END #PAGES \n");
- }
- if(!ps->i.MemMapIdx) {
- printf(" \n \n");
- return;
- }
- if(ps->i.MemMapIdx >= PAGE_STATISTICS_MEM_MAP_MAX_ENTRY - 2) {
- printf(" Maximum number of memory map entries reached. \n \n");
- return;
- }
- for(i = max(1, ps->i.MemMapPrintIdx); i <= ps->i.MemMapIdx; i++) {
- if(!ps->i.MemMap[i].cPages) {
- break;
- }
- qwAddrEnd = ps->i.MemMap[i].qwAddrBase + ((QWORD)ps->i.MemMap[i].cPages << 12);
- printf(
- " %016llx - %016llx %08x \n",
- ps->i.MemMap[i].qwAddrBase,
- qwAddrEnd - 1,
- ps->i.MemMap[i].cPages);
- }
- ps->i.MemMapPrintIdx = ps->i.MemMapIdx;
- if(!ps->i.MemMap[1].cPages) { // print extra line for formatting reasons.
- printf(" (No memory successfully read yet) \n");
- }
- printf(" \n");
-}
-
-VOID _PageStatShowUpdate(_Inout_ PPAGE_STATISTICS ps)
-{
- if(0 == ps->cPageTotal) { return; }
- QWORD qwPercentTotal = ((ps->cPageSuccess + ps->cPageFail) * 100) / ps->cPageTotal;
- QWORD qwPercentSuccess = (ps->cPageSuccess * 200 + 1) / (ps->cPageTotal * 2);
- QWORD qwPercentFail = (ps->cPageFail * 200 + 1) / (ps->cPageTotal * 2);
- QWORD qwTickCountElapsed = GetTickCount64() - ps->i.qwTickCountStart;
- QWORD qwSpeed = ((ps->cPageSuccess + ps->cPageFail) * 4) / (1 + (qwTickCountElapsed / 1000));
- HANDLE hConsole;
- CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
- BOOL isMBs = qwSpeed >= 1024;
- if(ps->i.fIsFirstPrintCompleted) {
-#ifdef WIN32
- hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
- GetConsoleScreenBufferInfo(hConsole, &consoleInfo);
- consoleInfo.dwCursorPosition.Y -= ps->i.fMemMap ? 9 : 7;
- SetConsoleCursorPosition(hConsole, consoleInfo.dwCursorPosition);
-#endif /* WIN32 */
-#if defined(LINUX) || defined(ANDROID)
- vmmprintf(ps->i.fMemMap ? "\033[9A" : "\033[7A"); // move cursor up 7/9 positions
-#endif /* LINUX || ANDROID */
- }
- if(ps->i.fMemMap) {
- _PageStatPrintMemMap(ps);
- }
- if(ps->cPageTotal < 0x0000000fffffffff) {
- vmmprintf(
- " Current Action: %s \n" \
- " Access Mode: %s \n" \
- " Progress: %llu / %llu (%llu%%) \n" \
- " Speed: %llu %s \n" \
- " Address: 0x%016llX \n" \
- " Pages read: %llu / %llu (%llu%%) \n" \
- " Pages failed: %llu (%llu%%) \n",
- ps->szAction,
- ps->fKMD ? "KMD (kernel module assisted DMA)" : "Normal ",
- (ps->cPageSuccess + ps->cPageFail) / 256,
- ps->cPageTotal / 256,
- qwPercentTotal,
- (isMBs ? qwSpeed >> 10 : qwSpeed),
- (isMBs ? "MB/s" : "kB/s"),
- ps->qwAddr,
- ps->cPageSuccess,
- ps->cPageTotal,
- qwPercentSuccess,
- ps->cPageFail,
- qwPercentFail);
- } else {
- vmmprintf(
- " Current Action: %s \n" \
- " Access Mode: %s \n" \
- " Progress: %llu / (unknown) \n" \
- " Speed: %llu %s \n" \
- " Address: 0x%016llX \n" \
- " Pages read: %llu \n" \
- " Pages failed: %llu \n",
- ps->szAction,
- ps->fKMD ? "KMD (kernel module assisted DMA)" : "Normal ",
- (ps->cPageSuccess + ps->cPageFail) / 256,
- (isMBs ? qwSpeed >> 10 : qwSpeed),
- (isMBs ? "MB/s" : "kB/s"),
- ps->qwAddr,
- ps->cPageSuccess,
- ps->cPageFail);
- }
- ps->i.fIsFirstPrintCompleted = TRUE;
-}
-
-VOID _PageStatThreadLoop(_In_ PPAGE_STATISTICS ps)
-{
- while(!ps->i.fThreadExit) {
- Sleep(100);
- if(ps->i.fUpdate) {
- ps->i.fUpdate = FALSE;
- _PageStatShowUpdate(ps);
- }
- }
- ExitThread(0);
-}
-
-VOID PageStatClose(_In_opt_ PPAGE_STATISTICS *ppPageStat)
-{
- BOOL status;
- DWORD dwExitCode;
- if(!ppPageStat || !*ppPageStat) { return; }
- (*ppPageStat)->i.fUpdate = TRUE;
- (*ppPageStat)->i.fThreadExit = TRUE;
- while((status = GetExitCodeThread((*ppPageStat)->i.hThread, &dwExitCode)) && STILL_ACTIVE == dwExitCode) {
- SwitchToThread();
- }
- if(!status) {
- Sleep(200);
- }
- LocalFree(*ppPageStat);
- *ppPageStat = NULL;
-}
-
-_Success_(return)
-BOOL PageStatInitialize(_Out_ PPAGE_STATISTICS *ppPageStat, _In_ QWORD qwAddrBase, _In_ QWORD qwAddrMax, _In_ LPSTR szAction, _In_ BOOL fKMD, _In_ BOOL fMemMap)
-{
- PPAGE_STATISTICS ps;
- ps = *ppPageStat = LocalAlloc(LMEM_ZEROINIT, sizeof(PAGE_STATISTICS));
- if(!ps) { return FALSE; }
- ps->qwAddr = qwAddrBase;
- ps->cPageTotal = (qwAddrMax - qwAddrBase + 1) / 4096;
- ps->szAction = szAction;
- ps->fKMD = fKMD;
- ps->i.fMemMap = fMemMap;
- ps->i.qwTickCountStart = GetTickCount64();
- ps->i.hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_PageStatThreadLoop, ps, 0, NULL);
- return TRUE;
-}
-
-VOID PageStatUpdate(_In_opt_ PPAGE_STATISTICS pPageStat, _In_ QWORD qwAddr, _In_ QWORD cPageSuccessAdd, _In_ QWORD cPageFailAdd)
-{
- if(!pPageStat) { return; }
- pPageStat->qwAddr = qwAddr;
- pPageStat->cPageSuccess += cPageSuccessAdd;
- pPageStat->cPageFail += cPageFailAdd;
- // add to memory map
- if(cPageSuccessAdd && (pPageStat->i.MemMapIdx < PAGE_STATISTICS_MEM_MAP_MAX_ENTRY - 1)) {
- if(!pPageStat->i.MemMapIdx || (qwAddr - (cPageSuccessAdd << 12)) != (pPageStat->i.MemMap[pPageStat->i.MemMapIdx].qwAddrBase + ((QWORD)pPageStat->i.MemMap[pPageStat->i.MemMapIdx].cPages << 12))) {
- pPageStat->i.MemMapIdx++;
- pPageStat->i.MemMap[pPageStat->i.MemMapIdx].qwAddrBase = qwAddr - (cPageSuccessAdd << 12);
- }
- pPageStat->i.MemMap[pPageStat->i.MemMapIdx].cPages += (DWORD)cPageSuccessAdd;
- }
- pPageStat->i.fUpdate = TRUE;
-}
-
-// ----------------------------------------------------------------------------
-// FUNCTION CALL STATISTICAL FUNCTIONALITY BELOW:
-// ----------------------------------------------------------------------------
-
-const LPSTR NAMES_VMM_STATISTICS_CALL[] = {
- "INITIALIZE",
- "VMMDLL_VfsList",
- "VMMDLL_VfsRead",
- "VMMDLL_VfsWrite",
- "VMMDLL_VfsInitializePlugins",
- "VMMDLL_MemReadEx",
- "VMMDLL_MemWrite",
- "VMMDLL_MemVirt2Phys",
- "VMMDLL_MemPrefetchPages",
- "VMMDLL_PidList",
- "VMMDLL_PidGetFromName",
- "VMMDLL_ProcessGetInformation",
- "VMMDLL_ProcessGetMemoryMap",
- "VMMDLL_ProcessGetMemoryMapEntry",
- "VMMDLL_ProcessGetModuleMap",
- "VMMDLL_ProcessGetModuleFromName",
- "VMMDLL_ProcessGetDirectories",
- "VMMDLL_ProcessGetSections",
- "VMMDLL_ProcessGetEAT",
- "VMMDLL_ProcessGetIAT",
- "VMMDLL_ProcessGetProcAddress",
- "VMMDLL_ProcessGetModuleBase",
- "VMMDLL_WinGetThunkEAT",
- "VMMDLL_WinGetThunkIAT",
- "VMMDLL_WinMemCompression_DecompressPage",
- "VMMDLL_Refresh",
- "PluginManager_List",
- "PluginManager_Read",
- "PluginManager_Write",
- "PluginManager_Notify"
-};
-
-typedef struct tdCALLSTAT {
- QWORD c;
- QWORD tm;
-} CALLSTAT, *PCALLSTAT;
-
-VOID Statistics_CallSetEnabled(_In_ BOOL fEnabled)
-{
- if(fEnabled && ctxMain->pvStatistics) { return; }
- if(!fEnabled && !ctxMain->pvStatistics) { return; }
- if(fEnabled) {
- ctxMain->pvStatistics = LocalAlloc(LMEM_ZEROINIT, (STATISTICS_ID_MAX + 1) * sizeof(CALLSTAT));
- } else {
- LocalFree(ctxMain->pvStatistics);
- ctxMain->pvStatistics = NULL;
- }
-}
-
-BOOL Statistics_CallGetEnabled()
-{
- return ctxMain->pvStatistics != NULL;
-}
-
-QWORD Statistics_CallStart()
-{
- QWORD tmNow;
- if(!ctxMain->pvStatistics) { return 0; }
- QueryPerformanceCounter((PLARGE_INTEGER)&tmNow);
- return tmNow;
-}
-
-VOID Statistics_CallEnd(_In_ DWORD fId, QWORD tmCallStart)
-{
- QWORD tmNow;
- PCALLSTAT pStat;
- if(!ctxMain->pvStatistics) { return; }
- if(fId > STATISTICS_ID_MAX) { return; }
- if(tmCallStart == 0) { return; }
- pStat = ((PCALLSTAT)ctxMain->pvStatistics) + fId;
- InterlockedIncrement64(&pStat->c);
- QueryPerformanceCounter((PLARGE_INTEGER)&tmNow);
- InterlockedAdd64(&pStat->tm, tmNow - tmCallStart);
-}
-
-VOID Statistics_CallToString(_In_opt_ PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcb)
-{
- BOOL result;
- QWORD qwFreq, uS;
- DWORD i, o = 0;
- PCALLSTAT pStat;
- LEECHCORE_STATISTICS LeechCoreStatistics = { 0 };
- DWORD cbLeechCoreStatistics = sizeof(LEECHCORE_STATISTICS);
- if(!pb) {
- *pcb = 79 * (STATISTICS_ID_MAX + LEECHCORE_STATISTICS_ID_MAX + 6);
- return;
- }
- QueryPerformanceFrequency((PLARGE_INTEGER)&qwFreq);
- o += snprintf(
- pb + o,
- cb - o,
- "FUNCTION CALL STATISTICS: \n" \
- "VALUES IN DECIMAL, TIME IN MICROSECONDS uS, STATISTICS = %s \n" \
- "FUNCTION CALL NAME CALLS TIME AVG TIME TOTAL\n" \
- "==============================================================================\n",
- ctxMain->pvStatistics ? "ENABLED " : "DISABLED"
- );
- // statistics
- for(i = 0; i <= STATISTICS_ID_MAX; i++) {
- if(ctxMain->pvStatistics) {
- pStat = ((PCALLSTAT)ctxMain->pvStatistics) + i;
- if(pStat->c) {
- uS = (pStat->tm * 1000000ULL) / qwFreq;
- o += snprintf(
- pb + o,
- cb - o,
- "%-40.40s %8i %8i %16lli\n",
- NAMES_VMM_STATISTICS_CALL[i],
- (DWORD)pStat->c,
- (DWORD)(uS / pStat->c),
- uS
- );
- continue;
- }
- }
- o += snprintf(
- pb + o,
- cb - o,
- "%-40.40s %8i %8i %16lli\n",
- NAMES_VMM_STATISTICS_CALL[i],
- 0, 0, 0ULL);
- }
- // leechcore statistics
- result = LeechCore_CommandData(LEECHCORE_COMMANDDATA_STATISTICS_GET, NULL, 0, (PBYTE)&LeechCoreStatistics, cbLeechCoreStatistics, &cbLeechCoreStatistics);
- if(result && (LeechCoreStatistics.magic == LEECHCORE_STATISTICS_MAGIC) && (LeechCoreStatistics.version == LEECHCORE_STATISTICS_VERSION) && LeechCoreStatistics.qwFreq) {
- for(i = 0; i <= LEECHCORE_STATISTICS_ID_MAX; i++) {
- if(LeechCoreStatistics.Call[i].c) {
- uS = (LeechCoreStatistics.Call[i].tm * 1000000ULL) / LeechCoreStatistics.qwFreq;
- o += snprintf(
- pb + o,
- cb - o,
- "%-40.40s %8i %8i %16lli\n",
- LEECHCORE_STATISTICS_NAME[i],
- (DWORD)LeechCoreStatistics.Call[i].c,
- (DWORD)(uS / LeechCoreStatistics.Call[i].c),
- uS
- );
- } else {
- o += snprintf(
- pb + o,
- cb - o,
- "%-40.40s %8i %8i %16lli\n",
- LEECHCORE_STATISTICS_NAME[i],
- 0, 0, 0ULL);
- }
- }
- }
- *pcb = o - 1;
-}
diff --git a/vmm/statistics.h b/vmm/statistics.h
deleted file mode 100644
index 11dc164..0000000
--- a/vmm/statistics.h
+++ /dev/null
@@ -1,109 +0,0 @@
-// statistics.h : definitions of statistics related functionality.
-//
-// (c) Ulf Frisk, 2016-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __STATISTICS_H__
-#define __STATISTICS_H__
-#include "vmm.h"
-
-#define PAGE_STATISTICS_MEM_MAP_MAX_ENTRY 2048
-
-typedef struct tdPageStatistics {
- QWORD qwAddr;
- QWORD cPageTotal;
- QWORD cPageSuccess;
- QWORD cPageFail;
- BOOL fKMD;
- LPSTR szAction;
- struct _InternalUseOnly {
- BOOL fUpdate;
- BOOL fThreadExit;
- BOOL fMemMap;
- BOOL fIsFirstPrintCompleted;
- HANDLE hThread;
- WORD wConsoleCursorPosition;
- QWORD qwTickCountStart;
- QWORD MemMapIdx;
- QWORD MemMapPrintIdx;
- struct {
- QWORD qwAddrBase;
- DWORD cPages;
- } MemMap[PAGE_STATISTICS_MEM_MAP_MAX_ENTRY];
- } i;
-} PAGE_STATISTICS, *PPAGE_STATISTICS;
-
-/*
-* Initialize the page statistics. This will also start displaying the page statistics
-* on the screen asynchronously. PageStatClose must be called to stop this.
-* -- ps = ptr to NULL pPageStat PageStatInitialize will initialize. Must be free'd with PageStatClose.
-* -- qwAddrBase = the base address that the statistics will be based upon.
-* -- qwAddrMax = the maximum address.
-* -- szAction = the text shown as action.
-* -- fKMD = is KMD mode.
-* -- fPageMap = display read memory map when PageStatClose is called.
-* -- return
-*/
-_Success_(return)
-BOOL PageStatInitialize(_Out_ PPAGE_STATISTICS *ppPageStat, _In_ QWORD qwAddrBase, _In_ QWORD qwAddrMax, _In_ LPSTR szAction, _In_ BOOL fKMD, _In_ BOOL fMemMap);
-
-/*
-* Do one last update of the on-screen page statistics, display the read memory map if
-* previously set in PageStatInitialize and stop the on-screen updates.
-* -- pPageStat = ptr to the PPAGE_STATISTICS struct to close and free.
-*/
-VOID PageStatClose(_In_opt_ PPAGE_STATISTICS *ppPageStat);
-
-/*
-* Update the page statistics with the current address and with successfully and failed
-* pages. Should not be called before PageStatInitialize and not after PageStatClose.
-* This function must be used if the memory map should be shown; otherwise it's possible
-* to alter the PPAGE_STATISTICS struct members directly.
-* -- pPageStat = pointer to page statistics struct.
-* -- qwAddr = new address (after completed operation).
-* -- cPageSuccessAdd = number of successfully read pages.
-* -- cPageFailAdd = number of pages that failed.
-*/
-VOID PageStatUpdate(_In_opt_ PPAGE_STATISTICS pPageStat, _In_ QWORD qwAddr, _In_ QWORD cPageSuccessAdd, _In_ QWORD cPageFailAdd);
-
-// NB! also update statistics.c!NAMES_VMM_STATISTICS_CALL
-#define STATISTICS_ID_INITIALIZE 0x00
-#define STATISTICS_ID_VMMDLL_VfsList 0x01
-#define STATISTICS_ID_VMMDLL_VfsRead 0x02
-#define STATISTICS_ID_VMMDLL_VfsWrite 0x03
-#define STATISTICS_ID_VMMDLL_VfsInitializePlugins 0x04
-#define STATISTICS_ID_VMMDLL_MemReadEx 0x05
-#define STATISTICS_ID_VMMDLL_MemWrite 0x06
-#define STATISTICS_ID_VMMDLL_MemVirt2Phys 0x07
-#define STATISTICS_ID_VMMDLL_MemPrefetchPages 0x08
-#define STATISTICS_ID_VMMDLL_PidList 0x09
-#define STATISTICS_ID_VMMDLL_PidGetFromName 0x0a
-#define STATISTICS_ID_VMMDLL_ProcessGetInformation 0x0b
-#define STATISTICS_ID_VMMDLL_ProcessGetMemoryMap 0x0c
-#define STATISTICS_ID_VMMDLL_ProcessGetMemoryMapEntry 0x0d
-#define STATISTICS_ID_VMMDLL_ProcessGetModuleMap 0x0e
-#define STATISTICS_ID_VMMDLL_ProcessGetModuleFromName 0x0f
-#define STATISTICS_ID_VMMDLL_ProcessGetDirectories 0x10
-#define STATISTICS_ID_VMMDLL_ProcessGetSections 0x11
-#define STATISTICS_ID_VMMDLL_ProcessGetEAT 0x12
-#define STATISTICS_ID_VMMDLL_ProcessGetIAT 0x13
-#define STATISTICS_ID_VMMDLL_ProcessGetProcAddress 0x14
-#define STATISTICS_ID_VMMDLL_ProcessGetModuleBase 0x15
-#define STATISTICS_ID_VMMDLL_WinGetThunkEAT 0x16
-#define STATISTICS_ID_VMMDLL_WinGetThunkIAT 0x17
-#define STATISTICS_ID_VMMDLL_WinMemCompression_DecompressPage 0x18
-#define STATISTICS_ID_VMMDLL_Refresh 0x19
-#define STATISTICS_ID_PluginManager_List 0x1a
-#define STATISTICS_ID_PluginManager_Read 0xab
-#define STATISTICS_ID_PluginManager_Write 0x1c
-#define STATISTICS_ID_PluginManager_Notify 0x1d
-#define STATISTICS_ID_MAX 0x1d
-#define STATISTICS_ID_NOLOG 0xffffffff
-
-VOID Statistics_CallSetEnabled(_In_ BOOL fEnabled);
-BOOL Statistics_CallGetEnabled();
-QWORD Statistics_CallStart();
-VOID Statistics_CallEnd(_In_ DWORD fId, QWORD tmCallStart);
-VOID Statistics_CallToString(_In_opt_ PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcb);
-
-#endif /* __STATISTICS_H__ */
diff --git a/vmm/util.c b/vmm/util.c
deleted file mode 100644
index ca1766a..0000000
--- a/vmm/util.c
+++ /dev/null
@@ -1,205 +0,0 @@
-// util.c : implementation of various utility functions.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include "util.h"
-
-QWORD Util_GetNumeric(_In_ LPSTR sz)
-{
- if((strlen(sz) > 1) && (sz[0] == '0') && ((sz[1] == 'x') || (sz[1] == 'X'))) {
- return strtoull(sz, NULL, 16); // Hex (starts with 0x)
- } else {
- return strtoull(sz, NULL, 10); // Not Hex -> try Decimal
- }
-}
-
-#define Util_2HexChar(x) (((((x) & 0xf) <= 9) ? '0' : ('a' - 10)) + ((x) & 0xf))
-
-#define UTIL_PRINTASCII \
- "................................ !\"#$%&'()*+,-./0123456789:;<=>?" \
- "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz`{|}~" \
- "................................................................" \
- "................................................................" \
-
-BOOL Util_FillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz)
-{
- DWORD i, j, o = 0, szMax, iMod;
- // checks
- if((cbInitialOffset > cb) || (cbInitialOffset > 0x1000) || (cbInitialOffset & 0xf)) { return FALSE; }
- *pcsz = szMax = cb * 5 + 80;
- if(cb > szMax) { return FALSE; }
- if(!sz) { return TRUE; }
- // fill buffer with bytes
- for(i = cbInitialOffset; i < cb + ((cb % 16) ? (16 - cb % 16) : 0); i++)
- {
- // address
- if(0 == i % 16) {
- iMod = i % 0x10000;
- sz[o++] = Util_2HexChar(iMod >> 12);
- sz[o++] = Util_2HexChar(iMod >> 8);
- sz[o++] = Util_2HexChar(iMod >> 4);
- sz[o++] = Util_2HexChar(iMod);
- sz[o++] = ' ';
- sz[o++] = ' ';
- sz[o++] = ' ';
- sz[o++] = ' ';
- } else if(0 == i % 8) {
- sz[o++] = ' ';
- }
- // hex
- if(i < cb) {
- sz[o++] = Util_2HexChar(pb[i] >> 4);
- sz[o++] = Util_2HexChar(pb[i]);
- sz[o++] = ' ';
- } else {
- sz[o++] = ' ';
- sz[o++] = ' ';
- sz[o++] = ' ';
- }
- // ascii
- if(15 == i % 16) {
- sz[o++] = ' ';
- sz[o++] = ' ';
- for(j = i - 15; j <= i; j++) {
- if(j >= cb) {
- sz[o++] = ' ';
- } else {
- sz[o++] = UTIL_PRINTASCII[pb[j]];
- }
- }
- sz[o++] = '\n';
- }
- }
- sz[o++] = 0;
- return TRUE;
-}
-
-VOID Util_PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset)
-{
- DWORD szMax;
- LPSTR sz;
- if(cb > 0x10000) {
- vmmprintf("Large output. Only displaying first 65kB.\n");
- cb = 0x10000 - cbInitialOffset;
- }
- Util_FillHexAscii(pb, cb, cbInitialOffset, NULL, &szMax);
- if(!(sz = LocalAlloc(0, szMax))) { return; }
- Util_FillHexAscii(pb, cb, cbInitialOffset, sz, &szMax);
- vmmprintf("%s", sz);
- LocalFree(sz);
-}
-
-VOID Util_PathSplit2(_In_ LPSTR sz, _Out_writes_(MAX_PATH) PCHAR _szBuf, _Out_ LPSTR *psz1, _Out_ LPSTR *psz2)
-{
- DWORD i;
- strcpy_s(_szBuf, MAX_PATH, sz);
- *psz1 = _szBuf;
- for(i = 0; i < MAX_PATH; i++) {
- if('\0' == _szBuf[i]) {
- *psz2 = _szBuf + i;
- return;
- }
- if('\\' == _szBuf[i]) {
- _szBuf[i] = '\0';
- *psz2 = _szBuf + i + 1;
- return;
- }
- }
-}
-
-VOID Util_PathSplit2_WCHAR(_In_ LPWSTR wsz, _Out_writes_(MAX_PATH) PCHAR _szBuf, _Out_ LPSTR *psz1, _Out_ LPSTR *psz2)
-{
- DWORD i;
- for(i = 0; i < MAX_PATH; i++) {
- _szBuf[i] = (CHAR)wsz[i];
- if(!_szBuf[i]) { break; }
- }
- _szBuf[i] = 0;
- *psz1 = _szBuf;
- for(i = 0; i < MAX_PATH; i++) {
- if('\0' == _szBuf[i]) {
- *psz2 = _szBuf + i;
- return;
- }
- if('\\' == _szBuf[i]) {
- _szBuf[i] = '\0';
- *psz2 = _szBuf + i + 1;
- return;
- }
- }
-}
-
-VOID Util_GetPathDll(_Out_writes_(MAX_PATH) PCHAR szPath, _In_opt_ HMODULE hModule)
-{
- SIZE_T i;
- GetModuleFileNameA(hModule, szPath, MAX_PATH - 4);
- for(i = strlen(szPath) - 1; i > 0; i--) {
- if(szPath[i] == '/' || szPath[i] == '\\') {
- szPath[i + 1] = '\0';
- return;
- }
- }
-}
-
-#define UTIL_NTSTATUS_SUCCESS ((NTSTATUS)0x00000000L)
-#define UTIL_NTSTATUS_END_OF_FILE ((NTSTATUS)0xC0000011L)
-
-NTSTATUS Util_VfsReadFile_FromPBYTE(_In_ PBYTE pbFile, _In_ QWORD cbFile, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
-{
- if(cbOffset > cbFile) { return UTIL_NTSTATUS_END_OF_FILE; }
- *pcbRead = (DWORD)min(cb, cbFile - cbOffset);
- memcpy(pb, pbFile + cbOffset, *pcbRead);
- return *pcbRead ? UTIL_NTSTATUS_SUCCESS : UTIL_NTSTATUS_END_OF_FILE;
-}
-
-NTSTATUS Util_VfsReadFile_FromQWORD(_In_ QWORD qwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset, _In_ BOOL fPrefix)
-{
- BYTE pbBuffer[32];
- DWORD cbBuffer;
- cbBuffer = snprintf(pbBuffer, 32, (fPrefix ? "0x%016llx" : "%016llx"), qwValue);
- return Util_VfsReadFile_FromPBYTE(pbBuffer, cbBuffer, pb, cb, pcbRead, cbOffset);
-}
-
-NTSTATUS Util_VfsReadFile_FromDWORD(_In_ DWORD dwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset, _In_ BOOL fPrefix)
-{
- BYTE pbBuffer[32];
- DWORD cbBuffer;
- cbBuffer = snprintf(pbBuffer, 32, (fPrefix ? "0x%08x" : "%08x"), dwValue);
- return Util_VfsReadFile_FromPBYTE(pbBuffer, cbBuffer, pb, cb, pcbRead, cbOffset);
-}
-
-NTSTATUS Util_VfsReadFile_FromBOOL(_In_ BOOL fValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
-{
- BYTE pbBuffer[1];
- pbBuffer[0] = fValue ? '1' : '0';
- return Util_VfsReadFile_FromPBYTE(pbBuffer, 1, pb, cb, pcbRead, cbOffset);
-}
-
-NTSTATUS Util_VfsWriteFile_BOOL(_Inout_ PBOOL pfTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset)
-{
- CHAR ch;
- if((cb > 0) && (cbOffset == 0)) {
- ch = *(PCHAR)pb;
- *pfTarget = (ch == 0 || ch == '0') ? FALSE : TRUE;
- }
- *pcbWrite = cb;
- return UTIL_NTSTATUS_SUCCESS;
-}
-
-NTSTATUS Util_VfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset, _In_ DWORD dwMinAllow)
-{
- DWORD dw;
- BYTE pbBuffer[9];
- if(cbOffset < 8) {
- snprintf(pbBuffer, 9, "%08x", *pdwTarget);
- cb = (DWORD)min(8 - cbOffset, cb);
- memcpy(pbBuffer + cbOffset, pb, cb);
- pbBuffer[8] = 0;
- dw = strtoul(pbBuffer, NULL, 16);
- dw = max(dw, dwMinAllow);
- *pdwTarget = dw;
- }
- *pcbWrite = cb;
- return UTIL_NTSTATUS_SUCCESS;
-}
diff --git a/vmm/util.h b/vmm/util.h
deleted file mode 100644
index c714bec..0000000
--- a/vmm/util.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// util.h : definitions of various utility functions.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __UTIL_H__
-#define __UTIL_H__
-#include "vmm.h"
-
-/*
-* Parse a string returning the QWORD representing the string. The string may
-* consist of a decimal or hexadecimal integer string. Hexadecimals must begin
-* with 0x.
-* -- sz
-* -- return
-*/
-QWORD Util_GetNumeric(_In_ LPSTR sz);
-
-/*
-* Print a maximum of 8192 bytes of binary data as hexascii on the screen.
-* -- pb
-* -- cb
-* -- cbInitialOffset = offset, must be max 0x1000 and multiple of 0x10.
-*/
-VOID Util_PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset);
-
-/*
-* Fill a human readable hex ascii memory dump into the caller supplied sz buffer.
-* -- pb
-* -- cb
-* -- cbInitialOffset = offset, must be max 0x1000 and multiple of 0x10.
-* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
-* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
-*/
-BOOL Util_FillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
-
-/*
-* Split a "path" string into two at the first '\' character. If no 2nd string
-* is not found then it's returned as null character '\0' (i.e. not as NULL).
-* -- sz = the original string to split (of maximum MAX_PATH length)
-* -- _szBuf = MAX_PATH sized buffer that will be overwritten and used throughout the lifetime of psz1/psz2 outputs.
-* -- psz1
-* -- psz2
-*/
-VOID Util_PathSplit2(_In_ LPSTR sz, _Out_writes_(MAX_PATH) PCHAR _szBuf, _Out_ LPSTR *psz1, _Out_ LPSTR *psz2);
-
-/*
-* Split a "path" string into two at the first '\' character. If no 2nd string
-* is not found then it's returned as null character '\0' (i.e. not as NULL).
-* -- wsz = the original string to split (of maximum MAX_PATH length)
-* -- _szBuf = MAX_PATH sized buffer that will be overwritten and used throughout the lifetime of psz1/psz2 outputs.
-* -- psz1
-* -- psz2
-*/
-VOID Util_PathSplit2_WCHAR(_In_ LPWSTR wsz, _Out_writes_(MAX_PATH) PCHAR _szBuf, _Out_ LPSTR *psz1, _Out_ LPSTR *psz2);
-
-/*
-* Return the path of the specified hModule (DLL) - ending with a backslash, or current Executable.
-* -- szPath
-* -- hModule = Optional, HMODULE handle for path to DLL, NULL for path to EXE.
-*/
-VOID Util_GetPathDll(_Out_writes_(MAX_PATH) PCHAR szPath, _In_opt_ HMODULE hModule);
-
-/*
-* Utility functions for read/write towards different underlying data representations.
-*/
-NTSTATUS Util_VfsReadFile_FromPBYTE(_In_ PBYTE pbFile, _In_ QWORD cbFile, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset);
-NTSTATUS Util_VfsReadFile_FromQWORD(_In_ QWORD qwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset, _In_ BOOL fPrefix);
-NTSTATUS Util_VfsReadFile_FromDWORD(_In_ DWORD dwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset, _In_ BOOL fPrefix);
-NTSTATUS Util_VfsReadFile_FromBOOL(_In_ BOOL fValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset);
-NTSTATUS Util_VfsWriteFile_BOOL(_Inout_ PBOOL pfTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset);
-NTSTATUS Util_VfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset, _In_ DWORD dwMinAllow);
-
-#endif /* __UTIL_H__ */
diff --git a/vmm/version.h b/vmm/version.h
deleted file mode 100644
index b428978..0000000
--- a/vmm/version.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#define STRINGIZE2(s) #s
-#define STRINGIZE(s) STRINGIZE2(s)
-
-#define VERSION_MAJOR 2
-#define VERSION_MINOR 2
-#define VERSION_REVISION 0
-#define VERSION_BUILD 0
-
-#define VER_FILE_DESCRIPTION_STR "The Memory Process File System : Core"
-#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
-#define VER_FILE_VERSION_STR STRINGIZE(VERSION_MAJOR) \
- "." STRINGIZE(VERSION_MINOR) \
- "." STRINGIZE(VERSION_REVISION) \
- "." STRINGIZE(VERSION_BUILD) \
-
-#define VER_COMPANY_NAME_STR ""
-#define VER_PRODUCTNAME_STR "vmm"
-#define VER_PRODUCT_VERSION VER_FILE_VERSION
-#define VER_PRODUCT_VERSION_STR VER_FILE_VERSION_STR
-#define VER_ORIGINAL_FILENAME_STR VER_PRODUCTNAME_STR ".dll"
-#define VER_INTERNAL_NAME_STR VER_ORIGINAL_FILENAME_STR
-#define VER_COPYRIGHT_STR "Copyright (c) Ulf Frisk 2018-2019"
diff --git a/vmm/vmm.c b/vmm/vmm.c
deleted file mode 100644
index 5a11a06..0000000
--- a/vmm/vmm.c
+++ /dev/null
@@ -1,1445 +0,0 @@
-// vmm.c : implementation of functions related to virtual memory management support.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-
-#include "vmm.h"
-#include "mm_x86.h"
-#include "mm_x86pae.h"
-#include "mm_x64.h"
-#include "vmmproc.h"
-#include "pluginmanager.h"
-#include "util.h"
-
-// ----------------------------------------------------------------------------
-// OBJECT MANAGER FUNCTIONALITY:
-//
-// The object manager is a minimal non-threaded way of allocating objects with
-// reference counts. When reference count reach zero the object is deallocated
-// automatically.
-//
-// All VmmOb functions are thread-safe and performs only minimum locking.
-//
-// A thread calls VmmOb_Alloc to allocate an object of a specific length. The
-// object initially have reference count 1. Reference counts may be increased
-// by calling VmmOb_INCREF and decreased by calling VmmOb_DECREF. If the ref-
-// count reach one or zero in a call to VmmOb_DECREF optional callbacks may be
-// made (specified at VmmOb_Alloc time). Callbacks may be useful for cleanup
-// tasks - such as decreasing reference count of sub-objects contained in the
-// object that is to be deallocated.
-//
-// A container provides atomic access to a single VmmOb object. This is useful
-// if a VmmOb object is to frequently be replaced by a new object in an atomic
-// way. An example of this is the process list object containing the process
-// information. The container holds a reference count to the object that is
-// contained.
-//
-// ----------------------------------------------------------------------------
-
-#define VMMOB_DEBUG_FOOTER_SIZE 0x20
-#define VMMOB_DEBUG_FOOTER_MAGIC 0x001122334455667788
-#define VMMOB_HEADER_MAGIC 0x0c0efefe
-
-// Internal object manager use only - same size as opaque VMMOB struct.
-typedef struct tdVMMOB_HEADER {
- DWORD magic; // magic value - VMMOB_HEADER_MAGIC
- WORD count; // reference count
- WORD tag; // tag - 2 chars, no null terminator
- VOID(*pfnRef_0)(_In_ PVOID pVmmOb); // callback - object specific cleanup before free
- VOID(*pfnRef_1)(_In_ PVOID pVmmOb); // callback - when object reach refcount 1 (not initial)
- DWORD dbg;
- DWORD cbData;
- BYTE pbData[];
-} VMMOB_HEADER, *PVMMOB_HEADER;
-
-/*
-* Allocate a new vmm object manager memory object.
-* -- tag = tag of the object to be allocated.
-* -- uFlags = flags as given by LocalAlloc.
-* -- uBytes = bytes of object (excluding object headers).
-* -- pfnRef_0 = optional callback for cleanup o be called before object is destroyed.
-* (if object has references that should be decremented before destruction).
-* -- pfnRef_1 = optional callback for when object reach refcount = 1 (excl. initial).
-* -- return = allocated object on success, with refcount = 1, - NULL on fail.
-*/
-PVOID VmmOb_Alloc(_In_ WORD tag, _In_ UINT uFlags, _In_ SIZE_T uBytes, _In_opt_ VOID(*pfnRef_0)(_In_ PVOID pVmmOb), _In_opt_ VOID(*pfnRef_1)(_In_ PVOID pVmmOb))
-{
- PVMMOB_HEADER pOb;
- if(uBytes > 0x40000000) { return NULL; }
- pOb = (PVMMOB_HEADER)LocalAlloc(uFlags, uBytes + sizeof(VMMOB_HEADER) + VMMOB_DEBUG_FOOTER_SIZE);
- if(!pOb) { return NULL; }
- pOb->magic = VMMOB_HEADER_MAGIC;
- pOb->count = 1;
- pOb->tag = tag;
- pOb->pfnRef_0 = pfnRef_0;
- pOb->pfnRef_1 = pfnRef_1;
- pOb->cbData = (DWORD)uBytes;
-#ifdef VMMOB_DEBUG
- DWORD i, cb = sizeof(VMMOB_HEADER) + pOb->cbData;
- PBYTE pb = (PBYTE)pOb;
- for(i = 0; i < VMMOB_DEBUG_FOOTER_SIZE; i += 8) {
- *(PQWORD)(pb + cb + i) = VMMOB_DEBUG_FOOTER_MAGIC;
- }
-#endif /* VMMOB_DEBUG */
- return pOb;
-}
-
-#define VmmOb_TpINCREF(pOb, type) (type*)((pOb && (((PVMMOB_HEADER)pOb)->magic == VMMOB_HEADER_MAGIC) && InterlockedIncrement16(&((PVMMOB_HEADER)pOb)->count)) ? pOb : NULL)
-
-/*
-* Increase the reference count of a vmm object manager object.
-* -- pVmmOb
-*/
-PVOID VmmOb_INCREF(PVOID pVmmOb)
-{
- PVMMOB_HEADER pOb = (PVMMOB_HEADER)pVmmOb;
- if(pOb && (pOb->magic == VMMOB_HEADER_MAGIC)) {
- InterlockedIncrement16(&pOb->count);
- return (PVMMOB)pVmmOb;
- }
- return NULL;
-}
-
-/*
-* Decrease the reference count of a vmm object manager object. If the reference
-* count reaches zero the object will be cleaned up.
-* -- pVmmOb
-*/
-VOID VmmOb_DECREF(PVOID pVmmOb)
-{
- PVMMOB_HEADER pOb = (PVMMOB_HEADER)pVmmOb;
- WORD c;
- if(pOb && (pOb->magic == VMMOB_HEADER_MAGIC)) {
- c = InterlockedDecrement16(&pOb->count);
-#ifdef VMMOB_DEBUG
- DWORD i, cb = sizeof(VMMOB_HEADER) + pOb->cbData;
- PBYTE pb = (PBYTE)pOb;
- for(i = 0; i < VMMOB_DEBUG_FOOTER_SIZE; i += 8) {
- if(*(PQWORD)(pb + cb + i) != VMMOB_DEBUG_FOOTER_MAGIC) {
- vmmprintfvv_fn("FOOTER OVERWRITTEN - MEMORY CORRUPTION? REFCNT: %i TAG: %02X\n", c, pOb->tag)
- }
- }
-#endif /* VMMOB_DEBUG */
- if(c == 0) {
- if(pOb->pfnRef_0) { pOb->pfnRef_0(pVmmOb); }
- LocalFree(pVmmOb);
- } else if((c == 1) && pOb->pfnRef_1) {
- pOb->pfnRef_1(pVmmOb);
- }
- }
-}
-
-/*
-* Initialize a VmmObContainer with an optional pVmmOb.
-*/
-VOID VmmObContainer_Initialize(_In_ PVMMOBCONTAINER pVmmObContainer, _In_opt_ PVOID pVmmOb)
-{
- InitializeCriticalSectionAndSpinCount(&pVmmObContainer->Lock, 4096);
- pVmmObContainer->pVmmOb = VmmOb_INCREF(pVmmOb);
-}
-
-/*
-* Retrieve an enclosed VmmOb from the given pVmmObContainer. Reference count
-* of the retrieved VmmOb must be decremented by caller after use is completed!
-*/
-PVOID VmmObContainer_GetOb(_In_ PVMMOBCONTAINER pVmmObContainer)
-{
- PVMMOB pOb;
- EnterCriticalSection(&pVmmObContainer->Lock);
- pOb = VmmOb_INCREF(pVmmObContainer->pVmmOb);
- LeaveCriticalSection(&pVmmObContainer->Lock);
- return pOb;
-}
-
-/*
-* Set or Replace a VmmOb in the pVmmObContainer.
-*/
-VOID VmmObContainer_SetOb(_In_ PVMMOBCONTAINER pVmmObContainer, _In_opt_ PVOID pVmmOb)
-{
- EnterCriticalSection(&pVmmObContainer->Lock);
- VmmOb_DECREF(pVmmObContainer->pVmmOb);
- pVmmObContainer->pVmmOb = VmmOb_INCREF(pVmmOb);
- LeaveCriticalSection(&pVmmObContainer->Lock);
-}
-
-VOID VmmObContainer_Close(_In_ PVMMOBCONTAINER pVmmObContainer)
-{
- if(!pVmmObContainer) { return; }
- EnterCriticalSection(&pVmmObContainer->Lock);
- VmmOb_DECREF(pVmmObContainer->pVmmOb);
- pVmmObContainer->pVmmOb = NULL;
- LeaveCriticalSection(&pVmmObContainer->Lock);
- DeleteCriticalSection(&pVmmObContainer->Lock);
-}
-
-// ----------------------------------------------------------------------------
-// DATASET STRUCT FUNCTIONALITY:
-// The VMMOB_DATASET/VmmObDataSet_* functionality allows for auto-growing arrays
-// of optionally unique data. The VmmObDataSet_Put is not thread safe and should
-// only be used at creation time in single-threaded context.
-// ----------------------------------------------------------------------------
-
-VOID VmmObDataSet_CallbackClose(PVMMOB_MEM pOb)
-{
- VmmOb_DECREF(((PVMMOB_DATASET)pOb)->pObData);
-}
-
-/*
-* Allocate a VmmObDataSet and optionally set it to only contain unique items.
-* CALLER_DECREF: return
-* -- fUnique = set will only contain unique values.
-* -- return
-*/
-PVMMOB_DATASET VmmObDataSet_Alloc(_In_ BOOL fUnique)
-{
- PVMMOB_DATASET pObDataSet;
- pObDataSet = VmmOb_Alloc('ds', 0, sizeof(VMMOB_DATASET), VmmObDataSet_CallbackClose, NULL);
- if(!pObDataSet) { return NULL; }
- pObDataSet->c = 0;
- pObDataSet->cMax = 0x40;
- pObDataSet->iListStart = 0;
- pObDataSet->fUnique = fUnique;
- pObDataSet->pObData = VmmOb_Alloc('dl', 0, pObDataSet->cMax * sizeof(VMMDATALIST), NULL, NULL);
- if(!pObDataSet->pObData) {
- VmmOb_DECREF(pObDataSet);
- return NULL;
- }
- return pObDataSet;
-}
-
-/*
-* Insert a value into a VmmObDataSet. This function is not meant to be called
-* in a multi-threaded context.
-* -- pDataSet
-* -- v
-* -- return = insertion was successful.
-*/
-BOOL VmmObDataSet_Put(_In_ PVMMOB_DATASET pDataSet, _In_ QWORD v)
-{
- PVMMOB_PDATA pObNextData = NULL;
- PVMMDATALIST pDataNew, pDataCurrent = NULL, pDataNext = NULL;
- // 1: increase storage space if required
- if(pDataSet->c == pDataSet->cMax) {
- pObNextData = VmmOb_Alloc('dl', 0, (QWORD)pDataSet->pObData->cbData << 1, NULL, NULL);
- if(!pObNextData) { return FALSE; }
- memcpy(pObNextData->pbData, pDataSet->pObData->pbData, pDataSet->pObData->cbData);
- VmmOb_DECREF(pDataSet->pObData);
- pDataSet->pObData = pObNextData;
- pDataSet->cMax <<= 1;
- }
- // 2: set up new item and check initial conditions
- pDataNew = pDataSet->pObData->pList + pDataSet->c;
- pDataNew->iNext = (DWORD)-1;
- pDataNew->Value = v;
- if(pDataSet->c == 0) {
- pDataSet->c++;
- return TRUE;
- }
- pDataCurrent = pDataSet->pObData->pList + pDataSet->iListStart;
- if(pDataCurrent->Value >= v) {
- if(pDataSet->fUnique && (pDataCurrent->Value == v)) {
- return FALSE;
- }
- pDataNew->iNext = pDataSet->iListStart;
- pDataSet->iListStart = pDataSet->c;
- pDataSet->c++;
- return TRUE;
- }
- // 3: walk list
- while(pDataCurrent->iNext != (DWORD)-1) {
- pDataNext = pDataSet->pObData->pList + pDataCurrent->iNext;
- if(pDataNext->Value >= v) {
- if(pDataSet->fUnique && (pDataNext->Value == v)) {
- return FALSE;
- }
- pDataNew->iNext = pDataCurrent->iNext;
- pDataCurrent->iNext = pDataSet->c;
- pDataSet->c++;
- return TRUE;
- }
- pDataCurrent = pDataNext;
- }
- // 4: insert at tail (not found previously)
- pDataCurrent->iNext = pDataSet->c;
- pDataSet->c++;
- return TRUE;
-}
-
-// ----------------------------------------------------------------------------
-// CACHE FUNCTIONALITY:
-// PHYSICAL MEMORY CACHING FOR READS AND PAGE TABLES
-// ----------------------------------------------------------------------------
-
-/*
-* Retrieve cache table from ctxVmm given a specific tag.
-*/
-PVMM_CACHE_TABLE VmmCacheTableGet(_In_ WORD wTblTag)
-{
- switch(wTblTag) {
- case VMM_CACHE_TAG_PHYS:
- return &ctxVmm->PHYS;
- case VMM_CACHE_TAG_TLB:
- return &ctxVmm->TLB;
- default:
- return NULL;
- }
-}
-
-#define VMM_CACHE2_GET_REGION(qwA) ((qwA >> 12) % VMM_CACHE2_REGIONS)
-#define VMM_CACHE2_GET_BUCKET(qwA) ((qwA >> 12) % VMM_CACHE2_BUCKETS)
-
-/*
-* Invalidate a cache entry (if exists)
-*/
-VOID VmmCacheInvalidate_2(_In_ WORD wTblTag, _In_ QWORD qwA)
-{
- DWORD iR, iB;
- PVMM_CACHE_TABLE t;
- PVMMOB_MEM pOb, pObNext;
- t = VmmCacheTableGet(wTblTag);
- if(!t || !t->fActive) { return; }
- iR = VMM_CACHE2_GET_REGION(qwA);
- iB = VMM_CACHE2_GET_BUCKET(qwA);
- EnterCriticalSection(&t->R[iR].Lock);
- pOb = t->R[iR].B[iB];
- while(pOb) {
- pObNext = pOb->FLink;
- if(pOb->h.qwA == qwA) {
- // detach bucket
- if(pOb->BLink) {
- pOb->BLink->FLink = pOb->FLink;
- } else {
- t->R[iR].B[iB] = pOb->FLink;
- }
- if(pOb->FLink) {
- pOb->FLink->BLink = pOb->BLink;
- }
- // detach age list
- if(pOb->AgeBLink) {
- pOb->AgeBLink->AgeFLink = pOb->AgeFLink;
- } else {
- t->R[iR].AgeFLink = pOb->AgeFLink;
- }
- if(pOb->AgeFLink) {
- pOb->AgeFLink->AgeBLink = pOb->AgeBLink;
- } else {
- t->R[iR].AgeBLink = pOb->AgeBLink;
- }
- // decrease count & decref
- InterlockedDecrement(&t->R[iR].c);
- VmmOb_DECREF(pOb);
- }
- pOb = pObNext;
- }
- LeaveCriticalSection(&t->R[iR].Lock);
-}
-
-VOID VmmCacheInvalidate(_In_ QWORD pa)
-{
- VmmCacheInvalidate_2(VMM_CACHE_TAG_TLB, pa);
- VmmCacheInvalidate_2(VMM_CACHE_TAG_PHYS, pa);
-}
-
-VOID VmmCacheReclaim(_In_ PVMM_CACHE_TABLE t, _In_ DWORD iR, _In_ BOOL fTotal)
-{
- DWORD cThreshold;
- PVMMOB_MEM pOb;
- EnterCriticalSection(&t->R[iR].Lock);
- cThreshold = fTotal ? 0 : max(0x10, t->R[iR].c >> 1);
- while(t->R[iR].c > cThreshold) {
- // get
- pOb = t->R[iR].AgeBLink;
- if(!pOb) {
- vmmprintf_fn("ERROR - SHOULD NOT HAPPEN - NULL OBJECT RETRIEVED\n");
- break;
- }
- // detach from age list
- t->R[iR].AgeBLink = pOb->AgeBLink;
- if(pOb->AgeBLink) {
- pOb->AgeBLink->AgeFLink = NULL;
- } else {
- t->R[iR].AgeFLink = NULL;
- }
- // detach from bucket list
- if(pOb->BLink) {
- pOb->BLink->FLink = NULL;
- } else {
- t->R[iR].B[VMM_CACHE2_GET_BUCKET(pOb->h.qwA)] = NULL;
- }
- // remove region refcount of object - callback will take care of
- // re-insertion into empty list when refcount becomes low enough.
- VmmOb_DECREF(pOb);
- InterlockedDecrement(&t->R[iR].c);
- }
- LeaveCriticalSection(&t->R[iR].Lock);
-}
-
-/*
-* Clear the specified cache from all entries.
-* -- wTblTag
-*/
-VOID VmmCacheClear(_In_ WORD wTblTag)
-{
- DWORD i;
- PVMM_CACHE_TABLE t;
- PVMM_PROCESS pObProcess = NULL;
- // 1: clear cache
- t = VmmCacheTableGet(wTblTag);
- for(i = 0; i < VMM_CACHE2_REGIONS; i++) {
- VmmCacheReclaim(t, i, TRUE);
- }
- // 2: if tlb cache clear -> update process 'is spider done' flag
- if(wTblTag == VMM_CACHE_TAG_TLB) {
- while((pObProcess = VmmProcessGetNext(pObProcess))) {
- if(pObProcess->fTlbSpiderDone) {
- EnterCriticalSection(&pObProcess->LockUpdate);
- pObProcess->fTlbSpiderDone = FALSE;
- LeaveCriticalSection(&pObProcess->LockUpdate);
- }
- }
- }
-}
-
-VOID VmmCache_CallbackRefCount1(PVMMOB_MEM pOb)
-{
- PVMM_CACHE_TABLE t;
- t = VmmCacheTableGet(((PVMMOB_HEADER)pOb)->tag);
- if(!t) {
- vmmprintf_fn("ERROR - SHOULD NOT HAPPEN - INVALID OBJECT TAG %02X\n", ((PVMMOB_HEADER)pOb)->tag);
- return;
- }
- if(!t->fActive) { return; }
- VmmOb_INCREF(pOb);
- InterlockedPushEntrySList(&t->ListHeadEmpty, &pOb->SListEmpty);
- InterlockedIncrement(&t->cEmpty);
-}
-
-/*
-* Return an entry retrieved with VmmCacheReserve to the cache.
-* NB! no other items may be returned with this function!
-* FUNCTION DECREF: pOb
-* -- pOb
-*/
-VOID VmmCacheReserveReturn(_In_opt_ PVMMOB_MEM pOb)
-{
- DWORD iR, iB;
- PVMM_CACHE_TABLE t;
- if(!pOb) { return; }
- t = VmmCacheTableGet(((PVMMOB_HEADER)pOb)->tag);
- if(!t) {
- vmmprintf_fn("ERROR - SHOULD NOT HAPPEN - INVALID OBJECT TAG %02X\n", ((PVMMOB_HEADER)pOb)->tag);
- return;
- }
- if((pOb->h.cb != 0x1000) || (pOb->h.qwA == (QWORD)-1) || !t->fActive) {
- // decrement refcount of object - callback will take care of
- // re-insertion into empty list when refcount becomes low enough.
- VmmOb_DECREF(pOb);
- return;
- }
- // insert into map - refcount will be overtaken by "cache region".
- iR = VMM_CACHE2_GET_REGION(pOb->h.qwA);
- iB = VMM_CACHE2_GET_BUCKET(pOb->h.qwA);
- EnterCriticalSection(&t->R[iR].Lock);
- // insert into "bucket"
- pOb->BLink = NULL;
- pOb->FLink = t->R[iR].B[iB];
- if(pOb->FLink) { pOb->FLink->BLink = pOb; }
- t->R[iR].B[iB] = pOb;
- // insert into "age list"
- pOb->AgeFLink = t->R[iR].AgeFLink;
- if(pOb->AgeFLink) { pOb->AgeFLink->AgeBLink = pOb; }
- pOb->AgeBLink = NULL;
- t->R[iR].AgeFLink = pOb;
- if(!t->R[iR].AgeBLink) { t->R[iR].AgeBLink = pOb; }
- InterlockedIncrement(&t->R[iR].c);
- LeaveCriticalSection(&t->R[iR].Lock);
-}
-
-PVMMOB_MEM VmmCacheReserve(_In_ WORD wTblTag)
-{
- PVMM_CACHE_TABLE t;
- PVMMOB_MEM pOb;
- PSLIST_ENTRY e;
- WORD iReclaimLast, cLoopProtect = 0;
- t = VmmCacheTableGet(wTblTag);
- if(!t || !t->fActive) { return NULL; }
- while(!(e = InterlockedPopEntrySList(&t->ListHeadEmpty))) {
- if(t->cTotal < VMM_CACHE2_MAX_ENTRIES) {
- // below max threshold -> create new
- pOb = VmmOb_Alloc(t->tag, LMEM_ZEROINIT, sizeof(VMMOB_MEM), NULL, VmmCache_CallbackRefCount1);
- if(!pOb) { return NULL; }
- pOb->h.magic = MEM_IO_SCATTER_HEADER_MAGIC;
- pOb->h.version = MEM_IO_SCATTER_HEADER_VERSION;
- pOb->h.cbMax = 0x1000;
- pOb->h.pb = pOb->pb;
- pOb->h.qwA = (QWORD)-1;
- VmmOb_INCREF(pOb); // "total list" reference
- InterlockedPushEntrySList(&t->ListHeadTotal, &pOb->SListTotal);
- InterlockedIncrement(&t->cTotal);
- return pOb; // return fresh object - refcount = 2.
- }
- // reclaim existing entries
- iReclaimLast = InterlockedIncrement16(&t->iReclaimLast);
- VmmCacheReclaim(t, iReclaimLast % VMM_CACHE2_REGIONS, FALSE);
- if(++cLoopProtect == VMM_CACHE2_REGIONS) {
- vmmprintf_fn("ERROR - SHOULD NOT HAPPEN - CACHE %02X DRAINED OF ENTRIES\n", wTblTag);
- Sleep(10);
- }
- }
- InterlockedDecrement(&t->cEmpty);
- pOb = CONTAINING_RECORD(e, VMMOB_MEM, SListEmpty);
- pOb->h.qwA = (QWORD)-1;
- pOb->h.cb = 0;
- return pOb; // reference overtaken by callee (from EmptyList)
-}
-
-PVMMOB_MEM VmmCacheGet(_In_ WORD wTblTag, _In_ QWORD qwA)
-{
- PVMM_CACHE_TABLE t;
- DWORD iR;
- PVMMOB_MEM pOb;
- t = VmmCacheTableGet(wTblTag);
- if(!t || !t->fActive) { return NULL; }
- iR = VMM_CACHE2_GET_REGION(qwA);
- EnterCriticalSection(&t->R[iR].Lock);
- pOb = t->R[iR].B[VMM_CACHE2_GET_BUCKET(qwA)];
- while(pOb && (qwA != pOb->h.qwA)) {
- pOb = pOb->FLink;
- }
- VmmOb_INCREF(pOb);
- LeaveCriticalSection(&t->R[iR].Lock);
- return pOb;
-}
-
-PVMMOB_MEM VmmCacheGet_FromDeviceOnMiss(_In_ WORD wTblTag, _In_ QWORD qwA)
-{
- PVMMOB_MEM pObMEM, pObReservedMEM;
- PMEM_IO_SCATTER_HEADER pMEM;
- pObMEM = VmmCacheGet(wTblTag, qwA);
- if(pObMEM) { return pObMEM; }
- pObReservedMEM = VmmCacheReserve(wTblTag);
- if(pObReservedMEM) {
- pMEM = &pObReservedMEM->h;
- pMEM->qwA = qwA;
- LeechCore_ReadScatter(&pMEM, 1);
- if(pMEM->cb == 0x1000) {
- VmmOb_INCREF(pObReservedMEM);
- VmmCacheReserveReturn(pObReservedMEM);
- return pObReservedMEM;
- }
- }
- VmmCacheReserveReturn(pObReservedMEM);
- return NULL;
-}
-
-BOOL VmmCacheExists(_In_ WORD wTblTag, _In_ QWORD qwA)
-{
- BOOL result;
- PVMMOB_MEM pOb;
- pOb = VmmCacheGet(wTblTag, qwA);
- result = pOb != NULL;
- VmmOb_DECREF(pOb);
- return result;
-}
-
-/*
-* Retrieve a page table from a given physical address (if possible).
-* CALLER DECREF: return
-* -- pa
-* -- fCacheOnly
-* -- return = Cache entry on success, NULL on fail.
-*/
-PVMMOB_MEM VmmTlbGetPageTable(_In_ QWORD pa, _In_ BOOL fCacheOnly)
-{
- PVMMOB_MEM pObMEM;
- pObMEM = VmmCacheGet(VMM_CACHE_TAG_TLB, pa);
- if(pObMEM) {
- InterlockedIncrement64(&ctxVmm->stat.cTlbCacheHit);
- return pObMEM;
- }
- if(fCacheOnly) { return NULL; }
- pObMEM = VmmCacheGet_FromDeviceOnMiss(VMM_CACHE_TAG_TLB, pa);
- if(!pObMEM) {
- InterlockedIncrement64(&ctxVmm->stat.cTlbReadFail);
- return NULL;
- }
- InterlockedIncrement64(&ctxVmm->stat.cTlbReadSuccess);
- if(VmmTlbPageTableVerify(pObMEM->h.pb, pObMEM->h.qwA, FALSE)) {
- return pObMEM;
- }
- VmmOb_DECREF(pObMEM);
- return NULL;
-}
-
-VOID VmmCache2Close(_In_ WORD wTblTag)
-{
- PVMM_CACHE_TABLE t;
- PVMMOB_MEM pOb;
- PSLIST_ENTRY e;
- DWORD i;
- t = VmmCacheTableGet(wTblTag);
- if(!t || !t->fActive) { return; }
- t->fActive = FALSE;
- // remove from "regions"
- for(i = 0; i < VMM_CACHE2_REGIONS; i++) {
- VmmCacheReclaim(t, i, TRUE);
- DeleteCriticalSection(&t->R[i].Lock);
- }
- // remove from "empty list"
- while(e = InterlockedPopEntrySList(&t->ListHeadEmpty)) {
- pOb = CONTAINING_RECORD(e, VMMOB_MEM, SListEmpty);
- VmmOb_DECREF(pOb);
- InterlockedDecrement(&t->cEmpty);
- }
- // remove from "total list"
- while(e = InterlockedPopEntrySList(&t->ListHeadTotal)) {
- pOb = CONTAINING_RECORD(e, VMMOB_MEM, SListTotal);
- VmmOb_DECREF(pOb);
- InterlockedDecrement(&t->cTotal);
- }
-}
-
-VOID VmmCache2Initialize(_In_ WORD wTblTag)
-{
- DWORD i;
- PVMM_CACHE_TABLE t;
- t = VmmCacheTableGet(wTblTag);
- if(!t || t->fActive) { return; }
- for(i = 0; i < VMM_CACHE2_REGIONS; i++) {
- InitializeCriticalSection(&t->R[i].Lock);
- }
- InitializeSListHead(&t->ListHeadEmpty);
- InitializeSListHead(&t->ListHeadTotal);
- t->fActive = TRUE;
- t->tag = wTblTag;
-}
-
-/*
-* Prefetch a set of addresses contained in pObPrefetchAddresses into the cache.
-* This is useful when reading data from somewhat known addresses over higher
-* latency connections.
-* -- pProcess
-* -- pObPrefetchAddresses
-*/
-VOID VmmCachePrefetchPages(_In_opt_ PVMM_PROCESS pProcess, _In_opt_ PVMMOB_DATASET pObPrefetchAddresses)
-{
- QWORD va;
- DWORD i, c = 0;
- PPMEM_IO_SCATTER_HEADER ppMEMs = NULL;
- if(!pObPrefetchAddresses || !pObPrefetchAddresses->c || (ctxVmm->flags & VMM_FLAG_NOCACHE)) { return; }
- if(!LeechCore_AllocScatterEmpty(pObPrefetchAddresses->c, &ppMEMs)) { return; }
- for(i = 0; i < pObPrefetchAddresses->c; i++) {
- va = pObPrefetchAddresses->pObData->pList[i].Value & ~0xfff;
- if(!(c && i && (ppMEMs[c]->qwA == va))) {
- ppMEMs[c]->qwA = va;
- c++;
- }
- }
- if(pProcess) {
- VmmReadScatterVirtual(pProcess, ppMEMs, c, 0);
- } else {
- VmmReadScatterPhysical(ppMEMs, c, 0);
- }
- LocalFree(ppMEMs);
-}
-
-// ----------------------------------------------------------------------------
-// PROCESS MANAGEMENT FUNCTIONALITY:
-//
-// The process 'object' represents a process in the analyzed system.
-//
-// The process 'object' is an object manager refcount object. The processes may
-// contain, in addition to values, sub-objects such as maps of loaded modules
-// and memory.
-//
-// Before updates to the process object happens the 'LockUpdate' generally
-// should be acquired.
-//
-// The active processes are contained in a 'process table' which is also an
-// object manager refcount object. Atmoic access (get and increase refcount) is
-// guarded by a object manager container which allows for easy retrieval of the
-// process table. The process table may also contain a process table for new
-// not yet committed process objects. When processes are refreshed in the back-
-// ground they are created (or copied by refcount increase) into the new table.
-// Once all processes are enumerated the function 'VmmProcessCreateFinish' is
-// called and replaces the 'old' table with the 'new' table which becomes the
-// active table. The 'old' replaced table is refcount-decreased and possibly
-// free'd as a result.
-//
-// The process object: VMM_PROCESS
-// The process table object (only used internally): VMMOB_PROCESS_TABLE
-// ----------------------------------------------------------------------------
-
-typedef struct tdVMMOB_PROCESS_TABLE {
- VMMOB ObHdr;
- SIZE_T c;
- WORD _iFLink;
- WORD _iFLinkM[VMM_PROCESSTABLE_ENTRIES_MAX];
- PVMM_PROCESS _M[VMM_PROCESSTABLE_ENTRIES_MAX];
- VMMOBCONTAINER NewPROC; // contains VMM_PROCESS_TABLE
-} VMMOB_PROCESS_TABLE, *PVMMOB_PROCESS_TABLE;
-
-/*
-* Retrieve pProcess for a given PVMMOB_PROCESS_TABLE.
-* CALLER DECREF: return
-* -- pt
-* -- dwPID
-* -- return
-*/
-PVMM_PROCESS VmmProcessGetEx(_In_ PVMMOB_PROCESS_TABLE pt, _In_ DWORD dwPID)
-{
- DWORD i, iStart;
- i = iStart = dwPID % VMM_PROCESSTABLE_ENTRIES_MAX;
- while(TRUE) {
- if(!pt->_M[i]) { return NULL; }
- if(pt->_M[i]->dwPID == dwPID) {
- return VmmOb_TpINCREF(pt->_M[i], VMM_PROCESS);
- }
- if(++i == VMM_PROCESSTABLE_ENTRIES_MAX) { i = 0; }
- if(i == iStart) { return NULL; }
- }
-}
-
-/*
-* Retrieve an existing process given a process id (PID).
-* CALLER DECREF: return
-* -- dwPID
-* -- return = a process struct, or NULL if not found.
-*/
-PVMM_PROCESS VmmProcessGet(_In_ DWORD dwPID)
-{
- PVMM_PROCESS pProcess;
- PVMMOB_PROCESS_TABLE pt = (PVMMOB_PROCESS_TABLE)VmmObContainer_GetOb(&ctxVmm->PROC);
- pProcess = VmmProcessGetEx(pt, dwPID);
- VmmOb_DECREF(pt);
- return pProcess;
-}
-
-/*
-* Retrieve the next process given a process. This may be useful when iterating
-* over a process list. NB! Listing of next item may fail prematurely if the
-* previous process is terminated while having a reference to it.
-* FUNCTION DECREF: pProcess
-* CALLER DECREF: return
-* -- pProcess = a process struct, or NULL if first.
- NB! function DECREF's pProcess and must not be used after call!
-* -- return = a process struct, or NULL if not found.
-*/
-PVMM_PROCESS VmmProcessGetNext(_In_opt_ PVMM_PROCESS pProcess)
-{
- PVMMOB_PROCESS_TABLE pt = (PVMMOB_PROCESS_TABLE)VmmObContainer_GetOb(&ctxVmm->PROC);
- PVMM_PROCESS pProcessNew;
- DWORD i, iStart;
- if(!pt) { goto fail; }
- if(!pProcess) {
- i = pt->_iFLink;
- if(!pt->_M[i]) { goto fail; }
- pProcessNew = VmmOb_TpINCREF(pt->_M[i], VMM_PROCESS);
- VmmOb_DECREF(pProcess);
- VmmOb_DECREF(pt);
- return pProcessNew;
- }
- i = iStart = pProcess->dwPID % VMM_PROCESSTABLE_ENTRIES_MAX;
- while(TRUE) {
- if(!pt->_M[i]) { goto fail; }
- if(pt->_M[i]->dwPID == pProcess->dwPID) {
- // current process -> retrieve next!
- i = pt->_iFLinkM[i];
- if(!pt->_M[i]) { goto fail; }
- pProcessNew = VmmOb_TpINCREF(pt->_M[i], VMM_PROCESS);
- VmmOb_DECREF(pProcess);
- VmmOb_DECREF(pt);
- return pProcessNew;
- }
- if(++i == VMM_PROCESSTABLE_ENTRIES_MAX) { i = 0; }
- if(i == iStart) { goto fail; }
- }
-fail:
- VmmOb_DECREF(pProcess);
- VmmOb_DECREF(pt);
- return NULL;
-}
-
-/*
-* Object manager callback before 'static process' object cleanup
-* decrease refcount of any internal objects.
-*/
-VOID VmmProcessStatic_CloseObCallback(_In_ PVOID pVmmOb)
-{
- PVMMOB_PROCESS_PERSISTENT pProcessStatic = (PVMMOB_PROCESS_PERSISTENT)pVmmOb;
- VmmObContainer_Close(&pProcessStatic->ObCLdrModulesCachePrefetch32);
- VmmObContainer_Close(&pProcessStatic->ObCLdrModulesCachePrefetch64);
-}
-
-/*
-* Object manager callback before 'static process' object cleanup
-* decrease refcount of any internal objects.
-*/
-VOID VmmProcessStatic_Initialize(_In_ PVMM_PROCESS pProcess)
-{
- EnterCriticalSection(&pProcess->LockUpdate);
- VmmOb_DECREF(&pProcess->pObProcessPersistent);
- pProcess->pObProcessPersistent = VmmOb_Alloc('PS', LMEM_ZEROINIT, sizeof(VMMOB_PROCESS_PERSISTENT), VmmProcessStatic_CloseObCallback, NULL);
- if(pProcess->pObProcessPersistent) {
- VmmObContainer_Initialize(&pProcess->pObProcessPersistent->ObCLdrModulesCachePrefetch32, NULL);
- VmmObContainer_Initialize(&pProcess->pObProcessPersistent->ObCLdrModulesCachePrefetch64, NULL);
- }
- LeaveCriticalSection(&pProcess->LockUpdate);
-}
-
-/*
-* Object manager callback before 'process' object cleanup - decrease refcount
-* of any internal 'memory map' and 'module map' objects.
-*/
-VOID VmmProcess_CloseObCallback(_In_ PVOID pVmmOb)
-{
- PVMM_PROCESS pProcess = (PVMM_PROCESS)pVmmOb;
- // general cleanup below
- VmmOb_DECREF(pProcess->pObMemMap);
- VmmOb_DECREF(pProcess->pObModuleMap);
- VmmOb_DECREF(pProcess->pObProcessPersistent);
- // plugin cleanup below
- VmmObContainer_Close(&pProcess->Plugin.ObCLdrModulesDisplayCache);
- // delete lock
- DeleteCriticalSection(&pProcess->LockUpdate);
-}
-
-/*
-* Object manager callback before 'process table' object cleanup - decrease
-* refcount of all contained 'process' objects.
-*/
-VOID VmmProcessTable_CloseObCallback(_In_ PVOID pVmmOb)
-{
- PVMMOB_PROCESS_TABLE pt = (PVMMOB_PROCESS_TABLE)pVmmOb;
- PVMM_PROCESS pProcess;
- WORD iProcess;
- // Close NewPROC
- VmmObContainer_Close(&pt->NewPROC);
- // DECREF all pProcess in table
- iProcess = pt->_iFLink;
- pProcess = pt->_M[iProcess];
- while(pProcess) {
- VmmOb_DECREF(pProcess);
- iProcess = pt->_iFLinkM[iProcess];
- pProcess = pt->_M[iProcess];
- if(!pProcess || iProcess == pt->_iFLink) { break; }
- }
-}
-
-/*
-* Create a new process object. New process object are created in a separate
-* data structure and won't become visible to the "Process" functions until
-* after the VmmProcessCreateFinish have been called.
-* CALLER DECREF: return
-* -- fTotalRefresh = create a completely new entry - i.e. do not copy any form
-* of data from the old entry such as module and memory maps.
-* -- dwPID
-* -- dwState
-* -- paDTB
-* -- paDTB_UserOpt
-* -- szName
-* -- fUserOnly = user mode process (hide supervisor pages from view)
-*/
-PVMM_PROCESS VmmProcessCreateEntry(_In_ BOOL fTotalRefresh, _In_ DWORD dwPID, _In_ DWORD dwState, _In_ QWORD paDTB, _In_ QWORD paDTB_UserOpt, _In_ CHAR szName[16], _In_ BOOL fUserOnly)
-{
- PVMMOB_PROCESS_TABLE ptOld = NULL, ptNew = NULL;
- QWORD i, iStart, cEmpty = 0, cValid = 0;
- PVMM_PROCESS pProcess = NULL, pProcessOld = NULL;
- PVMMOB_MEM pObDTB = NULL;
- BOOL result;
- // 1: Sanity check DTB
- pObDTB = VmmTlbGetPageTable(paDTB, FALSE);
- if(!pObDTB) { goto fail; }
- result = VmmTlbPageTableVerify(pObDTB->h.pb, paDTB, (ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64));
- VmmOb_DECREF(pObDTB);
- if(!result) { goto fail; }
- // 2: Allocate new 'Process Table' (if not already existing)
- ptOld = (PVMMOB_PROCESS_TABLE)VmmObContainer_GetOb(&ctxVmm->PROC);
- if(!ptOld) { goto fail; }
- ptNew = (PVMMOB_PROCESS_TABLE)VmmObContainer_GetOb(&ptOld->NewPROC);
- if(!ptNew) {
- ptNew = (PVMMOB_PROCESS_TABLE)VmmOb_Alloc('PT', LMEM_ZEROINIT, sizeof(VMMOB_PROCESS_TABLE), VmmProcessTable_CloseObCallback, NULL);
- if(!ptNew) { goto fail; }
- VmmObContainer_Initialize(&ptNew->NewPROC, NULL);
- VmmObContainer_SetOb(&ptOld->NewPROC, ptNew);
- }
- // 3: Sanity check - process to create not already in 'new' table.
- pProcess = VmmProcessGetEx(ptNew, dwPID);
- if(pProcess) { goto fail; }
- // 4: Prepare existing item, or create new item, for new PID
- if(!fTotalRefresh) {
- pProcess = VmmProcessGetEx(ptOld, dwPID);
- }
- if(!pProcess) {
- pProcess = (PVMM_PROCESS)VmmOb_Alloc('PR', LMEM_ZEROINIT, sizeof(VMM_PROCESS), VmmProcess_CloseObCallback, NULL);
- if(!pProcess) { goto fail; }
- InitializeCriticalSectionAndSpinCount(&pProcess->LockUpdate, 4096);
- memcpy(pProcess->szName, szName, 16);
- pProcess->szName[15] = 0;
- pProcess->dwPID = dwPID;
- pProcess->dwState = dwState;
- pProcess->paDTB = paDTB;
- pProcess->paDTB_UserOpt = paDTB_UserOpt;
- pProcess->fUserOnly = fUserOnly;
- pProcess->fTlbSpiderDone = pProcess->fTlbSpiderDone;
- VmmObContainer_Initialize(&pProcess->Plugin.ObCLdrModulesDisplayCache, NULL);
- // attach pre-existing static process info entry or create new
- pProcessOld = VmmProcessGet(dwPID);
- if(pProcessOld) {
- pProcess->pObProcessPersistent = VmmOb_TpINCREF(pProcessOld->pObProcessPersistent, VMMOB_PROCESS_PERSISTENT);
- } else {
- VmmProcessStatic_Initialize(pProcess);
- }
- VmmOb_DECREF(pProcessOld);
- pProcessOld = NULL;
- }
- // 5: Install new PID
- i = iStart = dwPID % VMM_PROCESSTABLE_ENTRIES_MAX;
- while(TRUE) {
- if(!ptNew->_M[i]) {
- ptNew->_M[i] = pProcess;
- ptNew->_iFLinkM[i] = ptNew->_iFLink;
- ptNew->_iFLink = (WORD)i;
- ptNew->c++;
- VmmOb_DECREF(ptOld);
- VmmOb_DECREF(ptNew);
- // pProcess already "consumed" by table insertion so increase before returning ...
- return VmmOb_TpINCREF(pProcess, VMM_PROCESS);
- }
- if(++i == VMM_PROCESSTABLE_ENTRIES_MAX) { i = 0; }
- if(i == iStart) { goto fail; }
- }
-fail:
- VmmOb_DECREF(pProcess);
- VmmOb_DECREF(ptOld);
- VmmOb_DECREF(ptNew);
- return NULL;
-}
-
-/*
-* Activate the pending, not yet active, processes added by VmmProcessCreateEntry.
-* This will also clear any previous processes.
-*/
-VOID VmmProcessCreateFinish()
-{
- PVMMOB_PROCESS_TABLE ptNew, ptOld;
- if(!(ptOld = VmmObContainer_GetOb(&ctxVmm->PROC))) {
- return;
- }
- if(!(ptNew = VmmObContainer_GetOb(&ptOld->NewPROC))) {
- VmmOb_DECREF(ptOld);
- return;
- }
- // Replace "existing" old process table with new.
- VmmObContainer_SetOb(&ctxVmm->PROC, ptNew);
- VmmOb_DECREF(ptNew);
- VmmOb_DECREF(ptOld);
-}
-
-/*
-* Clear the TLB spider flag in all process objects.
-*/
-VOID VmmProcessTlbClear()
-{
- PVMMOB_PROCESS_TABLE pt = (PVMMOB_PROCESS_TABLE)VmmObContainer_GetOb(&ctxVmm->PROC);
- PVMM_PROCESS pProcess;
- WORD iProcess;
- if(!pt) { return; }
- iProcess = pt->_iFLink;
- pProcess = pt->_M[iProcess];
- while(pProcess) {
- pProcess->fTlbSpiderDone = FALSE;
- iProcess = pt->_iFLinkM[iProcess];
- pProcess = pt->_M[iProcess];
- if(!pProcess || iProcess == pt->_iFLink) { break; }
- }
- VmmOb_DECREF(pt);
-}
-
-/*
-* List the PIDs and put them into the supplied table.
-* -- pPIDs = user allocated DWORD array to receive result, or NULL.
-* -- pcPIDs = ptr to number of DWORDs in pPIDs on entry - number of PIDs in system on exit.
-*/
-VOID VmmProcessListPIDs(_Out_writes_opt_(*pcPIDs) PDWORD pPIDs, _Inout_ PSIZE_T pcPIDs)
-{
- PVMMOB_PROCESS_TABLE pt = (PVMMOB_PROCESS_TABLE)VmmObContainer_GetOb(&ctxVmm->PROC);
- PVMM_PROCESS pProcess;
- WORD iProcess;
- DWORD i = 0;
- if(!pPIDs) {
- *pcPIDs = pt->c;
- VmmOb_DECREF(pt);
- return;
- }
- if(*pcPIDs < pt->c) {
- *pcPIDs = 0;
- VmmOb_DECREF(pt);
- return;
- }
- // copy all PIDs
- iProcess = pt->_iFLink;
- pProcess = pt->_M[iProcess];
- while(pProcess) {
- *(pPIDs + i) = pProcess->dwPID;
- i++;
- iProcess = pt->_iFLinkM[iProcess];
- pProcess = pt->_M[iProcess];
- if(!pProcess || (iProcess == pt->_iFLink)) { break; }
- }
- *pcPIDs = i;
- VmmOb_DECREF(pt);
-}
-
-/*
-* Create the initial process table at startup.
-*/
-BOOL VmmProcessTableCreateInitial()
-{
- PVMMOB_PROCESS_TABLE pt = (PVMMOB_PROCESS_TABLE)VmmOb_Alloc('PT', LMEM_ZEROINIT, sizeof(VMMOB_PROCESS_TABLE), VmmProcessTable_CloseObCallback, NULL);
- if(!pt) { return FALSE; }
- VmmObContainer_Initialize(&pt->NewPROC, NULL);
- VmmObContainer_Initialize(&ctxVmm->PROC, pt);
- VmmOb_DECREF(pt);
- return TRUE;
-}
-
-// ----------------------------------------------------------------------------
-// INTERNAL VMMU FUNCTIONALITY: VIRTUAL MEMORY ACCESS.
-// ----------------------------------------------------------------------------
-
-VOID VmmWriteScatterVirtual(_In_ PVMM_PROCESS pProcess, _Inout_ PPMEM_IO_SCATTER_HEADER ppMEMsVirt, _In_ DWORD cpMEMsVirt)
-{
- BOOL result;
- QWORD i, qwPA;
- PMEM_IO_SCATTER_HEADER pMEM_Virt;
- // loop over the items, this may not be very efficient compared to a true
- // scatter write, but since underlying hardware implementation does not
- // support it yet this will be fine ...
- if(!ctxMain->dev.fWritable) { return; }
- for(i = 0; i < cpMEMsVirt; i++) {
- pMEM_Virt = ppMEMsVirt[i];
- pMEM_Virt->cb = 0;
- result = VmmVirt2Phys(pProcess, pMEM_Virt->qwA, &qwPA);
- if(!result) { continue; }
- InterlockedIncrement64(&ctxVmm->stat.cPhysWrite);
- result = LeechCore_Write(qwPA, pMEM_Virt->pb, pMEM_Virt->cbMax);
- if(result) {
- pMEM_Virt->cb = pMEM_Virt->cbMax;
- VmmCacheInvalidate(qwPA & ~0xfff);
- }
- }
-}
-
-VOID VmmWriteScatterPhysical(_Inout_ PPMEM_IO_SCATTER_HEADER ppMEMsPhys, _In_ DWORD cpMEMsPhys)
-{
- BOOL result;
- QWORD i;
- PMEM_IO_SCATTER_HEADER pMEM_Phys;
- // loop over the items, this may not be very efficient compared to a true
- // scatter write, but since underlying hardware implementation does not
- // support it yet this will be fine ...
- if(!ctxMain->dev.fWritable) { return; }
- for(i = 0; i < cpMEMsPhys; i++) {
- pMEM_Phys = ppMEMsPhys[i];
- InterlockedIncrement64(&ctxVmm->stat.cPhysWrite);
- result = LeechCore_Write(pMEM_Phys->qwA, pMEM_Phys->pb, pMEM_Phys->cbMax);
- if(result) {
- pMEM_Phys->cb = pMEM_Phys->cbMax;
- VmmCacheInvalidate(pMEM_Phys->qwA & ~0xfff);
- }
- }
-}
-
-BOOL VmmWritePhysical(_In_ QWORD pa, _In_ PBYTE pb, _In_ DWORD cb)
-{
- QWORD paPage;
- // 1: invalidate any physical pages from cache
- paPage = pa & ~0xfff;
- do {
- InterlockedIncrement64(&ctxVmm->stat.cPhysWrite);
- VmmCacheInvalidate(paPage);
- paPage += 0x1000;
- } while(paPage < pa + cb);
- // 2: perform write
- return LeechCore_Write(pa, pb, cb);
-}
-
-BOOL VmmReadPhysicalPage(_In_ QWORD qwPA, _Inout_bytecount_(4096) PBYTE pbPage)
-{
- BOOL result;
- PVMMOB_MEM pObMEM, pObReservedEntry;
- PMEM_IO_SCATTER_HEADER pMEM;
- qwPA &= ~0xfff;
- pObMEM = VmmCacheGet(VMM_CACHE_TAG_PHYS, qwPA);
- if(pObMEM) {
- memcpy(pbPage, pObMEM->pb, 0x1000);
- VmmOb_DECREF(pObMEM);
- return TRUE;
- }
- pObReservedEntry = VmmCacheReserve(VMM_CACHE_TAG_PHYS);
- pMEM = &pObReservedEntry->h;
- pMEM->qwA = qwPA;
- LeechCore_ReadScatter(&pMEM, 1);
- result = pMEM->cb == 0x1000;
- if(result) {
- memcpy(pbPage, pMEM->pb, 0x1000);
- } else {
- ZeroMemory(pbPage, 0x1000);
- }
- VmmCacheReserveReturn(pObReservedEntry);
- return result;
-}
-
-VOID VmmReadScatterPhysical(_Inout_ PPMEM_IO_SCATTER_HEADER ppMEMsPhys, _In_ DWORD cpMEMsPhys, _In_ QWORD flags)
-{
- DWORD i, c;
- BOOL fCache;
- PMEM_IO_SCATTER_HEADER pMEM;
- PVMMOB_MEM pObCacheEntry, pObReservedMEM;
- DWORD cSpeculative;
- PMEM_IO_SCATTER_HEADER ppMEMsSpeculative[0x18];
- PVMMOB_MEM ppObCacheSpeculative[0x18];
- fCache = !(VMM_FLAG_NOCACHE & (flags | ctxVmm->flags));
- // 1: cache read
- if(fCache) {
- c = 0, cSpeculative = 0;
- for(i = 0; i < cpMEMsPhys; i++) {
- pMEM = ppMEMsPhys[i];
- pMEM->pvReserved2 = (PVOID)0;
- if(pMEM->cb == pMEM->cbMax) {
- // already valid -> skip
- pMEM->pvReserved2 = (PVOID)1; // 1 == already read
- c++;
- continue;
- }
- // retrieve from cache (if found)
- if((pMEM->cbMax == 0x1000) && (pObCacheEntry = VmmCacheGet(VMM_CACHE_TAG_PHYS, pMEM->qwA))) {
- // in cache - copy data into requester and set as completed!
- pMEM->pvReserved2 = (PVOID)2; // 2 == cache hit
- pMEM->cb = 0x1000;
- memcpy(pMEM->pb, pObCacheEntry->pb, 0x1000);
- VmmOb_DECREF(pObCacheEntry);
- InterlockedIncrement64(&ctxVmm->stat.cPhysCacheHit);
- c++;
- continue;
- }
- // add to potential speculative read map if read is small enough...
- if(cSpeculative < 0x18) {
- ppMEMsSpeculative[cSpeculative++] = pMEM;
- }
- }
- if(c == cpMEMsPhys) { return; } // all found in cache -> return!
- }
- // 2: speculative future read if negligible performance loss
- if(fCache && cSpeculative && (cSpeculative < 0x18)) {
- while(cSpeculative < 0x18) {
- ppObCacheSpeculative[cSpeculative] = VmmCacheReserve(VMM_CACHE_TAG_PHYS);
- ppMEMsSpeculative[cSpeculative] = &ppObCacheSpeculative[cSpeculative]->h;
- ppMEMsSpeculative[cSpeculative]->cb = 0;
- ppMEMsSpeculative[cSpeculative]->qwA = ((QWORD)ppMEMsSpeculative[cSpeculative - 1]->qwA & ~0xfff) + 0x1000;
- ppMEMsSpeculative[cSpeculative]->pvReserved2 = (PVOID)3; // 3 == speculative & backed by cache reserved
- cSpeculative++;
- }
- ppMEMsPhys = ppMEMsSpeculative;
- cpMEMsPhys = cSpeculative;
- }
- // 3: read!
- LeechCore_ReadScatter(ppMEMsPhys, cpMEMsPhys);
- // 4: statistics and read fail zero fixups (if required)
- for(i = 0; i < cpMEMsPhys; i++) {
- pMEM = ppMEMsPhys[i];
- if(pMEM->cb == pMEM->cbMax) {
- // success
- InterlockedIncrement64(&ctxVmm->stat.cPhysReadSuccess);
- } else {
- // fail
- InterlockedIncrement64(&ctxVmm->stat.cPhysReadFail);
- if((flags & VMM_FLAG_ZEROPAD_ON_FAIL) && (pMEM->qwA < ctxMain->dev.paMax)) {
- ZeroMemory(pMEM->pb, pMEM->cbMax);
- pMEM->cb = pMEM->cbMax;
- }
- }
- }
- // 5: cache put
- if(fCache) {
- for(i = 0; i < cpMEMsPhys; i++) {
- pMEM = ppMEMsPhys[i];
- if(3 == (QWORD)pMEM->pvReserved2) { // 3 == speculative & backed by cache reserved
- VmmCacheReserveReturn(ppObCacheSpeculative[i]);
- }
- if((0 == (QWORD)pMEM->pvReserved2) && (pMEM->cb == 0x1000)) { // 0 = default
- pObReservedMEM = VmmCacheReserve(VMM_CACHE_TAG_PHYS);
- pObReservedMEM->h.qwA = pMEM->qwA;
- pObReservedMEM->h.cb = 0x1000;
- memcpy(pObReservedMEM->h.pb, pMEM->pb, 0x1000);
- VmmCacheReserveReturn(pObReservedMEM);
- }
- }
- }
-}
-
-VOID VmmReadScatterVirtual(_In_ PVMM_PROCESS pProcess, _Inout_ PPMEM_IO_SCATTER_HEADER ppMEMsVirt, _In_ DWORD cpMEMsVirt, _In_ QWORD flags)
-{
- DWORD i = 0, iVA, iPA;
- QWORD qwPA;
- BYTE pbBufferSmall[0x20 * (sizeof(MEM_IO_SCATTER_HEADER) + sizeof(PMEM_IO_SCATTER_HEADER))];
- PBYTE pbBufferMEMs, pbBufferLarge = NULL;
- PMEM_IO_SCATTER_HEADER pIoPA, pIoVA;
- PPMEM_IO_SCATTER_HEADER ppMEMsPhys = NULL;
- // 1: allocate / set up buffers (if needed)
- if(cpMEMsVirt < 0x20) {
- ppMEMsPhys = (PPMEM_IO_SCATTER_HEADER)pbBufferSmall;
- pbBufferMEMs = pbBufferSmall + cpMEMsVirt * sizeof(PMEM_IO_SCATTER_HEADER);
- } else {
- if(!(pbBufferLarge = LocalAlloc(0, cpMEMsVirt * (sizeof(MEM_IO_SCATTER_HEADER) + sizeof(PMEM_IO_SCATTER_HEADER))))) { return; }
- ppMEMsPhys = (PPMEM_IO_SCATTER_HEADER)pbBufferLarge;
- pbBufferMEMs = pbBufferLarge + cpMEMsVirt * sizeof(PMEM_IO_SCATTER_HEADER);
- }
- // 2: translate virt2phys
- for(iVA = 0, iPA = 0; iVA < cpMEMsVirt; iVA++) {
- pIoVA = ppMEMsVirt[iVA];
- if(VmmVirt2Phys(pProcess, pIoVA->qwA, &qwPA)) {
- pIoPA = ppMEMsPhys[iPA] = (PMEM_IO_SCATTER_HEADER)pbBufferMEMs + iPA;
- iPA++;
- pIoPA->magic = MEM_IO_SCATTER_HEADER_MAGIC;
- pIoPA->version = MEM_IO_SCATTER_HEADER_VERSION;
- pIoPA->qwA = qwPA;
- pIoPA->cbMax = 0x1000;
- pIoPA->cb = 0;
- pIoPA->pb = pIoVA->pb;
- pIoPA->pvReserved1 = (PVOID)pIoVA;
- } else {
- pIoVA->cb = 0;
- }
- }
- // 3: read and check result
- VmmReadScatterPhysical(ppMEMsPhys, iPA, flags);
- while(iPA > 0) {
- iPA--;
- ((PMEM_IO_SCATTER_HEADER)ppMEMsPhys[iPA]->pvReserved1)->cb = ppMEMsPhys[iPA]->cb;
- }
- LocalFree(pbBufferLarge);
-}
-
-// ----------------------------------------------------------------------------
-// PUBLICALLY VISIBLE FUNCTIONALITY RELATED TO VMMU.
-// ----------------------------------------------------------------------------
-
-VOID VmmClose()
-{
- if(!ctxVmm) { return; }
- if(ctxVmm->pVmmVfsModuleList) { PluginManager_Close(); }
- if(ctxVmm->ThreadProcCache.fEnabled) {
- ctxVmm->ThreadProcCache.fEnabled = FALSE;
- while(ctxVmm->ThreadProcCache.hThread) {
- SwitchToThread();
- }
- }
- VmmObContainer_Close(&ctxVmm->PROC);
- if(ctxVmm->fnMemoryModel.pfnClose) {
- ctxVmm->fnMemoryModel.pfnClose();
- }
- VmmCache2Close(VMM_CACHE_TAG_PHYS);
- VmmCache2Close(VMM_CACHE_TAG_TLB);
- VmmObContainer_Close(&ctxVmm->ObCEPROCESSCachePrefetch);
- DeleteCriticalSection(&ctxVmm->MasterLock);
- LocalFree(ctxVmm);
- ctxVmm = NULL;
-}
-
-VOID VmmWriteEx(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _In_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbWrite)
-{
- DWORD i = 0, oVA = 0, cbWrite = 0, cbP, cMEMs;
- PBYTE pbBuffer;
- PMEM_IO_SCATTER_HEADER pMEMs, *ppMEMs;
- if(pcbWrite) { *pcbWrite = 0; }
- // allocate
- cMEMs = (DWORD)(((qwVA & 0xfff) + cb + 0xfff) >> 12);
- pbBuffer = (PBYTE)LocalAlloc(LMEM_ZEROINIT, cMEMs * (sizeof(MEM_IO_SCATTER_HEADER) + sizeof(PMEM_IO_SCATTER_HEADER)));
- if(!pbBuffer) { return; }
- pMEMs = (PMEM_IO_SCATTER_HEADER)pbBuffer;
- ppMEMs = (PPMEM_IO_SCATTER_HEADER)(pbBuffer + cMEMs * sizeof(MEM_IO_SCATTER_HEADER));
- // prepare pages
- while(oVA < cb) {
- ppMEMs[i] = &pMEMs[i];
- pMEMs[i].version = MEM_IO_SCATTER_HEADER_VERSION;
- pMEMs[i].qwA = qwVA + oVA;
- cbP = 0x1000 - ((qwVA + oVA) & 0xfff);
- cbP = min(cbP, cb - oVA);
- pMEMs[i].cbMax = cbP;
- pMEMs[i].pb = pb + oVA;
- oVA += cbP;
- i++;
- }
- // write and count result
- if(pProcess) {
- VmmWriteScatterVirtual(pProcess, ppMEMs, cMEMs);
- } else {
- VmmWriteScatterPhysical(ppMEMs, cMEMs);
- }
- if(pcbWrite) {
- for(i = 0; i < cMEMs; i++) {
- cbWrite += pMEMs[i].cb;
- }
- *pcbWrite = cbWrite;
- }
- LocalFree(pbBuffer);
-}
-
-BOOL VmmWrite(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _In_ PBYTE pb, _In_ DWORD cb)
-{
- DWORD cbWrite;
- VmmWriteEx(pProcess, qwVA, pb, cb, &cbWrite);
- return (cbWrite == cb);
-}
-
-VOID VmmReadEx(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ QWORD flags)
-{
- DWORD cbP, cMEMs, cbRead = 0;
- PBYTE pbBuffer;
- PMEM_IO_SCATTER_HEADER pMEMs, *ppMEMs;
- QWORD i, oVA;
- if(pcbReadOpt) { *pcbReadOpt = 0; }
- if(!cb) { return; }
- cMEMs = (DWORD)(((qwVA & 0xfff) + cb + 0xfff) >> 12);
- pbBuffer = (PBYTE)LocalAlloc(LMEM_ZEROINIT, 0x2000 + cMEMs * (sizeof(MEM_IO_SCATTER_HEADER) + sizeof(PMEM_IO_SCATTER_HEADER)));
- if(!pbBuffer) { return; }
- pMEMs = (PMEM_IO_SCATTER_HEADER)(pbBuffer + 0x2000);
- ppMEMs = (PPMEM_IO_SCATTER_HEADER)(pbBuffer + 0x2000 + cMEMs * sizeof(MEM_IO_SCATTER_HEADER));
- oVA = qwVA & 0xfff;
- // prepare "middle" pages
- for(i = 0; i < cMEMs; i++) {
- ppMEMs[i] = &pMEMs[i];
- pMEMs[i].magic = MEM_IO_SCATTER_HEADER_MAGIC;
- pMEMs[i].version = MEM_IO_SCATTER_HEADER_VERSION;
- pMEMs[i].qwA = qwVA - oVA + (i << 12);
- pMEMs[i].cbMax = 0x1000;
- pMEMs[i].pb = pb - oVA + (i << 12);
- }
- // fixup "first/last" pages
- pMEMs[0].pb = pbBuffer;
- if(cMEMs > 1) {
- pMEMs[cMEMs - 1].pb = pbBuffer + 0x1000;
- }
- // Read VMM and handle result
- if(pProcess) {
- VmmReadScatterVirtual(pProcess, ppMEMs, cMEMs, flags);
- } else {
- VmmReadScatterPhysical(ppMEMs, cMEMs, flags);
- }
- for(i = 0; i < cMEMs; i++) {
- if(pMEMs[i].cb == 0x1000) {
- cbRead += 0x1000;
- } else {
- ZeroMemory(pMEMs[i].pb, 0x1000);
- }
- }
- cbRead -= (pMEMs[0].cb == 0x1000) ? 0x1000 : 0; // adjust byte count for first page (if needed)
- cbRead -= ((cMEMs > 1) && (pMEMs[cMEMs - 1].cb == 0x1000)) ? 0x1000 : 0; // adjust byte count for last page (if needed)
- // Handle first page
- cbP = (DWORD)min(cb, 0x1000 - oVA);
- if(pMEMs[0].cb == 0x1000) {
- memcpy(pb, pMEMs[0].pb + oVA, cbP);
- cbRead += cbP;
- } else {
- ZeroMemory(pb, cbP);
- }
- // Handle last page
- if(cMEMs > 1) {
- cbP = (((qwVA + cb) & 0xfff) ? ((qwVA + cb) & 0xfff) : 0x1000);
- if(pMEMs[cMEMs - 1].cb == 0x1000) {
- memcpy(pb + ((QWORD)cMEMs << 12) - oVA - 0x1000, pMEMs[cMEMs - 1].pb, cbP);
- cbRead += cbP;
- } else {
- ZeroMemory(pb + ((QWORD)cMEMs << 12) - oVA - 0x1000, cbP);
- }
- }
- if(pcbReadOpt) { *pcbReadOpt = cbRead; }
- LocalFree(pbBuffer);
-}
-
-_Success_(return)
-BOOL VmmReadString_Unicode2Ansi(_In_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_writes_(cch) LPSTR sz, _In_ DWORD cch)
-{
- DWORD i = 0;
- BOOL result;
- WCHAR wsz[0x1000];
- if(cch) { sz[0] = 0; }
- if((cch < 2) || (cch > 0x1000)) { return FALSE; }
- result = VmmRead(pProcess, qwVA, (PBYTE)wsz, cch << 1);
- if(!result) { return FALSE; }
- for(i = 0; i < cch - 1; i++) {
- sz[i] = (CHAR)(((WORD)wsz[i] <= 0xff) ? wsz[i] : '?');
- if(sz[i] == 0) { return TRUE; }
- }
- sz[cch - 1] = 0;
- return TRUE;
-}
-
-BOOL VmmRead(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwA, _Out_ PBYTE pb, _In_ DWORD cb)
-{
- DWORD cbRead;
- VmmReadEx(pProcess, qwA, pb, cb, &cbRead, 0);
- return (cbRead == cb);
-}
-
-BOOL VmmReadPage(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwA, _Inout_bytecount_(4096) PBYTE pbPage)
-{
- DWORD cb;
- VmmReadEx(pProcess, qwA, pbPage, 0x1000, &cb, 0);
- return cb == 0x1000;
-}
-
-VOID VmmInitializeMemoryModel(_In_ VMM_MEMORYMODEL_TP tp)
-{
- switch(tp) {
- case VMM_MEMORYMODEL_X64:
- MmX64_Initialize();
- break;
- case VMM_MEMORYMODEL_X86PAE:
- MmX86PAE_Initialize();
- break;
- case VMM_MEMORYMODEL_X86:
- MmX86_Initialize();
- break;
- default:
- if(ctxVmm->fnMemoryModel.pfnClose) {
- ctxVmm->fnMemoryModel.pfnClose();
- }
- }
-}
-
-VOID VmmInitializeFunctions()
-{
- HMODULE hNtDll = NULL;
- if((hNtDll = LoadLibraryA("ntdll.dll"))) {
- ctxVmm->fn.RtlDecompressBuffer = (VMMFN_RtlDecompressBuffer*)GetProcAddress(hNtDll, "RtlDecompressBuffer");
- FreeLibrary(hNtDll);
- }
-}
-
-BOOL VmmInitialize()
-{
- // 1: allocate & initialize
- if(ctxVmm) { VmmClose(); }
- ctxVmm = (PVMM_CONTEXT)LocalAlloc(LMEM_ZEROINIT, sizeof(VMM_CONTEXT));
- if(!ctxVmm) { goto fail; }
- // 2: CACHE INIT: Process Table
- if(!VmmProcessTableCreateInitial()) { goto fail; }
- // 3: CACHE INIT: Translation Lookaside Buffer (TLB) Cache Table
- VmmCache2Initialize(VMM_CACHE_TAG_TLB);
- if(!ctxVmm->TLB.fActive) { goto fail; }
- // 4: CACHE INIT: Physical Memory Cache Table
- VmmCache2Initialize(VMM_CACHE_TAG_PHYS);
- if(!ctxVmm->PHYS.fActive) { goto fail; }
- // 5: OTHER INIT:
- VmmObContainer_Initialize(&ctxVmm->ObCEPROCESSCachePrefetch, NULL);
- InitializeCriticalSection(&ctxVmm->MasterLock);
- VmmInitializeFunctions();
- return TRUE;
-fail:
- VmmClose();
- return FALSE;
-}
diff --git a/vmm/vmm.h b/vmm/vmm.h
deleted file mode 100644
index 45811e7..0000000
--- a/vmm/vmm.h
+++ /dev/null
@@ -1,805 +0,0 @@
-// vmm.h : definitions related to virtual memory management support.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __VMM_H__
-#define __VMM_H__
-#include
-#include
-#include "leechcore.h"
-
-typedef unsigned __int64 QWORD, *PQWORD;
-#define VMM_MULTITHREAD_ENABLE
-#define VMMOB_DEBUG
-
-// ----------------------------------------------------------------------------
-// VMM configuration constants and struct definitions below:
-// ----------------------------------------------------------------------------
-
-#define VMM_STATUS_SUCCESS ((NTSTATUS)0x00000000L)
-#define VMM_STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
-#define VMM_STATUS_END_OF_FILE ((NTSTATUS)0xC0000011L)
-#define VMM_STATUS_FILE_INVALID ((NTSTATUS)0xC0000098L)
-#define VMM_STATUS_FILE_SYSTEM_LIMITATION ((NTSTATUS)0xC0000427L)
-
-#define VMM_PROCESSTABLE_ENTRIES_MAX 0x4000
-#define VMM_PROCESS_OS_ALLOC_PTR_MAX 0x4 // max number of operating system specific pointers that must be free'd
-#define VMM_MEMMAP_ENTRIES_MAX 0x4000
-
-#define VMM_MEMMAP_PAGE_W 0x0000000000000002
-#define VMM_MEMMAP_PAGE_NS 0x0000000000000004
-#define VMM_MEMMAP_PAGE_NX 0x8000000000000000
-#define VMM_MEMMAP_PAGE_MASK 0x8000000000000006
-
-#define VMM_MEMMAP_FLAG_MODULES 0x0001
-#define VMM_MEMMAP_FLAG_SCAN 0x0002
-#define VMM_MEMMAP_FLAG_ALL (VMM_MEMMAP_FLAG_MODULES | VMM_MEMMAP_FLAG_SCAN)
-
-#define VMM_CACHE_TABLESIZE 0x4011 // (not even # to prevent clogging at specific table 'hash' buckets)
-#define VMM_CACHE_TLB_ENTRIES 0x4000 // -> 64MB of cached data
-#define VMM_CACHE_PHYS_ENTRIES 0x4000 // -> 64MB of cached data
-
-#define VMM_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
-#define VMM_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
-#define VMM_FLAG_PROCESS_SHOW_TERMINATED 0x0004 // show terminated processes in the process list (if they can be found).
-
-#define PAGE_SIZE 0x1000
-
-static const LPSTR VMM_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
-
-typedef enum tdVMM_MEMORYMODEL_TP {
- VMM_MEMORYMODEL_NA = 0,
- VMM_MEMORYMODEL_X86 = 1,
- VMM_MEMORYMODEL_X86PAE = 2,
- VMM_MEMORYMODEL_X64 = 3
-} VMM_MEMORYMODEL_TP;
-
-typedef enum tdVMM_SYSTEM_TP {
- VMM_SYSTEM_UNKNOWN_X64 = 1,
- VMM_SYSTEM_WINDOWS_X64 = 2,
- VMM_SYSTEM_UNKNOWN_X86 = 3,
- VMM_SYSTEM_WINDOWS_X86 = 4
-} VMM_SYSTEM_TP;
-
-typedef struct tdVMM_MEMMAP_ENTRY {
- QWORD AddrBase;
- QWORD cPages;
- QWORD fPage;
- BOOL fWoW64;
- CHAR szTag[32];
-} VMM_MEMMAP_ENTRY, *PVMM_MEMMAP_ENTRY;
-
-typedef struct tdVMM_MODULEMAP_ENTRY {
- QWORD BaseAddress;
- QWORD EntryPoint;
- DWORD SizeOfImage;
- BOOL fWoW64;
- CHAR szName[32];
- // # of entries in EAT / IAT (lazy loaded due to performance reasons)
- BOOL fLoadedEAT;
- DWORD cbDisplayBufferEAT;
- BOOL fLoadedIAT;
- DWORD cbDisplayBufferIAT;
- DWORD cbDisplayBufferSections;
-} VMM_MODULEMAP_ENTRY, *PVMM_MODULEMAP_ENTRY;
-
-typedef struct tdVMMOB {
- BYTE Reserved[0x1c];
- DWORD cbData;
-} VMMOB, *PVMMOB;
-
-typedef struct tdVMMOBCONTAINER {
- CRITICAL_SECTION Lock;
- PVMMOB pVmmOb;
-} VMMOBCONTAINER, *PVMMOBCONTAINER;
-
-typedef struct tdVMMDATALIST {
- DWORD iNext;
- QWORD Value;
-} VMMDATALIST, *PVMMDATALIST;
-
-typedef struct tdVMMOB_DATA {
- BYTE Reserved[0x1c];
- DWORD cbData;
- union {
- BYTE pbData[];
- DWORD pdwData[];
- QWORD pqwData[];
- VMMDATALIST pList[];
- };
-} VMMOB_DATA, *PVMMOB_PDATA;
-
-typedef struct tdVMMOB_DATASET {
- VMMOB ObHdr;
- BOOL fUnique;
- DWORD c;
- DWORD cMax;
- DWORD iListStart;
- PVMMOB_PDATA pObData;
-} VMMOB_DATASET, *PVMMOB_DATASET;
-
-typedef struct tdVMMOB_MEMMAP {
- BYTE Reserved[0x1c];
- DWORD cbData;
- BOOL fValid; // map is valid (did not fail initialization)
- BOOL fTagModules; // map contains tags from modules.
- BOOL fTagScan; // map contains tags from scan.
- DWORD cMap; // # map entries.
- DWORD cbDisplay; // byte count of display map (even if not existing yet).
- PVMMOB_PDATA pObDisplay; // human readable memory map.
- VMM_MEMMAP_ENTRY pMap[]; // map entries
-} VMMOB_MEMMAP, *PVMMOB_MEMMAP;
-
-typedef struct tdVMMOB_MODULEMAP {
- BYTE Reserved[0x1c];
- DWORD cbData;
- BOOL fValid; // map is valid (did not fail initialization).
- DWORD cMap; // # map entries.
- DWORD cbDisplay; // size of 'text' module map.
- PBYTE pbDisplay; // 'text' module map stored in-object after pMap).
- VMM_MODULEMAP_ENTRY pMap[]; // map entries
-} VMMOB_MODULEMAP, *PVMMOB_MODULEMAP;
-
-// 'static' process information that should be kept even in the ase of a total
-// process refresh. Only use for information that may never change or things
-// that may not affect analysis (like cache preload addresses that only may
-// speed things up - but not change analysis result). May also be used by
-// internal plugins to store persistent information in various plugin-internal
-// thread safe ways. Use with extreme care!
-typedef struct tdVMMOB_PROCESS_PERSISTENT {
- VMMOB ObHdr;
- VMMOBCONTAINER ObCLdrModulesCachePrefetch32;
- VMMOBCONTAINER ObCLdrModulesCachePrefetch64;
- struct {
- QWORD vaVirt2Phys;
- } Plugin;
-} VMMOB_PROCESS_PERSISTENT, *PVMMOB_PROCESS_PERSISTENT;
-
-typedef struct tdVMM_PROCESS {
- VMMOB ObHdr;
- CRITICAL_SECTION LockUpdate;
- DWORD dwPID;
- DWORD dwState; // state of process, 0 = running
- QWORD paDTB;
- QWORD paDTB_UserOpt;
- CHAR szName[16];
- BOOL fUserOnly;
- BOOL fTlbSpiderDone;
- BOOL fFileCacheDisabled;
- PVMMOB_MEMMAP pObMemMap;
- PVMMOB_MODULEMAP pObModuleMap;
- PVMMOB_PROCESS_PERSISTENT pObProcessPersistent; // Always exists
- union {
- struct {
- QWORD vaEPROCESS;
- QWORD vaPEB;
- DWORD vaPEB32; // WoW64 only
- QWORD vaENTRY;
- BOOL fWow64;
- } win;
- } os;
- struct {
- VMMOBCONTAINER ObCLdrModulesDisplayCache;
- } Plugin;
-} VMM_PROCESS, *PVMM_PROCESS;
-
-#define VMM_CACHE2_REGIONS 17
-#define VMM_CACHE2_BUCKETS 2039
-#define VMM_CACHE2_MAX_ENTRIES 0x8000
-
-#define VMM_CACHE_TAG_PHYS 'Ph'
-#define VMM_CACHE_TAG_TLB 'Tb'
-
-typedef struct tdVMMOB_MEM {
- BYTE Reserved[0x1c];
- DWORD cbData;
- SLIST_ENTRY SListTotal;
- SLIST_ENTRY SListEmpty;
- struct tdVMMOB_MEM *FLink;
- struct tdVMMOB_MEM *BLink;
- struct tdVMMOB_MEM *AgeFLink;
- struct tdVMMOB_MEM *AgeBLink;
- MEM_IO_SCATTER_HEADER h;
- union {
- BYTE pb[0x1000];
- DWORD pdw[0x400];
- QWORD pqw[0x200];
- };
-} VMMOB_MEM, *PVMMOB_MEM, **PPVMMOB_MEM;
-
-typedef struct tdVMM_CACHE_TABLE {
- SLIST_HEADER ListHeadEmpty;
- SLIST_HEADER ListHeadTotal;
- DWORD cEmpty;
- DWORD cTotal;
- BOOL fActive;
- WORD tag;
- WORD iReclaimLast;
- struct {
- DWORD c;
- DWORD dwFuture;
- CRITICAL_SECTION Lock;
- PVMMOB_MEM AgeFLink;
- PVMMOB_MEM AgeBLink;
- PVMMOB_MEM B[VMM_CACHE2_BUCKETS];
- } R[VMM_CACHE2_REGIONS];
-} VMM_CACHE_TABLE, *PVMM_CACHE_TABLE;
-
-typedef struct tdVMM_VIRT2PHYS_INFORMATION {
- VMM_MEMORYMODEL_TP tpMemoryModel;
- QWORD va;
- QWORD pas[5]; // physical addresses of pagetable[PML]/page[0]
- QWORD PTEs[5]; // PTEs[PML]
- WORD iPTEs[5]; // Index of PTE in page table
-} VMM_VIRT2PHYS_INFORMATION, *PVMM_VIRT2PHYS_INFORMATION;
-
-typedef struct tdVMM_MEMORYMODEL_FUNCTIONS {
- VOID(*pfnClose)();
- BOOL(*pfnVirt2Phys)(_In_ QWORD paDTB, _In_ BOOL fUserOnly, _In_ BYTE iPML, _In_ QWORD va, _Out_ PQWORD ppa);
- VOID(*pfnVirt2PhysGetInformation)(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo);
- VOID(*pfnMapInitialize)(_In_ PVMM_PROCESS pProcess);
- VOID(*pfnMapTag)(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ QWORD vaLimit, _In_opt_ LPSTR szTag, _In_opt_ LPWSTR wszTag, _In_ BOOL fWoW64, _In_ BOOL fOverwrite);
- BOOL(*pfnMapGetEntries)(_In_ PVMM_PROCESS pProcess, _In_ DWORD flags, _Out_ PVMMOB_MEMMAP *ppObMemMap);
- BOOL(*pfnMapGetDisplay)(_In_ PVMM_PROCESS pProcess, _In_ DWORD flags, _Out_ PVMMOB_PDATA *ppObDisplay);
- VOID(*pfnTlbSpider)(_In_ PVMM_PROCESS pProcess);
- BOOL(*pfnTlbPageTableVerify)(_Inout_ PBYTE pb, _In_ QWORD pa, _In_ BOOL fSelfRefReq);
-} VMM_MEMORYMODEL_FUNCTIONS;
-
-// ----------------------------------------------------------------------------
-// VMM general constants and struct definitions below:
-// ----------------------------------------------------------------------------
-
-typedef struct tdVmmConfig {
- CHAR szMountPoint[1];
- CHAR szPythonPath[MAX_PATH];
- QWORD paCR3;
- // flags below
- BOOL fCommandIdentify;
- BOOL fVerboseDll;
- BOOL fVerbose;
- BOOL fVerboseExtra;
- BOOL fVerboseExtraTlp;
- BOOL fDisableBackgroundRefresh;
-} VMMCONFIG, *PVMMCONFIG;
-
-typedef struct tdVMM_STATISTICS {
- QWORD cPhysCacheHit;
- QWORD cPhysReadSuccess;
- QWORD cPhysReadFail;
- QWORD cPhysWrite;
- QWORD cTlbCacheHit;
- QWORD cTlbReadSuccess;
- QWORD cTlbReadFail;
- QWORD cRefreshPhys;
- QWORD cRefreshTlb;
- QWORD cRefreshProcessPartial;
- QWORD cRefreshProcessFull;
-} VMM_STATISTICS, *PVMM_STATISTICS;
-
-typedef struct tdVMM_WIN_EPROCESS_OFFSET {
- BOOL fValid;
- WORD cbMaxOffset;
- WORD State;
- WORD DTB;
- WORD Name;
- WORD PID;
- WORD FLink;
- WORD BLink;
- WORD PEB;
- WORD DTB_User;
-} VMM_WIN_EPROCESS_OFFSET, *PVMM_WIN_EPROCESS_OFFSET;
-
-typedef struct tdVMM_KERNELINFO {
- QWORD paDTB;
- QWORD vaBase;
- QWORD cbSize;
- // optional non-required values below
- VMM_WIN_EPROCESS_OFFSET OffsetEPROCESS;
- QWORD vaEntry;
- QWORD vaPsLoadedModuleList;
- QWORD vaKDBG;
- DWORD dwPidMemCompression;
-} VMM_KERNELINFO;
-
-typedef NTSTATUS VMMFN_RtlDecompressBuffer(
- USHORT CompressionFormat,
- PUCHAR UncompressedBuffer,
- ULONG UncompressedBufferSize,
- PUCHAR CompressedBuffer,
- ULONG CompressedBufferSize,
- PULONG FinalUncompressedSize
-);
-
-typedef struct tdVMM_DYNAMIC_LOAD_FUNCTIONS {
- // functions below may be loaded on startup
- // NB! null checks are required before use!
- VMMFN_RtlDecompressBuffer *RtlDecompressBuffer; // ntdll.dll!RtlDecompressBuffer
-} VMM_DYNAMIC_LOAD_FUNCTIONS;
-
-typedef struct tdVMM_CONTEXT {
- CRITICAL_SECTION MasterLock;
- VMMOBCONTAINER PROC; // contains VMM_PROCESS_TABLE
- VMM_MEMORYMODEL_FUNCTIONS fnMemoryModel;
- VMM_MEMORYMODEL_TP tpMemoryModel;
- BOOL f32;
- VMM_SYSTEM_TP tpSystem;
- DWORD flags; // VMM_FLAG_*
- struct {
- BOOL fEnabled;
- HANDLE hThread;
- DWORD cMs_TickPeriod;
- DWORD cTick_Phys;
- DWORD cTick_TLB;
- DWORD cTick_ProcPartial;
- DWORD cTick_ProcTotal;
- } ThreadProcCache;
- VMM_STATISTICS stat;
- VMM_KERNELINFO kernel;
- VMM_DYNAMIC_LOAD_FUNCTIONS fn;
- PVOID pVmmVfsModuleList;
- VMMOBCONTAINER ObCEPROCESSCachePrefetch;
- VMM_CACHE_TABLE PHYS;
- VMM_CACHE_TABLE TLB;
-} VMM_CONTEXT, *PVMM_CONTEXT;
-
-typedef struct tdVMM_MAIN_CONTEXT {
- VMMCONFIG cfg;
- LEECHCORE_CONFIG dev;
- PVOID pvStatistics;
-} VMM_MAIN_CONTEXT, *PVMM_MAIN_CONTEXT;
-
-// ----------------------------------------------------------------------------
-// VMM global variables below:
-// ----------------------------------------------------------------------------
-
-PVMM_CONTEXT ctxVmm;
-PVMM_MAIN_CONTEXT ctxMain;
-
-#define vmmprintf(format, ...) { if(ctxMain->cfg.fVerboseDll) { printf(format, ##__VA_ARGS__); } }
-#define vmmprintfv(format, ...) { if(ctxMain->cfg.fVerbose) { printf(format, ##__VA_ARGS__); } }
-#define vmmprintfvv(format, ...) { if(ctxMain->cfg.fVerboseExtra) { printf(format, ##__VA_ARGS__); } }
-#define vmmprintfvvv(format, ...) { if(ctxMain->cfg.fVerboseExtraTlp) { printf(format, ##__VA_ARGS__); } }
-#define vmmprintf_fn(format, ...) vmmprintf("%s: "format, __func__, ##__VA_ARGS__);
-#define vmmprintfv_fn(format, ...) vmmprintfv("%s: "format, __func__, ##__VA_ARGS__);
-#define vmmprintfvv_fn(format, ...) vmmprintfvv("%s: "format, __func__, ##__VA_ARGS__);
-#define vmmprintfvvv_fn(format, ...) vmmprintfvvv("%s: "format, __func__, ##__VA_ARGS__);
-
-// ----------------------------------------------------------------------------
-// CACHE AND TLB FUNCTIONALITY BELOW:
-// ----------------------------------------------------------------------------
-
-/*
-* Retrieve an item from the cache.
-* CALLER DECREF: return
-* -- wTblTag
-* -- qwA
-* -- return
-*/
-PVMMOB_MEM VmmCacheGet(_In_ WORD wTblTag, _In_ QWORD qwA);
-
-/*
-* Retrieve a page table (0x1000 bytes) via the TLB cache.
-* CALLER DECREF: return
-* -- pa
-* -- fCacheOnly = if set do not make a request to underlying device if not in cache.
-* -- return
-*/
-PVMMOB_MEM VmmTlbGetPageTable(_In_ QWORD pa, _In_ BOOL fCacheOnly);
-
-/*
-* Check if an address page exists in the indicated cache.
-* -- wTblTag
-* -- qwA
-* -- return
-*/
-BOOL VmmCacheExists(_In_ WORD wTblTag, _In_ QWORD qwA);
-
-/*
-* Check out an empty memory cache item from the cache. NB! once the item is
-* filled (successfully or unsuccessfully) it must be returned to the cache with
-* VmmCacheReserveReturn and must _NOT_ otherwise be DEFREF'ed.
-* CALLER DECREF SPECIAL: return
-* -- wTblTag
-* -- return
-*/
-PVMMOB_MEM VmmCacheReserve(_In_ WORD wTblTag);
-
-/*
-* Return an entry retrieved with VmmCacheReserve to the cache.
-* NB! no other items may be returned with this function!
-* FUNCTION DECREF SPECIAL: pOb
-* -- pOb
-*/
-VOID VmmCacheReserveReturn(_In_opt_ PVMMOB_MEM pOb);
-
-// ----------------------------------------------------------------------------
-// VMM object manager function definitions below:
-// ----------------------------------------------------------------------------
-
-/*
-* Allocate a new vmm object manager memory object.
-* -- tag = tag identifying the type of object.
-* -- uFlags = flags as given by LocalAlloc.
-* -- uBytes = bytes of object (excluding object header).
-* -- pfnRef_0 = optional callback for cleanup o be called before object is destroyed.
-* (if object contains objects which references should be decremented
- before destruction of this 'parent' object).
-* -- pfnRef_1 = optional callback for when object reach refcount = 1 at DECREF.
-* -- return = allocated object on success, with refcount = 1, - NULL on fail.
-*/
-PVOID VmmOb_Alloc(_In_ WORD tag, _In_ UINT uFlags, _In_ SIZE_T uBytes, _In_opt_ VOID(*pfnRef_0)(_In_ PVOID pVmmOb), _In_opt_ VOID(*pfnRef_1)(_In_ PVOID pVmmOb));
-
-/*
-* Increase the reference count of a vmm object by one.
-* -- pVmmOb
-* -- return
-*/
-PVOID VmmOb_INCREF(PVOID pVmmOb);
-
-/*
-* Decrease the reference count of a vmm object by one.
-* NB! Do not use object after DECREF - other threads might have also DECREF'ed
-* the object at same time making it to be free'd - making the memory invalid.
-*/
-VOID VmmOb_DECREF(PVOID pVmmOb);
-
-/*
-* Retrieve an enclosed VmmOb from the given pVmmObContainer. Reference count
-* of the retrieved VmmOb must be decremented by caller after use is completed!
-*/
-PVOID VmmObContainer_GetOb(_In_ PVMMOBCONTAINER pVmmObContainer);
-
-/*
-* Set or Replace a VmmOb in the pVmmObContainer.
-*/
-VOID VmmObContainer_SetOb(_In_ PVMMOBCONTAINER pVmmObContainer, _In_opt_ PVOID pVmmOb);
-
-/*
-* Allocate a VmmObDataSet and optionally set it to only contain unique items.
-* CALLER_DECREF: return
-* -- fUnique = set will only contain unique values.
-* -- return
-*/
-PVMMOB_DATASET VmmObDataSet_Alloc(_In_ BOOL fUnique);
-
-/*
-* Insert a value into a VmmObDataSet.
-* This function is not meant to be called in a multi-threaded context.
-* -- pDataSet
-* -- v
-* -- return = insertion was successful.
-*/
-BOOL VmmObDataSet_Put(_In_ PVMMOB_DATASET pDataSet, _In_ QWORD v);
-
-
-// ----------------------------------------------------------------------------
-// VMM function definitions below:
-// ----------------------------------------------------------------------------
-
-#ifdef VMM_MULTITHREAD_ENABLE
-
-#define VmmLockAcquire() // no need to acquire lock if multithreaded access is ok
-#define VmmLockRelease() // no need to acquire lock if multithreaded access is ok
-
-#else /* VMM_MULTITHREAD_ENABLE */
-
-/*
-* Acquire the VMM master lock. Required if interoperating with the VMM from a
-* function that has not already acquired the lock. Lock must be relased in a
-* fairly short amount of time in order for the VMM to continue working.
-* !!! MUST NEVER BE ACQUIRED FOR LENGTHY AMOUNT OF TIMES !!!
-*/
-inline VOID VmmLockAcquire()
-{
- EnterCriticalSection(&ctxVmm->MasterLock);
-}
-
-/*
-* Release VMM master lock that has previously been acquired by VmmLockAcquire.
-*/
-inline VOID VmmLockRelease()
-{
- LeaveCriticalSection(&ctxVmm->MasterLock);
-}
-
-#endif /* VMM_MULTITHREAD_ENABLE */
-
-/*
-* Write a virtually contigious arbitrary amount of memory.
-* -- pProcess
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = TRUE on success, FALSE on partial or zero write.
-*/
-BOOL VmmWrite(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Write physical memory and clear any VMM caches that may contain data.
-* -- pa
-* -- pb
-* -- cb
-* -- return
-*/
-BOOL VmmWritePhysical(_In_ QWORD pa, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Read a virtually contigious arbitrary amount of memory containing cch number of
-* unicode characters and convert them into ansi characters. Characters > 0xff are
-* converted into '?'. The result is guaranteed to be zero-terminated.
-* -- pProcess
-* -- qwVA
-* -- sz
-* -- cch
-* -- return
-*/
-_Success_(return)
-BOOL VmmReadString_Unicode2Ansi(_In_ PVMM_PROCESS pProcess, _In_ QWORD qwVA, _Out_writes_(cch) LPSTR sz, _In_ DWORD cch);
-
-/*
-* Read a contigious arbitrary amount of memory, virtual or physical.
-* Virtual memory is read if a process is specified in pProcess parameter.
-* Physical memory is read if NULL is specified in pProcess parameter.
-* -- pProcess
-* -- qwVA = NULL=='physical memory read', PTR=='virtual memory read'
-* -- pb
-* -- cb
-* -- return
-*/
-BOOL VmmRead(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwA, _Out_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Read a contigious arbitrary amount of memory, physical or virtual, and report
-* the number of bytes read in pcbRead.
-* Virtual memory is read if a process is specified in pProcess.
-* Physical memory is read if NULL is specified in pProcess.
-* -- pProcess = NULL=='physical memory read', PTR=='virtual memory read'
-* -- qwA
-* -- pb
-* -- cb
-* -- pcbRead
-* -- flags = flags as in VMM_FLAG_*
-*/
-VOID VmmReadEx(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ QWORD flags);
-
-/*
-* Read a single 4096-byte page of memory, virtual or physical.
-* Virtual memory is read if a process is specified in pProcess.
-* Physical memory is read if NULL is specified in pProcess.
-* -- pProcess = NULL=='physical memory read', PTR=='virtual memory read'
-* -- qwA
-* -- pbPage
-* -- return
-*/
-BOOL VmmReadPage(_In_opt_ PVMM_PROCESS pProcess, _In_ QWORD qwA, _Inout_bytecount_(4096) PBYTE pbPage);
-
-/*
-* Scatter read virtual memory. Non contiguous 4096-byte pages.
-* -- pProcess
-* -- ppMEMsVirt
-* -- cpMEMsVirt
-* -- flags = flags as in VMM_FLAG_*, [VMM_FLAG_NOCACHE for supression of data (not tlb) caching]
-*/
-VOID VmmReadScatterVirtual(_In_ PVMM_PROCESS pProcess, _Inout_ PPMEM_IO_SCATTER_HEADER ppMEMsVirt, _In_ DWORD cpMEMsVirt, _In_ QWORD flags);
-
-/*
-* Scatter read physical memory. Non contiguous 4096-byte pages.
-* -- ppMEMsPhys
-* -- cpMEMsPhys
-* -- flags = flags as in VMM_FLAG_*, [VMM_FLAG_NOCACHE for supression of caching]
-*/
-VOID VmmReadScatterPhysical(_Inout_ PPMEM_IO_SCATTER_HEADER ppMEMsPhys, _In_ DWORD cpMEMsPhys, _In_ QWORD flags);
-
-/*
-* Read a single 4096-byte page of physical memory.
-* -- qwPA
-* -- pbPage
-* -- return
-*/
-BOOL VmmReadPhysicalPage(_In_ QWORD qwPA, _Inout_bytecount_(4096) PBYTE pbPage);
-
-/*
-* Translate a virtual address to a physical address by walking the page tables.
-* -- paDTB
-* -- fUserOnly
-* -- va
-* -- ppa
-* -- return
-*/
-_Success_(return)
-inline BOOL VmmVirt2PhysEx(_In_ QWORD paDTB, _In_ BOOL fUserOnly, _In_ QWORD va, _Out_ PQWORD ppa)
-{
- if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return FALSE; }
- return ctxVmm->fnMemoryModel.pfnVirt2Phys(paDTB, fUserOnly, -1, va, ppa);
-}
-
-/*
-* Translate a virtual address to a physical address by walking the page tables.
-* -- pProcess
-* -- va
-* -- ppa
-* -- return
-*/
-_Success_(return)
-inline BOOL VmmVirt2Phys(_In_ PVMM_PROCESS pProcess, _In_ QWORD va, _Out_ PQWORD ppa)
-{
- if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return FALSE; }
- return ctxVmm->fnMemoryModel.pfnVirt2Phys(pProcess->paDTB, pProcess->fUserOnly, -1, va, ppa);
-}
-
-/*
-* Spider the TLB (page table cache) to load all page table pages into the cache.
-* This is done to speed up various subsequent virtual memory accesses.
-* NB! pages may fall out of the cache if it's in heavy use or doe to timing.
-* -- pProcess
-*/
-inline VOID VmmTlbSpider(_In_ PVMM_PROCESS pProcess)
-{
- if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return; }
- ctxVmm->fnMemoryModel.pfnTlbSpider(pProcess);
-}
-
-/*
-* Try verify that a supplied page table in pb is valid by analyzing it.
-* -- pb = 0x1000 bytes containing the page table page.
-* -- pa = physical address if the page table page.
-* -- fSelfRefReq = is a self referential entry required to be in the map? (PML4 for Windows).
-*/
-inline BOOL VmmTlbPageTableVerify(_Inout_ PBYTE pb, _In_ QWORD pa, _In_ BOOL fSelfRefReq)
-{
- if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return FALSE; }
- return ctxVmm->fnMemoryModel.pfnTlbPageTableVerify(pb, pa, fSelfRefReq);
-}
-
-/*
-* Retrieve information of the virtual2physical address translation for the
-* supplied process. The Virtual address must be supplied in pVirt2PhysInfo upon
-* entry.
-* -- pProcess
-* -- pVirt2PhysInfo
-*/
-inline VOID VmmVirt2PhysGetInformation(_Inout_ PVMM_PROCESS pProcess, _Inout_ PVMM_VIRT2PHYS_INFORMATION pVirt2PhysInfo)
-{
- if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return; }
- ctxVmm->fnMemoryModel.pfnVirt2PhysGetInformation(pProcess, pVirt2PhysInfo);
-}
-
-/*
-* Map a tag into the sorted memory map in O(log2) operations. Supply only one
-* of szTag or wszTag. Tags are usually module/dll name.
-* -- pProcess
-* -- vaBase
-* -- vaLimit = limit == vaBase + size (== top address in range +1)
-* -- szTag
-* -- wszTag
-* -- fWoW64
-* -- fOverwrite
-*/
-inline VOID VmmMemMapTag(_In_ PVMM_PROCESS pProcess, _In_ QWORD vaBase, _In_ QWORD vaLimit, _In_opt_ LPSTR szTag, _In_opt_ LPWSTR wszTag, _In_opt_ BOOL fWoW64, _In_ BOOL fOverwrite)
-{
- if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return; }
- ctxVmm->fnMemoryModel.pfnMapTag(pProcess, vaBase, vaLimit, szTag, wszTag, fWoW64, fOverwrite);
-}
-
-/*
-* Retrieve the memory map.
-* CALLER DECREF: ppObMemMap
-* -- pProcess
-* -- flags
-* -- ppObMemMap
-* -- return
-*/
-_Success_(return)
-inline BOOL VmmMemMapGetEntries(_In_ PVMM_PROCESS pProcess, _In_ DWORD flags, _Out_ PVMMOB_MEMMAP *ppObMemMap)
-{
- if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return FALSE; }
- return ctxVmm->fnMemoryModel.pfnMapGetEntries(pProcess, flags, ppObMemMap);
-}
-
-/*
-* Retrieve a human-readable memory map as text in buffer.
-* CALLER DECREF: ppObDisplay
-* -- pProcess
-* -- flags = flags as specified by VMM_MAP_FLAGS*
-* -- ppObDisplay
-* -- return
-*/
-_Success_(return)
-inline BOOL VmmMemMapGetDisplay(_In_ PVMM_PROCESS pProcess, _In_ DWORD flags, _Out_ PVMMOB_PDATA *ppObDisplay)
-{
- if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_NA) { return FALSE; }
- return ctxVmm->fnMemoryModel.pfnMapGetDisplay(pProcess, flags, ppObDisplay);
-}
-
-/*
-* Retrieve an existing process given a process id (PID).
-* CALLER DECREF: return
-* -- dwPID
-* -- return = a process struct, or NULL if not found.
-*/
-PVMM_PROCESS VmmProcessGet(_In_ DWORD dwPID);
-
-/*
-* Retrieve the next process given a process. This may be useful when iterating
-* over a process list. NB! Listing of next item may fail prematurely if the
-* previous process is terminated while having a reference to it.
-* FUNCTION DECREF: pProcess
-* CALLER DECREF: return
-* -- pProcess = a process struct, or NULL if first.
- NB! function DECREF's pProcess and must not be used after call!
-* -- return = a process struct, or NULL if not found.
-*/
-PVMM_PROCESS VmmProcessGetNext(_In_opt_ PVMM_PROCESS pProcess);
-
-/*
-* Create a new process object. New process object are created in a separate
-* data structure and won't become visible to the "Process" functions until
-* after the VmmProcessCreateFinish have been called.
-* CALLER DECREF: return
-* -- fTotalRefresh = create a completely new entry - i.e. do not copy any form
-* of data from the old entry such as module and memory maps.
-* -- dwPID
-* -- dwState
-* -- paDTB
-* -- paDTB_UserOpt
-* -- szName
-* -- fUserOnly = user mode process (hide supervisor pages from view)
-*/
-PVMM_PROCESS VmmProcessCreateEntry(_In_ BOOL fTotalRefresh, _In_ DWORD dwPID, _In_ DWORD dwState, _In_ QWORD paDTB, _In_ QWORD paDTB_UserOpt, _In_ CHAR szName[16], _In_ BOOL fUserOnly);
-
-/*
-* Activate the pending, not yet active, processes added by VmmProcessCreateEntry.
-* This will also clear any previous processes.
-*/
-VOID VmmProcessCreateFinish();
-
-/*
-* List the PIDs and put them into the supplied table.
-* -- pPIDs = user allocated DWORD array to receive result, or NULL.
-* -- pcPIDs = ptr to number of DWORDs in pPIDs on entry - number of PIDs in system on exit.
-*/
-VOID VmmProcessListPIDs(_Out_writes_opt_(*pcPIDs) PDWORD pPIDs, _Inout_ PSIZE_T pcPIDs);
-
-/*
-* Clear the specified cache from all entries.
-* -- wTblTag
-*/
-VOID VmmCacheClear(_In_ WORD wTblTag);
-
-/*
-* Invalidate cache entries belonging to a specific physical address.
-* -- pa
-*/
-VOID VmmCacheInvalidate(_In_ QWORD pa);
-
-/*
-* Prefetch a set of addresses contained in pObPrefetchAddresses into the cache.
-* This is useful when reading data from somewhat known addresses over higher
-* latency connections.
-* -- pProcess
-* -- pObPrefetchAddresses
-*/
-VOID VmmCachePrefetchPages(_In_opt_ PVMM_PROCESS pProcess, _In_opt_ PVMMOB_DATASET pObPrefetchAddresses);
-
-/*
-* Initialize the memory model specified and discard any previous memory models
-* that may be in action.
-* -- tp
-*/
-VOID VmmInitializeMemoryModel(_In_ VMM_MEMORYMODEL_TP tp);
-
-/*
-* Initialize a new VMM context. This must always be done before calling any
-* other VMM functions. An alternative way to do this is to call the function:
-* VmmProcInitialize.
-* -- return
-*/
-BOOL VmmInitialize();
-
-/*
-* Close and clean up the VMM context inside the PCILeech context, if existing.
-*/
-VOID VmmClose();
-
-#endif /* __VMM_H__ */
diff --git a/vmm/vmm.rc b/vmm/vmm.rc
deleted file mode 100644
index c26a624..0000000
Binary files a/vmm/vmm.rc and /dev/null differ
diff --git a/vmm/vmm.vcxproj b/vmm/vmm.vcxproj
deleted file mode 100644
index e091a8b..0000000
--- a/vmm/vmm.vcxproj
+++ /dev/null
@@ -1,166 +0,0 @@
-
-
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- 15.0
- {6326FCE0-1BA5-4AEC-9973-7783309FFD6B}
- Win32Proj
- vmm
- 10.0.17763.0
-
-
-
- DynamicLibrary
- true
- v141
- Unicode
- false
-
-
- DynamicLibrary
- false
- v141
- true
- Unicode
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- true
- $(SolutionDir)\files\
- $(SolutionDir)\files\temp\$(ProjectName)\
- $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH)
-
-
- $(SolutionDir)\files\
- $(SolutionDir)\files\temp\$(ProjectName)\
-
-
-
- NotUsing
- Level3
- Disabled
- true
- _DEBUG;VMM_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
- CompileAsC
-
-
- Windows
- true
- vmmdll.def
- $(OutDir)\lib\$(TargetName).pdb
- $(OutDir)\lib\$(TargetName).lib
- $(SolutionDir)\files\leechcore.lib;%(AdditionalDependencies)
-
-
-
-copy "$(OutDir)\lib\vmm.lib" "$(OutDir)\vmm.lib" /y
-
-
- copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y
-copy $(ProjectDir)\vmmdll.h $(SolutionDir)\files\ /y
-
-
-
-
- NotUsing
- Level3
- MaxSpeed
- true
- true
- true
- NDEBUG;VMM_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
- CompileAsC
- MultiThreadedDLL
-
-
- Windows
- true
- true
- true
- vmmdll.def
- UseLinkTimeCodeGeneration
- $(OutDir)\lib\$(TargetName).pdb
- $(OutDir)\lib\$(TargetName).lib
- $(SolutionDir)\files\leechcore.lib;%(AdditionalDependencies)
-
-
-
-copy "$(OutDir)\lib\vmm.lib" "$(OutDir)\vmm.lib" /y
-
-
- copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y
-copy $(ProjectDir)\vmmdll.h $(SolutionDir)\files\ /y
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/vmm/vmm.vcxproj.filters b/vmm/vmm.vcxproj.filters
deleted file mode 100644
index e05ca6f..0000000
--- a/vmm/vmm.vcxproj.filters
+++ /dev/null
@@ -1,145 +0,0 @@
-
-
-
-
- {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
-
-
- {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
- rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
-
-
- {aedb4365-6f4c-4a1b-b130-a1d3adc27bf6}
-
-
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files\leechcore
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
-
-
- Resource Files
-
-
-
-
- Resource Files
-
-
-
\ No newline at end of file
diff --git a/vmm/vmm.vcxproj.user b/vmm/vmm.vcxproj.user
deleted file mode 100644
index fa6ed15..0000000
--- a/vmm/vmm.vcxproj.user
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
- WindowsLocalDebugger
-
-
- WindowsLocalDebugger
-
-
\ No newline at end of file
diff --git a/vmm/vmmdll.c b/vmm/vmmdll.c
deleted file mode 100644
index b1abad6..0000000
--- a/vmm/vmmdll.c
+++ /dev/null
@@ -1,1109 +0,0 @@
-// vmmdll.h : implementation of core dynamic link library (dll) functionality
-// of the virtual memory manager (VMM) for The Memory Process File System.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-
-#include "vmmdll.h"
-#include "pluginmanager.h"
-#include "util.h"
-#include "pe.h"
-#include "statistics.h"
-#include "version.h"
-#include "vmm.h"
-#include "vmmproc.h"
-#include "vmmwin.h"
-#include "vmmvfs.h"
-#include "mm_x64_winpaged.h"
-
-// ----------------------------------------------------------------------------
-// Synchronization macro below. The VMM isn't thread safe so it's important to
-// serialize access to it over the VMM MasterLock. This master lock is shared
-// with internal VMM housekeeping functionality.
-// ----------------------------------------------------------------------------
-
-#define CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(id, fn) { \
- QWORD tm; \
- BOOL result; \
- if(!ctxVmm) { return FALSE; } \
- tm = Statistics_CallStart(); \
- VmmLockAcquire(); \
- result = fn; \
- VmmLockRelease(); \
- Statistics_CallEnd(id, tm); \
- return result; \
-}
-
-#define CALL_SYNCHRONIZED_IMPLEMENTATION_VMM_RETURN(id, RetTp, RetValFail, fn) { \
- QWORD tm; \
- RetTp retVal; \
- if(!ctxVmm) { return ((RetTp)RetValFail); } /* UNSUCCESSFUL */ \
- tm = Statistics_CallStart(); \
- VmmLockAcquire(); \
- retVal = fn; \
- VmmLockRelease(); \
- Statistics_CallEnd(id, tm); \
- return retVal; \
-}
-
-//-----------------------------------------------------------------------------
-// INITIALIZATION FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-_Success_(return)
-BOOL VmmDll_ConfigIntialize(_In_ DWORD argc, _In_ char* argv[])
-{
- char* argv2[3];
- CHAR chMountMount = '\0';
- DWORD i = 0;
- if((argc == 2) && argv[1][0] && (argv[1][0] != '-')) {
- // click to open -> only 1 argument ...
- argv2[0] = argv[0];
- argv2[1] = "-device";
- argv2[2] = argv[1];
- return VmmDll_ConfigIntialize(3, argv2);
- }
- while(i < argc) {
- if(0 == _stricmp(argv[i], "")) {
- i++;
- continue;
- } else if(0 == _stricmp(argv[i], "-printf")) {
- ctxMain->cfg.fVerboseDll = TRUE;
- i++;
- continue;
- } else if(0 == _stricmp(argv[i], "-v")) {
- ctxMain->cfg.fVerbose = TRUE;
- i++;
- continue;
- } else if(0 == _stricmp(argv[i], "-vv")) {
- ctxMain->cfg.fVerboseExtra = TRUE;
- i++;
- continue;
- } else if(0 == _stricmp(argv[i], "-vvv")) {
- ctxMain->cfg.fVerboseExtraTlp = TRUE;
- i++;
- continue;
- } else if(0 == _stricmp(argv[i], "-identify")) {
- ctxMain->cfg.fCommandIdentify = TRUE;
- i++;
- continue;
- } else if(0 == _stricmp(argv[i], "-norefresh")) {
- ctxMain->cfg.fDisableBackgroundRefresh = TRUE;
- i++;
- continue;
- } else if(i + 1 >= argc) {
- return FALSE;
- } else if(0 == strcmp(argv[i], "-cr3")) {
- ctxMain->cfg.paCR3 = Util_GetNumeric(argv[i + 1]);
- i += 2;
- continue;
- } else if(0 == strcmp(argv[i], "-max")) {
- ctxMain->dev.paMax = Util_GetNumeric(argv[i + 1]);
- i += 2;
- continue;
- } else if((0 == strcmp(argv[i], "-device")) || (0 == strcmp(argv[i], "-z"))) {
- strcpy_s(ctxMain->dev.szDevice, MAX_PATH, argv[i + 1]);
- i += 2;
- continue;
- } else if(0 == strcmp(argv[i], "-remote")) {
- strcpy_s(ctxMain->dev.szRemote, MAX_PATH, argv[i + 1]);
- i += 2;
- continue;
- } else if(0 == strcmp(argv[i], "-pythonpath")) {
- strcpy_s(ctxMain->cfg.szPythonPath, MAX_PATH, argv[i + 1]);
- i += 2;
- continue;
- } else if(0 == strcmp(argv[i], "-mount")) {
- chMountMount = argv[i + 1][0];
- i += 2;
- continue;
- } else {
- return FALSE;
- }
- }
- if((chMountMount > 'A' && chMountMount < 'Z') || (chMountMount > 'a' && chMountMount < 'z')) {
- ctxMain->cfg.szMountPoint[0] = chMountMount;
- } else {
- ctxMain->cfg.szMountPoint[0] = 'M';
- }
- if(ctxMain->dev.paMax == 0) { ctxMain->dev.paMax = 0x0000ffffffffffff; }
- if(ctxMain->dev.paMax < 0x00100000) { return FALSE; }
- ctxMain->cfg.fVerbose = ctxMain->cfg.fVerbose && ctxMain->cfg.fVerboseDll;
- ctxMain->cfg.fVerboseExtra = ctxMain->cfg.fVerboseExtra && ctxMain->cfg.fVerboseDll;
- ctxMain->cfg.fVerboseExtraTlp = ctxMain->cfg.fVerboseExtraTlp && ctxMain->cfg.fVerboseDll;
- ctxMain->dev.magic = LEECHCORE_CONFIG_MAGIC;
- ctxMain->dev.version = LEECHCORE_CONFIG_VERSION;
- ctxMain->dev.flags |= ctxMain->cfg.fVerboseDll ? LEECHCORE_CONFIG_FLAG_PRINTF : 0;
- ctxMain->dev.flags |= ctxMain->cfg.fVerbose ? LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_1 : 0;
- ctxMain->dev.flags |= ctxMain->cfg.fVerboseExtra ? LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_2 : 0;
- ctxMain->dev.flags |= ctxMain->cfg.fVerboseExtraTlp ? LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_3 : 0;
- return (ctxMain->dev.szDevice[0] != 0);
-}
-
-VOID VmmDll_PrintHelp()
-{
- vmmprintf(
- " \n" \
- " THE MEMORY PROCESS FILE SYSTEM v%i.%i.%i COMMAND LINE REFERENCE: \n" \
- " The Memory Process File System may be used in stand-alone mode with support \n" \
- " for memory dump files, local memory via rekall winpmem driver or together with\n" \
- " PCILeech if pcileech.dll is placed in the application directory. For infor- \n" \
- " mation about PCILeech please consult the separate PCILeech documentation. \n" \
- " ----- \n" \
- " The Memory Process File System (c) 2018 Ulf Frisk \n" \
- " License: GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 \n" \
- " Contact information: pcileech@frizk.net \n" \
- " The Memory Process File System: https://github.com/ufrisk/MemProcFS \n" \
- " PCILeech: https://github.com/ufrisk/pcileech \n" \
- " ----- \n" \
- " The recommended way to use the Memory Process File System is to specify the \n" \
- " memory acquisition device in the -device option and possibly more options. \n" \
- " Example 1: MemProcFS.exe -device c:\\temp\\memdump-win10x64.pmem \n" \
- " Example 2: MemProcFS.exe -device c:\\temp\\memdump-winXPx86.dumpit -v -vv \n" \
- " Example 3: MemProcFS.exe -device FPGA \n" \
- " Example 4: MemProcFS.exe -device PMEM://c:\\temp\\winpmem_x64.sys \n" \
- " The Memory Process File System may also be started the memory dump file name \n" \
- " as the only option. This allows to make file extensions associated so that \n" \
- " they may be opened by double-clicking on them. This mode allows no options. \n" \
- " Example 4: MemProcFS.exe c:\\dumps\\memdump-win7x64.dumpit \n" \
- " ----- \n" \
- " Valid options: \n" \
- " -device: select memory acquisition device or memory dump file to use. \n" \
- " Valid options: , PMEM, FPGA, TOTALMELTDOWN \n" \
- " --- \n" \
- " = memory dump file name optionally including path.\n" \
- " PMEM = use winpmem 'winpmem_64.sys' to acquire live memory. \n" \
- " PMEM://c:\\path\\to\\winpmem_64.sys = path to winpmem driver. \n" \
- " --- \n" \
- " Below acquisition devices require pcileech.dll and are not built-in: \n" \
- " TOTALMELTDOWN = use CVE-2018-1038 (vulnerable windows 7 only) \n" \
- " FPGA = use PCILeech PCIe DMA hardware memory acquisition device. \n" \
- " -v : verbose option. Additional information is displayed in the output. \n" \
- " Option has no value. Example: -v \n" \
- " -vv : extra verbose option. More detailed additional information is shown \n" \
- " in output. Option has no value. Example: -vv \n" \
- " -vvv : super verbose option. Show all data transferred such as PCIe TLPs. \n" \
- " Option has no value. Example: -vvv \n" \
- " -cr3 : base address of kernel/process page table (PML4) / CR3 CPU register. \n" \
- " -max : memory max address, valid range: 0x0 .. 0xffffffffffffffff \n" \
- " default: auto-detect (max supported by device / target system). \n" \
- " -pythonpath : specify the path to a python 3.6 installation for Windows. \n" \
- " The path given should be to the directory that contain: python36.dll \n" \
- " Example: -pythonpath \"C:\\Program Files\\Python36\" \n" \
- " -mount : drive letter to mount The Memory Process File system at. \n" \
- " default: M Example: -mount Q \n" \
- " -identify : scan memory for the operating system and the kernel page table. \n" \
- " This may help if the default auto-detect is not working. \n" \
- " Option has no value. Example: -identify \n" \
- " \n",
- VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION
- );
-}
-
-VOID VmmDll_FreeContext()
-{
- if(ctxVmm) {
- VmmClose();
- }
- if(ctxMain) {
- Statistics_CallSetEnabled(FALSE);
- LeechCore_Close();
- LocalFree(ctxMain);
- ctxMain = NULL;
- }
-}
-
-_Success_(return)
-BOOL VMMDLL_Initialize(_In_ DWORD argc, _In_ LPSTR argv[])
-{
- ctxMain = LocalAlloc(LMEM_ZEROINIT, sizeof(VMM_MAIN_CONTEXT));
- if(!ctxMain) {
- return FALSE;
- }
- // initialize configuration
- if(!VmmDll_ConfigIntialize((DWORD)argc, argv)) {
- VmmDll_PrintHelp();
- VmmDll_FreeContext();
- return FALSE;
- }
- // ctxMain.cfg context is inintialized from here onwards - vmmprintf is working!
- if(!LeechCore_Open(&ctxMain->dev)) {
- vmmprintf("MemProcFS: Failed to connect to memory acquisition device.\n");
- VmmDll_FreeContext();
- return FALSE;
- }
- // ctxMain.dev context is initialized from here onwards - device functionality is working!
- if(ctxMain->cfg.fCommandIdentify) {
- // if identify option is supplied try scan for page directory base...
- VmmProcIdentify();
- }
- if(!VmmProcInitialize()) {
- vmmprintf("MOUNT: INFO: PROC file system not mounted.\n");
- VmmDll_FreeContext();
- return FALSE;
- }
- // ctxVmm context is initialized from here onwards - vmm functionality is working!
- return TRUE;
-}
-
-_Success_(return)
-BOOL VMMDLL_Close()
-{
- VmmDll_FreeContext();
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// CONFIGURATION SETTINGS BELOW:
-//-----------------------------------------------------------------------------
-
-_Success_(return)
-BOOL VMMDLL_ConfigGet_VmmCore(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue)
-{
- switch(fOption) {
- case VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED:
- *pqwValue = ctxVmm->ThreadProcCache.fEnabled ? 1 : 0;
- break;
- case VMMDLL_OPT_CONFIG_TICK_PERIOD:
- *pqwValue = ctxVmm->ThreadProcCache.cMs_TickPeriod;
- break;
- case VMMDLL_OPT_CONFIG_READCACHE_TICKS:
- *pqwValue = ctxVmm->ThreadProcCache.cTick_Phys;
- break;
- case VMMDLL_OPT_CONFIG_TLBCACHE_TICKS:
- *pqwValue = ctxVmm->ThreadProcCache.cTick_TLB;
- break;
- case VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_PARTIAL:
- *pqwValue = ctxVmm->ThreadProcCache.cTick_ProcPartial;
- break;
- case VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_TOTAL:
- *pqwValue = ctxVmm->ThreadProcCache.cTick_ProcTotal;
- break;
- case VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL:
- *pqwValue = Statistics_CallGetEnabled() ? 1 : 0;
- return TRUE;
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-_Success_(return)
-BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue)
-{
- if(!pqwValue) { return FALSE; }
- if(fOption & 0x40000000) {
- if(fOption == VMMDLL_OPT_CONFIG_VMM_VERSION_MAJOR) {
- *pqwValue = VERSION_MAJOR;
- return TRUE;
- } else if(fOption == VMMDLL_OPT_CONFIG_VMM_VERSION_MINOR) {
- *pqwValue = VERSION_MINOR;
- return TRUE;
- } else if(fOption == VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION) {
- *pqwValue = VERSION_REVISION;
- return TRUE;
- }
- }
- if(!ctxVmm) { return FALSE; }
- // core options affecting only vmm.dll
- if(fOption & 0x40000000) {
- return VMMDLL_ConfigGet_VmmCore(fOption, pqwValue);
- }
- // core options affecting both vmm.dll and pcileech.dll
- if(fOption & 0x80000000) {
- switch(fOption) {
- case VMMDLL_OPT_CORE_PRINTF_ENABLE:
- *pqwValue = ctxMain->cfg.fVerboseDll ? 1 : 0;
- return TRUE;
- case VMMDLL_OPT_CORE_VERBOSE:
- *pqwValue = ctxMain->cfg.fVerbose ? 1 : 0;
- return TRUE;
- case VMMDLL_OPT_CORE_VERBOSE_EXTRA:
- *pqwValue = ctxMain->cfg.fVerboseExtra ? 1 : 0;
- return TRUE;
- case VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP:
- *pqwValue = ctxMain->cfg.fVerboseExtraTlp ? 1 : 0;
- return TRUE;
- case VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS:
- *pqwValue = ctxMain->dev.paMaxNative;
- return TRUE;
- case VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE:
- *pqwValue = ctxMain->dev.cbMaxSizeMemIo;
- return TRUE;
- case VMMDLL_OPT_CORE_SYSTEM:
- *pqwValue = ctxVmm->tpSystem;
- return TRUE;
- case VMMDLL_OPT_CORE_MEMORYMODEL:
- *pqwValue = ctxVmm->tpMemoryModel;
- return TRUE;
- default:
- return FALSE;
- }
- }
- // non-recognized option - possibly a device option to pass along to pcileech.dll
- return LeechCore_GetOption(fOption, pqwValue);
-}
-
-_Success_(return)
-BOOL VMMDLL_ConfigSet_VmmCore(_In_ ULONG64 fOption, _In_ ULONG64 qwValue)
-{
- switch(fOption) {
- case VMMDLL_OPT_CONFIG_TICK_PERIOD:
- ctxVmm->ThreadProcCache.cMs_TickPeriod = (DWORD)qwValue;
- break;
- case VMMDLL_OPT_CONFIG_READCACHE_TICKS:
- ctxVmm->ThreadProcCache.cTick_Phys = (DWORD)qwValue;
- break;
- case VMMDLL_OPT_CONFIG_TLBCACHE_TICKS:
- ctxVmm->ThreadProcCache.cTick_TLB = (DWORD)qwValue;
- break;
- case VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_PARTIAL:
- ctxVmm->ThreadProcCache.cTick_ProcPartial = (DWORD)qwValue;
- break;
- case VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_TOTAL:
- ctxVmm->ThreadProcCache.cTick_ProcTotal = (DWORD)qwValue;
- break;
- case VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL:
- Statistics_CallSetEnabled(qwValue ? TRUE : FALSE);
- return TRUE;
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-_Success_(return)
-BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue)
-{
- if(!ctxVmm) { return FALSE; }
- // core options affecting only vmm.dll
- if(fOption & 0x40000000) {
- return VMMDLL_ConfigSet_VmmCore(fOption, qwValue);
- }
- // core options affecting both vmm.dll and leechcore.dll
- if(fOption & 0x80000000) {
- LeechCore_SetOption(fOption, qwValue);
- switch(fOption) {
- case VMMDLL_OPT_CORE_PRINTF_ENABLE:
- ctxMain->cfg.fVerboseDll = qwValue ? TRUE : FALSE;
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_NOLOG,
- PluginManager_Notify(VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE, NULL, 0))
- return TRUE;
- case VMMDLL_OPT_CORE_VERBOSE:
- ctxMain->cfg.fVerbose = qwValue ? TRUE : FALSE;
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_NOLOG,
- PluginManager_Notify(VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE, NULL, 0))
- return TRUE;
- case VMMDLL_OPT_CORE_VERBOSE_EXTRA:
- ctxMain->cfg.fVerboseExtra = qwValue ? TRUE : FALSE;
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_NOLOG,
- PluginManager_Notify(VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE, NULL, 0))
- return TRUE;
- case VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP:
- ctxMain->cfg.fVerboseExtraTlp = qwValue ? TRUE : FALSE;
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_NOLOG,
- PluginManager_Notify(VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE, NULL, 0))
- return TRUE;
- default:
- return FALSE;
- }
- }
- // non-recognized option - possibly a device option to pass along to memdevice.dll
- return LeechCore_SetOption(fOption, qwValue);
-}
-
-//-----------------------------------------------------------------------------
-// VFS - VIRTUAL FILE SYSTEM FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-_Success_(return)
-BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_VfsList,
- VmmVfs_List(wcsPath, (PHANDLE)pFileList))
-}
-
-NTSTATUS VMMDLL_VfsRead(_In_ LPCWSTR wcsFileName, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM_RETURN(
- STATISTICS_ID_VMMDLL_VfsRead,
- NTSTATUS,
- VMMDLL_STATUS_UNSUCCESSFUL,
- VmmVfs_Read(wcsFileName, pb, cb, pcbRead, cbOffset))
-}
-
-NTSTATUS VMMDLL_VfsWrite(_In_ LPCWSTR wcsFileName, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM_RETURN(
- STATISTICS_ID_VMMDLL_VfsWrite,
- NTSTATUS,
- VMMDLL_STATUS_UNSUCCESSFUL,
- VmmVfs_Write(wcsFileName, pb, cb, pcbWrite, cbOffset))
-}
-
-NTSTATUS VMMDLL_UtilVfsReadFile_FromPBYTE(_In_ PBYTE pbFile, _In_ ULONG64 cbFile, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset)
-{
- return Util_VfsReadFile_FromPBYTE(pbFile, cbFile, pb, cb, pcbRead, cbOffset);
-}
-
-NTSTATUS VMMDLL_UtilVfsReadFile_FromQWORD(_In_ ULONG64 qwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix)
-{
- return Util_VfsReadFile_FromQWORD(qwValue, pb, cb, pcbRead, cbOffset, fPrefix);
-}
-
-NTSTATUS VMMDLL_UtilVfsReadFile_FromDWORD(_In_ DWORD dwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix)
-{
- return Util_VfsReadFile_FromDWORD(dwValue, pb, cb, pcbRead, cbOffset, fPrefix);
-}
-
-NTSTATUS VMMDLL_UtilVfsReadFile_FromBOOL(_In_ BOOL fValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset)
-{
- return Util_VfsReadFile_FromBOOL(fValue, pb, cb, pcbRead, cbOffset);
-}
-
-NTSTATUS VMMDLL_UtilVfsWriteFile_BOOL(_Inout_ PBOOL pfTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset)
-{
- return Util_VfsWriteFile_BOOL(pfTarget, pb, cb, pcbWrite, cbOffset);
-}
-
-NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset, _In_ DWORD dwMinAllow)
-{
- return Util_VfsWriteFile_DWORD(pdwTarget, pb, cb, pcbWrite, cbOffset, dwMinAllow);
-}
-
-
-
-//-----------------------------------------------------------------------------
-// PLUGIN MANAGER FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-_Success_(return)
-BOOL VMMDLL_VfsInitializePlugins()
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_VfsInitializePlugins,
- PluginManager_Initialize())
-}
-
-
-
-//-----------------------------------------------------------------------------
-// REFRESH FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-_Success_(return)
-BOOL VMMDLL_Refresh_Impl(_In_ DWORD dwReserved)
-{
- ULONG64 paMax;
- // enforce global lock even if 'multi thread' is enabled
- // we wish to avoid parallel process refreshes ...
- EnterCriticalSection(&ctxVmm->MasterLock);
- VmmCacheClear(VMM_CACHE_TAG_PHYS);
- VmmCacheClear(VMM_CACHE_TAG_TLB);
- VmmProc_RefreshProcesses(TRUE);
- // update max physical address (if volatile).
- if(ctxMain->dev.fVolatileMaxAddress) {
- if(LeechCore_GetOption(LEECHCORE_OPT_MEMORYINFO_ADDR_MAX, &paMax) && (paMax > 0x01000000)) {
- ctxMain->dev.paMax = paMax;
- }
- }
- LeaveCriticalSection(&ctxVmm->MasterLock);
- return TRUE;
-}
-
-_Success_(return)
-BOOL VMMDLL_Refresh(_In_ DWORD dwReserved)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_Refresh,
- VMMDLL_Refresh_Impl(dwReserved))
-}
-
-
-
-//-----------------------------------------------------------------------------
-// VMM CORE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs, _In_ DWORD flags)
-{
- DWORD i, cMEMs;
- PVMM_PROCESS pObProcess = NULL;
- if(!ctxVmm) { return 0; }
- VmmLockAcquire();
- if(dwPID == -1) {
- VmmReadScatterPhysical(ppMEMs, cpMEMs, flags);
- } else {
- pObProcess = VmmProcessGet(dwPID);
- if(!pObProcess) {
- VmmLockRelease();
- return FALSE;
- }
- VmmReadScatterVirtual(pObProcess, ppMEMs, cpMEMs, flags);
- VmmOb_DECREF(pObProcess);
- }
- for(i = 0, cMEMs = 0; i < cpMEMs; i++) {
- if(ppMEMs[i]->cb == ppMEMs[i]->cbMax) {
- cMEMs++;
- }
- }
- VmmLockRelease();
- return cMEMs;
-}
-
-_Success_(return)
-BOOL VMMDLL_MemReadEx_Impl(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags)
-{
- PVMM_PROCESS pObProcess = NULL;
- if(dwPID != -1) {
- pObProcess = VmmProcessGet(dwPID);
- if(!pObProcess) { return FALSE; }
- }
- VmmReadEx(pObProcess, qwVA, pb, cb, pcbReadOpt, flags);
- VmmOb_DECREF(pObProcess);
- return TRUE;
-}
-
-_Success_(return)
-BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_MemReadEx,
- VMMDLL_MemReadEx_Impl(dwPID, qwVA, pb, cb, pcbReadOpt, flags))
-}
-
-_Success_(return)
-BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb)
-{
- DWORD dwRead;
- return VMMDLL_MemReadEx(dwPID, qwVA, pb, cb, &dwRead, 0) && (dwRead == cb);
-}
-
-_Success_(return)
-BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage)
-{
- DWORD dwRead;
- return VMMDLL_MemReadEx(dwPID, qwVA, pbPage, 4096, &dwRead, 0) && (dwRead == 4096);
-}
-
-_Success_(return)
-BOOL VMMDLL_MemPrefetchPages_Impl(_In_ DWORD dwPID, _In_reads_(cPrefetchAddresses) PULONG64 pPrefetchAddresses, _In_ DWORD cPrefetchAddresses)
-{
- DWORD i;
- BOOL result = FALSE;
- PVMM_PROCESS pObProcess = NULL;
- PVMMOB_DATASET pObPrefetchAddresses = NULL;
- if(dwPID != (DWORD)-1) {
- pObProcess = VmmProcessGet(dwPID);
- if(!pObProcess) { goto fail; }
- }
- pObPrefetchAddresses = VmmObDataSet_Alloc(TRUE);
- if(!pObPrefetchAddresses) { goto fail; }
- for(i = 0; i < cPrefetchAddresses; i++) {
- VmmObDataSet_Put(pObPrefetchAddresses, pPrefetchAddresses[i] & ~0xfff);
- }
- VmmCachePrefetchPages(pObProcess, pObPrefetchAddresses);
- result = TRUE;
-fail:
- VmmOb_DECREF(pObPrefetchAddresses);
- VmmOb_DECREF(pObProcess);
- return result;
-}
-
-_Success_(return)
-BOOL VMMDLL_MemPrefetchPages(_In_ DWORD dwPID, _In_reads_(cPrefetchAddresses) PULONG64 pPrefetchAddresses, _In_ DWORD cPrefetchAddresses)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_MemPrefetchPages,
- VMMDLL_MemPrefetchPages_Impl(dwPID, pPrefetchAddresses, cPrefetchAddresses))
-}
-
-_Success_(return)
-BOOL VMMDLL_MemWrite_Impl(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb)
-{
- BOOL result;
- PVMM_PROCESS pObProcess = NULL;
- if(dwPID != -1) {
- pObProcess = VmmProcessGet(dwPID);
- if(!pObProcess) { return FALSE; }
- }
- result = VmmWrite(pObProcess, qwVA, pb, cb);
- VmmOb_DECREF(pObProcess);
- return result;
-}
-
-_Success_(return)
-BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_MemWrite,
- VMMDLL_MemWrite_Impl(dwPID, qwVA, pb, cb))
-}
-
-_Success_(return)
-BOOL VMMDLL_MemVirt2Phys_Impl(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA)
-{
- BOOL result;
- PVMM_PROCESS pObProcess = VmmProcessGet(dwPID);
- if(!pObProcess) { return FALSE; }
- result = VmmVirt2Phys(pObProcess, qwVA, pqwPA);
- VmmOb_DECREF(pObProcess);
- return result;
-}
-
-_Success_(return)
-BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_MemVirt2Phys,
- VMMDLL_MemVirt2Phys_Impl(dwPID, qwVA, pqwPA))
-}
-
-//-----------------------------------------------------------------------------
-// VMM PROCESS FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMap_Impl(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules)
-{
- PVMM_PROCESS pObProcess = NULL;
- PVMMOB_MEMMAP pObMap = NULL;
- pObProcess = VmmProcessGet(dwPID);
- if(!pObProcess) { return FALSE; }
- if(!VmmMemMapGetEntries(pObProcess, fIdentifyModules ? VMM_MEMMAP_FLAG_ALL : 0, &pObMap)) { goto fail; }
- if(!pMemMapEntries) {
- *pcMemMapEntries = pObMap->cMap;
- } else {
- if(!pObMap->cMap || (*pcMemMapEntries < pObMap->cMap)) { goto fail; }
- memcpy(pMemMapEntries, pObMap->pMap, sizeof(VMMDLL_MEMMAP_ENTRY) * pObMap->cMap);
- *pcMemMapEntries = pObMap->cMap;
- }
- VmmOb_DECREF(pObMap);
- VmmOb_DECREF(pObProcess);
- return TRUE;
-fail:
- VmmOb_DECREF(pObMap);
- VmmOb_DECREF(pObProcess);
- return FALSE;
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_ProcessGetMemoryMap,
- VMMDLL_ProcessGetMemoryMap_Impl(dwPID, pMemMapEntries, pcMemMapEntries, fIdentifyModules))
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMapEntry_Impl(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules)
-{
- PVMM_PROCESS pObProcess = NULL;
- DWORD i;
- PVMMOB_MEMMAP pObMap = NULL;
- PVMM_MEMMAP_ENTRY pe;
- pObProcess = VmmProcessGet(dwPID);
- if(!pObProcess) { return FALSE; }
- if(!VmmMemMapGetEntries(pObProcess, fIdentifyModules ? VMM_MEMMAP_FLAG_ALL : 0, &pObMap)) {goto fail; }
- for(i = 0; i < pObMap->cMap; i++) {
- pe = pObMap->pMap + i;
- if((pe->AddrBase >= va) && (va <= pe->AddrBase + (pe->cPages << 12))) {
- memcpy(pMemMapEntry, pe, sizeof(VMM_MEMMAP_ENTRY));
- VmmOb_DECREF(pObMap);
- VmmOb_DECREF(pObProcess);
- return TRUE;
- }
- }
-fail:
- VmmOb_DECREF(pObMap);
- VmmOb_DECREF(pObProcess);
- return FALSE;
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_ProcessGetMemoryMapEntry,
- VMMDLL_ProcessGetMemoryMapEntry_Impl(dwPID, pMemMapEntry, va, fIdentifyModules))
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleMap_Impl(_In_ DWORD dwPID, _Out_writes_opt_(*pcModuleEntries) PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries)
-{
- ULONG64 i;
- PVMM_PROCESS pObProcess = NULL;
- PVMMOB_MODULEMAP pObModuleMap;
- if(!pcModuleEntries) { return FALSE; }
- pObProcess = VmmProcessGet(dwPID);
- if(!pObProcess) { return FALSE; }
- if(VmmProc_ModuleMapGet(pObProcess, &pObModuleMap)) {
- if(!pModuleEntries) {
- *pcModuleEntries = pObModuleMap->cMap;
- } else {
- if(!pObModuleMap->pMap || (*pcModuleEntries < pObModuleMap->cMap)) {
- VmmOb_DECREF(pObModuleMap);
- VmmOb_DECREF(pObProcess);
- return FALSE;
- }
- for(i = 0; i < pObModuleMap->cMap; i++) {
- memcpy(pModuleEntries + i, pObModuleMap->pMap + i, sizeof(VMMDLL_MODULEMAP_ENTRY));
- }
- *pcModuleEntries = pObModuleMap->cMap;
- }
- VmmOb_DECREF(pObModuleMap);
- } else {
- *pcModuleEntries = 0;
- }
- VmmOb_DECREF(pObProcess);
- return TRUE;
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_ProcessGetModuleMap,
- VMMDLL_ProcessGetModuleMap_Impl(dwPID, pModuleEntries, pcModuleEntries))
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleFromName_Impl(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry)
-{
- BOOL result;
- ULONG64 i, cModuleEntries = 0;
- PVMMDLL_MODULEMAP_ENTRY pModuleEntries = NULL;
- result = VMMDLL_ProcessGetModuleMap_Impl(dwPID, NULL, &cModuleEntries);
- if(!result || !cModuleEntries) { return FALSE; }
- pModuleEntries = (PVMMDLL_MODULEMAP_ENTRY)LocalAlloc(0, sizeof(VMMDLL_MODULEMAP_ENTRY) * cModuleEntries);
- if(!pModuleEntries) { return FALSE; }
- result = VMMDLL_ProcessGetModuleMap_Impl(dwPID, pModuleEntries, &cModuleEntries);
- if(result && cModuleEntries) {
- for(i = 0; i < cModuleEntries; i++) {
- if(!_strnicmp(szModuleName, pModuleEntries[i].szName, 31)) {
- memcpy(pModuleEntry, pModuleEntries + i, sizeof(VMMDLL_MODULEMAP_ENTRY));
- LocalFree(pModuleEntries);
- return TRUE;
- }
- }
- }
- LocalFree(pModuleEntries);
- return FALSE;
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_ProcessGetModuleFromName,
- VMMDLL_ProcessGetModuleFromName_Impl(dwPID, szModuleName, pModuleEntry))
-}
-
-_Success_(return)
-BOOL VMMDLL_PidList_Impl(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs)
-{
- VmmProcessListPIDs(pPIDs, pcPIDs);
- return TRUE;
-}
-
-_Success_(return)
-BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_PidList,
- VMMDLL_PidList_Impl(pPIDs, pcPIDs))
-}
-
-_Success_(return)
-BOOL VMMDLL_PidGetFromName_Impl(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID)
-{
- PVMM_PROCESS pObProcess = NULL;
- while((pObProcess = VmmProcessGetNext(pObProcess))) {
- if(_strnicmp(szProcName, pObProcess->szName, 15)) { continue; }
- if(pObProcess->dwState) { continue; }
- *pdwPID = pObProcess->dwPID;
- VmmOb_DECREF(pObProcess);
- return TRUE;
- }
- return FALSE;
-}
-
-_Success_(return)
-BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_PidGetFromName,
- VMMDLL_PidGetFromName_Impl(szProcName, pdwPID))
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetInformation_Impl(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pInfo, _In_ PSIZE_T pcbProcessInfo)
-{
- PVMM_PROCESS pObProcess = NULL;
- if(!pcbProcessInfo) { return FALSE; }
- if(!pInfo) {
- *pcbProcessInfo = sizeof(VMMDLL_PROCESS_INFORMATION);
- return TRUE;
- }
- if(*pcbProcessInfo < sizeof(VMMDLL_PROCESS_INFORMATION)) { return FALSE; }
- if(pInfo->magic != VMMDLL_PROCESS_INFORMATION_MAGIC) { return FALSE; }
- if(pInfo->wVersion != VMMDLL_PROCESS_INFORMATION_VERSION) { return FALSE; }
- if(!(pObProcess = VmmProcessGet(dwPID))) { return FALSE; }
- ZeroMemory(pInfo, sizeof(VMMDLL_PROCESS_INFORMATION_MAGIC));
- // set general parameters
- pInfo->wVersion = VMMDLL_PROCESS_INFORMATION_VERSION;
- pInfo->wSize = sizeof(VMMDLL_PROCESS_INFORMATION);
- pInfo->tpMemoryModel = ctxVmm->tpMemoryModel;
- pInfo->tpSystem = ctxVmm->tpSystem;
- pInfo->fUserOnly = pObProcess->fUserOnly;
- pInfo->dwPID = dwPID;
- pInfo->dwState = pObProcess->dwState;
- pInfo->paDTB = pObProcess->paDTB;
- pInfo->paDTB_UserOpt = pObProcess->paDTB_UserOpt;
- memcpy(pInfo->szName, pObProcess->szName, sizeof(pInfo->szName));
- // set operating system specific parameters
- switch(ctxVmm->tpSystem) {
- case VMM_SYSTEM_WINDOWS_X64:
- pInfo->os.win.fWow64 = pObProcess->os.win.fWow64;
- pInfo->os.win.vaENTRY = pObProcess->os.win.vaENTRY;
- pInfo->os.win.vaEPROCESS = pObProcess->os.win.vaEPROCESS;
- pInfo->os.win.vaPEB = pObProcess->os.win.vaPEB;
- pInfo->os.win.vaPEB32 = pObProcess->os.win.vaPEB32;
- break;
- case VMM_SYSTEM_WINDOWS_X86:
- pInfo->os.win.vaENTRY = pObProcess->os.win.vaENTRY;
- pInfo->os.win.vaEPROCESS = pObProcess->os.win.vaEPROCESS;
- pInfo->os.win.vaPEB = pObProcess->os.win.vaPEB;
- break;
- }
- VmmOb_DECREF(pObProcess);
- return TRUE;
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_ProcessGetInformation,
- VMMDLL_ProcessGetInformation_Impl(dwPID, pProcessInformation, pcbProcessInformation))
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGet_Directories_Sections_IAT_EAT_Impl(
- _In_ DWORD dwPID,
- _In_ LPSTR szModule,
- _In_ DWORD cData,
- _Out_ PDWORD pcData,
- _Out_writes_opt_(16) PIMAGE_DATA_DIRECTORY pDataDirectory,
- _Out_opt_ PIMAGE_SECTION_HEADER pSections,
- _Out_opt_ PVMMDLL_EAT_ENTRY pEAT,
- _Out_opt_ PVOID pIAT,
- BOOL _In_ fDataDirectory,
- BOOL _In_ fSections,
- BOOL _In_ fEAT,
- BOOL _In_ fIAT
-)
-{
- DWORD i;
- PVMMOB_MODULEMAP pObModuleMap = NULL;
- PVMM_MODULEMAP_ENTRY pModule = NULL;
- PVMM_PROCESS pObProcess = NULL;
- pObProcess = VmmProcessGet(dwPID);
- if(!pObProcess) { goto fail; }
- // fetch requested module
- if(!VmmProc_ModuleMapGet(pObProcess, &pObModuleMap)) { goto fail; }
- for(i = 0; i < pObModuleMap->cMap; i++) {
- if(!_stricmp(pObModuleMap->pMap[i].szName, szModule)) {
- pModule = pObModuleMap->pMap + i;
- }
- }
- if(!pModule) { goto fail; }
- // data directories
- if(fDataDirectory) {
- if(!pDataDirectory) { *pcData = 16; goto success; }
- if(cData < 16) { goto fail; }
- VmmWin_PE_DIRECTORY_DisplayBuffer(pObProcess, pModule, NULL, 0, NULL, pDataDirectory);
- *pcData = 16;
- goto success;
- }
- // sections
- if(fSections) {
- i = PE_SectionGetNumberOf(pObProcess, pModule->BaseAddress);
- if(!pSections) { *pcData = i; goto success; }
- if(cData < i) { goto fail; }
- VmmWin_PE_SECTION_DisplayBuffer(pObProcess, pModule, NULL, 0, NULL, &cData, pSections);
- *pcData = cData;
- goto success;
- }
- // export address table (EAT)
- if(fEAT) {
- i = PE_EatGetNumberOf(pObProcess, pModule->BaseAddress);
- if(!pEAT) { *pcData = i; goto success; }
- if(cData < i) { goto fail; }
- VmmWin_PE_LoadEAT_DisplayBuffer(pObProcess, pModule, (PVMMPROC_WINDOWS_EAT_ENTRY)pEAT, cData, &cData);
- *pcData = cData;
- goto success;
- }
- // import address table (IAT)
- if(fIAT) {
- i = PE_IatGetNumberOf(pObProcess, pModule->BaseAddress);
- if(!pIAT) { *pcData = i; goto success; }
- if(cData < i) { goto fail; }
- VmmWin_PE_LoadIAT_DisplayBuffer(pObProcess, pModule, (PVMMWIN_IAT_ENTRY)pIAT, cData, &cData);
- *pcData = cData;
- goto success;
- }
-fail:
- VmmOb_DECREF(pObModuleMap);
- VmmOb_DECREF(pObProcess);
- return FALSE;
-success:
- VmmOb_DECREF(pObModuleMap);
- VmmOb_DECREF(pObProcess);
- return TRUE;
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_ProcessGetDirectories,
- VMMDLL_ProcessGet_Directories_Sections_IAT_EAT_Impl(dwPID, szModule, cData, pcData, pData, NULL, NULL, NULL, TRUE, FALSE, FALSE, FALSE))
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_ProcessGetSections,
- VMMDLL_ProcessGet_Directories_Sections_IAT_EAT_Impl(dwPID, szModule, cData, pcData, NULL, pData, NULL, NULL, FALSE, TRUE, FALSE, FALSE))
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_ProcessGetEAT,
- VMMDLL_ProcessGet_Directories_Sections_IAT_EAT_Impl(dwPID, szModule, cData, pcData, NULL, NULL, pData, NULL, FALSE, FALSE, TRUE, FALSE))
-}
-
-_Success_(return)
-BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_ProcessGetIAT,
- VMMDLL_ProcessGet_Directories_Sections_IAT_EAT_Impl(dwPID, szModule, cData, pcData, NULL, NULL, NULL, pData, FALSE, FALSE, FALSE, TRUE))
-}
-
-ULONG64 VMMDLL_ProcessGetProcAddress_Impl(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szFunctionName)
-{
- QWORD vaFn = 0;
- VMMDLL_MODULEMAP_ENTRY oModuleEntry = { 0 };
- PVMM_PROCESS pObProcess = NULL;
- pObProcess = VmmProcessGet(dwPID);
- if(!pObProcess) { return 0; }
- if(VMMDLL_ProcessGetModuleFromName_Impl(dwPID, szModuleName, &oModuleEntry)) {
- vaFn = PE_GetProcAddress(pObProcess, oModuleEntry.BaseAddress, szFunctionName);
- }
- VmmOb_DECREF(pObProcess);
- return vaFn;
-}
-
-ULONG64 VMMDLL_ProcessGetProcAddress(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szFunctionName)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM_RETURN(
- STATISTICS_ID_VMMDLL_ProcessGetIAT,
- ULONG64,
- 0,
- VMMDLL_ProcessGetProcAddress_Impl(dwPID, szModuleName, szFunctionName))
-}
-
-ULONG64 VMMDLL_ProcessGetModuleBase_Impl(_In_ DWORD dwPID, _In_ LPSTR szModuleName)
-{
- QWORD vaModuleBase = 0;
- VMMDLL_MODULEMAP_ENTRY oModuleEntry = { 0 };
- PVMM_PROCESS pObProcess = NULL;
- pObProcess = VmmProcessGet(dwPID);
- if(!pObProcess) { return 0; }
- if(VMMDLL_ProcessGetModuleFromName_Impl(dwPID, szModuleName, &oModuleEntry)) {
- vaModuleBase = oModuleEntry.BaseAddress;
- }
- VmmOb_DECREF(pObProcess);
- return vaModuleBase;
-}
-
-ULONG64 VMMDLL_ProcessGetModuleBase(_In_ DWORD dwPID, _In_ LPSTR szModuleName)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM_RETURN(
- STATISTICS_ID_VMMDLL_ProcessGetModuleBase,
- ULONG64,
- 0,
- VMMDLL_ProcessGetModuleBase_Impl(dwPID, szModuleName))
-}
-
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoEAT_Impl(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szExportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_EAT pThunkInfoEAT)
-{
- BOOL result;
- VMMDLL_MODULEMAP_ENTRY oModuleEntry = { 0 };
- PVMM_PROCESS pObProcess = NULL;
- pObProcess = VmmProcessGet(dwPID);
- if(!pObProcess) { return 0; }
- if(VMMDLL_ProcessGetModuleFromName_Impl(dwPID, szModuleName, &oModuleEntry)) {
- result = PE_GetThunkInfoEAT(pObProcess, oModuleEntry.BaseAddress, szExportFunctionName, (PPE_THUNKINFO_EAT)pThunkInfoEAT);
- }
- VmmOb_DECREF(pObProcess);
- return result;
-}
-
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoEAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szExportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_EAT pThunkInfoEAT)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_WinGetThunkEAT,
- VMMDLL_WinGetThunkInfoEAT_Impl(dwPID, szModuleName, szExportFunctionName, pThunkInfoEAT))
-}
-
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoIAT_Impl(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szImportModuleName, _In_ LPSTR szImportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_IAT pThunkInfoIAT)
-{
- BOOL result = FALSE;
- VMMDLL_MODULEMAP_ENTRY oModuleEntry = { 0 };
- PVMM_PROCESS pObProcess = NULL;
- if(sizeof(VMMDLL_WIN_THUNKINFO_IAT) != sizeof(PE_THUNKINFO_IAT)) { return FALSE; }
- pObProcess = VmmProcessGet(dwPID);
- if(!pObProcess) { return 0; }
- if(VMMDLL_ProcessGetModuleFromName_Impl(dwPID, szModuleName, &oModuleEntry)) {
- result = PE_GetThunkInfoIAT(pObProcess, oModuleEntry.BaseAddress, szImportModuleName, szImportFunctionName, (PPE_THUNKINFO_IAT)pThunkInfoIAT);
- }
- VmmOb_DECREF(pObProcess);
- return result;
-}
-
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoIAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szImportModuleName, _In_ LPSTR szImportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_IAT pThunkInfoIAT)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_WinGetThunkIAT,
- VMMDLL_WinGetThunkInfoIAT_Impl(dwPID, szModuleName, szImportModuleName, szImportFunctionName, pThunkInfoIAT))
-}
-
-_Success_(return)
-BOOL VMMDLL_WinMemCompression_DecompressPage(_In_ ULONG64 vaCompressedData, _In_opt_ DWORD cbCompressedData, _Out_writes_(4096) PBYTE pbDecompressedPage, _Out_opt_ PDWORD pcbCompressedData)
-{
- CALL_SYNCHRONIZED_IMPLEMENTATION_VMM(
- STATISTICS_ID_VMMDLL_WinMemCompression_DecompressPage,
- MmX64WinPaged_MemCompression_DecompressPage(vaCompressedData, cbCompressedData, pbDecompressedPage, pcbCompressedData))
-}
-
-_Success_(return)
-BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz)
-{
- return Util_FillHexAscii(pb, cb, cbInitialOffset, sz, pcsz);
-}
diff --git a/vmm/vmmdll.def b/vmm/vmmdll.def
deleted file mode 100644
index ce972b7..0000000
--- a/vmm/vmmdll.def
+++ /dev/null
@@ -1,50 +0,0 @@
-LIBRARY VMM
-EXPORTS
- VMMDLL_Initialize
- VMMDLL_Close
- VMMDLL_Refresh
-
- VMMDLL_ConfigGet
- VMMDLL_ConfigSet
-
- VMMDLL_VfsList
- VMMDLL_VfsRead
- VMMDLL_VfsWrite
-
- VMMDLL_UtilVfsReadFile_FromPBYTE
- VMMDLL_UtilVfsReadFile_FromQWORD
- VMMDLL_UtilVfsReadFile_FromDWORD
- VMMDLL_UtilVfsReadFile_FromBOOL
- VMMDLL_UtilVfsWriteFile_BOOL
- VMMDLL_UtilVfsWriteFile_DWORD
-
- VMMDLL_VfsInitializePlugins
-
- VMMDLL_MemReadScatter
- VMMDLL_MemReadPage
- VMMDLL_MemRead
- VMMDLL_MemReadEx
- VMMDLL_MemPrefetchPages
- VMMDLL_MemWrite
- VMMDLL_MemVirt2Phys
-
- VMMDLL_PidList
- VMMDLL_PidGetFromName
- VMMDLL_ProcessGetMemoryMap
- VMMDLL_ProcessGetMemoryMapEntry
- VMMDLL_ProcessGetModuleMap
- VMMDLL_ProcessGetModuleFromName
- VMMDLL_ProcessGetInformation
-
- VMMDLL_ProcessGetDirectories
- VMMDLL_ProcessGetSections
- VMMDLL_ProcessGetEAT
- VMMDLL_ProcessGetIAT
- VMMDLL_ProcessGetProcAddress
- VMMDLL_ProcessGetModuleBase
- VMMDLL_WinGetThunkInfoIAT
- VMMDLL_WinGetThunkInfoEAT
-
- VMMDLL_WinMemCompression_DecompressPage
-
- VMMDLL_UtilFillHexAscii
diff --git a/vmm/vmmdll.h b/vmm/vmmdll.h
deleted file mode 100644
index 6b1e71b..0000000
--- a/vmm/vmmdll.h
+++ /dev/null
@@ -1,656 +0,0 @@
-// vmmdll.h : header file to include in projects that use vmm.dll either as
-// stand anlone projects or as native plugins to vmm.dll.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 2.2
-//
-
-#include
-#include "leechcore.h"
-
-#ifndef __VMMDLL_H__
-#define __VMMDLL_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// INITIALIZATION FUNCTIONALITY BELOW:
-// Choose one way of initialzing the VMM / Memory Process File System.
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize VMM.DLL with command line parameters. For a more detailed info
-* about the parameters please see github wiki for Memory Process File System
-* and LeechCore. THIS IS THE PREFERED WAY OF INITIALIZING VMM.DLL
-* Important parameters are:
-* -printf = show printf style outputs)
-* -v -vv -vvv = extra verbosity levels)
-* -device = device as on format for LeechCore - please see leechcore.h or
-* Github documentation for additional information. Some values
-* are: , fpga, usb3380, hvsavedstate, totalmeltdown, pmem
-* -remote = remote LeechCore instance - please see leechcore.h or Github
-* documentation for additional information.
-* -norefresh = disable background refreshes (even if backing memory is
-* volatile memory).
-* -- argc
-* -- argv
-* -- return = success/fail
-*/
-_Success_(return)
-BOOL VMMDLL_Initialize(_In_ DWORD argc, _In_ LPSTR argv[]);
-
-/*
-* Close an initialized instance of VMM.DLL and clean up all allocated resources
-* including plugins, linked PCILeech.DLL and other memory resources.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_Close();
-
-/*
-* Perform a force refresh of all internal caches including:
-* - process listings
-* - memory cache
-* - page table cache
-* WARNING: function may take some time to execute!
-* -- dwReserved = reserved future use - must be zero
-* -- return = sucess/fail
-*/
-_Success_(return)
-BOOL VMMDLL_Refresh(_In_ DWORD dwReserved);
-
-
-//-----------------------------------------------------------------------------
-// CONFIGURATION SETTINGS BELOW:
-// Configure the memory process file system or the underlying memory
-// acquisition devices.
-//-----------------------------------------------------------------------------
-
-/*
-* Options used together with the functions: VMMDLL_GetOption & VMMDLL_SetOption
-* Options are defined with either: VMMDLL_OPT_* in this header file or as
-* MEMDEVICE_OPT_* in memdevice.h
-* For more detailed information check the sources for individual device types.
-*/
-#define VMMDLL_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define VMMDLL_OPT_CORE_VERBOSE 0x80000002 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
-#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
-#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
-#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
-
-#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
-#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
-#define VMMDLL_OPT_CONFIG_READCACHE_TICKS 0x40000003 // RW - memory cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_TLBCACHE_TICKS 0x40000004 // RW - page table (tlb) cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_PARTIAL 0x40000005 // RW - process refresh (partial) period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_TOTAL 0x40000006 // RW - process refresh (full) period (in ticks)
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MAJOR 0x40000007 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MINOR 0x40000008 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
-#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
-
-static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
-
-typedef enum tdVMMDLL_MEMORYMODEL_TP {
- VMMDLL_MEMORYMODEL_NA = 0,
- VMMDLL_MEMORYMODEL_X86 = 1,
- VMMDLL_MEMORYMODEL_X86PAE = 2,
- VMMDLL_MEMORYMODEL_X64 = 3
-} VMMDLL_MEMORYMODEL_TP;
-
-typedef enum tdVMMDLL_SYSTEM_TP {
- VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
- VMMDLL_SYSTEM_WINDOWS_X64 = 2,
- VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
- VMMDLL_SYSTEM_WINDOWS_X86 = 4
-} VMMDLL_SYSTEM_TP;
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- pqwValue = pointer to ULONG64 to receive option value.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- qwValue
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// VFS - VIRTUAL FILE SYSTEM FUNCTIONALITY BELOW:
-// This is the core of the memory process file system. All implementation and
-// analysis towards the file system is possible by using functionality below.
-//-----------------------------------------------------------------------------
-
-#define VMMDLL_STATUS_SUCCESS ((NTSTATUS)0x00000000L)
-#define VMMDLL_STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
-#define VMMDLL_STATUS_END_OF_FILE ((NTSTATUS)0xC0000011L)
-#define VMMDLL_STATUS_FILE_INVALID ((NTSTATUS)0xC0000098L)
-#define VMMDLL_STATUS_FILE_SYSTEM_LIMITATION ((NTSTATUS)0xC0000427L)
-
-typedef struct tdVMMDLL_VFS_FILELIST {
- VOID(*pfnAddFile) (_Inout_ HANDLE h, _In_ LPSTR szName, _In_ ULONG64 cb, _In_ PVOID pvReserved);
- VOID(*pfnAddDirectory)(_Inout_ HANDLE h, _In_ LPSTR szName, _In_ PVOID pvReserved);
- HANDLE h;
-} VMMDLL_VFS_FILELIST, *PVMMDLL_VFS_FILELIST;
-
-/*
-* Helper function macros for callbacks into the VMM_VFS_FILELIST structure.
-*/
-#define VMMDLL_VfsList_AddFile(pFileList, szName, cb) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddFile(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, cb, NULL); }
-#define VMMDLL_VfsList_AddDirectory(pFileList, szName) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddDirectory(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, NULL); }
-
-/*
-* List a directory of files in the memory process file system. Directories and
-* files will be listed by callbacks into functions supplied in the pFileList
-* parameter. If information of an individual file is needed it's neccessary
-* to list all files in its directory.
-* -- wcsPath
-* -- pFileList
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
-
-/*
-* Read select parts of a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbRead
-* -- cbOffset
-* -- return
-*
-*/
-NTSTATUS VMMDLL_VfsRead(_In_ LPCWSTR wcsFileName, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-
-/*
-* Write select parts to a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbWrite
-* -- cbOffset
-* -- return
-*/
-NTSTATUS VMMDLL_VfsWrite(_In_ LPCWSTR wcsFileName, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-
-/*
-* Utility functions for memory process file system read/write towards different
-* underlying data representations.
-*/
-NTSTATUS VMMDLL_UtilVfsReadFile_FromPBYTE(_In_ PBYTE pbFile, _In_ ULONG64 cbFile, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromQWORD(_In_ ULONG64 qwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromDWORD(_In_ DWORD dwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromBOOL(_In_ BOOL fValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_BOOL(_Inout_ PBOOL pfTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset, _In_ DWORD dwMinAllow);
-
-
-//-----------------------------------------------------------------------------
-// PLUGIN MANAGER FUNCTIONALITY BELOW:
-// Function and structures to initialize and use the memory process file system
-// plugin functionality. The plugin manager is started by a call to function:
-// VMM_VfsInitializePlugins. Each built-in plugin and external plugin of which
-// the DLL name matches m_*.dll will receive a call to its InitializeVmmPlugin
-// function. The plugin/module may decide to call pfnPluginManager_Register to
-// register plugins in the form of different names one or more times.
-// Example of registration function in a plugin DLL below:
-// 'VOID InitializeVmmPlugin(_In_ PVMM_PLUGIN_REGINFO pRegInfo)'
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize all potential plugins, both built-in and external, that maps into
-* the memory process file system. Please note that plugins are not loaded by
-* default - they have to be explicitly loaded by calling this function. They
-* will be unloaded on a general close of the vmm dll.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsInitializePlugins();
-
-#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
-#define VMMDLL_PLUGIN_CONTEXT_VERSION 2
-#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
-#define VMMDLL_PLUGIN_REGINFO_VERSION 3
-
-#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
-
-typedef struct tdVMMDLL_PLUGIN_CONTEXT {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- DWORD dwPID;
- PVOID pProcess;
- LPSTR szModule;
- LPSTR szPath;
- PVOID pvReserved1;
- PVOID pvReserved2;
-} VMMDLL_PLUGIN_CONTEXT, *PVMMDLL_PLUGIN_CONTEXT;
-
-typedef struct tdVMMDLL_PLUGIN_REGINFO {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel;
- VMMDLL_SYSTEM_TP tpSystem;
- HMODULE hDLL;
- HMODULE hReservedDll; // not for general use (only used for python).
- BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
- PVOID pvReserved1;
- PVOID pvReserved2;
- // general plugin registration info to be filled out by the plugin below:
- struct {
- CHAR szModuleName[32];
- BOOL fRootModule;
- BOOL fProcessModule;
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_info;
- // function plugin registration info to be filled out by the plugin below:
- struct {
- BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
- NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
- NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
- VOID(*pfnNotify)(_In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
- VOID(*pfnClose)();
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_fn;
-} VMMDLL_PLUGIN_REGINFO, *PVMMDLL_PLUGIN_REGINFO;
-
-//-----------------------------------------------------------------------------
-// VMM CORE FUNCTIONALITY BELOW:
-// Vmm core functaionlity such as read (and write) to both virtual and physical
-// memory. NB! writing will only work if the target is supported - i.e. not a
-// memory dump file...
-// To read physical memory specify dwPID as (DWORD)-1
-//-----------------------------------------------------------------------------
-
-// FLAG used to supress the default read cache in calls to VMM_MemReadEx()
-// which will lead to the read being fetched from the target system always.
-// Cached page tables (used for translating virtual2physical) are still used.
-#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
-#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
-
-/*
-* Read memory in various non-contigious locations specified by the pointers to
-* the items in the ppDMAs array. Result for each unit of work will be given
-* individually. No upper limit of number of items to read, but no performance
-* boost will be given if above hardware limit. Max size of each unit of work is
-* one 4k page (4096 bytes).
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-* -- pcpDMAsRead = optional count of number of successfully read ppDMAs.
-* -- flags = optional flags as given by VMMDLL_FLAG_*
-* -- return = the number of successfully read items.
-*/
-DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs, _In_ DWORD flags);
-
-/*
-* Read a single 4096-byte page of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pbPage
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
-
-/*
-* Read a contigious arbitrary amount of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Read a contigious amount of memory and report the number of bytes read in pcbRead.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- pcbRead
-* -- flags = flags as in VMMDLL_FLAG_*
-* -- return = success/fail. NB! reads may report as success even if 0 bytes are
-* read - it's recommended to verify pcbReadOpt parameter.
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
-
-/*
-* Prefetch a number of addresses (specified in the pA array) into the memory
-* cache. This function is to be used to batch larger known reads into local
-* cache before making multiple smaller reads - which will then happen from
-* the cache. Function exists for performance reasons.
-* -- dwPID = PID of target process, (DWORD)-1 for physical memory.
-* -- pPrefetchAddresses = array of addresses to read into cache.
-* -- cPrefetchAddresses
-*/
-_Success_(return)
-BOOL VMMDLL_MemPrefetchPages(_In_ DWORD dwPID, _In_reads_(cPrefetchAddresses) PULONG64 pPrefetchAddresses, _In_ DWORD cPrefetchAddresses);
-
-/*
-* Write a contigious arbitrary amount of memory. Please note some virtual memory
-* such as pages of executables (such as DLLs) may be shared between different
-* virtual memory over different processes. As an example a write to kernel32.dll
-* in one process is likely to affect kernel32 in the whole system - in all
-* processes. Heaps and Stacks and other memory are usually safe to write to.
-* Please take care when writing to memory!
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = TRUE on success, FALSE on partial or zero write.
-*/
-_Success_(return)
-BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Translate a virtual address to a physical address by walking the page tables
-* of the specified process.
-* -- dwPID
-* -- qwVA
-* -- pqwPA
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
-
-
-
-//-----------------------------------------------------------------------------
-// VMM PROCESS FUNCTIONALITY BELOW:
-// Functionality below is mostly relating to Windows processes.
-//-----------------------------------------------------------------------------
-
-/*
-* Retrieve an active process given it's name. Please note that if multiple
-* processes with the same name exists only one will be returned. If required to
-* parse all processes with the same name please iterate over the PID list by
-* calling VMMDLL_PidList together with VMMDLL_ProcessGetInformation.
-* -- szProcName = process name (truncated max 15 chars) case insensitive.
-* -- pdwPID = pointer that will receive PID on success.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
-
-/*
-* List the PIDs in the system.
-* -- pPIDs = DWORD array of at least number of PIDs in system, or NULL.
-* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
-
-// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
-#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
-#define VMMDLL_MEMMAP_FLAG_PAGE_NS 0x0000000000000004
-#define VMMDLL_MEMMAP_FLAG_PAGE_NX 0x8000000000000000
-#define VMMDLL_MEMMAP_FLAG_PAGE_MASK 0x8000000000000006
-
-typedef struct tdVMMDLL_MEMMAP_ENTRY {
- ULONG64 AddrBase;
- ULONG64 cPages;
- ULONG64 fPage;
- BOOL fWoW64;
- CHAR szTag[32];
-} VMMDLL_MEMMAP_ENTRY, *PVMMDLL_MEMMAP_ENTRY;
-
-/*
-* Retrieve memory map entries from the specified process. Memory map entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries bytes.
-* If the pMemMapEntries is set to NULL the number of memory map entries will be
-* given in the pcMemMapEntries parameter.
-* -- dwPID
-* -- pMemMapEntries = buffer of minimum length sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries, or NULL.
-* -- pcMemMapEntries = pointer to number of memory map entries.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
-
-/*
-* Retrieve a single memory map entry given a virtual address within that entrys
-* range.
-* -- dwPID
-* -- pMemMapEntry
-* -- va = virtual address in the memory map entry to retrieve.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
-
-typedef struct tdVMMDLL_MODULEMAP_ENTRY {
- ULONG64 BaseAddress;
- ULONG64 EntryPoint;
- DWORD SizeOfImage;
- BOOL fWoW64;
- CHAR szName[32];
-} VMMDLL_MODULEMAP_ENTRY, *PVMMDLL_MODULEMAP_ENTRY;
-
-/*
-* Retrieve the module entries from the specified process. The module entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries bytes long. If the
-* pcModuleEntries is set to NULL the number of module entries will be given
-* in the pcModuleEntries parameter.
-* -- dwPID
-* -- pModuleEntries = buffer of minimum length sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries, or NULL.
-* -- pcModuleEntries = pointer to number of memory map entries.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
-
-/*
-* Retrieve a module (.exe or .dll or similar) given a module name.
-* -- dwPID
-* -- szModuleName
-* -- pModuleEntry
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
-
-#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
-#define VMMDLL_PROCESS_INFORMATION_VERSION 2
-
-typedef struct tdVMMDLL_PROCESS_INFORMATION {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
- VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
- BOOL fUserOnly; // only user mode pages listed
- DWORD dwPID;
- DWORD dwState;
- CHAR szName[16];
- ULONG64 paDTB;
- ULONG64 paDTB_UserOpt; // may not exist
- union {
- struct {
- ULONG64 vaEPROCESS;
- ULONG64 vaPEB;
- ULONG64 vaENTRY;
- BOOL fWow64;
- DWORD vaPEB32; // WoW64 only
- } win;
- } os;
-} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
-
-/*
-* Retrieve various process information from a PID. Process information such as
-* name, page directory bases and the process state may be retrieved.
-* -- dwPID
-* -- pProcessInformation = if null, size is given in *pcbProcessInfo
-* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
-
-typedef struct tdVMMDLL_EAT_ENTRY {
- ULONG64 vaFunction;
- DWORD vaFunctionOffset;
- CHAR szFunction[40];
-} VMMDLL_EAT_ENTRY, *PVMMDLL_EAT_ENTRY;
-
-typedef struct tdVMMDLL_IAT_ENTRY {
- ULONG64 vaFunction;
- CHAR szFunction[40];
- CHAR szModule[64];
-} VMMDLL_IAT_ENTRY, *PVMMDLL_IAT_ENTRY;
-
-/*
-* Retrieve information about: Data Directories, Sections, Export Address Table
-* and Import Address Table (IAT).
-* If the pData == NULL upon entry the number of entries of the pData array must
-* have in order to be able to hold the data is returned.
-* -- dwPID
-* -- szModule
-* -- pData
-* -- cData
-* -- pcData
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-
-/*
-* Retrieve the virtual address of a given function inside a process/module.
-* -- dwPID
-* -- szModuleName
-* -- szFunctionName
-* -- return = virtual address of function, zero on fail.
-*/
-ULONG64 VMMDLL_ProcessGetProcAddress(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szFunctionName);
-
-/*
-* Retrieve the base address of a given module.
-* -- dwPID
-* -- szModuleName
-* -- return = virtual address of module base, zero on fail.
-*/
-ULONG64 VMMDLL_ProcessGetModuleBase(_In_ DWORD dwPID, _In_ LPSTR szModuleName);
-
-
-
-//-----------------------------------------------------------------------------
-// WINDOWS SPECIFIC UTILITY FUNCTIONS BELOW:
-//-----------------------------------------------------------------------------
-
-typedef struct tdVMMDLL_WIN_THUNKINFO_IAT {
- BOOL fValid;
- BOOL f32; // if TRUE fn is a 32-bit/4-byte entry, otherwise 64-bit/8-byte entry.
- ULONG64 vaThunk; // address of import address table 'thunk'.
- ULONG64 vaFunction; // value if import address table 'thunk' == address of imported function.
- ULONG64 vaNameModule; // address of name string for imported module.
- ULONG64 vaNameFunction; // address of name string for imported function.
-} VMMDLL_WIN_THUNKINFO_IAT, *PVMMDLL_WIN_THUNKINFO_IAT;
-
-typedef struct tdVMMDLL_WIN_THUNKINFO_EAT {
- BOOL fValid;
- DWORD valueThunk; // value of export address table 'thunk'.
- ULONG64 vaThunk; // address of import address table 'thunk'.
- ULONG64 vaNameFunction; // address of name string for exported function.
- ULONG64 vaFunction; // address of exported function (module base + value parameter).
-} VMMDLL_WIN_THUNKINFO_EAT, *PVMMDLL_WIN_THUNKINFO_EAT;
-
-/*
-* Retrieve information about the import address table IAT thunk for an imported
-* function. This includes the virtual address of the IAT thunk which is useful
-* for hooking.
-* -- dwPID
-* -- szModuleName
-* -- szImportModuleName
-* -- szImportFunctionName
-* -- pThunkIAT
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoIAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szImportModuleName, _In_ LPSTR szImportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_IAT pThunkInfoIAT);
-
-/*
-* Retrieve information about the export address table EAT thunk for an exported
-* function. This includes the virtual address of the EAT thunk which is useful
-* for hooking.
-* -- dwPID
-* -- szModuleName
-* -- pThunkEAT
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoEAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szExportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_EAT pThunkInfoEAT);
-
-/*
-* Decompress compressed memory page stored in the MemCompression process.
-* -- vaCompressedData = virtual address in 'MemCompression' to decompress.
-* -- cbCompressedData = length of compressed data in 'MemCompression' to decompress (or zero for auto-detect).
-* -- pbDecompressedPage
-* -- pcbCompressedData = optional ptr to receive length of compressed buffer.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinMemCompression_DecompressPage(
- _In_ ULONG64 vaCompressedData,
- _In_opt_ DWORD cbCompressedData,
- _Out_writes_(4096) PBYTE pbDecompressedPage,
- _Out_opt_ PDWORD pcbCompressedData
-);
-
-
-//-----------------------------------------------------------------------------
-// VMM UTIL FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-/*
-* Fill a human readable hex ascii memory dump into the caller supplied sz buffer.
-* -- pb
-* -- cb
-* -- cbInitialOffset = offset, must be max 0x1000 and multiple of 0x10.
-* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
-* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
-*/
-_Success_(return)
-BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __VMMDLL_H__ */
diff --git a/vmm/vmmproc.c b/vmm/vmmproc.c
deleted file mode 100644
index 5c35a74..0000000
--- a/vmm/vmmproc.c
+++ /dev/null
@@ -1,284 +0,0 @@
-// vfsproc.c : implementation of functions related to operating system and process parsing of virtual memory.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-
-#include "vmmproc.h"
-#include "vmmwin.h"
-#include "vmmwininit.h"
-#include "statistics.h"
-#include "util.h"
-
-// ----------------------------------------------------------------------------
-// GENERIC PROCESS RELATED FUNCTIONALITY BELOW:
-// ----------------------------------------------------------------------------
-
-/*
-* Try initialize from user supplied CR3/PML4 supplied in parameter at startup.
-* -- ctx
-* -- return
-*/
-BOOL VmmProcUserCR3TryInitialize64()
-{
- PVMM_PROCESS pObProcess;
- VmmInitializeMemoryModel(VMM_MEMORYMODEL_X64);
- pObProcess = VmmProcessCreateEntry(TRUE, 0, 0, ctxMain->cfg.paCR3, 0, "unknown_process", FALSE);
- VmmProcessCreateFinish();
- if(!pObProcess) {
- vmmprintfv("VmmProc: FAIL: Initialization of Process failed from user-defined CR3 %016llx.\n", ctxMain->cfg.paCR3);
- VmmInitializeMemoryModel(VMM_MEMORYMODEL_NA);
- return FALSE;
- }
- VmmTlbSpider(pObProcess);
- VmmOb_DECREF(pObProcess);
- ctxVmm->tpSystem = VMM_SYSTEM_UNKNOWN_X64;
- ctxVmm->kernel.paDTB = ctxMain->cfg.paCR3;
- return TRUE;
-}
-
-BOOL VmmProc_RefreshProcesses(_In_ BOOL fRefreshTotal)
-{
- BOOL result;
- PVMM_PROCESS pObProcessSystem;
- // statistic count
- if(!fRefreshTotal) { InterlockedIncrement64(&ctxVmm->stat.cRefreshProcessPartial); }
- if(fRefreshTotal) { InterlockedIncrement64(&ctxVmm->stat.cRefreshProcessFull); }
- // Single user-defined X64 process
- if(fRefreshTotal) {
- if(ctxVmm->tpSystem == VMM_SYSTEM_UNKNOWN_X64) {
- VmmProcUserCR3TryInitialize64();
- }
- }
- // Windows OS
- if((ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) || (ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86)) {
- vmmprintfvv_fn("ProcessRefresh: %s\n", (fRefreshTotal ? "Total" : "Partial"));
- pObProcessSystem = VmmProcessGet(4);
- if(!pObProcessSystem) {
- vmmprintf_fn("FAIL - SYSTEM PROCESS NOT FOUND - SHOULD NOT HAPPEN\n");
- return FALSE;
- }
- result = VmmWin_EnumerateEPROCESS(pObProcessSystem, fRefreshTotal);
- VmmOb_DECREF(pObProcessSystem);
- }
- return TRUE;
-}
-
-// Initial hard coded values that seems to be working nicely below. These values
-// may be changed in config options or by editing files in the .status directory.
-
-#define VMMPROC_UPDATERTHREAD_LOCAL_PERIOD 100
-#define VMMPROC_UPDATERTHREAD_LOCAL_PHYSCACHE (500 / VMMPROC_UPDATERTHREAD_LOCAL_PERIOD) // 0.5s
-#define VMMPROC_UPDATERTHREAD_LOCAL_TLB (5 * 1000 / VMMPROC_UPDATERTHREAD_LOCAL_PERIOD) // 5s
-#define VMMPROC_UPDATERTHREAD_LOCAL_PROC_REFRESHLIST (5 * 1000 / VMMPROC_UPDATERTHREAD_LOCAL_PERIOD) // 5s
-#define VMMPROC_UPDATERTHREAD_LOCAL_PROC_REFRESHTOTAL (15 * 1000 / VMMPROC_UPDATERTHREAD_LOCAL_PERIOD) // 15s
-
-#define VMMPROC_UPDATERTHREAD_REMOTE_PERIOD 100
-#define VMMPROC_UPDATERTHREAD_REMOTE_PHYSCACHE (15 * 1000 / VMMPROC_UPDATERTHREAD_REMOTE_PERIOD) // 15s
-#define VMMPROC_UPDATERTHREAD_REMOTE_TLB (3 * 60 * 1000 / VMMPROC_UPDATERTHREAD_REMOTE_PERIOD) // 3m
-#define VMMPROC_UPDATERTHREAD_REMOTE_PROC_REFRESHLIST (15 * 1000 / VMMPROC_UPDATERTHREAD_REMOTE_PERIOD) // 15s
-#define VMMPROC_UPDATERTHREAD_REMOTE_PROC_REFRESHTOTAL (3 * 60 * 1000 / VMMPROC_UPDATERTHREAD_REMOTE_PERIOD) // 3m
-
-DWORD VmmProcCacheUpdaterThread()
-{
- QWORD i = 0, paMax;
- BOOL fPHYS, fTLB, fProcPartial, fProcTotal;
- vmmprintfv("VmmProc: Start periodic cache flushing.\n");
- if(ctxMain->dev.fRemote) {
- ctxVmm->ThreadProcCache.cMs_TickPeriod = VMMPROC_UPDATERTHREAD_REMOTE_PERIOD;
- ctxVmm->ThreadProcCache.cTick_Phys = VMMPROC_UPDATERTHREAD_REMOTE_PHYSCACHE;
- ctxVmm->ThreadProcCache.cTick_TLB = VMMPROC_UPDATERTHREAD_REMOTE_TLB;
- ctxVmm->ThreadProcCache.cTick_ProcPartial = VMMPROC_UPDATERTHREAD_REMOTE_PROC_REFRESHLIST;
- ctxVmm->ThreadProcCache.cTick_ProcTotal = VMMPROC_UPDATERTHREAD_REMOTE_PROC_REFRESHTOTAL;
- } else {
- ctxVmm->ThreadProcCache.cMs_TickPeriod = VMMPROC_UPDATERTHREAD_LOCAL_PERIOD;
- ctxVmm->ThreadProcCache.cTick_Phys = VMMPROC_UPDATERTHREAD_LOCAL_PHYSCACHE;
- ctxVmm->ThreadProcCache.cTick_TLB = VMMPROC_UPDATERTHREAD_LOCAL_TLB;
- ctxVmm->ThreadProcCache.cTick_ProcPartial = VMMPROC_UPDATERTHREAD_LOCAL_PROC_REFRESHLIST;
- ctxVmm->ThreadProcCache.cTick_ProcTotal = VMMPROC_UPDATERTHREAD_LOCAL_PROC_REFRESHTOTAL;
- }
- while(ctxVmm->ThreadProcCache.fEnabled) {
- Sleep(ctxVmm->ThreadProcCache.cMs_TickPeriod);
- i++;
- fTLB = !(i % ctxVmm->ThreadProcCache.cTick_TLB);
- fPHYS = !(i % ctxVmm->ThreadProcCache.cTick_Phys);
- fProcTotal = !(i % ctxVmm->ThreadProcCache.cTick_ProcTotal);
- fProcPartial = !(i % ctxVmm->ThreadProcCache.cTick_ProcPartial) && !fProcTotal;
- EnterCriticalSection(&ctxVmm->MasterLock);
- // PHYS / TLB cache clear
- if(fPHYS) {
- VmmCacheClear(VMM_CACHE_TAG_PHYS);
- InterlockedIncrement64(&ctxVmm->stat.cRefreshPhys);
- }
- if(fTLB) {
- VmmCacheClear(VMM_CACHE_TAG_TLB);
- InterlockedIncrement64(&ctxVmm->stat.cRefreshTlb);
- }
- // refresh proc list
- if(fProcPartial || fProcTotal) {
- if(!VmmProc_RefreshProcesses(fProcTotal)) {
- vmmprintf("VmmProc: Failed to refresh memory process file system - aborting.\n");
- LeaveCriticalSection(&ctxVmm->MasterLock);
- goto fail;
- }
- // update max physical address (if volatile).
- if(ctxMain->dev.fVolatileMaxAddress) {
- if(LeechCore_GetOption(LEECHCORE_OPT_MEMORYINFO_ADDR_MAX, &paMax) && (paMax > 0x01000000)) {
- ctxMain->dev.paMax = paMax;
- }
- }
- }
- LeaveCriticalSection(&ctxVmm->MasterLock);
- }
-fail:
- vmmprintfv("VmmProc: Exit periodic cache flushing.\n");
- ctxVmm->ThreadProcCache.hThread = NULL;
- return 0;
-}
-
-VOID VmmProc_ModuleMapInitialize(_In_ PVMM_PROCESS pProcess)
-{
- if((ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) || (ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86)) {
- VmmTlbSpider(pProcess);
- VmmWin_ModuleMapInitialize(pProcess);
- }
-}
-
-_Success_(return)
-BOOL VmmProc_ModuleMapGet(_In_ PVMM_PROCESS pProcess, _Out_ PVMMOB_MODULEMAP *ppObModuleMap)
-{
- if(!pProcess->pObModuleMap) {
- VmmProc_ModuleMapInitialize(pProcess);
- }
- if(pProcess->pObModuleMap && pProcess->pObModuleMap->fValid) {
- *ppObModuleMap = VmmOb_INCREF(pProcess->pObModuleMap);
- return TRUE;
- }
- return FALSE;
-}
-
-VOID VmmProc_ScanTagsMemMap(_In_ PVMM_PROCESS pProcess)
-{
- if((ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) || (ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86)) {
- VmmWin_ScanTagsMemMap(pProcess);
- }
-}
-
-BOOL VmmProcInitialize()
-{
- BOOL result = FALSE;
- if(!VmmInitialize()) { return FALSE; }
- // 1: try initialize 'windows' with an optionally supplied CR3
- result = VmmWinInit_TryInitialize(ctxMain->cfg.paCR3);
- if(!result) {
- result = ctxMain->cfg.paCR3 && VmmProcUserCR3TryInitialize64();
- if(!result) {
- vmmprintf(
- "VmmProc: Unable to auto-identify operating system for PROC file system mount. \n" \
- " Please specify PageDirectoryBase (DTB/CR3) in the -cr3 option if value \n" \
- " is known. If unknown it may be recoverable with command 'identify'. \n");
- }
- }
- // set up cache maintenance in the form of a separate worker thread in case
- // the backend is a writeable device (FPGA). If the underlying device isn't
- // volatile then there is no need to update! NB! Files are not considered
- // to be volatile.
- if(result && ctxMain->dev.fVolatile && !ctxMain->cfg.fDisableBackgroundRefresh) {
- ctxVmm->ThreadProcCache.fEnabled = TRUE;
- ctxVmm->ThreadProcCache.hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)VmmProcCacheUpdaterThread, ctxVmm, 0, NULL);
- if(!ctxVmm->ThreadProcCache.hThread) { ctxVmm->ThreadProcCache.fEnabled = FALSE; }
- }
- return result;
-}
-
-// ----------------------------------------------------------------------------
-// SCAN/SEARCH TO IDENTIFY IMAGE:
-// - Currently Windows PageDirectoryBase/CR3/PML4 detection is supported only
-// ----------------------------------------------------------------------------
-
-_Success_(return)
-BOOL VmmProcPHYS_VerifyWindowsEPROCESS(_In_ PBYTE pb, _In_ QWORD cb, _In_ QWORD cbOffset, _Out_ PQWORD ppaPML4)
-{
- QWORD i;
- if(cb < cbOffset + 8) { return FALSE; }
- if((cb & 0x07) || (cb < 0x500) || (cbOffset < 0x500)) { return FALSE; }
- if(*(PQWORD)(pb + cbOffset) != 0x00006D6574737953) { return FALSE; } // not matching System00
- if(*(PQWORD)(pb + cbOffset + 8) & 0x00ffffffffffffff) { return FALSE; } // not matching 0000000
- // maybe we have EPROCESS struct here, scan back to see if we can find
- // 4 kernel addresses in a row and a potential PML4 after that and zero
- // DWORD before that. (EPROCESS HDR).
- for(i = cbOffset; i > cbOffset - 0x500; i -= 8) {
- if((*(PQWORD)(pb + i - 0x00) & 0xfffff00000000000)) { continue; }; // DirectoryTableBase
- if(!*(PQWORD)(pb + i - 0x00)) { continue; }; // DirectoryTableBase
- if((*(PQWORD)(pb + i - 0x08) & 0xffff800000000000) != 0xffff800000000000) { continue; }; // PTR
- if((*(PQWORD)(pb + i - 0x10) & 0xffff800000000000) != 0xffff800000000000) { continue; }; // PTR
- if((*(PQWORD)(pb + i - 0x18) & 0xffff800000000000) != 0xffff800000000000) { continue; }; // PTR
- if((*(PQWORD)(pb + i - 0x20) & 0xffff800000000000) != 0xffff800000000000) { continue; }; // PTR
- if((*(PDWORD)(pb + i - 0x24) != 0x00000000)) { continue; }; // SignalState
- *ppaPML4 = *(PQWORD)(pb + i - 0x00) & ~0xfff;
- return TRUE;
- }
- return FALSE;
-}
-
-_Success_(return)
-BOOL VmmProcPHYS_ScanForKernel(_Out_ PQWORD ppaPML4, _In_ QWORD paBase, _In_ QWORD paMax, _In_ LPSTR szDescription)
-{
- QWORD o, i, paCurrent;
- PBYTE pbBuffer8M = NULL;
- PPAGE_STATISTICS pPageStat = NULL;
- LEECHCORE_PAGESTAT_MINIMAL PageStatMinimal;
- BOOL result;
- // initialize / allocate memory
- paCurrent = paBase;
- if(!(pbBuffer8M = LocalAlloc(0, 0x800000))) { goto fail; }
- if(!PageStatInitialize(&pPageStat, paCurrent, paMax, szDescription, FALSE, FALSE)) { goto fail; }
- PageStatMinimal.h = (HANDLE)pPageStat;
- PageStatMinimal.pfnPageStatUpdate = PageStatUpdate;
- // loop kmd-find
- for(; paCurrent < paMax; paCurrent += 0x00800000) {
- if(!LeechCore_ReadEx(paCurrent, pbBuffer8M, 0x00800000, 0, &PageStatMinimal)) { continue; }
- for(o = 0; o < 0x00800000; o += 0x1000) {
- // Scan for windows EPROCESS (to get DirectoryBase/PML4)
- for(i = 0; i < 0x1000; i += 8) {
- if(*(PQWORD)(pbBuffer8M + o + i) == 0x00006D6574737953) {
- result = VmmProcPHYS_VerifyWindowsEPROCESS(pbBuffer8M, 0x00800000, o + i, ppaPML4);
- if(result) {
- pPageStat->szAction = "Windows System PageDirectoryBase/PML4 located";
- PageStatClose(&pPageStat);
- LocalFree(pbBuffer8M);
- return TRUE;
- }
- }
- }
- }
- }
-fail:
- PageStatClose(&pPageStat);
- LocalFree(pbBuffer8M);
- *ppaPML4 = 0;
- return FALSE;
-}
-
-BOOL VmmProcIdentify()
-{
- QWORD paPML4;
- BOOL result = FALSE;
- vmmprintf(
- "IDENTIFY: Scanning to identify target operating system and page directories...\n"
- " Currently supported oprerating systems:\n"
- " - Windows (64-bit).\n");
- if(ctxMain->dev.paMax > 0x100000000) {
- result = VmmProcPHYS_ScanForKernel(&paPML4, 0x100000000, ctxMain->dev.paMax, "Scanning 4GB+ to Identify (1/2) ...");
- }
- if(!result) {
- result = VmmProcPHYS_ScanForKernel(&paPML4, 0x01000000, 0x100000000, "Scanning 0-4GB to Identify (2/2) ...");
- }
- if(result) {
- vmmprintf("IDENTIFY: Succeeded: Windows System page directory base is located at: 0x%llx\n", paPML4);
- ctxMain->cfg.paCR3 = paPML4;
- return TRUE;
- }
- vmmprintf("IDENTIFY: Failed. No fully supported operating system detected.\n");
- return FALSE;
-}
diff --git a/vmm/vmmproc.h b/vmm/vmmproc.h
deleted file mode 100644
index 2fbf814..0000000
--- a/vmm/vmmproc.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// vmmproc.h : definitions related to operating system and process parsing of virtual memory
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __VMMPROC_H__
-#define __VMMPROC_H__
-#include "vmm.h"
-
-/*
-* Force a refresh of the process list.
-* -- fRefreshTotal = full refresh of processes should be done instead of partial.
-* -- return
-*/
-BOOL VmmProc_RefreshProcesses(_In_ BOOL fRefreshTotal);
-
-/*
-* Load operating system dependant module names, such as parsed from PE or ELF
-* into the modules map.
-*/
-VOID VmmProc_ModuleMapInitialize(_In_ PVMM_PROCESS pProcess);
-
-/*
-* Retrieve the module map. Map is generated on-demand if not already existing.
-* CALLER DECREF: ppObModuleMap
-* -- pProcess
-* -- ppObModuleMap
-* -- return
-*/
-_Success_(return)
-BOOL VmmProc_ModuleMapGet(_In_ PVMM_PROCESS pProcess, _Out_ PVMMOB_MODULEMAP *ppObModuleMap);
-
-/*
-* Scan additional process information (not already in the initialized modulemap)
-* and put the result into the memory map.
-*/
-VOID VmmProc_ScanTagsMemMap(_In_ PVMM_PROCESS pProcess);
-
-/*
-* Tries to automatically identify the operating system given by the supplied
-* memory device (fpga hardware or file). If an operating system is successfully
-* identified a VMM_CONTEXT will be created and stored within the PCILEECH_CONTEXT.
-* If the VMM fails to identify an operating system FALSE is returned.
-* -- return
-*/
-BOOL VmmProcInitialize();
-
-/*
-* Scans the memory for supported operating system structures, such as Windows
-* page directory bases and update the ctxMain.cfg with the correct value upon
-* success.
-* -- return
-*/
-BOOL VmmProcIdentify();
-
-#endif /* __VMMPROC_H__ */
diff --git a/vmm/vmmvfs.c b/vmm/vmmvfs.c
deleted file mode 100644
index f787ce7..0000000
--- a/vmm/vmmvfs.c
+++ /dev/null
@@ -1,383 +0,0 @@
-// vmmvfs.c : implementation related to virtual memory management / virtual file system interfacing.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#include "vmm.h"
-#include "vmmdll.h"
-#include "pluginmanager.h"
-#include "vmmproc.h"
-#include "vmmwin.h"
-#include "util.h"
-
-typedef struct tdVMMVFS_PATH {
- CHAR _sz[MAX_PATH];
- BOOL fRoot;
- BOOL fNamePID;
- DWORD dwPID;
- LPSTR szPath1;
- LPSTR szPath2;
-} VMMVFS_PATH, *PVMMVFS_PATH;
-
-BOOL VmmVfs_UtilVmmGetPidDirFile(_In_ LPCWSTR wcsFileName, _Out_ PVMMVFS_PATH pPath)
-{
- DWORD i = 0, iPID, iPath1 = 0, iPath2 = 0;
- // 1: convert to ascii string
- ZeroMemory(pPath, sizeof(VMMVFS_PATH));
- while(TRUE) {
- if(i >= MAX_PATH) { return FALSE; }
- if(wcsFileName[i] > 255) { return FALSE; }
- pPath->_sz[i] = (CHAR)wcsFileName[i];
- if(wcsFileName[i] == 0) { break; }
- i++;
- }
- // 1: Check for root only item
- pPath->fNamePID = !_stricmp(pPath->_sz, "\\name");
- pPath->fRoot = pPath->fNamePID || !_stricmp(pPath->_sz, "\\pid");
- if(pPath->fRoot) { return TRUE; }
- // 2: Check if starting with PID or NAME and move start index
- if(!strncmp(pPath->_sz, "\\pid\\", 5)) { i = 5; }
- if(!strncmp(pPath->_sz, "\\name\\", 6)) { i = 6; }
- if(i == 0) { return FALSE; }
- // 3: Locate start of PID number and 1st Path item (if any)
- while((i < MAX_PATH) && pPath->_sz[i] && (pPath->_sz[i] != '\\')) { i++; }
- if(pPath->_sz[i]) { iPath1 = i + 1; }
- pPath->_sz[i] = 0;
- i--;
- while((i > 0) && (pPath->_sz[i] >= '0') && (pPath->_sz[i] <= '9')) { i--; }
- iPID = i + 1;
- pPath->dwPID = (DWORD)Util_GetNumeric(&pPath->_sz[iPID]);
- if(!iPath1) { return TRUE; }
- // 4: Locate 2nd Path item (if any)
- i = iPath1;
- while((i < MAX_PATH) && pPath->_sz[i] && (pPath->_sz[i] != '\\')) { i++; }
- if(pPath->_sz[i]) {
- iPath2 = i + 1;
- pPath->_sz[i] = 0;
- }
- // 7: Finish
- pPath->szPath1 = &pPath->_sz[iPath1];
- if(iPath2) {
- pPath->szPath2 = &pPath->_sz[iPath2];
- }
- return TRUE;
-}
-
-// ----------------------------------------------------------------------------
-// FUNCTIONALITY RELATED TO: READ
-// ----------------------------------------------------------------------------
-
-NTSTATUS VmmVfsReadFileProcess(_In_ PVMM_PROCESS pProcess, _In_ PVMMVFS_PATH pPath, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
-{
- NTSTATUS nt;
- BYTE pbBuffer[0x800];
- DWORD cbBuffer;
- PVMMOB_PDATA pObMemMapDisplay;
- PVMMOB_MODULEMAP pObModuleMap;
- ZeroMemory(pbBuffer, 48);
- // read memory from "vmem" file
- if(!_stricmp(pPath->szPath1, "vmem")) {
- if((ctxVmm->tpMemoryModel != VMM_MEMORYMODEL_X64) && (cbOffset + cb >= 0x100000000)) {
- if(cbOffset >= 0x100000000) { return VMM_STATUS_END_OF_FILE; }
- cb = (DWORD)(0x100000000 - cbOffset);
- }
- VmmReadEx(pProcess, cbOffset, pb, cb, NULL, 0);
- *pcbRead = cb;
- return VMM_STATUS_SUCCESS;
- }
- // read the memory map
- if(!_stricmp(pPath->szPath1, "map")) {
- if(!VmmMemMapGetDisplay(pProcess, VMM_MEMMAP_FLAG_ALL, &pObMemMapDisplay)) { return VMMDLL_STATUS_FILE_INVALID; }
- nt = Util_VfsReadFile_FromPBYTE(pObMemMapDisplay->pbData, pObMemMapDisplay->cbData, pb, cb, pcbRead, cbOffset);
- VmmOb_DECREF(pObMemMapDisplay);
- return nt;
- }
- // read genereal numeric values from files, pml4, pid, name, virt
- if(!_stricmp(pPath->szPath1, "dtb")) {
- if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X64) {
- return Util_VfsReadFile_FromQWORD(pProcess->paDTB, pb, cb, pcbRead, cbOffset, FALSE);
- } else if((ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86) || (ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86PAE)) {
- return Util_VfsReadFile_FromDWORD((DWORD)pProcess->paDTB, pb, cb, pcbRead, cbOffset, FALSE);
- }
- }
- if(!_stricmp(pPath->szPath1, "dtb-user")) {
- if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X64) {
- return Util_VfsReadFile_FromQWORD(pProcess->paDTB_UserOpt, pb, cb, pcbRead, cbOffset, FALSE);
- } else if((ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86) || (ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86PAE)) {
- return Util_VfsReadFile_FromDWORD((DWORD)pProcess->paDTB_UserOpt, pb, cb, pcbRead, cbOffset, FALSE);
- }
- }
- if(!_stricmp(pPath->szPath1, "pid")) {
- cbBuffer = snprintf(pbBuffer, 32, "%i", pProcess->dwPID);
- return Util_VfsReadFile_FromPBYTE(pbBuffer, cbBuffer, pb, cb, pcbRead, cbOffset);
- }
- if(!_stricmp(pPath->szPath1, "name")) {
- cbBuffer = snprintf(pbBuffer, 32, "%s", pProcess->szName);
- return Util_VfsReadFile_FromPBYTE(pbBuffer, cbBuffer, pb, cb, pcbRead, cbOffset);
- }
- // windows specific reads below:
- if(ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) {
- if(!_stricmp(pPath->szPath1, "win-eprocess")) {
- return Util_VfsReadFile_FromQWORD(pProcess->os.win.vaEPROCESS, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(pPath->szPath1, "win-entry")) {
- return Util_VfsReadFile_FromQWORD(pProcess->os.win.vaENTRY, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(pPath->szPath1, "win-peb")) {
- return Util_VfsReadFile_FromQWORD(pProcess->os.win.vaPEB, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(pPath->szPath1, "win-modules") && VmmProc_ModuleMapGet(pProcess, &pObModuleMap)) {
- nt = Util_VfsReadFile_FromPBYTE(pObModuleMap->pbDisplay, pObModuleMap->cbDisplay, pb, cb, pcbRead, cbOffset);
- VmmOb_DECREF(pObModuleMap);
- return nt;
- }
- if(!_stricmp(pPath->szPath1, "win-peb32")) {
- return Util_VfsReadFile_FromDWORD(pProcess->os.win.vaPEB32, pb, cb, pcbRead, cbOffset, FALSE);
- }
- }
- if(ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86) {
- if(!_stricmp(pPath->szPath1, "win-eprocess")) {
- return Util_VfsReadFile_FromDWORD((DWORD)pProcess->os.win.vaEPROCESS, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(pPath->szPath1, "win-entry")) {
- return Util_VfsReadFile_FromDWORD((DWORD)pProcess->os.win.vaENTRY, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(pPath->szPath1, "win-peb")) {
- return Util_VfsReadFile_FromDWORD((DWORD)pProcess->os.win.vaPEB, pb, cb, pcbRead, cbOffset, FALSE);
- }
- if(!_stricmp(pPath->szPath1, "win-modules") && VmmProc_ModuleMapGet(pProcess, &pObModuleMap)) {
- nt = Util_VfsReadFile_FromPBYTE(pObModuleMap->pbDisplay, pObModuleMap->cbDisplay, pb, cb, pcbRead, cbOffset);
- VmmOb_DECREF(pObModuleMap);
- return nt;
- }
- }
- // no hit - call down the loadable modules chain for potential hits
- return PluginManager_Read(pProcess, pPath->szPath1, pPath->szPath2, pb, cb, pcbRead, cbOffset);
-}
-
-NTSTATUS VmmVfs_Read(LPCWSTR wcsFileName, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset)
-{
- NTSTATUS nt = VMM_STATUS_FILE_INVALID;
- VMMVFS_PATH path;
- CHAR _szBuf[MAX_PATH];
- LPSTR szModule, szModulePath;
- PVMM_PROCESS pObProcess;
- if(!ctxVmm) { return nt; }
- // read '\\pmem' - physical memory file:
- if(!_wcsicmp(wcsFileName, L"\\pmem")) {
- VmmReadEx(NULL, cbOffset, pb, cb, pcbRead, VMM_FLAG_ZEROPAD_ON_FAIL);
- return VMM_STATUS_SUCCESS;
- }
- // read files in process directories:
- if(!_wcsnicmp(wcsFileName, L"\\name", 5) || !_wcsnicmp(wcsFileName, L"\\pid", 4)) {
- if(!VmmVfs_UtilVmmGetPidDirFile(wcsFileName, &path)) { return nt; }
- pObProcess = VmmProcessGet(path.dwPID);
- if(!pObProcess) { return VMM_STATUS_FILE_INVALID; }
- nt = VmmVfsReadFileProcess(pObProcess, &path, pb, cb, pcbRead, cbOffset);
- VmmOb_DECREF(pObProcess);
- return nt;
- }
- // list files in any non-process modules directories
- Util_PathSplit2_WCHAR((LPWSTR)(wcsFileName + 1), _szBuf, &szModule, &szModulePath);
- return PluginManager_Read(NULL, szModule, szModulePath, pb, cb, pcbRead, cbOffset);
-}
-
-// ----------------------------------------------------------------------------
-// FUNCTIONALITY RELATED TO: WRITE
-// ----------------------------------------------------------------------------
-
-NTSTATUS VmmVfsWriteFileProcess(_In_ PVMM_PROCESS pProcess, _In_ PVMMVFS_PATH pPath, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset)
-{
- BOOL fFound, result;
- // read only files - report zero bytes written
- fFound =
- !_stricmp(pPath->szPath1, "map") ||
- !_stricmp(pPath->szPath1, "pml4") ||
- !_stricmp(pPath->szPath1, "pid") ||
- !_stricmp(pPath->szPath1, "name");
- if(fFound) {
- *pcbWrite = 0;
- return VMM_STATUS_SUCCESS;
- }
- // windows specific writes below:
- if((ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) || (ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86)) {
- fFound =
- !_stricmp(pPath->szPath1, "win-eprocess") ||
- !_stricmp(pPath->szPath1, "win-peb") ||
- !_stricmp(pPath->szPath1, "win-entry") ||
- !_stricmp(pPath->szPath1, "win-modules");
- if(fFound) {
- *pcbWrite = 0;
- return VMM_STATUS_SUCCESS;
- }
- }
- // write memory to "vmem" file
- if(!_stricmp(pPath->szPath1, "vmem")) {
- result = VmmWrite(pProcess, cbOffset, pb, cb);
- *pcbWrite = cb;
- return VMM_STATUS_SUCCESS;
- }
- // no hit - call down the loadable modules chain for potential hits
- return PluginManager_Write(pProcess, pPath->szPath1, pPath->szPath2, pb, cb, pcbWrite, cbOffset);
-}
-
-NTSTATUS VmmVfs_Write(LPCWSTR wcsFileName, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset)
-{
- NTSTATUS nt = VMM_STATUS_FILE_INVALID;
- BOOL result;
- VMMVFS_PATH path;
- CHAR _szBuf[MAX_PATH];
- PVMM_PROCESS pObProcess;
- LPSTR szModule, szModulePath;
- if(!ctxVmm) { return nt; }
- // read '\\pmem' - physical memory file:
- if(!_wcsicmp(wcsFileName, L"\\pmem")) {
- result = VmmWritePhysical(cbOffset, pb, cb);
- *pcbWrite = cb;
- return result ? VMM_STATUS_SUCCESS : VMM_STATUS_FILE_SYSTEM_LIMITATION;
- }
- // read files in process directories:
- if(!_wcsnicmp(wcsFileName, L"\\name", 5) || !_wcsnicmp(wcsFileName, L"\\pid", 4)) {
- if(!VmmVfs_UtilVmmGetPidDirFile(wcsFileName, &path) || !path.szPath1) { return nt; }
- pObProcess = VmmProcessGet(path.dwPID);
- if(!pObProcess) { return VMM_STATUS_FILE_INVALID; }
- nt = VmmVfsWriteFileProcess(pObProcess, &path, pb, cb, pcbWrite, cbOffset);
- return nt;
- }
- // list files in any non-process modules directories
- Util_PathSplit2_WCHAR((LPWSTR)(wcsFileName + 1), _szBuf, &szModule, &szModulePath);
- return PluginManager_Write(NULL, szModule, szModulePath, pb, cb, pcbWrite, cbOffset);
-}
-
-// ----------------------------------------------------------------------------
-// FUNCTIONALITY RELATED TO: LIST
-// ----------------------------------------------------------------------------
-
-VOID VmmVfsListFiles_OsSpecific(_In_ PVMM_PROCESS pProcess, _Inout_ PHANDLE pFileList)
-{
- PVMMOB_MODULEMAP pObModuleMap;
- // WINDOWS
- if(ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) {
- VMMDLL_VfsList_AddFile(pFileList, "win-eprocess", 16);
- if(pProcess->os.win.vaENTRY) {
- VMMDLL_VfsList_AddFile(pFileList, "win-entry", 16);
- }
- // 64-bit PEB and modules
- if(pProcess->os.win.vaPEB) {
- VMMDLL_VfsList_AddFile(pFileList, "win-peb", 16);
- }
- if(VmmProc_ModuleMapGet(pProcess, &pObModuleMap)) {
- if(pObModuleMap->cbDisplay) {
- VMMDLL_VfsList_AddFile(pFileList, "win-modules", pObModuleMap->cbDisplay);
- }
- VmmOb_DECREF(pObModuleMap);
- }
- // 32-bit PEB and modules
- if(pProcess->os.win.vaPEB32) {
- VMMDLL_VfsList_AddFile(pFileList, "win-peb32", 8);
- }
- }
- if(ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86) {
- VMMDLL_VfsList_AddFile(pFileList, "win-eprocess", 8);
- if(pProcess->os.win.vaENTRY) {
- VMMDLL_VfsList_AddFile(pFileList, "win-entry", 8);
- }
- // PEB and modules
- if(pProcess->os.win.vaPEB) {
- VMMDLL_VfsList_AddFile(pFileList, "win-peb", 8);
- }
- if(VmmProc_ModuleMapGet(pProcess, &pObModuleMap)) {
- if(pObModuleMap->cbDisplay) {
- VMMDLL_VfsList_AddFile(pFileList, "win-modules", pObModuleMap->cbDisplay);
- }
- VmmOb_DECREF(pObModuleMap);
- }
- }
-}
-
-_Success_(return)
-BOOL VmmVfsListFilesProcessRoot(_In_ PVMMVFS_PATH pPath, _Inout_ PHANDLE pFileList)
-{
- PVMM_PROCESS pObProcess = NULL;
- CHAR szBufferFileName[MAX_PATH];
- while((pObProcess = VmmProcessGetNext(pObProcess))) {
- if(pPath->fNamePID) {
- if(pObProcess->dwState) {
- sprintf_s(szBufferFileName, MAX_PATH - 1, "%s-(%x)-%i", pObProcess->szName, pObProcess->dwState, pObProcess->dwPID);
- } else {
- sprintf_s(szBufferFileName, MAX_PATH - 1, "%s-%i", pObProcess->szName, pObProcess->dwPID);
- }
- } else {
- sprintf_s(szBufferFileName, MAX_PATH - 1, "%i", pObProcess->dwPID);
- }
- VMMDLL_VfsList_AddDirectory(pFileList, szBufferFileName);
- }
- return TRUE;
-}
-
-_Success_(return)
-BOOL VmmVfsListFilesProcess(_In_ PVMM_PROCESS pProcess, _In_ PVMMVFS_PATH pPath, _Inout_ PHANDLE pFileList)
-{
- PVMMOB_MEMMAP pObMemMap = NULL;
- // populate process directory - list standard files and subdirectories
- if(!pPath->szPath1) {
- VmmMemMapGetEntries(pProcess, 0, &pObMemMap);
- VMMDLL_VfsList_AddFile(pFileList, "map", (pObMemMap ? pObMemMap->cbDisplay : 0));
- VmmOb_DECREF(pObMemMap);
- VMMDLL_VfsList_AddFile(pFileList, "name", 16);
- VMMDLL_VfsList_AddFile(pFileList, "pid", 10);
- if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X64) {
- VMMDLL_VfsList_AddFile(pFileList, "vmem", 0x0001000000000000);
- VMMDLL_VfsList_AddFile(pFileList, "dtb", 16);
- if(pProcess->paDTB_UserOpt) { VMMDLL_VfsList_AddFile(pFileList, "dtb-user", 16); }
- } else if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86 || ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86PAE) {
- VMMDLL_VfsList_AddFile(pFileList, "vmem", 0x100000000);
- VMMDLL_VfsList_AddFile(pFileList, "dtb", 8);
- if(pProcess->paDTB_UserOpt) { VMMDLL_VfsList_AddFile(pFileList, "dtb-user", 8); }
- }
- VmmVfsListFiles_OsSpecific(pProcess, pFileList);
- PluginManager_ListAll(pProcess, pFileList);
- return TRUE;
- }
- // no hit - call down the loadable modules chain for potential hits
- return PluginManager_List(pProcess, pPath->szPath1, pPath->szPath2, pFileList);
-}
-
-_Success_(return)
-BOOL VmmVfsListFilesRoot(_Inout_ PHANDLE pFileList)
-{
- VMMDLL_VfsList_AddDirectory(pFileList, "name");
- VMMDLL_VfsList_AddDirectory(pFileList, "pid");
- VMMDLL_VfsList_AddFile(pFileList, "pmem", ctxMain->dev.paMax);
- PluginManager_ListAll(NULL, pFileList);
- return TRUE;
-}
-
-BOOL VmmVfs_List(_In_ LPCWSTR wcsPath, _Inout_ PHANDLE pFileList)
-{
- BOOL result = FALSE;
- VMMVFS_PATH path;
- CHAR _szBuf[MAX_PATH];
- PVMM_PROCESS pObProcess;
- LPSTR szModule, szModulePath;
- if(!ctxVmm) { return FALSE; }
- // list files in root directory
- if(!_wcsicmp(wcsPath, L"\\")) {
- return VmmVfsListFilesRoot(pFileList);
- }
- // list files in name or pid directories:
- if(!_wcsnicmp(wcsPath, L"\\name", 5) || !_wcsnicmp(wcsPath, L"\\pid", 4)) {
- if(!VmmVfs_UtilVmmGetPidDirFile(wcsPath, &path)) { return FALSE; }
- if(path.fRoot) {
- return VmmVfsListFilesProcessRoot(&path, pFileList);
- }
- pObProcess = VmmProcessGet(path.dwPID);
- if(!pObProcess) { return FALSE; }
- result = VmmVfsListFilesProcess(pObProcess, &path, pFileList);
- VmmOb_DECREF(pObProcess);
- return result;
- }
- // list files in any non-process modules directories
- Util_PathSplit2_WCHAR((LPWSTR)(wcsPath + 1), _szBuf, &szModule, &szModulePath);
- return PluginManager_List(NULL, szModule, szModulePath, pFileList);
-}
diff --git a/vmm/vmmvfs.h b/vmm/vmmvfs.h
deleted file mode 100644
index aa6c061..0000000
--- a/vmm/vmmvfs.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// vmmvfs.h : definitions related to virtual memory management / virtual file system interfacing.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __VMMVFS_H__
-#define __VMMVFS_H__
-#include "vmm.h"
-
-/*
-* List files in the virtual file system directory specified by the path name.
-* -- wcsPath
-* -- pFileList
-* -- return
-*/
-BOOL VmmVfs_List(_In_ LPCWSTR wcsPath, _Inout_ PHANDLE pFileList);
-
-/*
-* Read the contents of a file into the caller supplied buffer. This file may be
-* a memory file or any other file in the "proc" virtual file system.
-* -- wcsFileName = full path file name
-* -- pb = buffer
-* -- cb = bytes to read/size of pb
-* -- pcbRead = bytes actually read
-* -- cbOffset = offset where to start read compared to file start
-*/
-NTSTATUS VmmVfs_Read(_In_ LPCWSTR wcsFileName, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ QWORD cbOffset);
-
-/*
-* Write the contents of a file into the caller supplied buffer. This file may be
-* a memory file or any other file in the "proc" virtual file system.
-* -- wcsFileName = full path file name
-* -- pb = buffer
-* -- cb = bytes to read/size of pb
-* -- pcbWrite = bytes actually read
-* -- cbOffset = offset where to start read compared to file start
-*/
-NTSTATUS VmmVfs_Write(_In_ LPCWSTR wcsFileName, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ QWORD cbOffset);
-
-#endif /* __VMMVFS_H__ */
diff --git a/vmm/vmmwin.c b/vmm/vmmwin.c
deleted file mode 100644
index 2155c82..0000000
--- a/vmm/vmmwin.c
+++ /dev/null
@@ -1,1364 +0,0 @@
-// vmmwin.c : implementation related to operating system and process
-// parsing of virtual memory. Windows related features only.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-
-#include "vmmwin.h"
-#include "vmmproc.h"
-#include "util.h"
-#include "pe.h"
-#include
-
-// ----------------------------------------------------------------------------
-// WINDOWS SPECIFIC PROCESS RELATED FUNCTIONALITY BELOW:
-// GENERAL FUNCTIONALITY
-// ----------------------------------------------------------------------------
-
-PIMAGE_NT_HEADERS VmmWin_GetVerifyHeaderPE(_In_ PVMM_PROCESS pProcess, _In_opt_ QWORD vaModule, _Inout_ PBYTE pbModuleHeader, _Out_ PBOOL pfHdr32)
-{
- PIMAGE_DOS_HEADER dosHeader;
- PIMAGE_NT_HEADERS ntHeader;
- *pfHdr32 = FALSE;
- if(vaModule) {
- if(!VmmReadPage(pProcess, vaModule, pbModuleHeader)) { return NULL; }
- }
- dosHeader = (PIMAGE_DOS_HEADER)pbModuleHeader; // dos header.
- if(!dosHeader || dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { return NULL; }
- if(dosHeader->e_lfanew > 0x800) { return NULL; }
- ntHeader = (PIMAGE_NT_HEADERS)(pbModuleHeader + dosHeader->e_lfanew); // nt header
- if(!ntHeader || ntHeader->Signature != IMAGE_NT_SIGNATURE) { return NULL; }
- if((ntHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) && (ntHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)) { return NULL; }
- *pfHdr32 = (ntHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC);
- return ntHeader;
-}
-
-// ----------------------------------------------------------------------------
-// WINDOWS SPECIFIC PROCESS RELATED FUNCTIONALITY BELOW:
-// IMPORT/EXPORT DIRECTORY PARSING
-// ----------------------------------------------------------------------------
-
-VOID VmmWin_PE_SECTION_DisplayBuffer(
- _In_ PVMM_PROCESS pProcess,
- _In_ PVMM_MODULEMAP_ENTRY pModule,
- _Out_writes_bytes_opt_(*pcbDisplayBuffer) PBYTE pbDisplayBufferOpt,
- _In_ DWORD cbDisplayBufferMax,
- _Out_opt_ PDWORD pcbDisplayBuffer,
- _Inout_opt_ PDWORD pcSectionsOpt,
- _Out_writes_opt_(*pcSectionsOpt) PIMAGE_SECTION_HEADER pSectionsOpt)
-{
- BYTE pbModuleHeader[0x1000] = { 0 };
- PIMAGE_NT_HEADERS64 ntHeader64;
- BOOL fHdr32;
- DWORD i, cSections, cSectionsOpt;
- PIMAGE_SECTION_HEADER pSectionBase;
- if(pcbDisplayBuffer) { *pcbDisplayBuffer = 0; }
- if(pcSectionsOpt) {
- cSectionsOpt = *pcSectionsOpt;
- *pcSectionsOpt = 0;
- }
- if(!(ntHeader64 = VmmWin_GetVerifyHeaderPE(pProcess, pModule->BaseAddress, pbModuleHeader, &fHdr32))) { return; }
- pSectionBase = fHdr32 ?
- (PIMAGE_SECTION_HEADER)((QWORD)ntHeader64 + sizeof(IMAGE_NT_HEADERS32)) :
- (PIMAGE_SECTION_HEADER)((QWORD)ntHeader64 + sizeof(IMAGE_NT_HEADERS64));
- cSections = (DWORD)(((QWORD)pbModuleHeader + 0x1000 - (QWORD)pSectionBase) / sizeof(IMAGE_SECTION_HEADER)); // max section headers possible in 0x1000 module header buffer
- cSections = (DWORD)min(cSections, ntHeader64->FileHeader.NumberOfSections); // FileHeader are the same in both 32/64-bit versions of struct
- if(pbDisplayBufferOpt) {
- for(i = 0; i < cSections; i++) {
- // 52 byte per line (indluding newline)
- *pcbDisplayBuffer += snprintf(
- pbDisplayBufferOpt + *pcbDisplayBuffer,
- cbDisplayBufferMax - *pcbDisplayBuffer,
- "%02x %-8.8s %016llx %08x %08x %c%c%c\n",
- i,
- pSectionBase[i].Name,
- pModule->BaseAddress + pSectionBase[i].VirtualAddress,
- pSectionBase[i].VirtualAddress,
- pSectionBase[i].Misc.VirtualSize,
- (pSectionBase[i].Characteristics & IMAGE_SCN_MEM_READ) ? 'r' : '-',
- (pSectionBase[i].Characteristics & IMAGE_SCN_MEM_WRITE) ? 'w' : '-',
- (pSectionBase[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) ? 'x' : '-'
- );
- }
- }
- if(pSectionsOpt && pcSectionsOpt && cSectionsOpt) {
- *pcSectionsOpt = min(cSectionsOpt, ntHeader64->FileHeader.NumberOfSections);
- memcpy(pSectionsOpt, pSectionBase, *pcSectionsOpt * sizeof(IMAGE_SECTION_HEADER));
- }
-}
-
-VOID VmmWin_PE_DIRECTORY_DisplayBuffer(
- _In_ PVMM_PROCESS pProcess,
- _In_ PVMM_MODULEMAP_ENTRY pModule,
- _Out_writes_bytes_opt_(*pcbDisplayBuffer) PBYTE pbDisplayBufferOpt,
- _In_ DWORD cbDisplayBufferMax,
- _Out_opt_ PDWORD pcbDisplayBuffer,
- _Out_writes_opt_(16) PIMAGE_DATA_DIRECTORY pDataDirectoryOpt)
-{
- BYTE i, pbModuleHeader[0x1000] = { 0 };
- PIMAGE_NT_HEADERS64 ntHeader64;
- PIMAGE_NT_HEADERS32 ntHeader32;
- PIMAGE_DATA_DIRECTORY pDataDirectoryBase;
- BOOL fHdr32;
- if(pcbDisplayBuffer) { *pcbDisplayBuffer = 0; }
- if(!(ntHeader64 = VmmWin_GetVerifyHeaderPE(pProcess, pModule->BaseAddress, pbModuleHeader, &fHdr32))) { return; }
- ntHeader32 = (PIMAGE_NT_HEADERS32)ntHeader64;
- pDataDirectoryBase = fHdr32 ? ntHeader32->OptionalHeader.DataDirectory : ntHeader64->OptionalHeader.DataDirectory;
- if(pbDisplayBufferOpt) {
- for(i = 0; i < 16; i++) {
- if(pbDisplayBufferOpt && pcbDisplayBuffer) {
- *pcbDisplayBuffer += snprintf(
- pbDisplayBufferOpt + *pcbDisplayBuffer,
- cbDisplayBufferMax - *pcbDisplayBuffer,
- "%x %-16.16s %016llx %08x %08x\n",
- i,
- PE_DATA_DIRECTORIES[i],
- pModule->BaseAddress + pDataDirectoryBase[i].VirtualAddress,
- pDataDirectoryBase[i].VirtualAddress,
- pDataDirectoryBase[i].Size
- );
- }
- }
- }
- if(pDataDirectoryOpt) {
- memcpy(pDataDirectoryOpt, pDataDirectoryBase, 16 * sizeof(IMAGE_DATA_DIRECTORY));
- }
-}
-
-_Success_(return)
-BOOL VmmWin_PE_LoadEAT_DisplayBuffer(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _Out_writes_opt_(cEATs) PVMMPROC_WINDOWS_EAT_ENTRY pEATs, _In_ DWORD cEATs, _Out_ PDWORD pcEATs)
-{
- BYTE pbModuleHeader[0x1000] = { 0 };
- PIMAGE_NT_HEADERS64 ntHeader64;
- PIMAGE_NT_HEADERS32 ntHeader32;
- QWORD oExportDirectory, cbExportDirectory;
- PBYTE pbExportDirectory = NULL;
- PIMAGE_EXPORT_DIRECTORY pExportDirectory;
- QWORD i, oNameOrdinal, ooName, oName, oFunction, wOrdinalFnIdx;
- DWORD vaFunctionOffset;
- BOOL fHdr32;
- *pcEATs = 0;
- // load both 32/64 bit ntHeader (only one will be valid)
- if(!(ntHeader64 = VmmWin_GetVerifyHeaderPE(pProcess, pModule->BaseAddress, pbModuleHeader, &fHdr32))) { goto fail; }
- ntHeader32 = (PIMAGE_NT_HEADERS32)ntHeader64;
- // Load Export Address Table (EAT)
- oExportDirectory = fHdr32 ?
- ntHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress :
- ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- cbExportDirectory = fHdr32 ?
- ntHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size :
- ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
- if(!oExportDirectory || !cbExportDirectory || cbExportDirectory > 0x01000000) { goto fail; }
- if(!(pbExportDirectory = LocalAlloc(0, cbExportDirectory))) { goto fail; }
- if(!VmmRead(pProcess, pModule->BaseAddress + oExportDirectory, pbExportDirectory, (DWORD)cbExportDirectory)) { goto fail; }
- // Walk exported functions
- pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)pbExportDirectory;
- for(i = 0; i < pExportDirectory->NumberOfNames && i < cEATs; i++) {
- //
- oNameOrdinal = pExportDirectory->AddressOfNameOrdinals + (i << 1);
- if((oNameOrdinal - sizeof(WORD) - oExportDirectory) > cbExportDirectory) { continue; }
- wOrdinalFnIdx = *(PWORD)(pbExportDirectory - oExportDirectory + oNameOrdinal);
- //
- ooName = pExportDirectory->AddressOfNames + (i << 2);
- if((ooName - sizeof(DWORD) - oExportDirectory) > cbExportDirectory) { continue; }
- oName = *(PDWORD)(pbExportDirectory - oExportDirectory + ooName);
- if((oName - 2 - oExportDirectory) > cbExportDirectory) { continue; }
- //
- oFunction = pExportDirectory->AddressOfFunctions + (wOrdinalFnIdx << 2);
- if((oFunction - sizeof(DWORD) - oExportDirectory) > cbExportDirectory) { continue; }
- vaFunctionOffset = *(PDWORD)(pbExportDirectory - oExportDirectory + oFunction);
- // store into caller supplied info struct
- pEATs[i].vaFunctionOffset = vaFunctionOffset;
- pEATs[i].vaFunction = pModule->BaseAddress + vaFunctionOffset;
- strncpy_s(pEATs[i].szFunction, 40, (LPSTR)(pbExportDirectory - oExportDirectory + oName), _TRUNCATE);
- }
- *pcEATs = (DWORD)i;
- LocalFree(pbExportDirectory);
- return TRUE;
-fail:
- LocalFree(pbExportDirectory);
- return FALSE;
-}
-
-VOID VmmWin_PE_LoadIAT_DisplayBuffer(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _Out_writes_(*pcIATs) PVMMWIN_IAT_ENTRY pIATs, _In_ DWORD cIATs, _Out_ PDWORD pcIATs)
-{
- BYTE pbModuleHeader[0x1000] = { 0 };
- PIMAGE_NT_HEADERS64 ntHeader64;
- PIMAGE_NT_HEADERS32 ntHeader32;
- QWORD i, oImportDirectory;
- PIMAGE_IMPORT_DESCRIPTOR pIID;
- PQWORD pIAT64, pHNA64;
- PDWORD pIAT32, pHNA32;
- PBYTE pbModule;
- DWORD cbModule, cbRead;
- BOOL fHdr32, fFnName;
- DWORD c, j;
- *pcIATs = 0;
- // Load the module
- if(pModule->SizeOfImage > 0x02000000) { return; }
- cbModule = pModule->SizeOfImage;
- if(!(pbModule = LocalAlloc(LMEM_ZEROINIT, cbModule))) { return; }
- VmmReadEx(pProcess, pModule->BaseAddress, pbModule, cbModule, &cbRead, 0);
- if(cbRead <= 0x2000) { goto cleanup; }
- // load both 32/64 bit ntHeader (only one will be valid)
- if(!(ntHeader64 = VmmWin_GetVerifyHeaderPE(pProcess, pModule->BaseAddress, pbModuleHeader, &fHdr32))) { goto cleanup; }
- ntHeader32 = (PIMAGE_NT_HEADERS32)ntHeader64;
- oImportDirectory = fHdr32 ?
- ntHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress :
- ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
- if(!oImportDirectory || (oImportDirectory >= cbModule)) { goto cleanup; }
- // Walk imported modules / functions
- pIID = (PIMAGE_IMPORT_DESCRIPTOR)(pbModule + oImportDirectory);
- i = 0, c = 0;
- while((oImportDirectory + (i + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR) < cbModule) && pIID[i].FirstThunk) {
- if(c >= cIATs) { break; }
- if(pIID[i].Name > cbModule - 64) { i++; continue; }
- if(fHdr32) {
- // 32-bit PE
- j = 0;
- pIAT32 = (PDWORD)(pbModule + pIID[i].FirstThunk);
- pHNA32 = (PDWORD)(pbModule + pIID[i].OriginalFirstThunk);
- while(TRUE) {
- if(c >= cIATs) { break; }
- if((QWORD)(pIAT32 + j) + sizeof(DWORD) - (QWORD)pbModule > cbModule) { break; }
- if((QWORD)(pHNA32 + j) + sizeof(DWORD) - (QWORD)pbModule > cbModule) { break; }
- if(!pIAT32[j]) { break; }
- if(!pHNA32[j]) { break; }
- fFnName = (pHNA32[j] < cbModule - 40);
- // store into caller supplied info struct
- pIATs[c].vaFunction = pIAT32[j];
- strncpy_s(pIATs[c].szFunction, 40, (fFnName ? (LPSTR)(pbModule + pHNA32[j] + 2) : ""), _TRUNCATE);
- strncpy_s(pIATs[c].szModule, 64, (LPSTR)(pbModule + pIID[i].Name), _TRUNCATE);
- c++;
- j++;
- }
- } else {
- // 64-bit PE
- j = 0;
- pIAT64 = (PQWORD)(pbModule + pIID[i].FirstThunk);
- pHNA64 = (PQWORD)(pbModule + pIID[i].OriginalFirstThunk);
- while(TRUE) {
- if(c >= cIATs) { break; }
- if((QWORD)(pIAT64 + j) + sizeof(QWORD) - (QWORD)pbModule > cbModule) { break; }
- if((QWORD)(pHNA64 + j) + sizeof(QWORD) - (QWORD)pbModule > cbModule) { break; }
- if(!pIAT64[j]) { break; }
- if(!pHNA64[j]) { break; }
- fFnName = (pHNA64[j] < cbModule - 40);
- // store into caller supplied info struct
- pIATs[c].vaFunction = pIAT64[j];
- strncpy_s(pIATs[c].szFunction, 40, (fFnName ? (LPSTR)(pbModule + pHNA64[j] + 2) : ""), _TRUNCATE);
- strncpy_s(pIATs[c].szModule, 64, (LPSTR)(pbModule + pIID[i].Name), _TRUNCATE);
- c++;
- j++;
- }
- }
- i++;
- }
- *pcIATs = c;
-cleanup:
- LocalFree(pbModule);
-}
-
-VOID VmmWin_PE_SetSizeSectionIATEAT_DisplayBuffer(_In_ PVMM_PROCESS pProcess, _Inout_ PVMM_MODULEMAP_ENTRY pModule)
-{
- BYTE pbModuleHeader[0x1000] = { 0 };
- PIMAGE_NT_HEADERS64 pNtHeaders64;
- BOOL fHdr32;
- // check if function is required
- if(pModule->fLoadedEAT && pModule->fLoadedIAT) { return; }
- EnterCriticalSection(&pProcess->LockUpdate);
- if(pModule->fLoadedEAT && pModule->fLoadedIAT) {
- LeaveCriticalSection(&pProcess->LockUpdate);
- return;
- }
- // load both 32/64 bit ntHeader (only one will be valid)
- if(!(pNtHeaders64 = VmmWin_GetVerifyHeaderPE(pProcess, pModule->BaseAddress, pbModuleHeader, &fHdr32))) {
- LeaveCriticalSection(&pProcess->LockUpdate);
- return;
- }
- // calculate display buffer size of: SECTIONS, EAT, IAT
- pModule->cbDisplayBufferSections = PE_SectionGetNumberOfEx(pProcess, pModule->BaseAddress, pbModuleHeader) * 52; // each display buffer human readable line == 52 bytes.
- if(!pModule->fLoadedEAT) {
- pModule->cbDisplayBufferEAT = PE_EatGetNumberOfEx(pProcess, pModule->BaseAddress, pbModuleHeader) * 64; // each display buffer human readable line == 64 bytes.
- pModule->fLoadedEAT = TRUE;
- }
- if(!pModule->fLoadedIAT) {
- pModule->cbDisplayBufferIAT = PE_IatGetNumberOfEx(pProcess, pModule->BaseAddress, pbModuleHeader) * 128; // each display buffer human readable line == 128 bytes.
- pModule->fLoadedIAT = TRUE;
- }
- LeaveCriticalSection(&pProcess->LockUpdate);
-}
-
-// ----------------------------------------------------------------------------
-// WINDOWS SPECIFIC PROCESS RELATED FUNCTIONALITY BELOW:
-// PEB/LDR USER MODE PARSING CODE (64-bit and 32-bit)
-// ----------------------------------------------------------------------------
-
-// more extensive definition of the Windows LDR_DATA_TABLE_ENTRY struct.
-typedef struct _VMMPROC_LDR_DATA_TABLE_ENTRY {
- LIST_ENTRY InLoadOrderModuleList;
- LIST_ENTRY InMemoryOrderModuleList;
- LIST_ENTRY InInitializationOrderModuleList;
- PVOID BaseAddress;
- PVOID EntryPoint;
- ULONG SizeOfImage;
- UNICODE_STRING FullDllName;
- UNICODE_STRING BaseDllName;
- ULONG Flags;
- SHORT LoadCount;
- SHORT TlsIndex;
- LIST_ENTRY HashTableEntry;
- ULONG TimeDateStamp;
-} VMMPROC_LDR_DATA_TABLE_ENTRY, *PVMMPROC_LDR_DATA_TABLE_ENTRY;
-
-#define VMMWIN_SCANLDRMODULES_PREFETCH_MAX 0x100
-
-VOID VmmWin_ScanLdrModules64(_In_ PVMM_PROCESS pProcess, _Inout_ PVMM_MODULEMAP_ENTRY pModules, _Inout_ PDWORD pcModules, _In_ DWORD cModulesMax, _Out_ PBOOL fWow64)
-{
- QWORD vaModuleLdrFirst, vaModuleLdr = 0;
- BYTE pbPEB[sizeof(PEB)], pbPEBLdrData[sizeof(PEB_LDR_DATA)], pbLdrModule[sizeof(VMMPROC_LDR_DATA_TABLE_ENTRY)];
- PPEB pPEB = (PPEB)pbPEB;
- PPEB_LDR_DATA pPEBLdrData = (PPEB_LDR_DATA)pbPEBLdrData;
- PVMMPROC_LDR_DATA_TABLE_ENTRY pLdrModule = (PVMMPROC_LDR_DATA_TABLE_ENTRY)pbLdrModule;
- PVMM_MODULEMAP_ENTRY pModule;
- PVMMOB_DATASET pObDataSet_vaModuleLdr = NULL;
- BOOL fNameRead;
- DWORD iModuleLdr;
- // prefetch existing addresses (if any) & allocate new vaModuleLdr DataSet
- pObDataSet_vaModuleLdr = VmmObContainer_GetOb(&pProcess->pObProcessPersistent->ObCLdrModulesCachePrefetch64);
- VmmCachePrefetchPages(pProcess, pObDataSet_vaModuleLdr);
- VmmOb_DECREF(pObDataSet_vaModuleLdr);
- pObDataSet_vaModuleLdr = VmmObDataSet_Alloc(TRUE);
- if(!pObDataSet_vaModuleLdr) { goto fail; }
- // set up initial entry in vaModuleLdr DataSet
- *fWow64 = FALSE;
- if(pProcess->fUserOnly) {
- // User mode process -> walk PEB LDR list to enumerate modules / .dlls.
- if(!pProcess->os.win.vaPEB) { goto fail; }
- if(!VmmRead(pProcess, pProcess->os.win.vaPEB, pbPEB, sizeof(PEB))) { goto fail; }
- if(!VmmRead(pProcess, (QWORD)pPEB->Ldr, pbPEBLdrData, sizeof(PEB_LDR_DATA))) { goto fail; }
- vaModuleLdrFirst = (QWORD)pPEBLdrData->InMemoryOrderModuleList.Flink - 0x10; // InLoadOrderModuleList == InMemoryOrderModuleList - 0x10
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, vaModuleLdrFirst);
- } else {
- // Kernel mode process -> walk PsLoadedModuleList to enumerate drivers / .sys and .dlls.
- if(!ctxVmm->kernel.vaPsLoadedModuleList) { goto fail; }
- if(!VmmRead(pProcess, ctxVmm->kernel.vaPsLoadedModuleList, (PBYTE)&vaModuleLdrFirst, sizeof(QWORD)) || !vaModuleLdrFirst) { goto fail; }
- if(!VmmRead(pProcess, ctxVmm->kernel.vaPsLoadedModuleList, pbPEBLdrData, sizeof(PEB_LDR_DATA))) { goto fail; }
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, vaModuleLdrFirst);
- }
- // loop!
- for(iModuleLdr = 0; iModuleLdr < pObDataSet_vaModuleLdr->c; iModuleLdr++) {
- vaModuleLdr = pObDataSet_vaModuleLdr->pObData->pList[iModuleLdr].Value;
- if(!VmmRead(pProcess, vaModuleLdr, pbLdrModule, sizeof(VMMPROC_LDR_DATA_TABLE_ENTRY))) { continue; }
- if(!pLdrModule->BaseAddress || !pLdrModule->SizeOfImage) { continue; }
- pModule = pModules + *pcModules;
- pModule->BaseAddress = (QWORD)pLdrModule->BaseAddress;
- pModule->EntryPoint = (QWORD)pLdrModule->EntryPoint;
- pModule->SizeOfImage = (DWORD)pLdrModule->SizeOfImage;
- pModule->fWoW64 = FALSE;
- if(!pLdrModule->BaseDllName.Length) { continue; }
- fNameRead = VmmReadString_Unicode2Ansi(pProcess, (QWORD)pLdrModule->BaseDllName.Buffer, pModule->szName, min(31, pLdrModule->BaseDllName.Length));
- fNameRead = fNameRead || PE_GetModuleName(pProcess, pModule->BaseAddress, pModule->szName, 32);
- if(fNameRead) {
- *fWow64 = pProcess->fUserOnly && (*fWow64 || !memcmp(pModule->szName, "wow64.dll", 10));
- vmmprintfvv_fn("%016llx %016llx %016llx %08x %i %s\n", vaModuleLdr, pModule->BaseAddress, pModule->EntryPoint, pModule->SizeOfImage, (pModule->fWoW64 ? 1 : 0), pModule->szName);
- *pcModules = *pcModules + 1;
- } else {
- vmmprintfvv_fn("SKIP: Unable to get name - paged out? PID=%04i BASE=0x%016llx\n", pProcess->dwPID, pModule->BaseAddress);
- }
- // add FLink/BLink lists
- if(pLdrModule->InLoadOrderModuleList.Flink && !((QWORD)pLdrModule->InLoadOrderModuleList.Flink & 0x7)) {
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, (QWORD)CONTAINING_RECORD(pLdrModule->InLoadOrderModuleList.Flink, VMMPROC_LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList));
- }
- if(pLdrModule->InLoadOrderModuleList.Blink && !((QWORD)pLdrModule->InLoadOrderModuleList.Blink & 0x7)) {
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, (QWORD)CONTAINING_RECORD(pLdrModule->InLoadOrderModuleList.Blink, VMMPROC_LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList));
- }
- if(pProcess->fUserOnly) {
- if(pLdrModule->InInitializationOrderModuleList.Flink && !((QWORD)pLdrModule->InInitializationOrderModuleList.Flink & 0x7)) {
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, (QWORD)CONTAINING_RECORD(pLdrModule->InInitializationOrderModuleList.Flink, VMMPROC_LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList));
- }
- if(pLdrModule->InInitializationOrderModuleList.Blink && !((QWORD)pLdrModule->InInitializationOrderModuleList.Blink & 0x7)) {
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, (QWORD)CONTAINING_RECORD(pLdrModule->InInitializationOrderModuleList.Blink, VMMPROC_LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList));
- }
- if(pLdrModule->InMemoryOrderModuleList.Flink && !((QWORD)pLdrModule->InMemoryOrderModuleList.Flink & 0x7)) {
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, (QWORD)CONTAINING_RECORD(pLdrModule->InMemoryOrderModuleList.Flink, VMMPROC_LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList));
- }
- if(pLdrModule->InMemoryOrderModuleList.Blink && !((QWORD)pLdrModule->InMemoryOrderModuleList.Blink & 0x7)) {
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, (QWORD)CONTAINING_RECORD(pLdrModule->InMemoryOrderModuleList.Blink, VMMPROC_LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList));
- }
- }
- if(*pcModules >= cModulesMax) { break; }
- }
- if(ctxMain->dev.fRemote && ctxVmm->ThreadProcCache.fEnabled) {
- VmmObContainer_SetOb(&pProcess->pObProcessPersistent->ObCLdrModulesCachePrefetch64, pObDataSet_vaModuleLdr);
- }
-fail:
- VmmOb_DECREF(pObDataSet_vaModuleLdr);
-}
-
-typedef struct _UNICODE_STRING32 {
- USHORT Length;
- USHORT MaximumLength;
- DWORD Buffer;
-} UNICODE_STRING32;
-
-typedef struct _LDR_MODULE32 {
- LIST_ENTRY32 InLoadOrderModuleList;
- LIST_ENTRY32 InMemoryOrderModuleList;
- LIST_ENTRY32 InInitializationOrderModuleList;
- DWORD BaseAddress;
- DWORD EntryPoint;
- ULONG SizeOfImage;
- UNICODE_STRING32 FullDllName;
- UNICODE_STRING32 BaseDllName;
- ULONG Flags;
- SHORT LoadCount;
- SHORT TlsIndex;
- LIST_ENTRY32 HashTableEntry;
- ULONG TimeDateStamp;
-} LDR_MODULE32, *PLDR_MODULE32;
-
-typedef struct _PEB_LDR_DATA32 {
- BYTE Reserved1[8];
- DWORD Reserved2[3];
- LIST_ENTRY32 InMemoryOrderModuleList;
-} PEB_LDR_DATA32, *PPEB_LDR_DATA32;
-
-typedef struct _PEB32 {
- BYTE Reserved1[2];
- BYTE BeingDebugged;
- BYTE Reserved2[1];
- DWORD Reserved3[2];
- DWORD Ldr;
- DWORD ProcessParameters;
- DWORD SubSystemData;
- DWORD ProcessHeap;
- DWORD Unknown1[27];
- DWORD NumberOfHeaps;
- DWORD MaximumNumberOfHeaps;
- DWORD ProcessHeaps;
- // ...
-} PEB32, *PPEB32;
-
-_Success_(return)
-BOOL VmmWin_ScanLdrModules32(_In_ PVMM_PROCESS pProcess, _Inout_ PVMM_MODULEMAP_ENTRY pModules, _Inout_ PDWORD pcModules, _In_ DWORD cModulesMax)
-{
- DWORD vaModuleLdrFirst32, vaModuleLdr32 = 0;
- BYTE pbPEB32[sizeof(PEB32)], pbPEBLdrData32[sizeof(PEB_LDR_DATA32)], pbLdrModule32[sizeof(LDR_MODULE32)];
- PPEB32 pPEB32 = (PPEB32)pbPEB32;
- PPEB_LDR_DATA32 pPEBLdrData32 = (PPEB_LDR_DATA32)pbPEBLdrData32;
- PLDR_MODULE32 pLdrModule32 = (PLDR_MODULE32)pbLdrModule32;
- PVMM_MODULEMAP_ENTRY pModule;
- PVMMOB_DATASET pObDataSet_vaModuleLdr = NULL;
- BOOL fNameRead;
- DWORD iModuleLdr;
- // prefetch existing addresses (if any) & allocate new vaModuleLdr DataSet
- pObDataSet_vaModuleLdr = VmmObContainer_GetOb(&pProcess->pObProcessPersistent->ObCLdrModulesCachePrefetch32);
- VmmCachePrefetchPages(pProcess, pObDataSet_vaModuleLdr);
- VmmOb_DECREF(pObDataSet_vaModuleLdr);
- pObDataSet_vaModuleLdr = VmmObDataSet_Alloc(TRUE);
- if(!pObDataSet_vaModuleLdr) { goto fail; }
- // set up initial entry in vaModuleLdr DataSet
- if(pProcess->fUserOnly) {
- if(!pProcess->os.win.vaPEB) { goto fail; }
- if(!VmmRead(pProcess, pProcess->os.win.vaPEB32, pbPEB32, sizeof(PEB32))) { goto fail; }
- if(!VmmRead(pProcess, (DWORD)pPEB32->Ldr, pbPEBLdrData32, sizeof(PEB_LDR_DATA32))) { goto fail; }
- vaModuleLdr32 = vaModuleLdrFirst32 = (DWORD)pPEBLdrData32->InMemoryOrderModuleList.Flink - 0x08; // InLoadOrderModuleList == InMemoryOrderModuleList - 0x08
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, vaModuleLdr32);
- } else if(ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86) {
- // Kernel mode process -> walk PsLoadedModuleList to enumerate drivers / .sys and .dlls.
- if(!ctxVmm->kernel.vaPsLoadedModuleList) { goto fail; }
- if(!VmmRead(pProcess, ctxVmm->kernel.vaPsLoadedModuleList, (PBYTE)&vaModuleLdrFirst32, sizeof(DWORD)) || !vaModuleLdrFirst32) { goto fail; }
- if(!VmmRead(pProcess, ctxVmm->kernel.vaPsLoadedModuleList, pbPEBLdrData32, sizeof(PEB_LDR_DATA32))) { goto fail; }
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, vaModuleLdrFirst32);
- } else {
- goto fail;
- }
- // loop!
- for(iModuleLdr = 0; iModuleLdr < pObDataSet_vaModuleLdr->c; iModuleLdr++) {
- vaModuleLdr32 = (DWORD)pObDataSet_vaModuleLdr->pObData->pList[iModuleLdr].Value;
- if(!VmmRead(pProcess, vaModuleLdr32, pbLdrModule32, sizeof(LDR_MODULE32))) { continue; }
- if(!pLdrModule32->BaseAddress || !pLdrModule32->SizeOfImage) { continue; }
- pModule = pModules + *pcModules;
- pModule->BaseAddress = (QWORD)pLdrModule32->BaseAddress;
- pModule->EntryPoint = (QWORD)pLdrModule32->EntryPoint;
- pModule->SizeOfImage = (DWORD)pLdrModule32->SizeOfImage;
- pModule->fWoW64 = TRUE;
- if(!pLdrModule32->BaseDllName.Length) { continue; }
- fNameRead = VmmReadString_Unicode2Ansi(pProcess, (QWORD)pLdrModule32->BaseDllName.Buffer, pModule->szName, min(31, pLdrModule32->BaseDllName.Length));
- fNameRead = fNameRead || PE_GetModuleName(pProcess, pModule->BaseAddress, pModule->szName, 32);
- if(fNameRead) {
- vmmprintfvv_fn("%08x %08x %08x %08x %s\n", vaModuleLdr32, (DWORD)pModule->BaseAddress, (DWORD)pModule->EntryPoint, pModule->SizeOfImage, pModule->szName);
- *pcModules = *pcModules + 1;
- } else {
- vmmprintfvv_fn("SKIP: Unable to get name - paged out? PID=%04i BASE=0x%08x\n", pProcess->dwPID, (DWORD)pModule->BaseAddress);
- }
- // add FLink/BLink lists
- if(pLdrModule32->InLoadOrderModuleList.Flink && !((DWORD)pLdrModule32->InLoadOrderModuleList.Flink & 0x3)) {
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, (QWORD)CONTAINING_RECORD32(pLdrModule32->InLoadOrderModuleList.Flink, LDR_MODULE32, InLoadOrderModuleList));
- }
- if(pLdrModule32->InLoadOrderModuleList.Blink && !((DWORD)pLdrModule32->InLoadOrderModuleList.Blink & 0x3)) {
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, (QWORD)CONTAINING_RECORD32(pLdrModule32->InLoadOrderModuleList.Blink, LDR_MODULE32, InLoadOrderModuleList));
- }
- if(pProcess->fUserOnly) {
- if(pLdrModule32->InInitializationOrderModuleList.Flink && !((DWORD)pLdrModule32->InInitializationOrderModuleList.Flink & 0x3)) {
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, (QWORD)CONTAINING_RECORD32(pLdrModule32->InInitializationOrderModuleList.Flink, LDR_MODULE32, InInitializationOrderModuleList));
- }
- if(pLdrModule32->InInitializationOrderModuleList.Blink && !((DWORD)pLdrModule32->InInitializationOrderModuleList.Blink & 0x3)) {
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, (QWORD)CONTAINING_RECORD32(pLdrModule32->InInitializationOrderModuleList.Blink, LDR_MODULE32, InInitializationOrderModuleList));
- }
- if(pLdrModule32->InMemoryOrderModuleList.Flink && !((DWORD)pLdrModule32->InMemoryOrderModuleList.Flink & 0x3)) {
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, (QWORD)CONTAINING_RECORD32(pLdrModule32->InMemoryOrderModuleList.Flink, LDR_MODULE32, InMemoryOrderModuleList));
- }
- if(pLdrModule32->InMemoryOrderModuleList.Blink && !((DWORD)pLdrModule32->InMemoryOrderModuleList.Blink & 0x3)) {
- VmmObDataSet_Put(pObDataSet_vaModuleLdr, (QWORD)CONTAINING_RECORD32(pLdrModule32->InMemoryOrderModuleList.Blink, LDR_MODULE32, InMemoryOrderModuleList));
- }
- }
- if(*pcModules >= cModulesMax) { break; }
- }
- if(ctxMain->dev.fRemote && ctxVmm->ThreadProcCache.fEnabled) {
- VmmObContainer_SetOb(&pProcess->pObProcessPersistent->ObCLdrModulesCachePrefetch64, pObDataSet_vaModuleLdr);
- }
- VmmOb_DECREF(pObDataSet_vaModuleLdr);
- return TRUE;
-fail:
- VmmOb_DECREF(pObDataSet_vaModuleLdr);
- return FALSE;
-}
-
-#define VMMPROCWINDOWS_MAX_MODULES 512
-
-VOID VmmWin_InitializeLdrModules(_In_ PVMM_PROCESS pProcess)
-{
- PVMM_MODULEMAP_ENTRY pModules, pModule;
- PVMMOB_MODULEMAP pOb = NULL;
- DWORD i, o, cModules;
- BOOL result, fWow64 = FALSE;
- if(pProcess->pObModuleMap) { return; }
- EnterCriticalSection(&pProcess->LockUpdate);
- if(pProcess->pObModuleMap) {
- LeaveCriticalSection(&pProcess->LockUpdate);
- return;
- }
- // allocate and enumerate
- pModules = (PVMM_MODULEMAP_ENTRY)LocalAlloc(LMEM_ZEROINIT, VMMPROCWINDOWS_MAX_MODULES * sizeof(VMM_MODULEMAP_ENTRY));
- if(!pModules) { goto fail; }
- cModules = 0;
- if(ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) {
- VmmWin_ScanLdrModules64(pProcess, pModules, &cModules, VMMPROCWINDOWS_MAX_MODULES, &fWow64);
- if((cModules > 0) && (!pModules[cModules - 1].BaseAddress)) { cModules--; }
- if(fWow64) {
- pProcess->os.win.vaPEB32 = (DWORD)pProcess->os.win.vaPEB - 0x1000;
- result = VmmWin_ScanLdrModules32(pProcess, pModules, &cModules, VMMPROCWINDOWS_MAX_MODULES);
- if(!result) {
- pProcess->os.win.vaPEB32 = (DWORD)pProcess->os.win.vaPEB + 0x1000;
- result = VmmWin_ScanLdrModules32(pProcess, pModules, &cModules, VMMPROCWINDOWS_MAX_MODULES);
- }
- if(!result) {
- pProcess->os.win.vaPEB32 = 0;
- }
- }
- if((cModules > 0) && (!pModules[cModules - 1].BaseAddress)) { cModules--; }
- if(!cModules) { goto fail; }
- pProcess->os.win.vaENTRY = pModules[0].EntryPoint;
- // allocate / set up VmmOb
- pOb = VmmOb_Alloc('MO', 0, sizeof(VMMOB_MODULEMAP) + cModules * (89ULL + sizeof(VMM_MODULEMAP_ENTRY)), NULL, NULL);
- if(!pOb) { goto fail; }
- pOb->pbDisplay = ((PBYTE)pOb->pMap) + cModules * sizeof(VMM_MODULEMAP_ENTRY);
- // create 'text' module map
- for(i = 0, o = 0; i < cModules; i++) {
- pModule = pModules + i;
- if(!pModule->BaseAddress) { continue; }
- o += snprintf(
- pOb->pbDisplay + o,
- 89,
- "%04x %8x %016llx-%016llx %s %s\n",
- i,
- pModule->SizeOfImage >> 12,
- pModule->BaseAddress,
- pModule->BaseAddress + pModule->SizeOfImage - 1,
- pModule->fWoW64 ? "32" : " ",
- pModule->szName
- );
- }
- pProcess->os.win.fWow64 = fWow64;
- pOb->cbDisplay = o;
- } else if(ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86) {
- pProcess->os.win.vaPEB32 = (DWORD)pProcess->os.win.vaPEB;
- VmmWin_ScanLdrModules32(pProcess, pModules, &cModules, VMMPROCWINDOWS_MAX_MODULES);
- if((cModules > 0) && (!pModules[cModules - 1].BaseAddress)) { cModules--; }
- pProcess->os.win.vaENTRY = pModules[0].EntryPoint;
- // allocate / set up VmmOb
- pOb = VmmOb_Alloc('MO', 0, sizeof(VMMOB_MODULEMAP) + cModules * (89ULL + sizeof(VMM_MODULEMAP_ENTRY)), NULL, NULL);
- if(!pOb) { goto fail; }
- pOb->pbDisplay = ((PBYTE)pOb->pMap) + cModules * sizeof(VMM_MODULEMAP_ENTRY);
- // create 'text' module map
- for(i = 0, o = 0; i < cModules; i++) {
- pModule = pModules + i;
- if(!pModule->BaseAddress) { continue; }
- o += snprintf(
- pOb->pbDisplay + o,
- 70,
- "%04x %8x %08x-%08x %s\n",
- i,
- pModule->SizeOfImage >> 12,
- (DWORD)pModule->BaseAddress,
- (DWORD)(pModule->BaseAddress + pModule->SizeOfImage - 1),
- pModule->szName
- );
- }
- pOb->cbDisplay = o;
- } else {
- LeaveCriticalSection(&pProcess->LockUpdate);
- return;
- }
- // copy modules map into Process struct
- pOb->fValid = TRUE;
- pOb->cMap = cModules;
- memcpy(pOb->pMap, pModules, cModules * sizeof(VMM_MODULEMAP_ENTRY));
- pProcess->pObModuleMap = pOb; // reference taken by pProcess -> no need for DECREF.
- LeaveCriticalSection(&pProcess->LockUpdate);
- LocalFree(pModules);
- return;
-fail:
- pProcess->pObModuleMap = VmmOb_Alloc('MO', LMEM_ZEROINIT, sizeof(VMMOB_MODULEMAP), NULL, NULL); // fValid set to false by default == failed initialization!
- LeaveCriticalSection(&pProcess->LockUpdate);
- LocalFree(pModules);
-}
-
-typedef struct tdVMMWIN_HEAP_SEGMENT64 {
- QWORD HeapEntry[2];
- DWORD SegmentSignature;
- DWORD SegmentFlags;
- LIST_ENTRY64 _ListEntry;
- QWORD Heap;
- QWORD BaseAddress;
- QWORD NumberOfPages;
- QWORD FirstEntry;
- QWORD LastValidEntry;
- DWORD NumberOfUnCommittedPages;
- DWORD NumberOfUnCommittedRanges;
- DWORD SegmentAllocatorBackTraceIndex;
- DWORD Reserved;
- LIST_ENTRY64 UCRSegmentList;
-} VMMWIN_HEAP_SEGMENT64, *PVMMWIN_HEAP_SEGMENT64;
-
-typedef struct tdVMMWIN_HEAP_SEGMENT32 {
- DWORD HeapEntry[2];
- DWORD SegmentSignature;
- DWORD SegmentFlags;
- LIST_ENTRY32 _ListEntry;
- DWORD Heap;
- DWORD BaseAddress;
- DWORD NumberOfPages;
- DWORD FirstEntry;
- DWORD LastValidEntry;
- DWORD NumberOfUnCommittedPages;
- DWORD NumberOfUnCommittedRanges;
- DWORD SegmentAllocatorBackTraceIndex;
- DWORD Reserved;
- LIST_ENTRY32 UCRSegmentList;
-} VMMWIN_HEAP_SEGMENT32, *PVMMWIN_HEAP_SEGMENT32;
-
-
-// ----------------------------------------------------------------------------
-// WINDOWS SPECIFIC PROCESS RELATED FUNCTIONALITY BELOW:
-// ----------------------------------------------------------------------------
-
-/*
-* Identify 64-bit HEAPs in a process and tag them into the memory map.
-* WINXP is not supported.
-*/
-VOID VmmWin_ScanPebHeap64(_In_ PVMM_PROCESS pProcess)
-{
- BOOL fReadHasMore, fFirst = TRUE;
- CHAR szBuffer[MAX_PATH];
- BYTE pbPEB[sizeof(PEB)];
- PPEB pPEB = (PPEB)pbPEB;
- DWORD i, j, cHeaps, cHeapsMax, cLoopProtect = 0;
- QWORD vaHeapPrimary, vaHeaps[0x80];
- PMEM_IO_SCATTER_HEADER pMEM, *ppMEMs = NULL;
- PVMMWIN_HEAP_SEGMENT64 pH, PH2;
- // 1: Read PEB
- if(!pProcess->os.win.vaPEB) { return; }
- if(!VmmRead(pProcess, pProcess->os.win.vaPEB, pbPEB, sizeof(PEB))) { return; }
- vaHeapPrimary = (QWORD)pPEB->Reserved4[1];
- cHeaps = (DWORD)((QWORD)pPEB->Reserved9[16]);
- cHeapsMax = (DWORD)((QWORD)pPEB->Reserved9[16] >> 32);
- if(cHeaps > 0x80) { return; } // probably not valid
- // 2: Read heap array
- if(!VmmRead(pProcess, (QWORD)pPEB->Reserved9[17], (PBYTE)vaHeaps, sizeof(QWORD) * cHeaps)) { return; }
- if(vaHeaps[0] != vaHeapPrimary) { return; }
- // 3: Read heap headers in one go (scatter read)
- if(!LeechCore_AllocScatterEmpty(cHeaps << 1, &ppMEMs)) { return; }
- for(i = 0; i < cHeaps; i++) {
- if(vaHeaps[i] & 0xffff) {
- LocalFree(ppMEMs);
- return;
- }
- ppMEMs[i]->qwA = vaHeaps[i];
- }
- // 4: Analyze result
- do {
- VmmReadScatterVirtual(pProcess, ppMEMs, cHeaps << 1, 0);
- fReadHasMore = FALSE;
- for(i = 0; i < (cHeaps << 1); i++) {
- pMEM = ppMEMs[i];
- if(pMEM->cb != 0x1000) { continue; }
- pH = PH2 = (PVMMWIN_HEAP_SEGMENT64)ppMEMs[i]->pb;
- if(pH->SegmentSignature != 0xffeeffee) { continue; }
- if(pH->Heap != vaHeaps[i % cHeaps]) { continue; } // heap address mis-match
- if(pH->NumberOfPages >= 0x40000) { continue; } // heap size > 1GB == unrealistic.
- // set tag
- sprintf_s(szBuffer, MAX_PATH, "HEAP%02X", i % cHeaps);
- VmmMemMapTag(pProcess, pH->BaseAddress, pH->BaseAddress + (pH->NumberOfPages << 12), szBuffer, NULL, FALSE, FALSE);
- // prepare next read
- pMEM[i].cb = 0;
- if((i >= cHeaps) || fFirst) { // BLink
- j = i + ((i < cHeaps) ? cHeaps : 0);
- // BLink inside same page -> jump forward
- if((PH2->_ListEntry.Blink - pMEM[i].qwA < 0x800) && ((PH2->_ListEntry.Blink & 0xfff) >= sizeof(VMMWIN_HEAP_SEGMENT64))) {
- PH2 = (PVMMWIN_HEAP_SEGMENT64)(ppMEMs[i]->pb + (PH2->_ListEntry.Blink & 0xfff) - 0x18);
- }
- pMEM[j].qwA = (QWORD)-1;
- if((((PH2->_ListEntry.Blink - 0x18) & 0xffff) == 0) && ((PH2->_ListEntry.Blink - 0x18) != vaHeaps[i])) {
- pMEM[j].qwA = PH2->_ListEntry.Blink - 0x18;
- fReadHasMore = TRUE;
- }
- }
- if(i < cHeaps) { // FLink
- pMEM[i].qwA = (QWORD)-1;
- if((((pH->_ListEntry.Flink - 0x18) & 0xffff) == 0) && ((pH->_ListEntry.Flink - 0x18) != vaHeaps[i])) {
- pMEM[i].qwA = pH->_ListEntry.Flink - 0x18;
- fReadHasMore = TRUE;
- }
- }
- }
- fFirst = FALSE;
- } while(fReadHasMore && (++cLoopProtect < 0x40));
- LocalFree(ppMEMs);
-}
-
-/*
-* Identify 32-bit HEAPs in a process and tag them into the memory map.
-* NB! The 32-bit variant below is NOT robust. It will fail a lot of times
-* especially on older versions - but it will fail silently without causing
-* harm except a few extra reads. Probably due to bad hardcoded values. It's
-* primarily heap-header analysis that is failing. But it seems to mostly work
-* on newer windows versions.
-* WINXP is not supported.
-*/
-VOID VmmWin_ScanPebHeap32(_In_ PVMM_PROCESS pProcess, _In_ BOOL fWow64)
-{
- BOOL fReadHasMore, fFirst = TRUE;
- CHAR szBuffer[MAX_PATH];
- BYTE pbPEB[sizeof(PEB32)];
- PPEB32 pPEB = (PPEB32)pbPEB;
- DWORD i, j, cHeaps, cHeapsMax, cLoopProtect = 0;
- DWORD vaHeapPrimary, vaHeaps[0x80];
- PMEM_IO_SCATTER_HEADER pMEM, *ppMEMs = NULL;
- PVMMWIN_HEAP_SEGMENT32 pH, PH2;
- // 1: Read PEB
- if(!fWow64 && !pProcess->os.win.vaPEB) { return; }
- if(fWow64 && !pProcess->os.win.vaPEB32) { return; }
- if(!VmmRead(pProcess, (fWow64 ? pProcess->os.win.vaPEB32 : pProcess->os.win.vaPEB), pbPEB, sizeof(PEB32))) { return; }
- vaHeapPrimary = pPEB->ProcessHeap;
- cHeaps = pPEB->NumberOfHeaps;
- cHeapsMax = pPEB->MaximumNumberOfHeaps;
- if(cHeaps > 0x80) { return; } // probably not valid
- // 2: Read heap array
- if(!VmmRead(pProcess, pPEB->ProcessHeaps, (PBYTE)vaHeaps, sizeof(DWORD) * cHeaps)) { return; }
- if(vaHeaps[0] != vaHeapPrimary) { return; }
- // 3: Read heap headers in one go (scatter read)
- if(!LeechCore_AllocScatterEmpty(cHeaps << 1, &ppMEMs)) { return; }
- for(i = 0; i < cHeaps; i++) {
- if(vaHeaps[i] & 0xffff) {
- LocalFree(ppMEMs);
- return;
- }
- ppMEMs[i]->qwA = vaHeaps[i];
- }
- VmmReadScatterVirtual(pProcess, ppMEMs, cHeaps, 0);
- // 4: Analyze result
- do {
- VmmReadScatterVirtual(pProcess, ppMEMs, cHeaps << 1, 0);
- fReadHasMore = FALSE;
- for(i = 0; i < (cHeaps << 1); i++) {
- pMEM = ppMEMs[i];
- if(pMEM->cb != 0x1000) { continue; }
- pH = PH2 = (PVMMWIN_HEAP_SEGMENT32)ppMEMs[i]->pb;
- if(pH->SegmentSignature != 0xffeeffee) { continue; }
- if(pH->Heap != vaHeaps[i % cHeaps]) { continue; } // heap address mis-match
- if(pH->NumberOfPages >= 0x40000) { continue; } // heap size > 1GB == unrealistic.
- // set tag
- sprintf_s(szBuffer, MAX_PATH, "HEAP%02X", i % cHeaps);
- VmmMemMapTag(pProcess, pH->BaseAddress, (QWORD)pH->BaseAddress + ((QWORD)pH->NumberOfPages << 12), szBuffer, NULL, fWow64, FALSE);
- // prepare next read
- pMEM[i].cb = 0;
- if((i >= cHeaps) || fFirst) { // BLink
- j = i + ((i < cHeaps) ? cHeaps : 0);
- // BLink inside same page -> jump forward
- if((PH2->_ListEntry.Blink - pMEM[i].qwA < 0x800) && ((PH2->_ListEntry.Blink & 0xfff) >= sizeof(VMMWIN_HEAP_SEGMENT64))) {
- PH2 = (PVMMWIN_HEAP_SEGMENT32)(ppMEMs[i]->pb + (PH2->_ListEntry.Blink & 0xfff) - 0x18);
- }
- pMEM[j].qwA = (QWORD)-1;
- if((((PH2->_ListEntry.Blink - 0x18) & 0xffff) == 0) && ((PH2->_ListEntry.Blink - 0x18) != vaHeaps[i])) {
- pMEM[j].qwA = PH2->_ListEntry.Blink - 0x18;
- fReadHasMore = TRUE;
- }
- }
- if(i < cHeaps) { // FLink
- pMEM[i].qwA = (QWORD)-1;
- if((((pH->_ListEntry.Flink - 0x18) & 0xffff) == 0) && ((pH->_ListEntry.Flink - 0x18) != vaHeaps[i])) {
- pMEM[i].qwA = pH->_ListEntry.Flink - 0x18;
- fReadHasMore = TRUE;
- }
- }
- }
- fFirst = FALSE;
- } while(fReadHasMore && (++cLoopProtect < 0x40));
- LocalFree(ppMEMs);
-}
-
-/*
-* Identify module names by scanning for PE headers and tag them into the memory map.
-*/
-VOID VmmWin_ScanHeaderPE(_In_ PVMM_PROCESS pProcess)
-{
- DWORD cMap;
- PVMMOB_MEMMAP pObMemMap = NULL;
- PVMM_MEMMAP_ENTRY pMap;
- PVMM_MEMMAP_ENTRY ppMAPs[0x400];
- PPMEM_IO_SCATTER_HEADER ppMEMs = NULL;
- DWORD i, cMEMs = 0, cbImageSize;
- BOOL result;
- CHAR szBuffer[MAX_PATH];
- // 1: checks and allocate buffers for parallel read of MZ header candidates
- if(!LeechCore_AllocScatterEmpty(0x400, &ppMEMs)) { return; }
- if(!VmmMemMapGetEntries(pProcess, 0, &pObMemMap)) { return; }
- cMap = pObMemMap->cMap;
- pMap = pObMemMap->pMap;
- // 2: scan memory map for MZ header candidates and put them on list for read
- for(i = 0; i < cMap - 1; i++) {
- if(ctxVmm->tpMemoryModel == VMM_MEMORYMODEL_X86) {
- result =
- !(pMap[i].AddrBase & 0xffff) && // starts at even 0x10000 offset
- !pMap[i].szTag[0]; // tag not already set
- } else {
- result =
- (pMap[i].cPages == 1) && // PE header is only 1 page
- !(pMap[i].AddrBase & 0xffff) && // starts at even 0x10000 offset
- !pMap[i].szTag[0] && // tag not already set
- (pMap[i].fPage & VMM_MEMMAP_PAGE_NX) && // no-execute
- !(pMap[i + 1].fPage & VMM_MEMMAP_PAGE_NX); // next page is executable
- }
- if(result) {
- ppMEMs[cMEMs]->qwA = pMap[i].AddrBase;
- ppMAPs[cMEMs] = pMap + i;
- cMEMs++;
- if(cMEMs == 0x400) { break; }
- }
- }
- // 3: read all MZ header candicates previously selected and try load name from them (after read is successful)
- if(cMEMs) {
- VmmReadScatterVirtual(pProcess, ppMEMs, cMEMs, 0);
- for(i = 0; i < cMEMs; i++) {
- if(ppMEMs[i]->cb == 0x1000) {
- result = PE_GetModuleNameEx(pProcess, ppMAPs[i]->AddrBase, TRUE, ppMEMs[i]->pb, szBuffer, _countof(szBuffer), &cbImageSize);
- if(result && (cbImageSize < 0x01000000)) {
- VmmMemMapTag(pProcess, ppMAPs[i]->AddrBase, ppMAPs[i]->AddrBase + cbImageSize, szBuffer, NULL, FALSE, FALSE);
- }
- }
- }
- }
- LocalFree(ppMEMs);
- VmmOb_DECREF(pObMemMap);
-}
-
-// ----------------------------------------------------------------------------
-// WINDOWS EPROCESS WALKING FUNCTIONALITY FOR 64/32 BIT BELOW:
-// ----------------------------------------------------------------------------
-
-#define VMMPROC_EPROCESS_MAX_SIZE 0x500
-#define VMMWIN_EPROCESS_PREFETCH_MAX 0x200
-
-/*
-* Very ugly hack that tries to locate some offsets required withn the EPROCESS struct.
-*/
-VOID VmmWin_OffsetLocatorEPROCESS64(_In_ PVMM_PROCESS pSystemProcess)
-{
- BOOL f;
- WORD i;
- QWORD va1, vaPEB, paPEB;
- BYTE pb0[VMMPROC_EPROCESS_MAX_SIZE], pb1[VMMPROC_EPROCESS_MAX_SIZE], pbPage[0x1000];
- BYTE pbZero[0x800];
- QWORD paMax, paDTB_0, paDTB_1;
- PVMM_WIN_EPROCESS_OFFSET pOffsetEPROCESS = &ctxVmm->kernel.OffsetEPROCESS;
- ZeroMemory(pOffsetEPROCESS, sizeof(VMM_WIN_EPROCESS_OFFSET));
- if(!VmmRead(pSystemProcess, pSystemProcess->os.win.vaEPROCESS, pb0, VMMPROC_EPROCESS_MAX_SIZE)) { return; }
- if(ctxMain->cfg.fVerboseExtra) {
- vmmprintf_fn("%016llx %016llx\n", pSystemProcess->paDTB, pSystemProcess->os.win.vaEPROCESS);
- Util_PrintHexAscii(pb0, VMMPROC_EPROCESS_MAX_SIZE, 0);
- }
- // find offset State (static for now)
- if(*(PDWORD)(pb0 + 0x04)) { return; }
- pOffsetEPROCESS->State = 0x04;
- // find offset PML4 (static for now)
- if(pSystemProcess->paDTB != (0xfffffffffffff000 & *(PQWORD)(pb0 + 0x28))) { return; }
- pOffsetEPROCESS->DTB = 0x28;
- // find offset for Name
- for(i = 0, f = FALSE; i < VMMPROC_EPROCESS_MAX_SIZE - 8; i += 8) {
- if(*(PQWORD)(pb0 + i) == 0x00006D6574737953) {
- pOffsetEPROCESS->Name = i;
- f = TRUE;
- break;
- }
- }
- if(!f) { return; }
- // find offset for PID, FLink, BLink (assumed to be following eachother)
- for(i = 0, f = FALSE; i < VMMPROC_EPROCESS_MAX_SIZE - 8; i += 8) {
- if(*(PQWORD)(pb0 + i) == 4) {
- // PID = correct, this is a candidate
- if(0xffff000000000000 != (0xffff000000000003 & *(PQWORD)(pb0 + i + 8))) { continue; } // FLink not valid kernel pointer
- va1 = *(PQWORD)(pb0 + i + 8) - i - 8;
- f = VmmRead(pSystemProcess, va1, pb1, VMMPROC_EPROCESS_MAX_SIZE);
- if(!f) { continue; }
- f = FALSE;
- if((*(PQWORD)(pb1 + pOffsetEPROCESS->Name) != 0x6578652e73736d73) && // smss.exe
- (*(PQWORD)(pb1 + pOffsetEPROCESS->Name) != 0x7972747369676552) && // Registry
- (*(PQWORD)(pb1 + pOffsetEPROCESS->Name) != 0x5320657275636553)) // Secure System
- {
- continue;
- }
- if((*(PQWORD)(pb1 + i + 16) - i - 8) != pSystemProcess->os.win.vaEPROCESS) {
- continue;
- }
- pOffsetEPROCESS->PID = i;
- pOffsetEPROCESS->FLink = i + 8;
- pOffsetEPROCESS->BLink = i + 16;
- f = TRUE;
- break;
- }
- }
- if(!f) { return; }
- // skip over "processes" without PEB
- while((*(PQWORD)(pb1 + pOffsetEPROCESS->Name) == 0x5320657275636553) || // Secure System
- (*(PQWORD)(pb1 + pOffsetEPROCESS->Name) == 0x7972747369676552)) // Registry
- {
- va1 = *(PQWORD)(pb1 + pOffsetEPROCESS->FLink) - pOffsetEPROCESS->FLink;
- f = VmmRead(pSystemProcess, va1, pb1, VMMPROC_EPROCESS_MAX_SIZE);
- if(!f) { return; }
- }
- if(ctxMain->cfg.fVerboseExtra) {
- vmmprintf("---------------------------------------------------------------------------\n");
- Util_PrintHexAscii(pb1, VMMPROC_EPROCESS_MAX_SIZE, 0);
- }
- // find offset for PEB (in EPROCESS)
- for(i = 0x300, f = FALSE; i < 0x480; i += 8) {
- if(*(PQWORD)(pb0 + i)) { continue; }
-vaPEB = *(PQWORD)(pb1 + i);
-if(!vaPEB || (vaPEB & 0xffff800000000fff)) { continue; }
-// Verify potential PEB
-if(!VmmVirt2PhysEx(*(PQWORD)(pb1 + pOffsetEPROCESS->DTB), TRUE, vaPEB, &paPEB)) { continue; }
-if(!VmmReadPhysicalPage(paPEB, pbPage)) { continue; }
-if(*(PWORD)pbPage == 0x5a4d) { continue; } // MZ header -> likely entry point or something not PEB ...
-pOffsetEPROCESS->PEB = i;
-f = TRUE;
-break;
- }
- if(!f) { return; }
- // find "optional" offset for user cr3/pml4 (post meltdown only)
- // System have an entry pointing to a shadow PML4 which has empty user part
- // smss.exe do not have an entry since it's running as admin ...
- pOffsetEPROCESS->DTB_User = 0;
- ZeroMemory(pbZero, 0x800);
- paMax = ctxMain->dev.paMax;
- for(i = pOffsetEPROCESS->DTB + 8; i < VMMPROC_EPROCESS_MAX_SIZE - 8; i += 8) {
- paDTB_0 = *(PQWORD)(pb0 + i); // EPROCESS entry item of System
- paDTB_1 = *(PQWORD)(pb1 + i); // EPROCESS entry item of smss.exe
- f = ((paDTB_1 & ~1) != 0);
- f = f || (paDTB_0 == 0);
- f = f || (paDTB_0 & 0xffe);
- f = f || (paDTB_0 >= paMax);
- f = f || !VmmReadPhysicalPage((paDTB_0 & ~0xfff), pbPage);
- f = f || memcmp(pbPage, pbZero, 0x800);
- f = f || !VmmTlbPageTableVerify(pbPage, (paDTB_0 & ~0xfff), TRUE);
- if(!f) {
- pOffsetEPROCESS->DTB_User = i;
- break;
- }
- }
- vmmprintfvv_fn(
- "PID: %x STATE: %x DTB: %x DTB_User: %x NAME: %x PEB: %x FLink: %x\n",
- pOffsetEPROCESS->PID,
- pOffsetEPROCESS->State,
- pOffsetEPROCESS->DTB,
- pOffsetEPROCESS->DTB_User,
- pOffsetEPROCESS->Name,
- pOffsetEPROCESS->PEB,
- pOffsetEPROCESS->FLink);
- pOffsetEPROCESS->cbMaxOffset = min(VMMPROC_EPROCESS_MAX_SIZE, 16 + max(max(max(pOffsetEPROCESS->State, pOffsetEPROCESS->PID), max(pOffsetEPROCESS->Name, pOffsetEPROCESS->FLink)), max(pOffsetEPROCESS->DTB_User, max(pOffsetEPROCESS->DTB, pOffsetEPROCESS->PEB))));
- pOffsetEPROCESS->fValid = TRUE;
-}
-
-/*
-* Try walk the EPROCESS list in the Windows kernel to enumerate processes into
-* the VMM/PROC file system.
-* NB! This may be done to refresh an existing PID cache hence migration code.
-* -- pSystemProcess
-* -- return
-*/
-BOOL VmmWin_EnumerateEPROCESS64(_In_ PVMM_PROCESS pSystemProcess, _In_ BOOL fTotalRefresh)
-{
- PQWORD pqwDTB, pqwDTB_User, pqwFLink, pqwBLink, pqwPEB;
- PDWORD pdwState, pdwPID;
- LPSTR szName;
- BYTE pb[VMMPROC_EPROCESS_MAX_SIZE];
- PVMM_PROCESS pObProcess = NULL;
- QWORD vaSystemEPROCESS, vaEPROCESS, cNewProcessCollision = 0;
- DWORD iProc = 0;
- BOOL fShowTerminated, fUser;
- PVMM_WIN_EPROCESS_OFFSET pOffsetEPROCESS = &ctxVmm->kernel.OffsetEPROCESS;
- PVMMOB_DATASET pObSetAddressEPROCESS = NULL;
- fShowTerminated = ctxVmm->flags & VMM_FLAG_PROCESS_SHOW_TERMINATED;
- vaSystemEPROCESS = pSystemProcess->os.win.vaEPROCESS;
- // retrieve offsets
- if(!pOffsetEPROCESS->fValid) {
- VmmWin_OffsetLocatorEPROCESS64(pSystemProcess);
- if(!pOffsetEPROCESS->fValid) {
- vmmprintf("VmmProc: Unable to locate EPROCESS offsets.\n");
- return FALSE;
- }
- }
- vmmprintfvv_fn("%016llx %016llx\n", pSystemProcess->paDTB, vaSystemEPROCESS);
- pdwState = (PDWORD)(pb + pOffsetEPROCESS->State);
- pdwPID = (PDWORD)(pb + pOffsetEPROCESS->PID);
- pqwDTB = (PQWORD)(pb + pOffsetEPROCESS->DTB);
- pqwDTB_User = (PQWORD)(pb + pOffsetEPROCESS->DTB_User);
- pqwFLink = (PQWORD)(pb + pOffsetEPROCESS->FLink);
- pqwBLink = (PQWORD)(pb + pOffsetEPROCESS->BLink);
- szName = (LPSTR)(pb + pOffsetEPROCESS->Name);
- pqwPEB = (PQWORD)(pb + pOffsetEPROCESS->PEB);
- // prefetch pages into cache (if any)
- pObSetAddressEPROCESS = VmmObContainer_GetOb(&ctxVmm->ObCEPROCESSCachePrefetch);
- VmmCachePrefetchPages(pSystemProcess, pObSetAddressEPROCESS);
- VmmOb_DECREF(pObSetAddressEPROCESS);
- // initialize address set
- if(!(pObSetAddressEPROCESS = VmmObDataSet_Alloc(TRUE))) { return FALSE; }
- VmmObDataSet_Put(pObSetAddressEPROCESS, vaSystemEPROCESS);
- // loop!
- vmmprintfvv_fn(" # STATE PID DTB EPROCESS PEB NAME \n");
- for(iProc = 0; iProc < pObSetAddressEPROCESS->c; iProc++) {
- vaEPROCESS = pObSetAddressEPROCESS->pObData->pList[iProc].Value;
- if(!VmmRead(pSystemProcess, vaEPROCESS, pb, pOffsetEPROCESS->cbMaxOffset)) { continue; }
- if(*pqwDTB & 0xffffff0000000000) { continue; }
- VmmOb_DECREF(pObProcess);
- pObProcess = NULL;
- if(*pqwDTB && *(PQWORD)szName && (fShowTerminated || !*pdwState)) {
- fUser =
- !((*pdwPID == 4) || ((*pdwState == 0) && (*pqwPEB == 0))) ||
- (*(PQWORD)(szName + 0x00) == 0x72706d6f436d654d) && (*(PDWORD)(szName + 0x08) == 0x69737365); // MemCompression "process"
- pObProcess = VmmProcessCreateEntry(
- fTotalRefresh,
- *pdwPID,
- *pdwState,
- ~0xfff & *pqwDTB,
- pOffsetEPROCESS->DTB_User ? (~0xfff & *pqwDTB_User) : 0,
- szName,
- fUser);
- if(!pObProcess) {
- vmmprintfv("VMM: WARNING: PID '%i' already exists.\n", *pdwPID);
- if(++cNewProcessCollision >= 8) {
- continue;
- }
- }
- }
- if(pObProcess) {
- pObProcess->os.win.vaEPROCESS = vaEPROCESS;
- if(*pqwPEB % PAGE_SIZE) {
- vmmprintfv("VMM: WARNING: Bad PEB alignment for PID: '%i' (0x%016llx).\n", *pdwPID, *pqwPEB);
- } else {
- pObProcess->os.win.vaPEB = *pqwPEB;
- }
- } else {
- szName[14] = 0; // in case of bad string data ...
- }
- vmmprintfvv_fn("%04i (%s) %08x %012llx %016llx %012llx %s\n",
- iProc,
- pObProcess ? "list" : "skip",
- *pdwPID,
- ~0xfff & *pqwDTB,
- vaEPROCESS,
- *pqwPEB,
- szName);
- // Add FLink & BLink
- if(0xffff800000000000 == (0xffff800000000007 & *pqwFLink)) {
- VmmObDataSet_Put(pObSetAddressEPROCESS, *pqwFLink - pOffsetEPROCESS->FLink);
- }
- if(0xffff800000000000 == (0xffff800000000007 & *pqwBLink)) {
- VmmObDataSet_Put(pObSetAddressEPROCESS, *pqwBLink - pOffsetEPROCESS->FLink);
- }
- }
- VmmObContainer_SetOb(&ctxVmm->ObCEPROCESSCachePrefetch, pObSetAddressEPROCESS);
- VmmOb_DECREF(&pObSetAddressEPROCESS);
- VmmOb_DECREF(pObProcess);
- VmmProcessCreateFinish();
- return (iProc > 10);
-}
-
-/*
-* Very ugly hack that tries to locate some offsets required withn the EPROCESS struct.
-*/
-VOID VmmWin_OffsetLocatorEPROCESS32(_In_ PVMM_PROCESS pSystemProcess)
-{
- BOOL f;
- WORD i;
- DWORD va1, vaPEB;
- QWORD paPEB;
- BYTE pb0[VMMPROC_EPROCESS_MAX_SIZE], pb1[VMMPROC_EPROCESS_MAX_SIZE], pbPage[0x1000];
- PVMM_WIN_EPROCESS_OFFSET pOffsetEPROCESS = &ctxVmm->kernel.OffsetEPROCESS;
- ZeroMemory(pOffsetEPROCESS, sizeof(VMM_WIN_EPROCESS_OFFSET));
- //BYTE pbZero[0x800]
- //QWORD paMax, paDTB_0, paDTB_1;
- if(!VmmRead(pSystemProcess, pSystemProcess->os.win.vaEPROCESS, pb0, VMMPROC_EPROCESS_MAX_SIZE)) { return; }
- if(ctxMain->cfg.fVerboseExtra) {
- vmmprintf("vmmwin.c!32_OffsetLocatorEPROCESS: %016llx %016llx\n", pSystemProcess->paDTB, pSystemProcess->os.win.vaEPROCESS);
- Util_PrintHexAscii(pb0, VMMPROC_EPROCESS_MAX_SIZE, 0);
- }
- // find offset State (static for now)
- if(*(PDWORD)(pb0 + 0x04)) { return; }
- pOffsetEPROCESS->State = 0x04;
- // find offset PML4 (static for now)
- //if(pSystemProcess->paDTB != (0xfffff000 & *(PDWORD)(pb0 + 0x18))) { return FALSE; }
- pOffsetEPROCESS->DTB = 0x18;
- // find offset for Name
- for(i = 0, f = FALSE; i < VMMPROC_EPROCESS_MAX_SIZE - 4; i += 4) {
- if(*(PQWORD)(pb0 + i) == 0x00006D6574737953) {
- pOffsetEPROCESS->Name = i;
- f = TRUE;
- break;
- }
- }
- if(!f) { return; }
- // find offset for PID, FLink, BLink (assumed to be following eachother)
- for(i = 0, f = FALSE; i < VMMPROC_EPROCESS_MAX_SIZE - 4; i += 4) {
- if(*(PDWORD)(pb0 + i) == 4) {
- // PID = correct, this is a candidate
- if(0x80000000 != (0x80000003 & *(PDWORD)(pb0 + i + 4))) { continue; } // FLink not valid kernel pointer
- va1 = *(PDWORD)(pb0 + i + 4) - i - 4;
- f = VmmRead(pSystemProcess, va1, pb1, VMMPROC_EPROCESS_MAX_SIZE);
- if(!f) { continue; }
- f = FALSE;
- if((*(PQWORD)(pb1 + pOffsetEPROCESS->Name) != 0x6578652e73736d73) && // smss.exe
- (*(PQWORD)(pb1 + pOffsetEPROCESS->Name) != 0x7972747369676552) && // Registry
- (*(PQWORD)(pb1 + pOffsetEPROCESS->Name) != 0x5320657275636553)) // Secure System
- {
- continue;
- }
- if((*(PDWORD)(pb1 + i + 8) - i - 4) != pSystemProcess->os.win.vaEPROCESS) {
- continue;
- }
- pOffsetEPROCESS->PID = i;
- pOffsetEPROCESS->FLink = i + 4;
- pOffsetEPROCESS->BLink = i + 8;
- f = TRUE;
- break;
- }
- }
- if(!f) { return; }
- // skip over "processes" without PEB
- while((*(PQWORD)(pb1 + pOffsetEPROCESS->Name) == 0x5320657275636553) || // Secure System
- (*(PQWORD)(pb1 + pOffsetEPROCESS->Name) == 0x7972747369676552)) // Registry
- {
- va1 = *(PDWORD)(pb1 + pOffsetEPROCESS->FLink) - pOffsetEPROCESS->FLink;
- f = VmmRead(pSystemProcess, va1, pb1, VMMPROC_EPROCESS_MAX_SIZE);
- if(!f) { return; }
- }
- if(ctxMain->cfg.fVerboseExtra) {
- vmmprintf("---------------------------------------------------------------------------\n");
- Util_PrintHexAscii(pb1, VMMPROC_EPROCESS_MAX_SIZE, 0);
- }
- // find offset for PEB (in EPROCESS)
- for(i = 0x100, f = FALSE; i < 0x240; i += 4) {
- if(*(PDWORD)(pb0 + i)) { continue; }
- vaPEB = *(PDWORD)(pb1 + i);
- if(!vaPEB || (vaPEB & 0x80000fff)) { continue; }
- // Verify potential PEB
- if(!VmmVirt2PhysEx(*(PDWORD)(pb1 + pOffsetEPROCESS->DTB), TRUE, vaPEB, &paPEB)) { continue; }
- if(!VmmReadPhysicalPage(paPEB, pbPage)) { continue; }
- if(*(PWORD)pbPage == 0x5a4d) { continue; } // MZ header -> likely entry point or something not PEB ...
- pOffsetEPROCESS->PEB = i;
- f = TRUE;
- break;
- }
- if(!f) { return; }
- // find "optional" offset for user cr3/pml4 (post meltdown only)
- // System have an entry pointing to a shadow PML4 which has empty user part
- // smss.exe do not have an entry since it's running as admin ...
- pOffsetEPROCESS->DTB_User = 0;
- /*
- ZeroMemory(pbZero, 0x800);
- paMax = ctxMain->cfg.paAddrMax;
- for(i = *pdwoDTB + 4; i < VMMPROC_EPROCESS_MAX_SIZE - 4; i += 4) {
- paDTB_0 = *(PDWORD)(pb0 + i); // EPROCESS entry item of System
- paDTB_1 = *(PDWORD)(pb1 + i); // EPROCESS entry item of smss.exe
- f = (paDTB_1 != 0);
- f = f || (paDTB_0 == 0);
- f = f || (paDTB_0 & 0x1f);
- f = f || (paDTB_0 >= paMax);
- f = f || !VmmReadPhysicalPage(paDTB_0, pbPage);
- f = f || memcmp(pbPage, pbZero, 0x800);
- f = f || !VmmTlbPageTableVerify(pbPage, paDTB_0, TRUE);
- if(!f) {
- *dwoDTB_User = i;
- break;
- }
- }
- */
- vmmprintfvv_fn(
- "PID: %x STATE: %x DTB: %x DTB_User: %x NAME: %x PEB: %x FLink: %x\n",
- pOffsetEPROCESS->PID,
- pOffsetEPROCESS->State,
- pOffsetEPROCESS->DTB,
- pOffsetEPROCESS->DTB_User,
- pOffsetEPROCESS->Name,
- pOffsetEPROCESS->PEB,
- pOffsetEPROCESS->FLink);
- pOffsetEPROCESS->cbMaxOffset = min(VMMPROC_EPROCESS_MAX_SIZE, 16 + max(max(max(pOffsetEPROCESS->State, pOffsetEPROCESS->PID), max(pOffsetEPROCESS->Name, pOffsetEPROCESS->FLink)), max(pOffsetEPROCESS->DTB_User, max(pOffsetEPROCESS->DTB, pOffsetEPROCESS->PEB))));
- pOffsetEPROCESS->fValid = TRUE;
-}
-
-BOOL VmmWin_EnumerateEPROCESS32(_In_ PVMM_PROCESS pSystemProcess, _In_ BOOL fTotalRefresh)
-{
- PDWORD pdwDTB, pdwDTB_User, pdwFLink, pdwBLink, pdwPEB;
- PDWORD pdwState, pdwPID;
- LPSTR szName;
- BYTE pb[VMMPROC_EPROCESS_MAX_SIZE];
- PVMM_PROCESS pObProcess = NULL;
- DWORD vaSystemEPROCESS, vaEPROCESS, cPID = 0, cNewProcessCollision = 0;
- DWORD iProc = 0;
- BOOL fShowTerminated, fUser;
- PVMM_WIN_EPROCESS_OFFSET pOffsetEPROCESS = &ctxVmm->kernel.OffsetEPROCESS;
- PVMMOB_DATASET pObSetAddressEPROCESS = NULL;
- fShowTerminated = ctxVmm->flags & VMM_FLAG_PROCESS_SHOW_TERMINATED;
- vaSystemEPROCESS = (DWORD)pSystemProcess->os.win.vaEPROCESS;
- // retrieve offsets
- if(!pOffsetEPROCESS->fValid) {
- VmmWin_OffsetLocatorEPROCESS32(pSystemProcess);
- if(!pOffsetEPROCESS->fValid) {
- vmmprintf("VmmProc: Unable to locate EPROCESS offsets.\n");
- return FALSE;
- }
- }
- vmmprintfvv_fn("%016llx %08x\n", pSystemProcess->paDTB, vaSystemEPROCESS);
- pdwState = (PDWORD)(pb + pOffsetEPROCESS->State);
- pdwPID = (PDWORD)(pb + pOffsetEPROCESS->PID);
- pdwDTB = (PDWORD)(pb + pOffsetEPROCESS->DTB);
- pdwDTB_User = (PDWORD)(pb + pOffsetEPROCESS->DTB_User);
- pdwFLink = (PDWORD)(pb + pOffsetEPROCESS->FLink);
- pdwBLink = (PDWORD)(pb + pOffsetEPROCESS->BLink);
- szName = (LPSTR)(pb + pOffsetEPROCESS->Name);
- pdwPEB = (PDWORD)(pb + pOffsetEPROCESS->PEB);
- // prefetch pages into cache (if any)
- pObSetAddressEPROCESS = VmmObContainer_GetOb(&ctxVmm->ObCEPROCESSCachePrefetch);
- VmmCachePrefetchPages(pSystemProcess, pObSetAddressEPROCESS);
- VmmOb_DECREF(pObSetAddressEPROCESS);
- // initialize address set
- if(!(pObSetAddressEPROCESS = VmmObDataSet_Alloc(TRUE))) { return FALSE; }
- VmmObDataSet_Put(pObSetAddressEPROCESS, vaSystemEPROCESS);
- // loop!
- vmmprintfvv_fn(" # STATE PID DTB EPROCESS PEB NAME \n");
-
- for(iProc = 0; iProc < pObSetAddressEPROCESS->c; iProc++) {
- vaEPROCESS = (DWORD)pObSetAddressEPROCESS->pObData->pList[iProc].Value;
- if(!VmmRead(pSystemProcess, vaEPROCESS, pb, pOffsetEPROCESS->cbMaxOffset)) { continue; }
- if(*pdwDTB & 0x1f) { continue; }
- VmmOb_DECREF(pObProcess);
- pObProcess = NULL;
- if(*pdwDTB && *(PQWORD)szName && (fShowTerminated || !*pdwState)) {
- fUser =
- !((*pdwPID == 4) || ((*pdwState == 0) && (*pdwPEB == 0))) ||
- ((*(PQWORD)(szName + 0x00) == 0x72706d6f436d654d) && (*(PDWORD)(szName + 0x08) == 0x69737365)); // MemCompression "process"
- pObProcess = VmmProcessCreateEntry(
- fTotalRefresh,
- *pdwPID,
- *pdwState,
- *pdwDTB & 0xffffffe0,
- pOffsetEPROCESS->DTB_User ? (~0xfff & *pdwDTB_User) : 0,
- szName,
- fUser);
- }
- if(pObProcess) {
- pObProcess->os.win.vaEPROCESS = vaEPROCESS;
- if(*pdwPEB % PAGE_SIZE) {
- vmmprintfv("VMM: WARNING: Bad PEB alignment for PID: '%i' (0x%08x).\n", *pdwPID, *pdwPEB);
- } else {
- pObProcess->os.win.vaPEB = *pdwPEB;
- }
- if(!pObProcess) {
- vmmprintfv("VMM: WARNING: PID '%i' already exists.\n", *pdwPID);
- if(++cNewProcessCollision >= 8) {
- break;
- }
- }
- } else {
- szName[14] = 0; // in case of bad string data ...
- }
- vmmprintfvv_fn("%04i (%s) %08x %08x %08x %08x %s\n",
- iProc,
- pObProcess ? "list" : "skip",
- *pdwPID,
- *pdwDTB & 0xffffffe0,
- vaEPROCESS,
- *pdwPEB,
- szName);
- // Add FLink & BLink
- if(0x80000000 == (0x80000003 & *pdwFLink)) {
- VmmObDataSet_Put(pObSetAddressEPROCESS, *pdwFLink - pOffsetEPROCESS->FLink);
- }
- if(0x80000000 == (0x80000003 & *pdwBLink)) {
- VmmObDataSet_Put(pObSetAddressEPROCESS, *pdwBLink - pOffsetEPROCESS->FLink);
- }
- }
- VmmObContainer_SetOb(&ctxVmm->ObCEPROCESSCachePrefetch, pObSetAddressEPROCESS);
- VmmOb_DECREF(&pObSetAddressEPROCESS);
- VmmOb_DECREF(pObProcess);
- VmmProcessCreateFinish();
- return (iProc > 10);
-}
-
-BOOL VmmWin_EnumerateEPROCESS(_In_ PVMM_PROCESS pSystemProcess, _In_ BOOL fRefreshTotal)
-{
- // spider TLB and set up initial system process and enumerate EPROCESS
- VmmTlbSpider(pSystemProcess);
- switch(ctxVmm->tpMemoryModel) {
- case VMM_MEMORYMODEL_X64:
- return VmmWin_EnumerateEPROCESS64(pSystemProcess, fRefreshTotal);
- case VMM_MEMORYMODEL_X86:
- case VMM_MEMORYMODEL_X86PAE:
- return VmmWin_EnumerateEPROCESS32(pSystemProcess, fRefreshTotal);
- }
- return FALSE;
-}
-
-VOID VmmWin_ModuleMapInitialize(_In_ PVMM_PROCESS pProcess)
-{
- VmmWin_InitializeLdrModules(pProcess);
-}
-
-VOID VmmWin_ScanTagsMemMap(_In_ PVMM_PROCESS pProcess)
-{
- // scan for not already known pe name headers
- VmmWin_ScanHeaderPE(pProcess);
- // scan for heaps
- if(ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X64) {
- VmmWin_ScanPebHeap64(pProcess);
- if(pProcess->os.win.fWow64) {
- VmmWin_ScanPebHeap32(pProcess, TRUE);
- }
- }
- if(ctxVmm->tpSystem == VMM_SYSTEM_WINDOWS_X86) {
- VmmWin_ScanPebHeap32(pProcess, FALSE);
- }
-}
diff --git a/vmm/vmmwin.h b/vmm/vmmwin.h
deleted file mode 100644
index 7d45e68..0000000
--- a/vmm/vmmwin.h
+++ /dev/null
@@ -1,122 +0,0 @@
-// vmmwin.h : definitions related to windows operating system and processes.
-// parsing of virtual memory. Windows related features only.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifndef __VMMWIN_H__
-#define __VMMWIN_H__
-#include "vmm.h"
-
-typedef struct tdVMMWIN_EAT_ENTRY {
- QWORD vaFunction;
- DWORD vaFunctionOffset;
- CHAR szFunction[40];
-} VMMPROC_WINDOWS_EAT_ENTRY, *PVMMPROC_WINDOWS_EAT_ENTRY;
-
-typedef struct tdVMMWIN_IAT_ENTRY {
- ULONG64 vaFunction;
- CHAR szFunction[40];
- CHAR szModule[64];
-} VMMWIN_IAT_ENTRY, *PVMMWIN_IAT_ENTRY;
-
-/*
-* Load the size of the required display buffer for sections, imports and export
-* into the pModule struct. The size is a direct consequence of the number of
-* functions since fixed line sizes are used for all these types. Loading is
-* done in a recource efficient way to minimize I/O as much as possible.
-* -- pProcess
-* -- pModule
-*/
-VOID VmmWin_PE_SetSizeSectionIATEAT_DisplayBuffer(_In_ PVMM_PROCESS pProcess, _Inout_ PVMM_MODULEMAP_ENTRY pModule);
-
-/*
-* Walk the export address table (EAT) from a given pProcess and store it in the
-* in the caller supplied pEATs/pcEATs structures.
-* -- pProcess
-* -- pModule
-* -- pEATs
-* -- cEATs
-* -- pcEATs = number of actual items of pEATs written.
-* -- return
-*/
-_Success_(return)
-BOOL VmmWin_PE_LoadEAT_DisplayBuffer(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _Out_writes_opt_(cEATs) PVMMPROC_WINDOWS_EAT_ENTRY pEATs, _In_ DWORD cEATs, _Out_ PDWORD pcEATs);
-
-/*
-* Walk the import address table (IAT) from a given pProcess and store it in the
-* in the caller supplied pIATs/pcIATs structures.
-* -- pProcess
-* -- pModule
-* -- pIATs
-* -- cIATs
-* -- pcIATs = number of actual items of pIATs on exit
-*/
-VOID VmmWin_PE_LoadIAT_DisplayBuffer(_In_ PVMM_PROCESS pProcess, _In_ PVMM_MODULEMAP_ENTRY pModule, _Out_writes_(*pcIATs) PVMMWIN_IAT_ENTRY pIATs, _In_ DWORD cIATs, _Out_ PDWORD pcIATs);
-
-/*
-* Fill the pbDisplayBuffer with a human readable version of the data directories.
-* This is guaranteed to be exactly 864 bytes (excluding NULL terminator).
-* Alternatively copy the 16 data directories into pDataDirectoryOpt.
-* -- pProcess
-* -- pModule
-* -- pbDisplayBufferOpt
-* -- cbDisplayBufferMax
-* -- pcbDisplayBuffer
-* -- pDataDirectoryOpt
-*/
-VOID VmmWin_PE_DIRECTORY_DisplayBuffer(
- _In_ PVMM_PROCESS pProcess,
- _In_ PVMM_MODULEMAP_ENTRY pModule,
- _Out_writes_bytes_opt_(*pcbDisplayBuffer) PBYTE pbDisplayBufferOpt,
- _In_ DWORD cbDisplayBufferMax,
- _Out_opt_ PDWORD pcbDisplayBuffer,
- _Out_writes_opt_(16) PIMAGE_DATA_DIRECTORY pDataDirectoryOpt);
-
-/*
-* Fill the pbDisplayBuffer with a human readable version of the PE sections.
-* Alternatively copy the sections into the pSectionsOpt buffer.
-* -- pProcess
-* -- pModule
-* -- pbDisplayBufferOpt
-* -- cbDisplayBufferMax
-* -- pcbDisplayBuffer
-* -- pcSectionsOpt = size of buffer pSectionsOpt on entry, # returned entries on exit
-* -- pSectionsOpt
-*/
-VOID VmmWin_PE_SECTION_DisplayBuffer(
- _In_ PVMM_PROCESS pProcess,
- _In_ PVMM_MODULEMAP_ENTRY pModule,
- _Out_writes_bytes_opt_(*pcbDisplayBuffer) PBYTE pbDisplayBufferOpt,
- _In_ DWORD cbDisplayBufferMax,
- _Out_opt_ PDWORD pcbDisplayBuffer,
- _Inout_opt_ PDWORD pcSectionsOpt,
- _Out_writes_opt_(*pcSectionsOpt) PIMAGE_SECTION_HEADER pSectionsOpt);
-
-/*
-* Initialize the module names into the ctxVMM. This is performed by a PEB/Ldr
-* scan of in-process memory structures. This may be unreliable of process is
-* obfuscated.
-* -- pProcess
-*/
-VOID VmmWin_ModuleMapInitialize(_In_ PVMM_PROCESS pProcess);
-
-/*
-* Scan the process for various information that is put into the memory map. It
-* is recommended to initialize the ModuleMap before calling this function so it
-* can skip trying do double work identifying already known modules.
-* -- pProcess
-*/
-VOID VmmWin_ScanTagsMemMap(_In_ PVMM_PROCESS pProcess);
-
-/*
-* Try walk the EPROCESS list in the Windows kernel to enumerate processes into
-* the VMM/PROC file system.
-* NB! This may be done to refresh an existing PID cache hence migration code.
-* -- fTotalRefresh = create completely new process entries (instead of updating).
-* -- pSystemProcess
-* -- return
-*/
-BOOL VmmWin_EnumerateEPROCESS(_In_ PVMM_PROCESS pSystemProcess, _In_ BOOL fRefreshTotal);
-
-#endif /* __VMMWIN_H__ */
diff --git a/vmm/vmmwininit.c b/vmm/vmmwininit.c
deleted file mode 100644
index eface21..0000000
--- a/vmm/vmmwininit.c
+++ /dev/null
@@ -1,520 +0,0 @@
-// vmmwininit.c : implementation of detection mechanisms for Windows operating
-// systems. Contains functions for detecting DTB and Memory Model
-// as well as the Windows kernel base and core functionality.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-
-#include "vmm.h"
-#include "vmmwin.h"
-#include "pe.h"
-#include "util.h"
-
-/*
-* Scan a page table hierarchy between virtual addresses between vaMin and vaMax
-* for the first occurence of large 2MB pages. This is usually 'ntoskrnl.exe' if
-* the OS is Windows. 'ntoskrnl.exe'.
-* -- paTable = set to: physical address of PML4
-* -- vaBase = set to 0
-* -- vaMin = 0xFFFFF80000000000 (if windows kernel)
-* -- vaMax = 0xFFFFF803FFFFFFFF (if windows kernel)
-* -- cPML = set to 4
-* -- pvaBase
-* -- pcbSize
-*/
-VOID VmmWinInit_FindNtosScan64_LargePageWalk(_In_ QWORD paTable, _In_ QWORD vaBase, _In_ QWORD vaMin, _In_ QWORD vaMax, _In_ BYTE iPML, _Inout_ PQWORD pvaBase, _Inout_ PQWORD pcbSize)
-{
- const QWORD PML_REGION_SIZE[5] = { 0, 12, 21, 30, 39 };
- QWORD i, pte, vaCurrent, vaSizeRegion;
- PVMMOB_MEM pObPTEs = NULL;
- pObPTEs = VmmTlbGetPageTable(paTable, FALSE);
- if(!pObPTEs) { return; }
- if(iPML == 4) {
- *pvaBase = 0;
- *pcbSize = 0;
- if(!VmmTlbPageTableVerify(pObPTEs->pb, paTable, TRUE)) { goto finish; }
- vaBase = 0;
- }
- for(i = 0; i < 512; i++) {
- // address in range
- vaSizeRegion = 1ULL << PML_REGION_SIZE[iPML];
- vaCurrent = vaBase + (i << PML_REGION_SIZE[iPML]);
- vaCurrent |= (vaCurrent & 0x0000800000000000) ? 0xffff000000000000 : 0; // sign extend
- if(*pvaBase && (vaCurrent > (*pvaBase + *pcbSize))) { goto finish; }
- if(vaCurrent < vaMin) { continue; }
- if(vaCurrent > vaMax) { goto finish; }
- // check PTEs
- pte = pObPTEs->pqw[i];
- if(!(pte & 0x01)) { continue; } // NOT VALID
- if(iPML == 2) {
- if(!(pte & 0x80)) { continue; }
- if(!*pvaBase) { *pvaBase = vaCurrent; }
- *pcbSize += 0x200000;
- continue;
- } else {
- if(pte & 0x80) { continue; } // PS = 1
- VmmWinInit_FindNtosScan64_LargePageWalk(pte & 0x0000fffffffff000, vaCurrent, vaMin, vaMax, iPML - 1, pvaBase, pcbSize);
- }
- }
-finish:
- VmmOb_DECREF(pObPTEs);
-}
-
-/*
-* Sometimes the PageDirectoryBase (PML4) is known, but the kernel location may
-* be unknown. This functions walks the page table in the area in which ntoskrnl
-* is loaded looking for 2MB large pages. If an area in 2MB pages are found it
-* is scanned for the ntoskrnl.exe base.
-* -- pSystemProcess
-* -- return = virtual address of ntoskrnl.exe base if successful, otherwise 0.
-*/
-QWORD VmmWinInit_FindNtosScan64(PVMM_PROCESS pSystemProcess)
-{
- PBYTE pb;
- QWORD p, o, vaCurrentMin, vaBase, cbSize;
- CHAR szModuleName[MAX_PATH] = { 0 };
- vaCurrentMin = 0xFFFFF80000000000;
- while(TRUE) {
- vaBase = 0;
- cbSize = 0;
- VmmWinInit_FindNtosScan64_LargePageWalk(pSystemProcess->paDTB, 0, vaCurrentMin, 0xFFFFF807FFFFFFFF, 4, &vaBase, &cbSize);
- if(!vaBase) { return 0; }
- vaCurrentMin = vaBase + cbSize;
- if(cbSize >= 0x01000000) { continue; } // too big
- if(cbSize <= 0x00400000) { continue; } // too small
- // try locate ntoskrnl.exe base inside suggested area
- if(!(pb = (PBYTE)LocalAlloc(0, cbSize))) { return 0; }
- VmmReadEx(pSystemProcess, vaBase, pb, (DWORD)cbSize, NULL, 0);
- for(p = 0; p < cbSize; p += 0x1000) {
- // check for (1) MZ header, (2) POOLCODE section, (3) ntoskrnl.exe module name
- if(*(PWORD)(pb + p) != 0x5a4d) { continue; } // MZ header
- for(o = 0; o < 0x1000; o += 8) {
- if(*(PQWORD)(pb + p + o) == 0x45444F434C4F4F50) { // POOLCODE
- PE_GetModuleNameEx(pSystemProcess, vaBase + p, FALSE, pb + p, szModuleName, _countof(szModuleName), NULL);
- if(!_stricmp(szModuleName, "ntoskrnl.exe")) {
- LocalFree(pb);
- return vaBase + p;
- }
- }
- }
- }
- LocalFree(pb);
- }
- return 0;
-}
-
-/*
-* Locate the virtual base address of 'ntoskrnl.exe' given any address inside
-* the kernel. Localization will be done by a scan-back method. A maximum of
-* 32MB will be scanned back.
-* -- pSystemProcess
-* -- return = virtual address of ntoskrnl.exe base if successful, otherwise 0
-*/
-QWORD VmmWinInit_FindNtosScanHint64(_In_ PVMM_PROCESS pSystemProcess, _In_ QWORD vaHint)
-{
- PBYTE pb;
- QWORD vaBase, o, p, vaNtosBase = 0;
- DWORD cbRead;
- CHAR szModuleName[MAX_PATH] = { 0 };
- pb = LocalAlloc(0, 0x00200000);
- if(!pb) { goto cleanup; }
- // Scan back in 2MB chunks a time, (ntoskrnl.exe is loaded in 2MB pages).
- for(vaBase = vaHint & ~0x1fffff; vaBase + 0x02000000 > vaHint; vaBase -= 0x200000) {
- VmmReadEx(pSystemProcess, vaBase, pb, 0x200000, &cbRead, 0);
- // only fail here if all virtual memory in read fails. reason is that kernel is
- // properly mapped in memory (with NX MZ header in separate page) with empty
- // space before next valid kernel pages when running Virtualization Based Security.
- if(!cbRead) { goto cleanup; }
- for(p = 0; p < 0x200000; p += 0x1000) {
- // check for (1) MZ header, (2) POOLCODE section, (3) ntoskrnl.exe module name
- if(*(PWORD)(pb + p) != 0x5a4d) { continue; } // MZ header
- for(o = 0; o < 0x1000; o += 8) {
- if(*(PQWORD)(pb + p + o) == 0x45444F434C4F4F50) { // POOLCODE
- PE_GetModuleNameEx(pSystemProcess, vaBase + p, FALSE, pb + p, szModuleName, _countof(szModuleName), NULL);
- if(!_stricmp(szModuleName, "ntoskrnl.exe")) {
- LocalFree(pb);
- return vaBase + p;
- }
- }
- }
- }
- }
-cleanup:
- LocalFree(pb);
- return vaNtosBase;
-}
-
-/*
-* scans the relatively limited memory space 0x80000000-0x83ffffff for the base
-* of 'ntoskrnl.exe'. NB! this is a very non-optimized way of doing things and
-* should be improved upon to increase startup performance - but 64MB is not a
-* huge amount of memory and it's only scanned at startup ...
-* -- pSystemProcess
-* -- return = virtual address of ntoskrnl.exe base if successful, otherwise 0.
-*/
-DWORD VmmWinInit_FindNtosScan32(_In_ PVMM_PROCESS pSystemProcess)
-{
- DWORD o, p;
- PBYTE pb;
- CHAR szModuleName[MAX_PATH] = { 0 };
- if(!(pb = LocalAlloc(LMEM_ZEROINIT, 0x04000000))) { return 0; }
- for(p = 0; p < 0x04000000; p += 0x1000) {
- // read 8MB chunks when required.
- if(0 == p % 0x00800000) {
- VmmReadEx(pSystemProcess, 0x80000000ULL + p, pb + p, 0x00800000, NULL, 0);
- }
- // check for (1) MZ header, (2) POOLCODE section, (3) ntoskrnl.exe module name
- if(*(PWORD)(pb + p) != 0x5a4d) { continue; } // MZ header
- for(o = 0; o < 0x1000; o += 8) {
- if(*(PQWORD)(pb + p + o) == 0x45444F434C4F4F50) { // POOLCODE
- PE_GetModuleNameEx(pSystemProcess, 0x80000000ULL + p, FALSE, pb + p, szModuleName, _countof(szModuleName), NULL);
- if(!_stricmp(szModuleName, "ntoskrnl.exe")) {
- LocalFree(pb);
- return 0x80000000 + p;
- }
- }
- }
- }
- LocalFree(pb);
- return 0;
-}
-
-/*
-* Scan for the 'ntoskrnl.exe' by using the DTB and memory model information
-* from the ctxVmm. Return the system process (if found).
-* CALLER DECREF: return
-* -- return = system process - NB! CALLER must DECREF!
-*/
-PVMM_PROCESS VmmWinInit_FindNtosScan()
-{
- QWORD vaKernelBase = 0, cbKernelSize, vaKernelHint;
- PVMM_PROCESS pObSystemProcess = NULL;
- // 1: Pre-initialize System PID (required by VMM)
- pObSystemProcess = VmmProcessCreateEntry(TRUE, 4, 0, ctxVmm->kernel.paDTB, 0, "System", FALSE);
- if(!pObSystemProcess) { return NULL; }
- VmmProcessCreateFinish();
- // 2: Spider DTB to speed things up.
- VmmTlbSpider(pObSystemProcess);
- // 3: Find the base of 'ntoskrnl.exe'
- if(VMM_MEMORYMODEL_X64 == ctxVmm->tpMemoryModel) {
- LeechCore_GetOption(LEECHCORE_OPT_MEMORYINFO_OS_KERNELBASE, &vaKernelBase);
- if(!vaKernelBase) {
- vaKernelHint = ctxVmm->kernel.vaEntry;
- if(!vaKernelHint) { LeechCore_GetOption(LEECHCORE_OPT_MEMORYINFO_OS_KERNELHINT, &vaKernelHint); }
- if(!vaKernelHint) { LeechCore_GetOption(LEECHCORE_OPT_MEMORYINFO_OS_PsActiveProcessHead, &vaKernelHint); }
- if(!vaKernelHint) { LeechCore_GetOption(LEECHCORE_OPT_MEMORYINFO_OS_PsLoadedModuleList, &vaKernelHint); }
- if(vaKernelHint) {
- vaKernelBase = VmmWinInit_FindNtosScanHint64(pObSystemProcess, vaKernelHint);
- }
- }
- if(!vaKernelBase) {
- vaKernelBase = VmmWinInit_FindNtosScan64(pObSystemProcess);
- }
- } else {
- vaKernelBase = VmmWinInit_FindNtosScan32(pObSystemProcess);
- }
- if(!vaKernelBase) { goto fail; }
- cbKernelSize = PE_GetSize(pObSystemProcess, vaKernelBase);
- if(!cbKernelSize) { goto fail; }
- ctxVmm->kernel.vaBase = vaKernelBase;
- ctxVmm->kernel.cbSize = cbKernelSize;
- return pObSystemProcess;
-fail:
- VmmOb_DECREF(pObSystemProcess);
- return NULL;
-}
-
-/*
-* Check if a page looks like the Windows Kernel x86 Directory Table Base (DTB)
-* in the 32-bit mode - i.e. the PD of the System process.
-* 1: self-referential entry exists at offset 0xC00
-* 2: PDE[0] is a user-mode PDE pointing to a PT.
-* 3: a minimum number of supervisor-mode PDEs must exist.
-*/
-_Success_(return)
-BOOL VmmWinInit_DTB_FindValidate_X86(_In_ QWORD pa, _In_reads_(0x1000) PBYTE pbPage)
-{
- DWORD c, i;
- if((*(PDWORD)(pbPage + 0xc00) & 0xfffff003) != pa + 0x03) { return FALSE; } // self-referential entry exists
- if(*pbPage != 0x67) { return FALSE; } // user-mode page table exists at 1st PTE (index 0)
- for(c = 0, i = 0x800; i < 0x1000; i += 4) { // minimum number of supervisor entries above 0x800
- if((*(pbPage + i) == 0x63) || (*(pbPage + i) == 0xe3)) { c++; }
- if(c > 16) { return TRUE; }
- }
- return FALSE;
-}
-
-/*
-* Check if a page looks like the Windows Kernel x86 Directory Table Base (DTB)
-* in the 32-bit PAE memory mode - i.e. the PDPT of the System process.
-* Also please note that this may not be the actual PDPT used by the kernel -
-* it may very well rather be the PDPT probably set up by WinLoad and then the
-* 'System' process uses another. But it works for auto-detect!
-* 1: (4) valid PDPT entries with consecutive physical addresses of the PDPT.
-* 2: all zeroes for the rest of the page.
-*/
-_Success_(return)
-BOOL VmmWinInit_DTB_FindValidate_X86PAE(_In_ QWORD pa, _In_reads_(0x1000) PBYTE pbPage)
-{
- for(QWORD i = 0; i < 0x1000; i += 8) {
- if((i < 0x20) && ((*(PQWORD)(pbPage + i) != pa + (i << 9) + 0x1001))) {
- return FALSE;
- } else if((i >= 0x20) && *(PQWORD)(pbPage + i)) {
- return FALSE;
- }
- }
- return TRUE;
-}
-
-_Success_(return)
-BOOL VmmWinInit_DTB_FindValidate_X64(_In_ QWORD pa, _In_reads_(0x1000) PBYTE pbPage)
-{
- DWORD c, i;
- BOOL fSelfRef = FALSE;
- QWORD pte, paMax;
- paMax = ctxMain->dev.paMax;
- // check for user-mode page table with PDPT below max physical address and not NX.
- pte = *(PQWORD)pbPage;
- if(((pte & 0x0000000000000087) != 0x07) || ((pte & 0x0000fffffffff000) > paMax)) { return FALSE; }
- for(c = 0, i = 0x800; i < 0x1000; i += 8) { // minimum number of supervisor entries above 0x800
- pte = *(PQWORD)(pbPage + i);
- // check for user-mode page table with PDPT below max physical address and not NX.
- if(((pte & 0x8000ff0000000087) == 0x03) && ((pte & 0x0000fffffffff000) < paMax)) { c++; }
- // check for self-referential entry
- if((*(PQWORD)(pbPage + i) & 0x0000fffffffff083) == pa + 0x03) { fSelfRef = TRUE; }
- }
- return fSelfRef && (c >= 6);
-}
-
-/*
-* Find and validate the low stub (loaded <1MB if exists). The low stub almost
-* always exists on real hardware. It may be missing on virtual machines though.
-* Upon success both the PML4 and 'ntoskrnl.exe' KernelEntry point are located.
-* The PML4 is stored as the ctxVmm->kernel.paDTB and the KernelEntry is stored
-* as ctxVmm->kernel.vaHintOpt
-*/
-BOOL VmmWinInit_DTB_FindValidate_X64_LowStub(_In_ PBYTE pbLowStub1M)
-{
- DWORD o = 0;
- while(o < 0x100000) {
- o += 0x1000;
- if(0x00000001000600E9 != (0xffffffffffff00ff & *(PQWORD)(pbLowStub1M + o + 0x000))) { continue; } // START BYTES
- if(0xfffff80000000000 != (0xfffff80000000003 & *(PQWORD)(pbLowStub1M + o + 0x070))) { continue; } // KERNEL ENTRY
- if(0xffffff0000000fff & *(PQWORD)(pbLowStub1M + o + 0x0a0)) { continue; } // PML4
- ctxVmm->kernel.vaEntry = *(PQWORD)(pbLowStub1M + o + 0x070);
- ctxVmm->kernel.paDTB = *(PQWORD)(pbLowStub1M + o + 0x0a0);
- return TRUE;
- }
- return FALSE;
-}
-
-/*
-* Tries to locate the Directory Table Base and the Memory Model by using various
-* detection and scanning functions. Upon success memory model and kernel DTB is
-* returned in the ctxVmm context.
--- return
-*/
-_Success_(return)
-BOOL VmmWinInit_DTB_FindValidate()
-{
- DWORD pa;
- QWORD paDTB = 0;
- PBYTE pb16M;
- if(!(pb16M = LocalAlloc(LMEM_ZEROINIT, 0x01000000))) { return FALSE; }
- // 1: try locate DTB via X64 low stub in lower 1MB
- LeechCore_Read(0, pb16M, 0x00100000);
- if(VmmWinInit_DTB_FindValidate_X64_LowStub(pb16M)) {
- VmmInitializeMemoryModel(VMM_MEMORYMODEL_X64);
- paDTB = ctxVmm->kernel.paDTB;
- }
- // 2: try locate DTB by scanning in lower 16MB
- // X64
- if(!paDTB) {
- for(pa = 0; pa < 0x01000000; pa += 0x1000) {
- if(pa == 0x00100000) {
- LeechCore_Read(0x00100000, pb16M + 0x00100000, 0x00f00000);
- }
- if(VmmWinInit_DTB_FindValidate_X64(pa, pb16M + pa)) {
- VmmInitializeMemoryModel(VMM_MEMORYMODEL_X64);
- paDTB = pa;
- break;
- }
- }
- }
- // X86-PAE
- if(!paDTB) {
- for(pa = 0; pa < 0x01000000; pa += 0x1000) {
- if(VmmWinInit_DTB_FindValidate_X86PAE(pa, pb16M + pa)) {
- VmmInitializeMemoryModel(VMM_MEMORYMODEL_X86PAE);
- paDTB = pa;
- break;
- }
- }
- }
- // X86
- if(!paDTB) {
- for(pa = 0; pa < 0x01000000; pa += 0x1000) {
- if(VmmWinInit_DTB_FindValidate_X86(pa, pb16M + pa)) {
- VmmInitializeMemoryModel(VMM_MEMORYMODEL_X86);
- paDTB = pa;
- break;
- }
- }
- }
- LocalFree(pb16M);
- if(!paDTB) { return FALSE; }
- ctxVmm->kernel.paDTB = paDTB;
- return TRUE;
-}
-
-/*
-* Validate a DTB supplied by the user. The memory model will be detected and
-* the result will be stored in the ctxVmm context upon success.
-* -- paDTB
-* -- return
-*/
-BOOL VmmWinInit_DTB_Validate(QWORD paDTB)
-{
- BYTE pb[0x1000];
- paDTB = paDTB & ~0xfff;
- if(!LeechCore_Read(paDTB, pb, 0x1000)) { return FALSE; }
- if(VmmWinInit_DTB_FindValidate_X64(paDTB, pb)) {
- VmmInitializeMemoryModel(VMM_MEMORYMODEL_X64);
- ctxVmm->kernel.paDTB = paDTB;
- return TRUE;
- }
- if(VmmWinInit_DTB_FindValidate_X86PAE(paDTB, pb)) {
- VmmInitializeMemoryModel(VMM_MEMORYMODEL_X86PAE);
- ctxVmm->kernel.paDTB = paDTB;
- return TRUE;
- }
- if(VmmWinInit_DTB_FindValidate_X86(paDTB, pb)) {
- VmmInitializeMemoryModel(VMM_MEMORYMODEL_X86);
- ctxVmm->kernel.paDTB = paDTB;
- return TRUE;
- }
- return FALSE;
-}
-
-BOOL VmmWinInit_FindPsLoadedModuleListKDBG(_In_ PVMM_PROCESS pSystemProcess)
-{
- PBYTE pbData = NULL, pbKDBG;
- IMAGE_SECTION_HEADER SectionHeader;
- DWORD o, va32 = 0;
- QWORD va, va64 = 0;
- // 1: Try locate 'PsLoadedModuleList' by querying the microsoft crash dump
- // file used. This will fail if another memory acqusition device is used.
- if(LeechCore_GetOption(LEECHCORE_OPT_MEMORYINFO_OS_PsLoadedModuleList, &va) && va) {
- if(ctxVmm->f32 && VmmRead(pSystemProcess, va, (PBYTE)&va32, 4) && (va32 > 0x80000000)) {
- ctxVmm->kernel.vaPsLoadedModuleList = va32;
- return TRUE;
- }
- if(!ctxVmm->f32 && VmmRead(pSystemProcess, va, (PBYTE)&va64, 8) && (va64 > 0xffff800000000000)) {
- ctxVmm->kernel.vaPsLoadedModuleList = va64;
- return TRUE;
- }
- }
- // 2: Try locate 'PsLoadedModuleList' by exported kernel symbol. If this is
- // possible it's most probably Windows 10 and KDBG will be encrypted so
- // no need to continue looking for it.
- ctxVmm->kernel.vaPsLoadedModuleList = PE_GetProcAddress(pSystemProcess, ctxVmm->kernel.vaBase, "PsLoadedModuleList");
- if(ctxVmm->kernel.vaPsLoadedModuleList) { return TRUE; }
- // 3: Try locate 'KDBG' by looking in 'ntoskrnl.exe' '.text' section. This
- // is the normal way of finding it on 64-bit Windows below Windows 10.
- // This also works on 32-bit Windows versions - so use this method for
- // simplicity rather than using a separate 32-bit method.
- if(!ctxVmm->kernel.vaKDBG) {
- if(!PE_SectionGetFromName(pSystemProcess, ctxVmm->kernel.vaBase, ".data", &SectionHeader)) { goto fail; }
- if((SectionHeader.Misc.VirtualSize > 0x00100000) || (SectionHeader.VirtualAddress > 0x01000000)) { goto fail; }
- if(!(pbData = LocalAlloc(LMEM_ZEROINIT, SectionHeader.Misc.VirtualSize))) { goto fail; }
- VmmReadEx(pSystemProcess, ctxVmm->kernel.vaBase + SectionHeader.VirtualAddress, pbData, SectionHeader.Misc.VirtualSize, NULL, 0);
- for(o = 16; o <= SectionHeader.Misc.VirtualSize - 0x290; o += 4) {
- if(*(PDWORD)(pbData + o) == 0x4742444b) { // KDBG tag
- pbKDBG = pbData + o - 16;
- if(ctxVmm->kernel.vaBase != *(PQWORD)(pbKDBG + 0x18)) { continue; }
- // fetch PsLoadedModuleList
- va = *(PQWORD)(pbKDBG + 0x48);
- if((va < ctxVmm->kernel.vaBase) || (va > ctxVmm->kernel.vaBase + ctxVmm->kernel.cbSize)) { goto fail; }
- if(!VmmRead(pSystemProcess, va, (PBYTE)&ctxVmm->kernel.vaPsLoadedModuleList, ctxVmm->f32 ? 4 : 8)) { goto fail; }
- // finish!
- ctxVmm->kernel.vaKDBG = ctxVmm->kernel.vaBase + SectionHeader.VirtualAddress + o - 16;
- LocalFree(pbData);
- return TRUE;
- }
- }
- }
-fail:
- LocalFree(pbData);
- return FALSE;
-}
-
-/*
-* Try initialize the VMM from scratch with new WINDOWS support.
-* -- paDTBOpt
-* -- return
-*/
-BOOL VmmWinInit_TryInitialize(_In_opt_ QWORD paDTBOpt)
-{
- PVMM_PROCESS pObSystemProcess = NULL, pObProcess = NULL;
- QWORD vaPsInitialSystemProcess, vaSystemEPROCESS;
- // Fetch Directory Base (DTB (PML4)) and initialize Memory Model.
- if(paDTBOpt) {
- if(!VmmWinInit_DTB_Validate(paDTBOpt)) {
- vmmprintfv("VmmWinInit_TryInitialize: Initialization Failed. Unable to verify user-supplied (0x%016llx) DTB. #1\n", paDTBOpt);
- goto fail;
- }
- } else if(LeechCore_GetOption(LEECHCORE_OPT_MEMORYINFO_OS_DTB, &paDTBOpt)) {
- if(!VmmWinInit_DTB_Validate(paDTBOpt)) {
- vmmprintfv("VmmWinInit_TryInitialize: Warning: Unable to verify crash-dump supplied DTB. (0x%016llx) #1\n", paDTBOpt);
- goto fail;
- }
- } else if(!ctxVmm->kernel.paDTB) {
- if(!VmmWinInit_DTB_FindValidate()) {
- vmmprintfv("VmmWinInit_TryInitialize: Initialization Failed. Unable to locate valid DTB. #2\n");
- goto fail;
- }
- }
- vmmprintfvv_fn("INFO: DTB located at: %016llx. MemoryModel: %s\n", ctxVmm->kernel.paDTB, VMM_MEMORYMODEL_TOSTRING[ctxVmm->tpMemoryModel]);
- // Fetch 'ntoskrnl.exe' base address
- if(!(pObSystemProcess = VmmWinInit_FindNtosScan())) {
- vmmprintfv("VmmWinInit_TryInitialize: Initialization Failed. Unable to locate ntoskrnl.exe. #3\n");
- goto fail;
- }
- vmmprintfvv_fn("INFO: NTOS located at: %016llx.\n", ctxVmm->kernel.vaBase);
- // Locate System EPROCESS
- vaPsInitialSystemProcess = PE_GetProcAddress(pObSystemProcess, ctxVmm->kernel.vaBase, "PsInitialSystemProcess");
- if(!VmmRead(pObSystemProcess, vaPsInitialSystemProcess, (PBYTE)&vaSystemEPROCESS, 8)) {
- vmmprintfv("VmmWinInit_TryInitialize: Initialization Failed. Unable to locate EPROCESS. #4\n");
- goto fail;
- }
- if((VMM_MEMORYMODEL_X86 == ctxVmm->tpMemoryModel) || (VMM_MEMORYMODEL_X86PAE == ctxVmm->tpMemoryModel)) {
- vaSystemEPROCESS &= 0xffffffff;
- }
- pObSystemProcess->os.win.vaEPROCESS = vaSystemEPROCESS;
- vmmprintfvv_fn("INFO: PsInitialSystemProcess located at %016llx.\n", vaPsInitialSystemProcess);
- vmmprintfvv_fn("INFO: EPROCESS located at %016llx.\n", vaSystemEPROCESS);
- // Enumerate processes
- if(!VmmWin_EnumerateEPROCESS(pObSystemProcess, TRUE)) {
- vmmprintfv("VmmWinInit: Initialization Failed. Unable to walk EPROCESS. #5\n");
- goto fail;
- }
- ctxVmm->tpSystem = (VMM_MEMORYMODEL_X64 == ctxVmm->tpMemoryModel) ? VMM_SYSTEM_WINDOWS_X64 : VMM_SYSTEM_WINDOWS_X86;
- // Optionally fetch PsLoadedModuleList / KDBG
- VmmWinInit_FindPsLoadedModuleListKDBG(pObSystemProcess);
- VmmOb_DECREF(pObSystemProcess);
- // Optionally retrieve PID of MemCompression process
- while((pObProcess = VmmProcessGetNext(pObProcess))) {
- if(memcmp("MemCompression", pObProcess->szName, 15)) { continue; }
- ctxVmm->kernel.dwPidMemCompression = pObProcess->dwPID;
- VmmOb_DECREF(pObProcess);
- pObProcess = NULL;
- break;
- }
- return TRUE;
-fail:
- VmmInitializeMemoryModel(VMM_MEMORYMODEL_NA); // clean memory model
- ZeroMemory(&ctxVmm->kernel, sizeof(VMM_KERNELINFO));
- VmmOb_DECREF(pObSystemProcess);
- return FALSE;
-}
diff --git a/vmm/vmmwininit.h b/vmm/vmmwininit.h
deleted file mode 100644
index 1c0a1bd..0000000
--- a/vmm/vmmwininit.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// vmmwininit.h : declarations of detection mechanisms for Windows operating
-// systems. Contains functions for detecting DTB and Memory Model
-// as well as the Windows kernel base and core functionality.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-
-#ifndef __VMMWININIT_H__
-#define __VMMWININIT_H__
-#include "vmm.h"
-
-/*
-* Try initialize the VMM from scratch with new WINDOWS support.
-* -- paDTB
-* -- return
-*/
-_Success_(return)
-BOOL VmmWinInit_TryInitialize(_In_opt_ QWORD paDTB);
-
-#endif /* __VMMWININIT_H__ */
diff --git a/vmm_example/leechcore.h b/vmm_example/leechcore.h
deleted file mode 100644
index 46af16a..0000000
--- a/vmm_example/leechcore.h
+++ /dev/null
@@ -1,471 +0,0 @@
-// leechcore.h : header file for the leechcore module - which purpose is to
-// expose low-level device physical memory functionality.
-//
-// This library is thread-safe in all functions with the notable exceptions of
-// the LeechCore_Open() and LeechCore_Close() functions. Some devices may allow
-// multi-threaded access while in reality most devices are single-threaded and
-// will control synchronization where necessary with locks.
-//
-// The library is initialized by calling LeechCore_Open with a LEECHCORE_CONFIG
-// struct containing the correct configuration paramters. Note that the version
-// and magic values must be set in addition to the szDevice configuration value
-// Also, it may be possible to optionally connect to a remote leechcore service
-// or instance over RPC by specifying a szRemote configuration value.
-//
-// ----------------------------------------------------------------------------
-//
-// Remote instance: szRemote configuration value. Connect to a remote leechcore
-// instance by specifying a configuration value in the szRemote parameter. If a
-// loaded already valid instance exists remotely this will be prioritized above
-// the value in szDevice. If the acquisition device is not yet loaded by the
-// remote instance the value in szDevice will be used. Normally, the connection
-// will take place as a mutually authenticated encrypted connection secured by
-// kerberos. If not possible or desirable the 'insecure' value may be specified
-// to disable authentication and security.
-// Syntax:
-// rpc://:: (port = optional, remote_spn = kerberos)
-// (SPN of remote service or 'insecure' )
-// Examples:
-// rpc://insecure:remotehost.example.com (connect insecure to remote host )
-// rpc://user@ad.domain.com:192.0.0.5 (connect secure to remote host )
-// rpc://insecure:127.0.0.0:6666 (connect insecure non-default port)
-//
-// ----------------------------------------------------------------------------
-//
-// Device to connect to: szDevice contains the device to capture memory from.
-// Supported memory acquisition devices are:
-// USB3380 : hardware, read/write, 32-bit (4GB) addressing only. Requires a
-// PCILeech flashed USB3380 device connected over USB and Google
-// Android WinUSB drivers to be installed. Download and install from:
-// http://developer.android.com/sdk/win-usb.html#download
-// Syntax:
-// USB3380
-// USB3380://USB2 (force USB2 connection speed)
-//
-// FPGA : hardware, read/write - requires a PCILeech FPGA flashed hardware
-// device as shown at: https://github.com/ufrisk/pcileech-fpga
-// Also requires the FTD3XX.DLL from ftdichip to be placed in the
-// same directory as the executable. Download from ftdichip at:
-// http://www.ftdichip.com/Drivers/D3XX/FTD3XXLibrary_v1.2.0.6.zip
-// Syntax:
-// FGPA
-// FPGA://[:[:]] (values are optional)
-//
-// SP605TCP : hardware, read/write - connect to a remote SP605 FPGA over the
-// network using the implementation created by @d_olex.
-// https://github.com/Cr4sh/s6_pcie_microblaze
-// Syntax:
-// SP605TCP://[:] (port is optional)
-//
-// RAWTCP : read/write - connect to a remote raw tcp device - such as HPE iLO
-// that have been patched to support DMA as per blog entry below:
-// https://www.synacktiv.com/posts/exploit/using-your-bmc-as-a-dma-device-plugging-pcileech-to-hpe-ilo-4.html
-// Syntax:
-// RAWTCP://[:] (port is optional)
-//
-// HvSavedState : read-only - connect to a Hyper-V saved state file. In order
-// to do so the .dll file 'vmsavedstatedumpprovider.dll' must be
-// placed in same directory as the executable file.
-//
-// PMEM : load the rekall winpmem driver into the kernel and connect to it
-// to acquire memory. The signed driver `.sys` file may be found at:
-// https://github.com/Velocidex/c-aff4/tree/master/tools/pmem/resources/winpmem
-// Download the driver file `att_winpmem_64.sys` and copy it to the
-// directory of leechcore.dll and run executable as elevated admin
-// using syntax below:
-// Syntax:
-// PMEM (use att_winpmem_64.sys in directory of executable)
-// PMEM://
-//
-// TOTALMELTDOWN : read/write - requires a Windows 7 system vulnerable to the
-// "Total Meltdown" vulnerability - CVE-2018-1038.
-// Syntax:
-// TOTALMELTDOWN
-//
-// FILE : use dump file, either a raw linear memory dump or full crash dump.
-// Which format to use is auto-detected. If it looks like a full cash
-// dump that format will be used, otherwise it will be assumed that a
-// raw linear memory dump is to be used.
-// Syntax:
-// (no device-type prefix - just use the file name)
-// FILE://
-//
-// DumpIt : DumpIt is a "virtual" device. It's only possible to use the DumpIt
-// device if the main process containing LeechCore has been started
-// with DumpIt in LiveKD mode.
-// Example 1:
-// DumpIt.exe /LIVEKD /A MemProcFS.exe
-// Example 2:
-// DumpIt.exe /LIVEKD /A LeechSvc.exe /C "interactive insecure"
-// and then connect to remote service by:
-// MemProcFS.exe -remote rpc://insecure:192.168.x.x -device DumpIt
-//
-// EXISTING : Attach to existing already loaded configuration. This is done
-// instead of the default behaviour of closing any existing devices
-// and initializing the new requested device. If no existing device
-// exists the call to LeechCore_Open will fail.
-// Syntax:
-// EXISTING
-//
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 1.1.0
-//
-#ifndef __LEECHCORE_H__
-#define __LEECHCORE_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// WINDOWS / LINUX COMPATIBILITY BELOW:
-//-----------------------------------------------------------------------------
-
-#ifdef _WIN32
-#include
-typedef unsigned __int64 QWORD, *PQWORD;
-#define DLLEXPORT __declspec(dllexport)
-#endif /* _WIN32 */
-#ifdef LINUX
-#include
-#include
-typedef void VOID, *PVOID, *LPVOID;
-typedef void *HANDLE, **PHANDLE;
-typedef uint32_t BOOL, *PBOOL;
-typedef uint8_t BYTE, *PBYTE;
-typedef char CHAR, *PCHAR, *PSTR, *LPSTR;
-typedef uint16_t WORD, *PWORD, USHORT, *PUSHORT;
-typedef uint32_t DWORD, *PDWORD;
-typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64;
-#define MAX_PATH 260
-#define DLLEXPORT __attribute__((visibility("default")))
-#define _In_
-#define _Out_
-#define _In_z_
-#define _Inout_
-#define _In_opt_
-#define _Out_opt_
-#define _Out_writes_(x)
-#define _Check_return_opt_
-#define _Printf_format_string_
-#define _Inout_updates_bytes_(x)
-#define _In_reads_(cbDataIn)
-#define _Out_writes_opt_(x)
-#define _Success_(return)
-#endif /* LINUX */
-
-//-----------------------------------------------------------------------------
-// GENERAL HEADER DEFINES BELOW:
-//-----------------------------------------------------------------------------
-
-#define MEM_IO_SCATTER_HEADER_MAGIC 0xffff6548
-#define MEM_IO_SCATTER_HEADER_VERSION 0x0003
-
-typedef struct tdMEM_IO_SCATTER_HEADER {
- DWORD magic; // magic
- WORD version; // version
- WORD Future1;
- ULONG64 qwA; // base address.
- DWORD cbMax; // bytes to read (DWORD boundry, max 0x1000); pb must have room for this.
- DWORD cb; // bytes read into result buffer.
- PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
- PVOID pvReserved1; // reserved for use by caller.
- PVOID pvReserved2; // reserved for use by caller.
- PVOID Future2[8];
-} MEM_IO_SCATTER_HEADER, *PMEM_IO_SCATTER_HEADER, **PPMEM_IO_SCATTER_HEADER;
-
-//-----------------------------------------------------------------------------
-// LEECHCORE INITIALIZATION / CLOSE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-typedef enum tdLEECHCORE_DEVICE {
- LEECHCORE_DEVICE_NA = 0,
- LEECHCORE_DEVICE_FILE = 1,
- LEECHCORE_DEVICE_PMEM = 2,
- LEECHCORE_DEVICE_FPGA = 3,
- LEECHCORE_DEVICE_SP605_TCP = 4,
- LEECHCORE_DEVICE_USB3380 = 5,
- LEECHCORE_DEVICE_TOTALMELTDOWN = 6,
- LEECHCORE_DEVICE_HVSAVEDSTATE = 7,
- LEECHCORE_DEVICE_RAWTCP = 8,
-} LEECHCORE_DEVICE;
-
-#define LEECHCORE_CONFIG_MAGIC 0xffff6549
-#define LEECHCORE_CONFIG_VERSION 0x0001
-
-#define LEECHCORE_CONFIG_FLAG_PRINTF 0x0001
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_1 0x0002
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_2 0x0004
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_3 0x0008
-#define LEECHCORE_CONFIG_FLAG_REMOTE_NO_COMPRESS 0x0010
-
-typedef struct tdLEECHCORE_CONFIG {
- DWORD magic; // set by caller.
- WORD version; // set by caller.
- WORD flags; // set by caller, updated by device.
- ULONG64 paMax; // set by caller, updated by device.
- ULONG64 cbMaxSizeMemIo; // set by caller, updated by device.
- ULONG64 paMaxNative; // set by device.
- LEECHCORE_DEVICE tpDevice; // set by device.
- BOOL fWritable; // set by device. (is device writable?)
- BOOL fVolatile; // set by device. (is device volatile / memory may change?)
- BOOL fVolatileMaxAddress; // set by device. (is max address volatile? - poll changes with LEECHCORE_OPT_MEMORYINFO_ADDR_MAX)
- BOOL fRemote; // set by device.
- WORD VersionMajor; // set by device.
- WORD VersionMinor; // set by device.
- WORD VersionRevision; // set by device.
- CHAR szDevice[MAX_PATH]; // set by caller.
- CHAR szRemote[MAX_PATH]; // set by caller.
- // optional 'printf' function pointer. if set to non null value 'printf'
- // calls will be redirected. useful when logging to files.
- _Check_return_opt_ int(*pfn_printf_opt)(_In_z_ _Printf_format_string_ char const* const _Format, ...); // set by caller.
-} LEECHCORE_CONFIG, *PLEECHCORE_CONFIG;
-
-typedef struct tdLEECHCORE_PAGESTAT_MINIMAL {
- HANDLE h;
- VOID(*pfnPageStatUpdate)(HANDLE h, ULONG64 pa, ULONG64 cPageSuccessAdd, ULONG64 cPageFailAdd);
-} LEECHCORE_PAGESTAT_MINIMAL, *PLEECHCORE_PAGESTAT_MINIMAL;
-
-/*
-* Open a connection to the target device. The LeechCore initialization may fail
-* if the underlying device cannot be opened or if the LeechCore is already
-* initialized. If already initialized please connect with device EXISTING or
-* call LeechCore_Close() before opening a new device.
-* -- pInformation
-* -- result
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Open(_Inout_ PLEECHCORE_CONFIG pConfig);
-
-/*
-* Clean up various device related stuff and deallocate memory buffers.
-*/
-DLLEXPORT VOID LeechCore_Close();
-
-
-
-//-----------------------------------------------------------------------------
-// LEECHCORE CORE READ AND WRITE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_FLAG_READ_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_VERIFY 0x02
-
-/*
-* Allocate a scatter buffer containing empty 0x1000-sized ppMEMs with address
-* set to zero. Caller is responsible for calling LocalFree(ppMEMs).
-* -- cMEMs
-* -- pppMEMs = pointer to receive ppMEMs on success.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_AllocScatterEmpty(_In_ DWORD cMEMs, _Out_ PPMEM_IO_SCATTER_HEADER *pppMEMs);
-
-/*
-* Read memory in various non-contigious locations specified by the items in the
-* phDMAs array. Result for each unit of work will be given individually. No upper
-* limit of number of items to read, but no performance boost will be given if
-* above hardware limit. Max size of each unit of work is one 4k page (4096 bytes).
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-*/
-DLLEXPORT VOID LeechCore_ReadScatter(_Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_Read(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_READ_RETRY
-* -- pPageStat = optional minimal statistic struct to update.
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_ReadEx(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb, _In_ DWORD flags, _In_opt_ PLEECHCORE_PAGESTAT_MINIMAL pPageStat);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Write(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_WRITE_*
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_WriteEx(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD flags);
-
-/*
-* Probe the memory of the target system to check whether it's readable or not.
-* Please note that not all devices support this natively.
-* -- pa = address to start probe from.
-* -- cPages = number of 4kB pages to probe.
-* -- pbResultMap = result map, 1 byte represents 1 page, 0 = fail, 1 = success.
-* (individual page elements in pbResultMap must be set to 0 [fail] on call
-* for probe to take place on individual page).
-* -- return = FALSE if not supported by underlying hardware, TRUE if supported.
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Probe(_In_ QWORD pa, _In_ DWORD cPages, _Inout_updates_bytes_(cPages) PBYTE pbResultMap);
-
-
-
-//-----------------------------------------------------------------------------
-// GET/SET DEVICE OPTIONS BELOW. SOME OPTIONS ARE GENERAL LEECHCORE OPTIONS
-// WHILE OTHER ARE DEVICE SPECIFIC. USE FUNCTIONS:
-// LeechCore_GetOption() AND LeechCore_GetOption() TO GET/SET OPTIONS.
-// FOR DEVICE-SPECIFIC OPTIONS PLEASE SEE INDIVIDUAL DEVICE FILES FOR MORE
-// DETAILED INFORMATION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE 0x80000002 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-
-#define LEECHCORE_OPT_CORE_VERSION_MAJOR 0x01000001 // R
-#define LEECHCORE_OPT_CORE_VERSION_MINOR 0x01000002 // R
-#define LEECHCORE_OPT_CORE_VERSION_REVISION 0x01000003 // R
-
-#define LEECHCORE_OPT_MEMORYINFO_VALID 0x02000001 // R
-#define LEECHCORE_OPT_MEMORYINFO_ADDR_MAX 0x02000002 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_32BIT 0x02000003 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_PAE 0x02000004 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MINOR 0x02000005 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MAJOR 0x02000006 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_DTB 0x02000007 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PFN 0x02000008 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsLoadedModuleList 0x02000009 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsActiveProcessHead 0x0200000a // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_MACHINE_IMAGE_TP 0x0200000b // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_NUM_PROCESSORS 0x0200000c // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_SYSTEMTIME 0x0200000d // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_UPTIME 0x0200000e // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELBASE 0x0200000f // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELHINT 0x02000010 // R
-
-#define LEECHCORE_OPT_FPGA_PROBE_MAXPAGES 0x03000001 // RW
-#define LEECHCORE_OPT_FPGA_RX_FLUSH_LIMIT 0x03000002 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_RX 0x03000003 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_TX 0x03000004 // RW
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_READ 0x03000005 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_WRITE 0x03000006 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_WRITE 0x03000007 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_READ 0x03000008 // RW - uS
-#define LEECHCORE_OPT_FPGA_RETRY_ON_ERROR 0x03000009 // RW
-#define LEECHCORE_OPT_FPGA_DEVICE_ID 0x03000080 // R
-#define LEECHCORE_OPT_FPGA_FPGA_ID 0x03000081 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MAJOR 0x03000082 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MINOR 0x03000083 // R
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- pqwValue = pointer to QWORD to receive option value.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_GetOption(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- qwValue
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_SetOption(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// TRANSFER DEVICE DEPENDANT COMMANDS OR DATA TO/FROM UNDERLYING DEVICES AND
-// PERFORM ACTIONS USING THE LeechCore_CommandData() FUNCTION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_COMMANDDATA_FPGA_WRITE_TLP 0x00000101 // R
-#define LEECHCORE_COMMANDDATA_FPGA_LISTEN_TLP 0x00000102 // R
-#define LEECHCORE_COMMANDDATA_STATISTICS_GET 0x80000100 // R
-
-#define LEECHCORE_STATISTICS_MAGIC 0xffff6550
-#define LEECHCORE_STATISTICS_VERSION 0x0001
-#define LEECHCORE_STATISTICS_ID_OPEN 0x00
-#define LEECHCORE_STATISTICS_ID_READSCATTER 0x01
-#define LEECHCORE_STATISTICS_ID_WRITE 0x02
-#define LEECHCORE_STATISTICS_ID_PROBE 0x03
-#define LEECHCORE_STATISTICS_ID_GETOPTION 0x04
-#define LEECHCORE_STATISTICS_ID_SETOPTION 0x05
-#define LEECHCORE_STATISTICS_ID_COMMANDDATA 0x06
-#define LEECHCORE_STATISTICS_ID_MAX 0x06
-
-static const LPSTR LEECHCORE_STATISTICS_NAME[] = {
- "LeechCore_Open",
- "LeechCore_ReadScatter",
- "LeechCore_Write",
- "LeechCore_Probe",
- "LeechCore_GetOption",
- "LeechCore_SetOption",
- "LeechCore_CommandData"
-};
-
-typedef struct tdLEECHCORE_STATISTICS {
- DWORD magic;
- WORD version;
- WORD Reserved0;
- DWORD Reserved1;
- QWORD qwFreq;
- struct {
- QWORD c;
- QWORD tm; // total time in qwFreq ticks
- } Call[0x10];
-} LEECHCORE_STATISTICS, *PLEECHCORE_STATISTICS;
-
-/*
-* Transfer device dependant commands/data to/from the underlying device and
-* perform device dependant actions.
-* -- fOption
-* -- cbDataIn
-* -- pbDataIn
-* -- pbDataOut
-* -- cbDataOut
-* -- pcbDataOut
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_CommandData(
- _In_ ULONG64 fOption,
- _In_reads_(cbDataIn) PBYTE pbDataIn,
- _In_ DWORD cbDataIn,
- _Out_writes_opt_(cbDataOut) PBYTE pbDataOut,
- _In_ DWORD cbDataOut,
- _Out_opt_ PDWORD pcbDataOut
-);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __LEECHCORE_H__ */
diff --git a/vmm_example/vmm_example.vcxproj b/vmm_example/vmm_example.vcxproj
deleted file mode 100644
index 8d24555..0000000
--- a/vmm_example/vmm_example.vcxproj
+++ /dev/null
@@ -1,110 +0,0 @@
-
-
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- 15.0
- {45CC506E-E97A-45B8-8050-B2C5BC8A4B15}
- vmmexample
- 10.0.17763.0
-
-
-
- Application
- true
- v141
- Unicode
- false
-
-
- Application
- false
- v141
- true
- Unicode
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(SolutionDir)\files\
- $(SolutionDir)\files\temp\$(ProjectName)\
-
-
- $(SolutionDir)\files\
- $(SolutionDir)\files\temp\$(ProjectName)\
-
-
-
- Level3
- Disabled
- true
- true
-
-
- $(SolutionDir)\files\vmm.lib;%(AdditionalDependencies)
- $(OutDir)\lib\$(TargetName).pdb
-
-
-
-
-
-
- copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y
-copy $(SolutionDir)\files\vmmdll.h $(ProjectDir)\ /y
-
-
-
-
- Level3
- MaxSpeed
- true
- true
- true
- true
-
-
- true
- true
- $(SolutionDir)\files\vmm.lib;%(AdditionalDependencies)
- UseLinkTimeCodeGeneration
- $(OutDir)\lib\$(TargetName).pdb
-
-
-
-
-
-
- copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y
-copy $(SolutionDir)\files\vmmdll.h $(ProjectDir)\ /y
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/vmm_example/vmm_example.vcxproj.filters b/vmm_example/vmm_example.vcxproj.filters
deleted file mode 100644
index 450a2b9..0000000
--- a/vmm_example/vmm_example.vcxproj.filters
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
- {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
-
-
- {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
- rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
-
-
- {2dda230c-a689-4065-8a56-84c4b1a989b8}
-
-
-
-
- Header Files\vmm
-
-
- Header Files\vmm
-
-
-
-
- Source Files
-
-
-
\ No newline at end of file
diff --git a/vmm_example/vmm_example.vcxproj.user b/vmm_example/vmm_example.vcxproj.user
deleted file mode 100644
index fa6ed15..0000000
--- a/vmm_example/vmm_example.vcxproj.user
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
- WindowsLocalDebugger
-
-
- WindowsLocalDebugger
-
-
\ No newline at end of file
diff --git a/vmm_example/vmmdll.h b/vmm_example/vmmdll.h
deleted file mode 100644
index 42befa8..0000000
--- a/vmm_example/vmmdll.h
+++ /dev/null
@@ -1,645 +0,0 @@
-// vmmdll.h : header file to include in projects that use vmm.dll either as
-// stand anlone projects or as native plugins to vmm.dll.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 2.1
-//
-
-#include
-#include "leechcore.h"
-
-#ifndef __VMMDLL_H__
-#define __VMMDLL_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// INITIALIZATION FUNCTIONALITY BELOW:
-// Choose one way of initialzing the VMM / Memory Process File System.
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize VMM.DLL with command line parameters. For a more detailed info
-* about the parameters please see github wiki for Memory Process File System
-* and LeechCore. THIS IS THE PREFERED WAY OF INITIALIZING VMM.DLL
-* Important parameters are:
-* -printf = show printf style outputs)
-* -v -vv -vvv = extra verbosity levels)
-* -device = device as on format for LeechCore - please see leechcore.h or
-* Github documentation for additional information. Some values
-* are: , fpga, usb3380, hvsavedstate, totalmeltdown, pmem
-* -remote = remote LeechCore instance - please see leechcore.h or Github
-* documentation for additional information.
-* -norefresh = disable background refreshes (even if backing memory is
-* volatile memory).
-* -- argc
-* -- argv
-* -- return = success/fail
-*/
-_Success_(return)
-BOOL VMMDLL_Initialize(_In_ DWORD argc, _In_ LPSTR argv[]);
-
-/*
-* Close an initialized instance of VMM.DLL and clean up all allocated resources
-* including plugins, linked PCILeech.DLL and other memory resources.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_Close();
-
-
-
-//-----------------------------------------------------------------------------
-// CONFIGURATION SETTINGS BELOW:
-// Configure the memory process file system or the underlying memory
-// acquisition devices.
-//-----------------------------------------------------------------------------
-
-/*
-* Options used together with the functions: VMMDLL_GetOption & VMMDLL_SetOption
-* Options are defined with either: VMMDLL_OPT_* in this header file or as
-* MEMDEVICE_OPT_* in memdevice.h
-* For more detailed information check the sources for individual device types.
-*/
-#define VMMDLL_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define VMMDLL_OPT_CORE_VERBOSE 0x80000002 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
-#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
-#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
-#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
-
-#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
-#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
-#define VMMDLL_OPT_CONFIG_READCACHE_TICKS 0x40000003 // RW - memory cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_TLBCACHE_TICKS 0x40000004 // RW - page table (tlb) cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_PARTIAL 0x40000005 // RW - process refresh (partial) period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_TOTAL 0x40000006 // RW - process refresh (full) period (in ticks)
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MAJOR 0x40000007 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MINOR 0x40000008 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
-#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
-
-static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
-
-typedef enum tdVMMDLL_MEMORYMODEL_TP {
- VMMDLL_MEMORYMODEL_NA = 0,
- VMMDLL_MEMORYMODEL_X86 = 1,
- VMMDLL_MEMORYMODEL_X86PAE = 2,
- VMMDLL_MEMORYMODEL_X64 = 3
-} VMMDLL_MEMORYMODEL_TP;
-
-typedef enum tdVMMDLL_SYSTEM_TP {
- VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
- VMMDLL_SYSTEM_WINDOWS_X64 = 2,
- VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
- VMMDLL_SYSTEM_WINDOWS_X86 = 4
-} VMMDLL_SYSTEM_TP;
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- pqwValue = pointer to ULONG64 to receive option value.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- qwValue
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// VFS - VIRTUAL FILE SYSTEM FUNCTIONALITY BELOW:
-// This is the core of the memory process file system. All implementation and
-// analysis towards the file system is possible by using functionality below.
-//-----------------------------------------------------------------------------
-
-#define VMMDLL_STATUS_SUCCESS ((NTSTATUS)0x00000000L)
-#define VMMDLL_STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
-#define VMMDLL_STATUS_END_OF_FILE ((NTSTATUS)0xC0000011L)
-#define VMMDLL_STATUS_FILE_INVALID ((NTSTATUS)0xC0000098L)
-#define VMMDLL_STATUS_FILE_SYSTEM_LIMITATION ((NTSTATUS)0xC0000427L)
-
-typedef struct tdVMMDLL_VFS_FILELIST {
- VOID(*pfnAddFile) (_Inout_ HANDLE h, _In_ LPSTR szName, _In_ ULONG64 cb, _In_ PVOID pvReserved);
- VOID(*pfnAddDirectory)(_Inout_ HANDLE h, _In_ LPSTR szName, _In_ PVOID pvReserved);
- HANDLE h;
-} VMMDLL_VFS_FILELIST, *PVMMDLL_VFS_FILELIST;
-
-/*
-* Helper function macros for callbacks into the VMM_VFS_FILELIST structure.
-*/
-#define VMMDLL_VfsList_AddFile(pFileList, szName, cb) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddFile(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, cb, NULL); }
-#define VMMDLL_VfsList_AddDirectory(pFileList, szName) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddDirectory(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, NULL); }
-
-/*
-* List a directory of files in the memory process file system. Directories and
-* files will be listed by callbacks into functions supplied in the pFileList
-* parameter. If information of an individual file is needed it's neccessary
-* to list all files in its directory.
-* -- wcsPath
-* -- pFileList
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
-
-/*
-* Read select parts of a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbRead
-* -- cbOffset
-* -- return
-*
-*/
-NTSTATUS VMMDLL_VfsRead(_In_ LPCWSTR wcsFileName, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-
-/*
-* Write select parts to a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbWrite
-* -- cbOffset
-* -- return
-*/
-NTSTATUS VMMDLL_VfsWrite(_In_ LPCWSTR wcsFileName, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-
-/*
-* Utility functions for memory process file system read/write towards different
-* underlying data representations.
-*/
-NTSTATUS VMMDLL_UtilVfsReadFile_FromPBYTE(_In_ PBYTE pbFile, _In_ ULONG64 cbFile, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromQWORD(_In_ ULONG64 qwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromDWORD(_In_ DWORD dwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromBOOL(_In_ BOOL fValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_BOOL(_Inout_ PBOOL pfTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset, _In_ DWORD dwMinAllow);
-
-
-//-----------------------------------------------------------------------------
-// PLUGIN MANAGER FUNCTIONALITY BELOW:
-// Function and structures to initialize and use the memory process file system
-// plugin functionality. The plugin manager is started by a call to function:
-// VMM_VfsInitializePlugins. Each built-in plugin and external plugin of which
-// the DLL name matches m_*.dll will receive a call to its InitializeVmmPlugin
-// function. The plugin/module may decide to call pfnPluginManager_Register to
-// register plugins in the form of different names one or more times.
-// Example of registration function in a plugin DLL below:
-// 'VOID InitializeVmmPlugin(_In_ PVMM_PLUGIN_REGINFO pRegInfo)'
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize all potential plugins, both built-in and external, that maps into
-* the memory process file system. Please note that plugins are not loaded by
-* default - they have to be explicitly loaded by calling this function. They
-* will be unloaded on a general close of the vmm dll.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsInitializePlugins();
-
-#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
-#define VMMDLL_PLUGIN_CONTEXT_VERSION 2
-#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
-#define VMMDLL_PLUGIN_REGINFO_VERSION 3
-
-#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
-
-typedef struct tdVMMDLL_PLUGIN_CONTEXT {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- DWORD dwPID;
- PVOID pProcess;
- LPSTR szModule;
- LPSTR szPath;
- PVOID pvReserved1;
- PVOID pvReserved2;
-} VMMDLL_PLUGIN_CONTEXT, *PVMMDLL_PLUGIN_CONTEXT;
-
-typedef struct tdVMMDLL_PLUGIN_REGINFO {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel;
- VMMDLL_SYSTEM_TP tpSystem;
- HMODULE hDLL;
- HMODULE hReservedDll; // not for general use (only used for python).
- BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
- PVOID pvReserved1;
- PVOID pvReserved2;
- // general plugin registration info to be filled out by the plugin below:
- struct {
- CHAR szModuleName[32];
- BOOL fRootModule;
- BOOL fProcessModule;
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_info;
- // function plugin registration info to be filled out by the plugin below:
- struct {
- BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
- NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
- NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
- VOID(*pfnNotify)(_In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
- VOID(*pfnClose)();
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_fn;
-} VMMDLL_PLUGIN_REGINFO, *PVMMDLL_PLUGIN_REGINFO;
-
-//-----------------------------------------------------------------------------
-// VMM CORE FUNCTIONALITY BELOW:
-// Vmm core functaionlity such as read (and write) to both virtual and physical
-// memory. NB! writing will only work if the target is supported - i.e. not a
-// memory dump file...
-// To read physical memory specify dwPID as (DWORD)-1
-//-----------------------------------------------------------------------------
-
-// FLAG used to supress the default read cache in calls to VMM_MemReadEx()
-// which will lead to the read being fetched from the target system always.
-// Cached page tables (used for translating virtual2physical) are still used.
-#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
-#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
-
-/*
-* Read memory in various non-contigious locations specified by the pointers to
-* the items in the ppDMAs array. Result for each unit of work will be given
-* individually. No upper limit of number of items to read, but no performance
-* boost will be given if above hardware limit. Max size of each unit of work is
-* one 4k page (4096 bytes).
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-* -- pcpDMAsRead = optional count of number of successfully read ppDMAs.
-* -- flags = optional flags as given by VMMDLL_FLAG_*
-* -- return = the number of successfully read items.
-*/
-DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs, _In_ DWORD flags);
-
-/*
-* Read a single 4096-byte page of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pbPage
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
-
-/*
-* Read a contigious arbitrary amount of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Read a contigious amount of memory and report the number of bytes read in pcbRead.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- pcbRead
-* -- flags = flags as in VMMDLL_FLAG_*
-* -- return = success/fail. NB! reads may report as success even if 0 bytes are
-* read - it's recommended to verify pcbReadOpt parameter.
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
-
-/*
-* Prefetch a number of addresses (specified in the pA array) into the memory
-* cache. This function is to be used to batch larger known reads into local
-* cache before making multiple smaller reads - which will then happen from
-* the cache. Function exists for performance reasons.
-* -- dwPID = PID of target process, (DWORD)-1 for physical memory.
-* -- pPrefetchAddresses = array of addresses to read into cache.
-* -- cPrefetchAddresses
-*/
-_Success_(return)
-BOOL VMMDLL_MemPrefetchPages(_In_ DWORD dwPID, _In_reads_(cPrefetchAddresses) PULONG64 pPrefetchAddresses, _In_ DWORD cPrefetchAddresses);
-
-/*
-* Write a contigious arbitrary amount of memory. Please note some virtual memory
-* such as pages of executables (such as DLLs) may be shared between different
-* virtual memory over different processes. As an example a write to kernel32.dll
-* in one process is likely to affect kernel32 in the whole system - in all
-* processes. Heaps and Stacks and other memory are usually safe to write to.
-* Please take care when writing to memory!
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = TRUE on success, FALSE on partial or zero write.
-*/
-_Success_(return)
-BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Translate a virtual address to a physical address by walking the page tables
-* of the specified process.
-* -- dwPID
-* -- qwVA
-* -- pqwPA
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
-
-
-
-//-----------------------------------------------------------------------------
-// VMM PROCESS FUNCTIONALITY BELOW:
-// Functionality below is mostly relating to Windows processes.
-//-----------------------------------------------------------------------------
-
-/*
-* Retrieve an active process given it's name. Please note that if multiple
-* processes with the same name exists only one will be returned. If required to
-* parse all processes with the same name please iterate over the PID list by
-* calling VMMDLL_PidList together with VMMDLL_ProcessGetInformation.
-* -- szProcName = process name (truncated max 15 chars) case insensitive.
-* -- pdwPID = pointer that will receive PID on success.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
-
-/*
-* List the PIDs in the system.
-* -- pPIDs = DWORD array of at least number of PIDs in system, or NULL.
-* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
-
-// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
-#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
-#define VMMDLL_MEMMAP_FLAG_PAGE_NS 0x0000000000000004
-#define VMMDLL_MEMMAP_FLAG_PAGE_NX 0x8000000000000000
-#define VMMDLL_MEMMAP_FLAG_PAGE_MASK 0x8000000000000006
-
-typedef struct tdVMMDLL_MEMMAP_ENTRY {
- ULONG64 AddrBase;
- ULONG64 cPages;
- ULONG64 fPage;
- BOOL fWoW64;
- CHAR szTag[32];
-} VMMDLL_MEMMAP_ENTRY, *PVMMDLL_MEMMAP_ENTRY;
-
-/*
-* Retrieve memory map entries from the specified process. Memory map entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries bytes.
-* If the pMemMapEntries is set to NULL the number of memory map entries will be
-* given in the pcMemMapEntries parameter.
-* -- dwPID
-* -- pMemMapEntries = buffer of minimum length sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries, or NULL.
-* -- pcMemMapEntries = pointer to number of memory map entries.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
-
-/*
-* Retrieve a single memory map entry given a virtual address within that entrys
-* range.
-* -- dwPID
-* -- pMemMapEntry
-* -- va = virtual address in the memory map entry to retrieve.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
-
-typedef struct tdVMMDLL_MODULEMAP_ENTRY {
- ULONG64 BaseAddress;
- ULONG64 EntryPoint;
- DWORD SizeOfImage;
- BOOL fWoW64;
- CHAR szName[32];
-} VMMDLL_MODULEMAP_ENTRY, *PVMMDLL_MODULEMAP_ENTRY;
-
-/*
-* Retrieve the module entries from the specified process. The module entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries bytes long. If the
-* pcModuleEntries is set to NULL the number of module entries will be given
-* in the pcModuleEntries parameter.
-* -- dwPID
-* -- pModuleEntries = buffer of minimum length sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries, or NULL.
-* -- pcModuleEntries = pointer to number of memory map entries.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
-
-/*
-* Retrieve a module (.exe or .dll or similar) given a module name.
-* -- dwPID
-* -- szModuleName
-* -- pModuleEntry
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
-
-#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
-#define VMMDLL_PROCESS_INFORMATION_VERSION 2
-
-typedef struct tdVMMDLL_PROCESS_INFORMATION {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
- VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
- BOOL fUserOnly; // only user mode pages listed
- DWORD dwPID;
- DWORD dwState;
- CHAR szName[16];
- ULONG64 paDTB;
- ULONG64 paDTB_UserOpt; // may not exist
- union {
- struct {
- ULONG64 vaEPROCESS;
- ULONG64 vaPEB;
- ULONG64 vaENTRY;
- BOOL fWow64;
- DWORD vaPEB32; // WoW64 only
- } win;
- } os;
-} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
-
-/*
-* Retrieve various process information from a PID. Process information such as
-* name, page directory bases and the process state may be retrieved.
-* -- dwPID
-* -- pProcessInformation = if null, size is given in *pcbProcessInfo
-* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
-
-typedef struct tdVMMDLL_EAT_ENTRY {
- ULONG64 vaFunction;
- DWORD vaFunctionOffset;
- CHAR szFunction[40];
-} VMMDLL_EAT_ENTRY, *PVMMDLL_EAT_ENTRY;
-
-typedef struct tdVMMDLL_IAT_ENTRY {
- ULONG64 vaFunction;
- CHAR szFunction[40];
- CHAR szModule[64];
-} VMMDLL_IAT_ENTRY, *PVMMDLL_IAT_ENTRY;
-
-/*
-* Retrieve information about: Data Directories, Sections, Export Address Table
-* and Import Address Table (IAT).
-* If the pData == NULL upon entry the number of entries of the pData array must
-* have in order to be able to hold the data is returned.
-* -- dwPID
-* -- szModule
-* -- pData
-* -- cData
-* -- pcData
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-
-/*
-* Retrieve the virtual address of a given function inside a process/module.
-* -- dwPID
-* -- szModuleName
-* -- szFunctionName
-* -- return = virtual address of function, zero on fail.
-*/
-ULONG64 VMMDLL_ProcessGetProcAddress(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szFunctionName);
-
-/*
-* Retrieve the base address of a given module.
-* -- dwPID
-* -- szModuleName
-* -- return = virtual address of module base, zero on fail.
-*/
-ULONG64 VMMDLL_ProcessGetModuleBase(_In_ DWORD dwPID, _In_ LPSTR szModuleName);
-
-
-
-//-----------------------------------------------------------------------------
-// WINDOWS SPECIFIC UTILITY FUNCTIONS BELOW:
-//-----------------------------------------------------------------------------
-
-typedef struct tdVMMDLL_WIN_THUNKINFO_IAT {
- BOOL fValid;
- BOOL f32; // if TRUE fn is a 32-bit/4-byte entry, otherwise 64-bit/8-byte entry.
- ULONG64 vaThunk; // address of import address table 'thunk'.
- ULONG64 vaFunction; // value if import address table 'thunk' == address of imported function.
- ULONG64 vaNameModule; // address of name string for imported module.
- ULONG64 vaNameFunction; // address of name string for imported function.
-} VMMDLL_WIN_THUNKINFO_IAT, *PVMMDLL_WIN_THUNKINFO_IAT;
-
-typedef struct tdVMMDLL_WIN_THUNKINFO_EAT {
- BOOL fValid;
- DWORD valueThunk; // value of export address table 'thunk'.
- ULONG64 vaThunk; // address of import address table 'thunk'.
- ULONG64 vaNameFunction; // address of name string for exported function.
- ULONG64 vaFunction; // address of exported function (module base + value parameter).
-} VMMDLL_WIN_THUNKINFO_EAT, *PVMMDLL_WIN_THUNKINFO_EAT;
-
-/*
-* Retrieve information about the import address table IAT thunk for an imported
-* function. This includes the virtual address of the IAT thunk which is useful
-* for hooking.
-* -- dwPID
-* -- szModuleName
-* -- szImportModuleName
-* -- szImportFunctionName
-* -- pThunkIAT
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoIAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szImportModuleName, _In_ LPSTR szImportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_IAT pThunkInfoIAT);
-
-/*
-* Retrieve information about the export address table EAT thunk for an exported
-* function. This includes the virtual address of the EAT thunk which is useful
-* for hooking.
-* -- dwPID
-* -- szModuleName
-* -- pThunkEAT
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoEAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szExportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_EAT pThunkInfoEAT);
-
-/*
-* Decompress compressed memory page stored in the MemCompression process.
-* -- vaCompressedData = virtual address in 'MemCompression' to decompress.
-* -- cbCompressedData = length of compressed data in 'MemCompression' to decompress (or zero for auto-detect).
-* -- pbDecompressedPage
-* -- pcbCompressedData = optional ptr to receive length of compressed buffer.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinMemCompression_DecompressPage(
- _In_ ULONG64 vaCompressedData,
- _In_opt_ DWORD cbCompressedData,
- _Out_writes_(4096) PBYTE pbDecompressedPage,
- _Out_opt_ PDWORD pcbCompressedData
-);
-
-
-//-----------------------------------------------------------------------------
-// VMM UTIL FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-/*
-* Fill a human readable hex ascii memory dump into the caller supplied sz buffer.
-* -- pb
-* -- cb
-* -- cbInitialOffset = offset, must be max 0x1000 and multiple of 0x10.
-* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
-* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
-*/
-_Success_(return)
-BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __VMMDLL_H__ */
diff --git a/vmm_example/vmmdll_example.c b/vmm_example/vmmdll_example.c
deleted file mode 100644
index f3b17fa..0000000
--- a/vmm_example/vmmdll_example.c
+++ /dev/null
@@ -1,655 +0,0 @@
-// vmmdll_example.c - Memory Process File System / Virtual Memory Manager DLL API usage examples
-//
-// Note that this is not a complete list of the VMM API. For the complete list please consult the vmmdll.h header file.
-//
-// (c) Ulf Frisk, 2018
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-
-#include
-#include
-#include
-#include "vmmdll.h"
-
-#pragma comment(lib, "vmm")
-
-// ----------------------------------------------------------------------------
-// Initialize from type of device, FILE, FPGA or Total Meltdown (CVE-2018-1038).
-// Ensure only one is active below at one single time!
-// INITIALIZE_FROM_FILE contains file name to a raw memory dump.
-// ----------------------------------------------------------------------------
-#define _INITIALIZE_FROM_FILE "c:\\temp\\win10.raw"
-//#define _INITIALIZE_FROM_FPGA
-//#define _INITIALIZE_FROM_TOTALMELTDOWN
-
-// ----------------------------------------------------------------------------
-// Utility functions below:
-// ----------------------------------------------------------------------------
-
-VOID ShowKeyPress()
-{
- printf("PRESS ANY KEY TO CONTINUE ...\n");
- Sleep(250);
- _getch();
-}
-
-VOID PrintHexAscii(_In_ PBYTE pb, _In_ DWORD cb)
-{
- DWORD szMax;
- LPSTR sz;
- VMMDLL_UtilFillHexAscii(pb, cb, 0, NULL, &szMax);
- if(!(sz = LocalAlloc(0, szMax))) { return; }
- VMMDLL_UtilFillHexAscii(pb, cb, 0, sz, &szMax);
- printf(sz);
- LocalFree(sz);
-}
-
-VOID CallbackList_AddFile(_Inout_ HANDLE h, _In_ LPSTR szName, _In_ ULONG64 cb, _In_ PVOID pvReserved)
-{
- printf(" FILE: '%s'\tSize: %i\n", szName, (DWORD)cb);
-}
-
-VOID CallbackList_AddDirectory(_Inout_ HANDLE h, _In_ LPSTR szName, _In_ PVOID pvReserved)
-{
- printf(" DIR: '%s'\n", szName);
-}
-
-// ----------------------------------------------------------------------------
-// Main entry point which contains various sample code how to use PCILeech DLL.
-// Please walk though for different API usage examples. To select device ensure
-// one device type only is uncommented in the #defines above.
-// ----------------------------------------------------------------------------
-int main(_In_ int argc, _In_ char* argv[])
-{
- BOOL result;
- NTSTATUS nt;
- DWORD i, dwPID;
- DWORD dw = 0;
- QWORD va;
- BYTE pbPage1[0x1000], pbPage2[0x1000];
-
-#ifdef _INITIALIZE_FROM_FILE
- // Initialize PCILeech DLL with a memory dump file.
- printf("------------------------------------------------------------\n");
- printf("#01: Initialize from file: \n");
- ShowKeyPress();
- printf("CALL: VMMDLL_InitializeFile\n");
- result = VMMDLL_Initialize(3, (LPSTR[]){ "", "-device", _INITIALIZE_FROM_FILE });
- if(result) {
- printf("SUCCESS: VMMDLL_InitializeFile\n");
- } else {
- printf("FAIL: VMMDLL_InitializeFile\n");
- return 1;
- }
-#endif /* _INITIALIZE_FROM_FILE */
-
-#ifdef _INITIALIZE_FROM_TOTALMELTDOWN
- // Initialize VMM DLL from a linked PCILeech with the TotalMeltdown exploit.
- printf("------------------------------------------------------------\n");
- printf("#01: Initialize from TotalMeltdown: \n");
- ShowKeyPress();
- printf("CALL: VMMDLL_Initialize\n");
- result = result = VMMDLL_Initialize(3, (LPSTR[]) { "", "-device", "totalmeltdown" });
- if(result) {
- printf("SUCCESS: VMMDLL_Initialize\n");
- } else {
- printf("FAIL: VMMDLL_Initialize\n");
- return 1;
- }
-#endif /* _INITIALIZE_FROM_TOTALMELTDOWN */
-
-#ifdef _INITIALIZE_FROM_FPGA
- // Initialize VMM DLL from a linked PCILeech with a FPGA hardware device
- printf("------------------------------------------------------------\n");
- printf("#01: Initialize from FPGA: \n");
- ShowKeyPress();
- printf("CALL: VMMDLL_Initialize\n");
- result = VMMDLL_Initialize(3, (LPSTR[]) { "", "-device", "fpga" });
- if(result) {
- printf("SUCCESS: VMMDLL_Initialize\n");
- } else {
- printf("FAIL: VMMDLL_Initialize\n");
- return 1;
- }
- // Retrieve the ID of the FPPA (SP605/PCIeScreamer/AC701 ...) and the bitstream version
- ULONG64 qwID, qwVersionMajor, qwVersionMinor;
- ShowKeyPress();
- printf("CALL: VMMDLL_ConfigGet\n");
- result =
- VMMDLL_ConfigGet(VMMDLL_OPT_DEVICE_FPGA_FPGA_ID, &qwID) &&
- VMMDLL_ConfigGet(VMMDLL_OPT_DEVICE_FPGA_VERSION_MAJOR, &qwVersionMajor) &&
- VMMDLL_ConfigGet(VMMDLL_OPT_DEVICE_FPGA_VERSION_MINOR, &qwVersionMinor);
- if(result) {
- printf("SUCCESS: VMMDLL_ConfigGet\n");
- printf(" ID = %lli\n", qwID);
- printf(" VERSION = %lli.%lli\n", qwVersionMajor, qwVersionMinor);
- } else {
- printf("FAIL: VMMDLL_ConfigGet\n");
- return 1;
- }
- // Retrieve the read delay value (in microseconds uS) that is used by the
- // FPGA to pause in every read. Sometimes it may be a good idea to adjust
- // this (and other related values) to lower versions if the FPGA device
- // still works stable without errors. Use PCIleech_DeviceConfigSet to set
- // values.
- ULONG64 qwReadDelay;
- ShowKeyPress();
- printf("CALL: VMMDLL_ConfigGet\n");
- result = VMMDLL_ConfigGet(VMMDLL_OPT_DEVICE_FPGA_DELAY_READ, &qwReadDelay);
- if(result) {
- printf("SUCCESS: VMMDLL_ConfigGet\n");
- printf(" FPGA Read Delay in microseconds (uS) = %lli\n", qwReadDelay);
- } else {
- printf("FAIL: VMMDLL_ConfigGet\n");
- return 1;
- }
-#endif /* _INITIALIZE_FROM_FPGA */
-
-
- // Read physical memory at physical address 0x1000 and display the first
- // 0x100 bytes on-screen.
- printf("------------------------------------------------------------\n");
- printf("#02: Read from physical memory (0x1000 bytes @ 0x1000). \n");
- ShowKeyPress();
- printf("CALL: VMMDLL_MemRead\n");
- result = VMMDLL_MemRead(-1, 0x1000, pbPage1, 0x1000);
- if(result) {
- printf("SUCCESS: VMMDLL_MemRead\n");
- PrintHexAscii(pbPage1, 0x100);
- } else {
- printf("FAIL: VMMDLL_MemRead\n");
- return 1;
- }
-
-
- // Retrieve PID of explorer.exe
- // NB! if multiple explorer.exe exists only one will be returned by this
- // specific function call. Please see .h file for additional information
- // about how to retrieve the complete list of PIDs in the system by using
- // the function PCILeech_VmmProcessListPIDs instead.
- printf("------------------------------------------------------------\n");
- printf("#03: Get PID from the first 'explorer.exe' process found. \n");
- ShowKeyPress();
- printf("CALL: VMMDLL_PidGetFromName\n");
- result = VMMDLL_PidGetFromName("explorer.exe", &dwPID);
- if(result) {
- printf("SUCCESS: VMMDLL_PidGetFromName\n");
- printf(" PID = %i\n", dwPID);
- } else {
- printf("FAIL: VMMDLL_PidGetFromName\n");
- return 1;
- }
-
-
- // Retrieve additional process information such as: name of the process,
- // PML4 (PageDirectoryBase) PML4-USER (if exists) and Process State.
- printf("------------------------------------------------------------\n");
- printf("#04: Get Process Information from 'explorer.exe'. \n");
- ShowKeyPress();
- VMMDLL_PROCESS_INFORMATION ProcessInformation;
- SIZE_T cbProcessInformation = sizeof(VMMDLL_PROCESS_INFORMATION);
- ZeroMemory(&ProcessInformation, sizeof(VMMDLL_PROCESS_INFORMATION));
- ProcessInformation.magic = VMMDLL_PROCESS_INFORMATION_MAGIC;
- ProcessInformation.wVersion = VMMDLL_PROCESS_INFORMATION_VERSION;
- printf("CALL: VMMDLL_ProcessGetInformation\n");
- result = VMMDLL_ProcessGetInformation(dwPID, &ProcessInformation, &cbProcessInformation);
- if(result) {
- printf("SUCCESS: VMMDLL_ProcessGetInformation\n");
- printf(" Name = %s\n", ProcessInformation.szName);
- printf(" PageDirectoryBase = 0x%016llx\n", ProcessInformation.paDTB);
- printf(" PageDirectoryBaseUser = 0x%016llx\n", ProcessInformation.paDTB_UserOpt);
- printf(" ProcessState = 0x%08x\n", ProcessInformation.dwState);
- } else {
- printf("FAIL: VMMDLL_ProcessGetInformation\n");
- return 1;
- }
-
-
- // Retrieve the memory map from the page table. This function also tries to
- // make additional parsing to identify modules and tag the memory map with
- // them. This is done by multiple methods internally and may sometimes be
- // more resilient against anti-reversing techniques that may be employed in
- // some processes.
- printf("------------------------------------------------------------\n");
- printf("#05: Get Memory Map of 'explorer.exe'. \n");
- ShowKeyPress();
- ULONG64 cMemMapEntries;
- PVMMDLL_MEMMAP_ENTRY pMemMapEntries;
- printf("CALL: VMMDLL_ProcessGetMemoryMap #1\n");
- result = VMMDLL_ProcessGetMemoryMap(dwPID, NULL, &cMemMapEntries, TRUE);
- if(result) {
- printf("SUCCESS: VMMDLL_ProcessGetMemoryMap #1\n");
- printf(" Count = %lli\n", cMemMapEntries);
- } else {
- printf("FAIL: VMMDLL_ProcessGetMemoryMap #1\n");
- return 1;
- }
- pMemMapEntries = (PVMMDLL_MEMMAP_ENTRY)LocalAlloc(0, cMemMapEntries * sizeof(VMMDLL_MEMMAP_ENTRY));
- if(!pMemMapEntries) {
- printf("FAIL: OutOfMemory\n");
- return 1;
- }
- printf("CALL: VMMDLL_ProcessGetMemoryMap #2\n");
- result = VMMDLL_ProcessGetMemoryMap(dwPID, pMemMapEntries, &cMemMapEntries, TRUE);
- if(result) {
- printf("SUCCESS: VMMDLL_ProcessGetMemoryMap #2\n");
- printf(" # #PAGES ADRESS_RANGE SRWX\n");
- printf(" ====================================================\n");
- for(i = 0; i < cMemMapEntries; i++) {
- printf(
- " %04x %8x %016llx-%016llx %sr%s%s%s%s\n",
- i,
- (DWORD)pMemMapEntries[i].cPages,
- pMemMapEntries[i].AddrBase,
- pMemMapEntries[i].AddrBase + (pMemMapEntries[i].cPages << 12) - 1,
- pMemMapEntries[i].fPage & VMMDLL_MEMMAP_FLAG_PAGE_NS ? "-" : "s",
- pMemMapEntries[i].fPage & VMMDLL_MEMMAP_FLAG_PAGE_W ? "w" : "-",
- pMemMapEntries[i].fPage & VMMDLL_MEMMAP_FLAG_PAGE_NX ? "-" : "x",
- pMemMapEntries[i].szTag[0] ? (pMemMapEntries[i].fWoW64 ? " 32 " : " ") : "",
- pMemMapEntries[i].szTag
- );
- }
- } else {
- printf("FAIL: VMMDLL_ProcessGetMemoryMap #2\n");
- return 1;
- }
-
-
- // Retrieve the list of loaded DLLs from the process. Please note that this
- // list is retrieved by parsing in-process memory structures such as the
- // process environment block (PEB) which may be partly destroyed in some
- // processes due to obfuscation and anti-reversing. If that is the case the
- // memory map may use alternative parsing techniques to list DLLs.
- printf("------------------------------------------------------------\n");
- printf("#06: Get Module Map of 'explorer.exe'. \n");
- ShowKeyPress();
- ULONG64 cModules;
- PVMMDLL_MODULEMAP_ENTRY pModules;
- printf("CALL: VMMDLL_ProcessGetModuleMap #1\n");
- result = VMMDLL_ProcessGetModuleMap(dwPID, NULL, &cModules);
- if(result) {
- printf("SUCCESS: VMMDLL_ProcessGetModuleMap #1\n");
- printf(" Count = %lli\n", cModules);
- } else {
- printf("FAIL: VMMDLL_ProcessGetModuleMap #1\n");
- return 1;
- }
- pModules = (PVMMDLL_MODULEMAP_ENTRY)LocalAlloc(0, cModules * sizeof(VMMDLL_MODULEMAP_ENTRY));
- if(!pModules) {
- printf("FAIL: OutOfMemory\n");
- return 1;
- }
- printf("CALL: VMMDLL_ProcessGetModuleMap #2\n");
- result = VMMDLL_ProcessGetModuleMap(dwPID, pModules, &cModules);
- if(result) {
- printf("SUCCESS: VMMDLL_ProcessGetModuleMap #2\n");
- printf(" MODULE_NAME BASE SIZE ENTRY\n");
- printf(" ======================================================================================\n");
- for(i = 0; i < cModules; i++) {
- printf(
- " %-40.40s %i %016llx %08x %016llx\n",
- pModules[i].szName,
- pModules[i].fWoW64 ? 32 : 64,
- pModules[i].BaseAddress,
- pModules[i].SizeOfImage,
- pModules[i].EntryPoint
- );
- }
- } else {
- printf("FAIL: VMMDLL_ProcessGetModuleMap #2\n");
- return 1;
- }
-
-
- // Retrieve the module of kernel32.dll by its name. Note it is also possible
- // to retrieve it by retrieving the complete module map (list) and iterate
- // over it. But if the name of the module is known this is more convenient.
- // This required that the PEB and LDR list in-process haven't been tampered
- // with ...
- printf("------------------------------------------------------------\n");
- printf("#07: Get by name 'kernel32.dll' in 'explorer.exe'. \n");
- ShowKeyPress();
- VMMDLL_MODULEMAP_ENTRY ModuleEntry;
- printf("CALL: VMMDLL_ProcessGetModuleFromName\n");
- result = VMMDLL_ProcessGetModuleFromName(dwPID, "kernel32.dll", &ModuleEntry);
- if(result) {
- printf("SUCCESS: VMMDLL_ProcessGetModuleFromName\n");
- printf(" MODULE_NAME BASE SIZE ENTRY\n");
- printf(" ======================================================================================\n");
- printf(
- " %-40.40s %i %016llx %08x %016llx\n",
- ModuleEntry.szName,
- ModuleEntry.fWoW64 ? 32 : 64,
- ModuleEntry.BaseAddress,
- ModuleEntry.SizeOfImage,
- ModuleEntry.EntryPoint
- );
- } else {
- printf("FAIL: VMMDLL_ProcessGetModuleFromName\n");
- return 1;
- }
-
-
- // Retrieve the memory at the base of kernel32.dll previously fetched and
- // display the first 0x200 bytes of it. This read is fetched from the cache
- // by default (if possible). If reads should be forced from the DMA device
- // please specify the flag: VMM_FLAG_NOCACHE
- printf("------------------------------------------------------------\n");
- printf("#08: Read 0x200 bytes of 'kernel32.dll' in 'explorer.exe'. \n");
- ShowKeyPress();
- DWORD cRead;
- printf("CALL: VMMDLL_MemReadEx\n");
- result = VMMDLL_MemReadEx(dwPID, ModuleEntry.BaseAddress, pbPage2, 0x1000, &cRead, 0); // standard cached read
- //result = VMMDLL_MemReadEx(dwPID, ModuleEntry.BaseAddress, pbPage2, 0x1000, &cRead, VMMDLL_FLAG_NOCACHE); // uncached read
- if(result) {
- printf("SUCCESS: VMMDLL_MemReadEx\n");
- PrintHexAscii(pbPage2, min(cRead, 0x200));
- } else {
- printf("FAIL: VMMDLL_MemReadEx\n");
- return 1;
- }
-
-
- // List the sections from the module of kernel32.dll.
- printf("------------------------------------------------------------\n");
- printf("#09: List sections of 'kernel32.dll' in 'explorer.exe'. \n");
- ShowKeyPress();
- DWORD cSections;
- PIMAGE_SECTION_HEADER pSectionHeaders;
- printf("CALL: VMMDLL_ProcessGetSections #1\n");
- result = VMMDLL_ProcessGetSections(dwPID, "kernel32.dll", NULL, 0, &cSections);
- if(result) {
- printf("SUCCESS: VMMDLL_ProcessGetSections #1\n");
- printf(" Count = %lli\n", cModules);
- } else {
- printf("FAIL: VMMDLL_ProcessGetSections #1\n");
- return 1;
- }
- pSectionHeaders = (PIMAGE_SECTION_HEADER)LocalAlloc(LMEM_ZEROINIT, cSections * sizeof(IMAGE_SECTION_HEADER));
- if(!pModules) {
- printf("FAIL: OutOfMemory\n");
- return 1;
- }
- printf("CALL: VMMDLL_ProcessGetSections #2\n");
- result = VMMDLL_ProcessGetSections(dwPID, "kernel32.dll", pSectionHeaders, cSections, &cSections);
- if(result) {
- printf("SUCCESS: VMMDLL_ProcessGetSections #2\n");
- printf(" # NAME OFFSET SIZE RWX\n");
- printf(" =================================\n");
- for(i = 0; i < cSections; i++) {
- printf(
- " %02lx %-8.8s %08x %08x %c%c%c\n",
- i,
- pSectionHeaders[i].Name,
- pSectionHeaders[i].VirtualAddress,
- pSectionHeaders[i].Misc.VirtualSize,
- (pSectionHeaders[i].Characteristics & IMAGE_SCN_MEM_READ) ? 'r' : '-',
- (pSectionHeaders[i].Characteristics & IMAGE_SCN_MEM_WRITE) ? 'w' : '-',
- (pSectionHeaders[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) ? 'x' : '-'
- );
- }
- } else {
- printf("FAIL: VMMDLL_ProcessGetSections #2\n");
- return 1;
- }
-
-
- // Retrieve and display the data directories of kernel32.dll. The number of
- // data directories in a PE is always 16 - so this can be used to simplify
- // calling the functionality somewhat.
- printf("------------------------------------------------------------\n");
- printf("#10: List directories of 'kernel32.dll' in 'explorer.exe'. \n");
- ShowKeyPress();
- LPCSTR DIRECTORIES[16] = { "EXPORT", "IMPORT", "RESOURCE", "EXCEPTION", "SECURITY", "BASERELOC", "DEBUG", "ARCHITECTURE", "GLOBALPTR", "TLS", "LOAD_CONFIG", "BOUND_IMPORT", "IAT", "DELAY_IMPORT", "COM_DESCRIPTOR", "RESERVED" };
- DWORD cDirectories;
- IMAGE_DATA_DIRECTORY pDirectories[16];
- printf("CALL: VMMDLL_ProcessGetDirectories\n");
- result = VMMDLL_ProcessGetDirectories(dwPID, "kernel32.dll", pDirectories, 16, &cDirectories);
- if(result) {
- printf("SUCCESS: PCIleech_VmmProcess_GetDirectories\n");
- printf(" # NAME OFFSET SIZE\n");
- printf(" =====================================\n");
- for(i = 0; i < 16; i++) {
- printf(
- " %02lx %-16.16s %08x %08x\n",
- i,
- DIRECTORIES[i],
- pDirectories[i].VirtualAddress,
- pDirectories[i].Size
- );
- }
- } else {
- printf("FAIL: VMMDLL_ProcessGetDirectories\n");
- return 1;
- }
-
-
- // Retrieve the export address table (EAT) of kernel32.dll
- printf("------------------------------------------------------------\n");
- printf("#11: exports of 'kernel32.dll' in 'explorer.exe'. \n");
- ShowKeyPress();
- DWORD cEATs;
- PVMMDLL_EAT_ENTRY pEATs;
- printf("CALL: VMMDLL_ProcessGetEAT #1\n");
- result = VMMDLL_ProcessGetEAT(dwPID, "kernel32.dll", NULL, 0, &cEATs);
- if(result) {
- printf("SUCCESS: VMMDLL_ProcessGetEAT #1\n");
- printf(" Count = %i\n", cEATs);
- } else {
- printf("FAIL: VMMDLL_ProcessGetEAT #1\n");
- return 1;
- }
- pEATs = (PVMMDLL_EAT_ENTRY)LocalAlloc(LMEM_ZEROINIT, cEATs * sizeof(VMMDLL_EAT_ENTRY));
- if(!pEATs) {
- printf("FAIL: OutOfMemory\n");
- return 1;
- }
- printf("CALL: VMMDLL_ProcessGetEAT #2\n");
- result = VMMDLL_ProcessGetEAT(dwPID, "kernel32.dll", pEATs, cEATs, &cEATs);
- if(result) {
- printf("SUCCESS: VMMDLL_ProcessGetEAT #2\n");
- printf(" # OFFSET NAME\n");
- printf(" =================================\n");
- for(i = 0; i < cEATs; i++) {
- printf(
- " %04lx %08x %s\n",
- i,
- pEATs[i].vaFunctionOffset,
- pEATs[i].szFunction
- );
- }
- } else {
- printf("FAIL: VMMDLL_ProcessGetEAT #2\n");
- return 1;
- }
-
-
- // Retrieve the import address table (IAT) of kernel32.dll
- printf("------------------------------------------------------------\n");
- printf("#12: imports of 'kernel32.dll' in 'explorer.exe'. \n");
- ShowKeyPress();
- DWORD cIATs;
- PVMMDLL_IAT_ENTRY pIATs;
- printf("CALL: VMMDLL_ProcessGetIAT #1\n");
- result = VMMDLL_ProcessGetIAT(dwPID, "kernel32.dll", NULL, 0, &cIATs);
- if(result) {
- printf("SUCCESS: VMMDLL_ProcessGetIAT #1\n");
- printf(" Count = %i\n", cIATs);
- } else {
- printf("FAIL: VMMDLL_ProcessGetIAT #1\n");
- return 1;
- }
- pIATs = (PVMMDLL_IAT_ENTRY)LocalAlloc(LMEM_ZEROINIT, cIATs * sizeof(VMMDLL_IAT_ENTRY));
- if(!pIATs) {
- printf("FAIL: OutOfMemory\n");
- return 1;
- }
- printf("CALL: VMMDLL_ProcessGetIAT #2\n");
- result = VMMDLL_ProcessGetIAT(dwPID, "kernel32.dll", pIATs, cIATs, &cIATs);
- if(result) {
- printf("SUCCESS: VMMDLL_ProcessGetIAT #2\n");
- printf(" # VIRTUAL_ADDRESS MODULE!NAME\n");
- printf(" ===================================\n");
- for(i = 0; i < cIATs; i++) {
- printf(
- " %04lx %016llx %s!%s\n",
- i,
- pIATs[i].vaFunction,
- pIATs[i].szModule,
- pIATs[i].szFunction
- );
- }
- } else {
- printf("FAIL: VMMDLL_ProcessGetIAT #2\n");
- return 1;
- }
-
-
- // The Memory Process File System exists virtually in the form of a virtual
- // file system even if it may not be mounted at a mount point or drive.
- // It is possible to call the functions 'List', 'Read' and 'Write' by using
- // the API.
- // Virtual File System: 'List'.
- printf("------------------------------------------------------------\n");
- printf("#13: call the file system 'List' function on the root dir. \n");
- ShowKeyPress();
- VMMDLL_VFS_FILELIST VfsFileList;
- VfsFileList.h = 0; // your handle passed to the callback functions (not used in example).
- VfsFileList.pfnAddDirectory = CallbackList_AddDirectory;
- VfsFileList.pfnAddFile = CallbackList_AddFile;
- printf("CALL: VMMDLL_VfsList\n");
- result = VMMDLL_VfsList(L"\\", &VfsFileList);
- if(result) {
- printf("SUCCESS: VMMDLL_VfsList\n");
- } else {
- printf("FAIL: VMMDLL_VfsList\n");
- return 1;
- }
-
-
- // Virtual File System: 'Read' of 0x100 bytes from the offset 0x1000
- // in the physical memory by reading the /pmem physical memory file.
- printf("------------------------------------------------------------\n");
- printf("#14: call the file system 'Read' function on the pmem file. \n");
- ShowKeyPress();
- printf("CALL: VMMDLL_VfsRead\n");
- nt = VMMDLL_VfsRead(L"\\pmem", pbPage1, 0x100, &i, 0x1000);
- if(nt == VMMDLL_STATUS_SUCCESS) {
- printf("SUCCESS: VMMDLL_VfsRead\n");
- PrintHexAscii(pbPage1, i);
- } else {
- printf("FAIL: VMMDLL_VfsRead\n");
- return 1;
- }
-
-
- // Initialize plugin manager so that statistics may be read in the
- // following read call to the .status built-in module/plugin.
- printf("------------------------------------------------------------\n");
- printf("#15: initialize virtual file system plugins \n");
- printf(" (this is required for following read call) \n");
- ShowKeyPress();
- printf("CALL: VMMDLL_VfsInitializePlugins\n");
- result = VMMDLL_VfsInitializePlugins();
- if(result) {
- printf("SUCCESS: VMMDLL_VfsInitializePlugins\n");
- } else {
- printf("FAIL: VMMDLL_VfsInitializePlugins\n");
- return 1;
- }
-
-
- // Virtual File System: 'Read' statistics from the .status module/plugin.
- printf("------------------------------------------------------------\n");
- printf("#16: call file system 'Read' on .status\\statistics \n");
- ShowKeyPress();
- printf("CALL: VMMDLL_VfsRead\n");
- nt = VMMDLL_VfsRead(L"\\.status\\statistics", pbPage1, 0x1000, &i, 0);
- if(nt == VMMDLL_STATUS_SUCCESS) {
- printf("SUCCESS: VMMDLL_VfsRead\n");
- printf("%s", (LPSTR)pbPage1);
- } else {
- printf("FAIL: VMMDLL_VfsRead\n");
- return 1;
- }
-
-
- // Get base virtual address of ntoskrnl.exe
- printf("------------------------------------------------------------\n");
- printf("#17: get ntoskrnl.exe base virtual address \n");
- ShowKeyPress();
- printf("CALL: VMMDLL_ProcessGetModuleBase\n");
- va = VMMDLL_ProcessGetModuleBase(4, "ntoskrnl.exe");
- if(va) {
- printf("SUCCESS: VMMDLL_ProcessGetModuleBase\n");
- printf(" %s = %016llx\n", "ntoskrnl.exe", va);
- } else {
- printf("FAIL: VMMDLL_ProcessGetModuleBase\n");
- return 1;
- }
-
-
- // GetProcAddress from ntoskrnl.exe
- printf("------------------------------------------------------------\n");
- printf("#18: get proc address for ntoskrnl.exe!KeGetCurrentIrql \n");
- ShowKeyPress();
- printf("CALL: VMMDLL_ProcessGetProcAddress\n");
- va = VMMDLL_ProcessGetProcAddress(4, "ntoskrnl.exe", "KeGetCurrentIrql");
- if(va) {
- printf("SUCCESS: VMMDLL_ProcessGetProcAddress\n");
- printf(" %s!%s = %016llx\n", "ntoskrnl.exe", "KeGetCurrentIrql", va);
- } else {
- printf("FAIL: VMMDLL_ProcessGetProcAddress\n");
- return 1;
- }
-
-
- // Get EAT Thunk from ntoskrnl.exe!KeGetCurrentIrql
- printf("------------------------------------------------------------\n");
- printf("#19: Address of EAT thunk for ntoskrnl.exe!KeGetCurrentIrql \n");
- ShowKeyPress();
- VMMDLL_WIN_THUNKINFO_EAT oThunkInfoEAT;
- ZeroMemory(&oThunkInfoEAT, sizeof(VMMDLL_WIN_THUNKINFO_EAT));
- printf("CALL: VMMDLL_WinGetThunkInfoEAT\n");
- result = VMMDLL_WinGetThunkInfoEAT(4, "ntoskrnl.exe", "KeGetCurrentIrql", &oThunkInfoEAT);
- if(result) {
- printf("SUCCESS: VMMDLL_WinGetThunkInfoEAT\n");
- printf(" vaFunction: %016llx\n", oThunkInfoEAT.vaFunction);
- printf(" vaThunk: %016llx\n", oThunkInfoEAT.vaThunk);
- printf(" valueThunk: %08x\n", oThunkInfoEAT.valueThunk);
- printf(" vaNameFunc: %016llx\n", oThunkInfoEAT.vaNameFunction);
- } else {
- printf("FAIL: VMMDLL_WinGetThunkInfoEAT\n");
- return 1;
- }
-
-
- // Get IAT Thunk ntoskrnl.exe -> hal.dll!HalSendNMI
- printf("------------------------------------------------------------\n");
- printf("#20: Address of IAT thunk for hal.dll!HalSendNMI in ntoskrnl\n");
- ShowKeyPress();
- VMMDLL_WIN_THUNKINFO_IAT oThunkInfoIAT;
- ZeroMemory(&oThunkInfoIAT, sizeof(VMMDLL_WIN_THUNKINFO_IAT));
- printf("CALL: VMMDLL_WinGetThunkInfoIAT\n");
- result = VMMDLL_WinGetThunkInfoIAT(4, "ntoskrnl.Exe", "hal.Dll", "HalSendNMI", &oThunkInfoIAT);
- if(result) {
- printf("SUCCESS: VMMDLL_WinGetThunkInfoIAT\n");
- printf(" vaFunction: %016llx\n", oThunkInfoIAT.vaFunction);
- printf(" vaThunk: %016llx\n", oThunkInfoIAT.vaThunk);
- printf(" vaNameFunction: %016llx\n", oThunkInfoIAT.vaNameFunction);
- printf(" vaNameModule: %016llx\n", oThunkInfoIAT.vaNameModule);
- }
- else {
- printf("FAIL: VMMDLL_WinGetThunkInfoEAT\n");
- return 1;
- }
-
-
-
- // Finish everything and exit!
- printf("------------------------------------------------------------\n");
- printf("#99: FINISHED EXAMPLES! \n");
- ShowKeyPress();
- printf("FINISHED TEST CASES - EXITING!\n");
- return 0;
-}
diff --git a/vmmpyc/leechcore.h b/vmmpyc/leechcore.h
deleted file mode 100644
index 46af16a..0000000
--- a/vmmpyc/leechcore.h
+++ /dev/null
@@ -1,471 +0,0 @@
-// leechcore.h : header file for the leechcore module - which purpose is to
-// expose low-level device physical memory functionality.
-//
-// This library is thread-safe in all functions with the notable exceptions of
-// the LeechCore_Open() and LeechCore_Close() functions. Some devices may allow
-// multi-threaded access while in reality most devices are single-threaded and
-// will control synchronization where necessary with locks.
-//
-// The library is initialized by calling LeechCore_Open with a LEECHCORE_CONFIG
-// struct containing the correct configuration paramters. Note that the version
-// and magic values must be set in addition to the szDevice configuration value
-// Also, it may be possible to optionally connect to a remote leechcore service
-// or instance over RPC by specifying a szRemote configuration value.
-//
-// ----------------------------------------------------------------------------
-//
-// Remote instance: szRemote configuration value. Connect to a remote leechcore
-// instance by specifying a configuration value in the szRemote parameter. If a
-// loaded already valid instance exists remotely this will be prioritized above
-// the value in szDevice. If the acquisition device is not yet loaded by the
-// remote instance the value in szDevice will be used. Normally, the connection
-// will take place as a mutually authenticated encrypted connection secured by
-// kerberos. If not possible or desirable the 'insecure' value may be specified
-// to disable authentication and security.
-// Syntax:
-// rpc://:: (port = optional, remote_spn = kerberos)
-// (SPN of remote service or 'insecure' )
-// Examples:
-// rpc://insecure:remotehost.example.com (connect insecure to remote host )
-// rpc://user@ad.domain.com:192.0.0.5 (connect secure to remote host )
-// rpc://insecure:127.0.0.0:6666 (connect insecure non-default port)
-//
-// ----------------------------------------------------------------------------
-//
-// Device to connect to: szDevice contains the device to capture memory from.
-// Supported memory acquisition devices are:
-// USB3380 : hardware, read/write, 32-bit (4GB) addressing only. Requires a
-// PCILeech flashed USB3380 device connected over USB and Google
-// Android WinUSB drivers to be installed. Download and install from:
-// http://developer.android.com/sdk/win-usb.html#download
-// Syntax:
-// USB3380
-// USB3380://USB2 (force USB2 connection speed)
-//
-// FPGA : hardware, read/write - requires a PCILeech FPGA flashed hardware
-// device as shown at: https://github.com/ufrisk/pcileech-fpga
-// Also requires the FTD3XX.DLL from ftdichip to be placed in the
-// same directory as the executable. Download from ftdichip at:
-// http://www.ftdichip.com/Drivers/D3XX/FTD3XXLibrary_v1.2.0.6.zip
-// Syntax:
-// FGPA
-// FPGA://[:[:]] (values are optional)
-//
-// SP605TCP : hardware, read/write - connect to a remote SP605 FPGA over the
-// network using the implementation created by @d_olex.
-// https://github.com/Cr4sh/s6_pcie_microblaze
-// Syntax:
-// SP605TCP://[:] (port is optional)
-//
-// RAWTCP : read/write - connect to a remote raw tcp device - such as HPE iLO
-// that have been patched to support DMA as per blog entry below:
-// https://www.synacktiv.com/posts/exploit/using-your-bmc-as-a-dma-device-plugging-pcileech-to-hpe-ilo-4.html
-// Syntax:
-// RAWTCP://[:] (port is optional)
-//
-// HvSavedState : read-only - connect to a Hyper-V saved state file. In order
-// to do so the .dll file 'vmsavedstatedumpprovider.dll' must be
-// placed in same directory as the executable file.
-//
-// PMEM : load the rekall winpmem driver into the kernel and connect to it
-// to acquire memory. The signed driver `.sys` file may be found at:
-// https://github.com/Velocidex/c-aff4/tree/master/tools/pmem/resources/winpmem
-// Download the driver file `att_winpmem_64.sys` and copy it to the
-// directory of leechcore.dll and run executable as elevated admin
-// using syntax below:
-// Syntax:
-// PMEM (use att_winpmem_64.sys in directory of executable)
-// PMEM://
-//
-// TOTALMELTDOWN : read/write - requires a Windows 7 system vulnerable to the
-// "Total Meltdown" vulnerability - CVE-2018-1038.
-// Syntax:
-// TOTALMELTDOWN
-//
-// FILE : use dump file, either a raw linear memory dump or full crash dump.
-// Which format to use is auto-detected. If it looks like a full cash
-// dump that format will be used, otherwise it will be assumed that a
-// raw linear memory dump is to be used.
-// Syntax:
-// (no device-type prefix - just use the file name)
-// FILE://
-//
-// DumpIt : DumpIt is a "virtual" device. It's only possible to use the DumpIt
-// device if the main process containing LeechCore has been started
-// with DumpIt in LiveKD mode.
-// Example 1:
-// DumpIt.exe /LIVEKD /A MemProcFS.exe
-// Example 2:
-// DumpIt.exe /LIVEKD /A LeechSvc.exe /C "interactive insecure"
-// and then connect to remote service by:
-// MemProcFS.exe -remote rpc://insecure:192.168.x.x -device DumpIt
-//
-// EXISTING : Attach to existing already loaded configuration. This is done
-// instead of the default behaviour of closing any existing devices
-// and initializing the new requested device. If no existing device
-// exists the call to LeechCore_Open will fail.
-// Syntax:
-// EXISTING
-//
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 1.1.0
-//
-#ifndef __LEECHCORE_H__
-#define __LEECHCORE_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// WINDOWS / LINUX COMPATIBILITY BELOW:
-//-----------------------------------------------------------------------------
-
-#ifdef _WIN32
-#include
-typedef unsigned __int64 QWORD, *PQWORD;
-#define DLLEXPORT __declspec(dllexport)
-#endif /* _WIN32 */
-#ifdef LINUX
-#include
-#include
-typedef void VOID, *PVOID, *LPVOID;
-typedef void *HANDLE, **PHANDLE;
-typedef uint32_t BOOL, *PBOOL;
-typedef uint8_t BYTE, *PBYTE;
-typedef char CHAR, *PCHAR, *PSTR, *LPSTR;
-typedef uint16_t WORD, *PWORD, USHORT, *PUSHORT;
-typedef uint32_t DWORD, *PDWORD;
-typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64;
-#define MAX_PATH 260
-#define DLLEXPORT __attribute__((visibility("default")))
-#define _In_
-#define _Out_
-#define _In_z_
-#define _Inout_
-#define _In_opt_
-#define _Out_opt_
-#define _Out_writes_(x)
-#define _Check_return_opt_
-#define _Printf_format_string_
-#define _Inout_updates_bytes_(x)
-#define _In_reads_(cbDataIn)
-#define _Out_writes_opt_(x)
-#define _Success_(return)
-#endif /* LINUX */
-
-//-----------------------------------------------------------------------------
-// GENERAL HEADER DEFINES BELOW:
-//-----------------------------------------------------------------------------
-
-#define MEM_IO_SCATTER_HEADER_MAGIC 0xffff6548
-#define MEM_IO_SCATTER_HEADER_VERSION 0x0003
-
-typedef struct tdMEM_IO_SCATTER_HEADER {
- DWORD magic; // magic
- WORD version; // version
- WORD Future1;
- ULONG64 qwA; // base address.
- DWORD cbMax; // bytes to read (DWORD boundry, max 0x1000); pb must have room for this.
- DWORD cb; // bytes read into result buffer.
- PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
- PVOID pvReserved1; // reserved for use by caller.
- PVOID pvReserved2; // reserved for use by caller.
- PVOID Future2[8];
-} MEM_IO_SCATTER_HEADER, *PMEM_IO_SCATTER_HEADER, **PPMEM_IO_SCATTER_HEADER;
-
-//-----------------------------------------------------------------------------
-// LEECHCORE INITIALIZATION / CLOSE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-typedef enum tdLEECHCORE_DEVICE {
- LEECHCORE_DEVICE_NA = 0,
- LEECHCORE_DEVICE_FILE = 1,
- LEECHCORE_DEVICE_PMEM = 2,
- LEECHCORE_DEVICE_FPGA = 3,
- LEECHCORE_DEVICE_SP605_TCP = 4,
- LEECHCORE_DEVICE_USB3380 = 5,
- LEECHCORE_DEVICE_TOTALMELTDOWN = 6,
- LEECHCORE_DEVICE_HVSAVEDSTATE = 7,
- LEECHCORE_DEVICE_RAWTCP = 8,
-} LEECHCORE_DEVICE;
-
-#define LEECHCORE_CONFIG_MAGIC 0xffff6549
-#define LEECHCORE_CONFIG_VERSION 0x0001
-
-#define LEECHCORE_CONFIG_FLAG_PRINTF 0x0001
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_1 0x0002
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_2 0x0004
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_3 0x0008
-#define LEECHCORE_CONFIG_FLAG_REMOTE_NO_COMPRESS 0x0010
-
-typedef struct tdLEECHCORE_CONFIG {
- DWORD magic; // set by caller.
- WORD version; // set by caller.
- WORD flags; // set by caller, updated by device.
- ULONG64 paMax; // set by caller, updated by device.
- ULONG64 cbMaxSizeMemIo; // set by caller, updated by device.
- ULONG64 paMaxNative; // set by device.
- LEECHCORE_DEVICE tpDevice; // set by device.
- BOOL fWritable; // set by device. (is device writable?)
- BOOL fVolatile; // set by device. (is device volatile / memory may change?)
- BOOL fVolatileMaxAddress; // set by device. (is max address volatile? - poll changes with LEECHCORE_OPT_MEMORYINFO_ADDR_MAX)
- BOOL fRemote; // set by device.
- WORD VersionMajor; // set by device.
- WORD VersionMinor; // set by device.
- WORD VersionRevision; // set by device.
- CHAR szDevice[MAX_PATH]; // set by caller.
- CHAR szRemote[MAX_PATH]; // set by caller.
- // optional 'printf' function pointer. if set to non null value 'printf'
- // calls will be redirected. useful when logging to files.
- _Check_return_opt_ int(*pfn_printf_opt)(_In_z_ _Printf_format_string_ char const* const _Format, ...); // set by caller.
-} LEECHCORE_CONFIG, *PLEECHCORE_CONFIG;
-
-typedef struct tdLEECHCORE_PAGESTAT_MINIMAL {
- HANDLE h;
- VOID(*pfnPageStatUpdate)(HANDLE h, ULONG64 pa, ULONG64 cPageSuccessAdd, ULONG64 cPageFailAdd);
-} LEECHCORE_PAGESTAT_MINIMAL, *PLEECHCORE_PAGESTAT_MINIMAL;
-
-/*
-* Open a connection to the target device. The LeechCore initialization may fail
-* if the underlying device cannot be opened or if the LeechCore is already
-* initialized. If already initialized please connect with device EXISTING or
-* call LeechCore_Close() before opening a new device.
-* -- pInformation
-* -- result
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Open(_Inout_ PLEECHCORE_CONFIG pConfig);
-
-/*
-* Clean up various device related stuff and deallocate memory buffers.
-*/
-DLLEXPORT VOID LeechCore_Close();
-
-
-
-//-----------------------------------------------------------------------------
-// LEECHCORE CORE READ AND WRITE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_FLAG_READ_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_VERIFY 0x02
-
-/*
-* Allocate a scatter buffer containing empty 0x1000-sized ppMEMs with address
-* set to zero. Caller is responsible for calling LocalFree(ppMEMs).
-* -- cMEMs
-* -- pppMEMs = pointer to receive ppMEMs on success.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_AllocScatterEmpty(_In_ DWORD cMEMs, _Out_ PPMEM_IO_SCATTER_HEADER *pppMEMs);
-
-/*
-* Read memory in various non-contigious locations specified by the items in the
-* phDMAs array. Result for each unit of work will be given individually. No upper
-* limit of number of items to read, but no performance boost will be given if
-* above hardware limit. Max size of each unit of work is one 4k page (4096 bytes).
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-*/
-DLLEXPORT VOID LeechCore_ReadScatter(_Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_Read(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_READ_RETRY
-* -- pPageStat = optional minimal statistic struct to update.
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_ReadEx(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb, _In_ DWORD flags, _In_opt_ PLEECHCORE_PAGESTAT_MINIMAL pPageStat);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Write(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_WRITE_*
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_WriteEx(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD flags);
-
-/*
-* Probe the memory of the target system to check whether it's readable or not.
-* Please note that not all devices support this natively.
-* -- pa = address to start probe from.
-* -- cPages = number of 4kB pages to probe.
-* -- pbResultMap = result map, 1 byte represents 1 page, 0 = fail, 1 = success.
-* (individual page elements in pbResultMap must be set to 0 [fail] on call
-* for probe to take place on individual page).
-* -- return = FALSE if not supported by underlying hardware, TRUE if supported.
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Probe(_In_ QWORD pa, _In_ DWORD cPages, _Inout_updates_bytes_(cPages) PBYTE pbResultMap);
-
-
-
-//-----------------------------------------------------------------------------
-// GET/SET DEVICE OPTIONS BELOW. SOME OPTIONS ARE GENERAL LEECHCORE OPTIONS
-// WHILE OTHER ARE DEVICE SPECIFIC. USE FUNCTIONS:
-// LeechCore_GetOption() AND LeechCore_GetOption() TO GET/SET OPTIONS.
-// FOR DEVICE-SPECIFIC OPTIONS PLEASE SEE INDIVIDUAL DEVICE FILES FOR MORE
-// DETAILED INFORMATION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE 0x80000002 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-
-#define LEECHCORE_OPT_CORE_VERSION_MAJOR 0x01000001 // R
-#define LEECHCORE_OPT_CORE_VERSION_MINOR 0x01000002 // R
-#define LEECHCORE_OPT_CORE_VERSION_REVISION 0x01000003 // R
-
-#define LEECHCORE_OPT_MEMORYINFO_VALID 0x02000001 // R
-#define LEECHCORE_OPT_MEMORYINFO_ADDR_MAX 0x02000002 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_32BIT 0x02000003 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_PAE 0x02000004 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MINOR 0x02000005 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MAJOR 0x02000006 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_DTB 0x02000007 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PFN 0x02000008 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsLoadedModuleList 0x02000009 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsActiveProcessHead 0x0200000a // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_MACHINE_IMAGE_TP 0x0200000b // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_NUM_PROCESSORS 0x0200000c // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_SYSTEMTIME 0x0200000d // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_UPTIME 0x0200000e // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELBASE 0x0200000f // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELHINT 0x02000010 // R
-
-#define LEECHCORE_OPT_FPGA_PROBE_MAXPAGES 0x03000001 // RW
-#define LEECHCORE_OPT_FPGA_RX_FLUSH_LIMIT 0x03000002 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_RX 0x03000003 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_TX 0x03000004 // RW
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_READ 0x03000005 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_WRITE 0x03000006 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_WRITE 0x03000007 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_READ 0x03000008 // RW - uS
-#define LEECHCORE_OPT_FPGA_RETRY_ON_ERROR 0x03000009 // RW
-#define LEECHCORE_OPT_FPGA_DEVICE_ID 0x03000080 // R
-#define LEECHCORE_OPT_FPGA_FPGA_ID 0x03000081 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MAJOR 0x03000082 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MINOR 0x03000083 // R
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- pqwValue = pointer to QWORD to receive option value.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_GetOption(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- qwValue
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_SetOption(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// TRANSFER DEVICE DEPENDANT COMMANDS OR DATA TO/FROM UNDERLYING DEVICES AND
-// PERFORM ACTIONS USING THE LeechCore_CommandData() FUNCTION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_COMMANDDATA_FPGA_WRITE_TLP 0x00000101 // R
-#define LEECHCORE_COMMANDDATA_FPGA_LISTEN_TLP 0x00000102 // R
-#define LEECHCORE_COMMANDDATA_STATISTICS_GET 0x80000100 // R
-
-#define LEECHCORE_STATISTICS_MAGIC 0xffff6550
-#define LEECHCORE_STATISTICS_VERSION 0x0001
-#define LEECHCORE_STATISTICS_ID_OPEN 0x00
-#define LEECHCORE_STATISTICS_ID_READSCATTER 0x01
-#define LEECHCORE_STATISTICS_ID_WRITE 0x02
-#define LEECHCORE_STATISTICS_ID_PROBE 0x03
-#define LEECHCORE_STATISTICS_ID_GETOPTION 0x04
-#define LEECHCORE_STATISTICS_ID_SETOPTION 0x05
-#define LEECHCORE_STATISTICS_ID_COMMANDDATA 0x06
-#define LEECHCORE_STATISTICS_ID_MAX 0x06
-
-static const LPSTR LEECHCORE_STATISTICS_NAME[] = {
- "LeechCore_Open",
- "LeechCore_ReadScatter",
- "LeechCore_Write",
- "LeechCore_Probe",
- "LeechCore_GetOption",
- "LeechCore_SetOption",
- "LeechCore_CommandData"
-};
-
-typedef struct tdLEECHCORE_STATISTICS {
- DWORD magic;
- WORD version;
- WORD Reserved0;
- DWORD Reserved1;
- QWORD qwFreq;
- struct {
- QWORD c;
- QWORD tm; // total time in qwFreq ticks
- } Call[0x10];
-} LEECHCORE_STATISTICS, *PLEECHCORE_STATISTICS;
-
-/*
-* Transfer device dependant commands/data to/from the underlying device and
-* perform device dependant actions.
-* -- fOption
-* -- cbDataIn
-* -- pbDataIn
-* -- pbDataOut
-* -- cbDataOut
-* -- pcbDataOut
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_CommandData(
- _In_ ULONG64 fOption,
- _In_reads_(cbDataIn) PBYTE pbDataIn,
- _In_ DWORD cbDataIn,
- _Out_writes_opt_(cbDataOut) PBYTE pbDataOut,
- _In_ DWORD cbDataOut,
- _Out_opt_ PDWORD pcbDataOut
-);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __LEECHCORE_H__ */
diff --git a/vmmpyc/version.h b/vmmpyc/version.h
deleted file mode 100644
index a2ebf60..0000000
--- a/vmmpyc/version.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#define STRINGIZE2(s) #s
-#define STRINGIZE(s) STRINGIZE2(s)
-
-#define VERSION_MAJOR 2
-#define VERSION_MINOR 2
-#define VERSION_REVISION 0
-#define VERSION_BUILD 0
-
-#define VER_FILE_DESCRIPTION_STR "The Memory Process File System : Python API"
-#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
-#define VER_FILE_VERSION_STR STRINGIZE(VERSION_MAJOR) \
- "." STRINGIZE(VERSION_MINOR) \
- "." STRINGIZE(VERSION_REVISION) \
- "." STRINGIZE(VERSION_BUILD) \
-
-#define VER_COMPANY_NAME_STR ""
-#define VER_PRODUCTNAME_STR "vmmpyc"
-#define VER_PRODUCT_VERSION VER_FILE_VERSION
-#define VER_PRODUCT_VERSION_STR VER_FILE_VERSION_STR
-#define VER_ORIGINAL_FILENAME_STR VER_PRODUCTNAME_STR ".dll"
-#define VER_INTERNAL_NAME_STR VER_ORIGINAL_FILENAME_STR
-#define VER_COPYRIGHT_STR "Copyright (c) Ulf Frisk 2018-2019"
diff --git a/vmmpyc/vmmdll.h b/vmmpyc/vmmdll.h
deleted file mode 100644
index 6b1e71b..0000000
--- a/vmmpyc/vmmdll.h
+++ /dev/null
@@ -1,656 +0,0 @@
-// vmmdll.h : header file to include in projects that use vmm.dll either as
-// stand anlone projects or as native plugins to vmm.dll.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 2.2
-//
-
-#include
-#include "leechcore.h"
-
-#ifndef __VMMDLL_H__
-#define __VMMDLL_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// INITIALIZATION FUNCTIONALITY BELOW:
-// Choose one way of initialzing the VMM / Memory Process File System.
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize VMM.DLL with command line parameters. For a more detailed info
-* about the parameters please see github wiki for Memory Process File System
-* and LeechCore. THIS IS THE PREFERED WAY OF INITIALIZING VMM.DLL
-* Important parameters are:
-* -printf = show printf style outputs)
-* -v -vv -vvv = extra verbosity levels)
-* -device = device as on format for LeechCore - please see leechcore.h or
-* Github documentation for additional information. Some values
-* are: , fpga, usb3380, hvsavedstate, totalmeltdown, pmem
-* -remote = remote LeechCore instance - please see leechcore.h or Github
-* documentation for additional information.
-* -norefresh = disable background refreshes (even if backing memory is
-* volatile memory).
-* -- argc
-* -- argv
-* -- return = success/fail
-*/
-_Success_(return)
-BOOL VMMDLL_Initialize(_In_ DWORD argc, _In_ LPSTR argv[]);
-
-/*
-* Close an initialized instance of VMM.DLL and clean up all allocated resources
-* including plugins, linked PCILeech.DLL and other memory resources.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_Close();
-
-/*
-* Perform a force refresh of all internal caches including:
-* - process listings
-* - memory cache
-* - page table cache
-* WARNING: function may take some time to execute!
-* -- dwReserved = reserved future use - must be zero
-* -- return = sucess/fail
-*/
-_Success_(return)
-BOOL VMMDLL_Refresh(_In_ DWORD dwReserved);
-
-
-//-----------------------------------------------------------------------------
-// CONFIGURATION SETTINGS BELOW:
-// Configure the memory process file system or the underlying memory
-// acquisition devices.
-//-----------------------------------------------------------------------------
-
-/*
-* Options used together with the functions: VMMDLL_GetOption & VMMDLL_SetOption
-* Options are defined with either: VMMDLL_OPT_* in this header file or as
-* MEMDEVICE_OPT_* in memdevice.h
-* For more detailed information check the sources for individual device types.
-*/
-#define VMMDLL_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define VMMDLL_OPT_CORE_VERBOSE 0x80000002 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
-#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
-#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
-#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
-
-#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
-#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
-#define VMMDLL_OPT_CONFIG_READCACHE_TICKS 0x40000003 // RW - memory cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_TLBCACHE_TICKS 0x40000004 // RW - page table (tlb) cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_PARTIAL 0x40000005 // RW - process refresh (partial) period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_TOTAL 0x40000006 // RW - process refresh (full) period (in ticks)
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MAJOR 0x40000007 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MINOR 0x40000008 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
-#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
-
-static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
-
-typedef enum tdVMMDLL_MEMORYMODEL_TP {
- VMMDLL_MEMORYMODEL_NA = 0,
- VMMDLL_MEMORYMODEL_X86 = 1,
- VMMDLL_MEMORYMODEL_X86PAE = 2,
- VMMDLL_MEMORYMODEL_X64 = 3
-} VMMDLL_MEMORYMODEL_TP;
-
-typedef enum tdVMMDLL_SYSTEM_TP {
- VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
- VMMDLL_SYSTEM_WINDOWS_X64 = 2,
- VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
- VMMDLL_SYSTEM_WINDOWS_X86 = 4
-} VMMDLL_SYSTEM_TP;
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- pqwValue = pointer to ULONG64 to receive option value.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- qwValue
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// VFS - VIRTUAL FILE SYSTEM FUNCTIONALITY BELOW:
-// This is the core of the memory process file system. All implementation and
-// analysis towards the file system is possible by using functionality below.
-//-----------------------------------------------------------------------------
-
-#define VMMDLL_STATUS_SUCCESS ((NTSTATUS)0x00000000L)
-#define VMMDLL_STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
-#define VMMDLL_STATUS_END_OF_FILE ((NTSTATUS)0xC0000011L)
-#define VMMDLL_STATUS_FILE_INVALID ((NTSTATUS)0xC0000098L)
-#define VMMDLL_STATUS_FILE_SYSTEM_LIMITATION ((NTSTATUS)0xC0000427L)
-
-typedef struct tdVMMDLL_VFS_FILELIST {
- VOID(*pfnAddFile) (_Inout_ HANDLE h, _In_ LPSTR szName, _In_ ULONG64 cb, _In_ PVOID pvReserved);
- VOID(*pfnAddDirectory)(_Inout_ HANDLE h, _In_ LPSTR szName, _In_ PVOID pvReserved);
- HANDLE h;
-} VMMDLL_VFS_FILELIST, *PVMMDLL_VFS_FILELIST;
-
-/*
-* Helper function macros for callbacks into the VMM_VFS_FILELIST structure.
-*/
-#define VMMDLL_VfsList_AddFile(pFileList, szName, cb) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddFile(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, cb, NULL); }
-#define VMMDLL_VfsList_AddDirectory(pFileList, szName) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddDirectory(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, NULL); }
-
-/*
-* List a directory of files in the memory process file system. Directories and
-* files will be listed by callbacks into functions supplied in the pFileList
-* parameter. If information of an individual file is needed it's neccessary
-* to list all files in its directory.
-* -- wcsPath
-* -- pFileList
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
-
-/*
-* Read select parts of a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbRead
-* -- cbOffset
-* -- return
-*
-*/
-NTSTATUS VMMDLL_VfsRead(_In_ LPCWSTR wcsFileName, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-
-/*
-* Write select parts to a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbWrite
-* -- cbOffset
-* -- return
-*/
-NTSTATUS VMMDLL_VfsWrite(_In_ LPCWSTR wcsFileName, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-
-/*
-* Utility functions for memory process file system read/write towards different
-* underlying data representations.
-*/
-NTSTATUS VMMDLL_UtilVfsReadFile_FromPBYTE(_In_ PBYTE pbFile, _In_ ULONG64 cbFile, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromQWORD(_In_ ULONG64 qwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromDWORD(_In_ DWORD dwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromBOOL(_In_ BOOL fValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_BOOL(_Inout_ PBOOL pfTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset, _In_ DWORD dwMinAllow);
-
-
-//-----------------------------------------------------------------------------
-// PLUGIN MANAGER FUNCTIONALITY BELOW:
-// Function and structures to initialize and use the memory process file system
-// plugin functionality. The plugin manager is started by a call to function:
-// VMM_VfsInitializePlugins. Each built-in plugin and external plugin of which
-// the DLL name matches m_*.dll will receive a call to its InitializeVmmPlugin
-// function. The plugin/module may decide to call pfnPluginManager_Register to
-// register plugins in the form of different names one or more times.
-// Example of registration function in a plugin DLL below:
-// 'VOID InitializeVmmPlugin(_In_ PVMM_PLUGIN_REGINFO pRegInfo)'
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize all potential plugins, both built-in and external, that maps into
-* the memory process file system. Please note that plugins are not loaded by
-* default - they have to be explicitly loaded by calling this function. They
-* will be unloaded on a general close of the vmm dll.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsInitializePlugins();
-
-#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
-#define VMMDLL_PLUGIN_CONTEXT_VERSION 2
-#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
-#define VMMDLL_PLUGIN_REGINFO_VERSION 3
-
-#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
-
-typedef struct tdVMMDLL_PLUGIN_CONTEXT {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- DWORD dwPID;
- PVOID pProcess;
- LPSTR szModule;
- LPSTR szPath;
- PVOID pvReserved1;
- PVOID pvReserved2;
-} VMMDLL_PLUGIN_CONTEXT, *PVMMDLL_PLUGIN_CONTEXT;
-
-typedef struct tdVMMDLL_PLUGIN_REGINFO {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel;
- VMMDLL_SYSTEM_TP tpSystem;
- HMODULE hDLL;
- HMODULE hReservedDll; // not for general use (only used for python).
- BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
- PVOID pvReserved1;
- PVOID pvReserved2;
- // general plugin registration info to be filled out by the plugin below:
- struct {
- CHAR szModuleName[32];
- BOOL fRootModule;
- BOOL fProcessModule;
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_info;
- // function plugin registration info to be filled out by the plugin below:
- struct {
- BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
- NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
- NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
- VOID(*pfnNotify)(_In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
- VOID(*pfnClose)();
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_fn;
-} VMMDLL_PLUGIN_REGINFO, *PVMMDLL_PLUGIN_REGINFO;
-
-//-----------------------------------------------------------------------------
-// VMM CORE FUNCTIONALITY BELOW:
-// Vmm core functaionlity such as read (and write) to both virtual and physical
-// memory. NB! writing will only work if the target is supported - i.e. not a
-// memory dump file...
-// To read physical memory specify dwPID as (DWORD)-1
-//-----------------------------------------------------------------------------
-
-// FLAG used to supress the default read cache in calls to VMM_MemReadEx()
-// which will lead to the read being fetched from the target system always.
-// Cached page tables (used for translating virtual2physical) are still used.
-#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
-#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
-
-/*
-* Read memory in various non-contigious locations specified by the pointers to
-* the items in the ppDMAs array. Result for each unit of work will be given
-* individually. No upper limit of number of items to read, but no performance
-* boost will be given if above hardware limit. Max size of each unit of work is
-* one 4k page (4096 bytes).
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-* -- pcpDMAsRead = optional count of number of successfully read ppDMAs.
-* -- flags = optional flags as given by VMMDLL_FLAG_*
-* -- return = the number of successfully read items.
-*/
-DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs, _In_ DWORD flags);
-
-/*
-* Read a single 4096-byte page of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pbPage
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
-
-/*
-* Read a contigious arbitrary amount of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Read a contigious amount of memory and report the number of bytes read in pcbRead.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- pcbRead
-* -- flags = flags as in VMMDLL_FLAG_*
-* -- return = success/fail. NB! reads may report as success even if 0 bytes are
-* read - it's recommended to verify pcbReadOpt parameter.
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
-
-/*
-* Prefetch a number of addresses (specified in the pA array) into the memory
-* cache. This function is to be used to batch larger known reads into local
-* cache before making multiple smaller reads - which will then happen from
-* the cache. Function exists for performance reasons.
-* -- dwPID = PID of target process, (DWORD)-1 for physical memory.
-* -- pPrefetchAddresses = array of addresses to read into cache.
-* -- cPrefetchAddresses
-*/
-_Success_(return)
-BOOL VMMDLL_MemPrefetchPages(_In_ DWORD dwPID, _In_reads_(cPrefetchAddresses) PULONG64 pPrefetchAddresses, _In_ DWORD cPrefetchAddresses);
-
-/*
-* Write a contigious arbitrary amount of memory. Please note some virtual memory
-* such as pages of executables (such as DLLs) may be shared between different
-* virtual memory over different processes. As an example a write to kernel32.dll
-* in one process is likely to affect kernel32 in the whole system - in all
-* processes. Heaps and Stacks and other memory are usually safe to write to.
-* Please take care when writing to memory!
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = TRUE on success, FALSE on partial or zero write.
-*/
-_Success_(return)
-BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Translate a virtual address to a physical address by walking the page tables
-* of the specified process.
-* -- dwPID
-* -- qwVA
-* -- pqwPA
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
-
-
-
-//-----------------------------------------------------------------------------
-// VMM PROCESS FUNCTIONALITY BELOW:
-// Functionality below is mostly relating to Windows processes.
-//-----------------------------------------------------------------------------
-
-/*
-* Retrieve an active process given it's name. Please note that if multiple
-* processes with the same name exists only one will be returned. If required to
-* parse all processes with the same name please iterate over the PID list by
-* calling VMMDLL_PidList together with VMMDLL_ProcessGetInformation.
-* -- szProcName = process name (truncated max 15 chars) case insensitive.
-* -- pdwPID = pointer that will receive PID on success.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
-
-/*
-* List the PIDs in the system.
-* -- pPIDs = DWORD array of at least number of PIDs in system, or NULL.
-* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
-
-// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
-#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
-#define VMMDLL_MEMMAP_FLAG_PAGE_NS 0x0000000000000004
-#define VMMDLL_MEMMAP_FLAG_PAGE_NX 0x8000000000000000
-#define VMMDLL_MEMMAP_FLAG_PAGE_MASK 0x8000000000000006
-
-typedef struct tdVMMDLL_MEMMAP_ENTRY {
- ULONG64 AddrBase;
- ULONG64 cPages;
- ULONG64 fPage;
- BOOL fWoW64;
- CHAR szTag[32];
-} VMMDLL_MEMMAP_ENTRY, *PVMMDLL_MEMMAP_ENTRY;
-
-/*
-* Retrieve memory map entries from the specified process. Memory map entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries bytes.
-* If the pMemMapEntries is set to NULL the number of memory map entries will be
-* given in the pcMemMapEntries parameter.
-* -- dwPID
-* -- pMemMapEntries = buffer of minimum length sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries, or NULL.
-* -- pcMemMapEntries = pointer to number of memory map entries.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
-
-/*
-* Retrieve a single memory map entry given a virtual address within that entrys
-* range.
-* -- dwPID
-* -- pMemMapEntry
-* -- va = virtual address in the memory map entry to retrieve.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
-
-typedef struct tdVMMDLL_MODULEMAP_ENTRY {
- ULONG64 BaseAddress;
- ULONG64 EntryPoint;
- DWORD SizeOfImage;
- BOOL fWoW64;
- CHAR szName[32];
-} VMMDLL_MODULEMAP_ENTRY, *PVMMDLL_MODULEMAP_ENTRY;
-
-/*
-* Retrieve the module entries from the specified process. The module entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries bytes long. If the
-* pcModuleEntries is set to NULL the number of module entries will be given
-* in the pcModuleEntries parameter.
-* -- dwPID
-* -- pModuleEntries = buffer of minimum length sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries, or NULL.
-* -- pcModuleEntries = pointer to number of memory map entries.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
-
-/*
-* Retrieve a module (.exe or .dll or similar) given a module name.
-* -- dwPID
-* -- szModuleName
-* -- pModuleEntry
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
-
-#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
-#define VMMDLL_PROCESS_INFORMATION_VERSION 2
-
-typedef struct tdVMMDLL_PROCESS_INFORMATION {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
- VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
- BOOL fUserOnly; // only user mode pages listed
- DWORD dwPID;
- DWORD dwState;
- CHAR szName[16];
- ULONG64 paDTB;
- ULONG64 paDTB_UserOpt; // may not exist
- union {
- struct {
- ULONG64 vaEPROCESS;
- ULONG64 vaPEB;
- ULONG64 vaENTRY;
- BOOL fWow64;
- DWORD vaPEB32; // WoW64 only
- } win;
- } os;
-} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
-
-/*
-* Retrieve various process information from a PID. Process information such as
-* name, page directory bases and the process state may be retrieved.
-* -- dwPID
-* -- pProcessInformation = if null, size is given in *pcbProcessInfo
-* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
-
-typedef struct tdVMMDLL_EAT_ENTRY {
- ULONG64 vaFunction;
- DWORD vaFunctionOffset;
- CHAR szFunction[40];
-} VMMDLL_EAT_ENTRY, *PVMMDLL_EAT_ENTRY;
-
-typedef struct tdVMMDLL_IAT_ENTRY {
- ULONG64 vaFunction;
- CHAR szFunction[40];
- CHAR szModule[64];
-} VMMDLL_IAT_ENTRY, *PVMMDLL_IAT_ENTRY;
-
-/*
-* Retrieve information about: Data Directories, Sections, Export Address Table
-* and Import Address Table (IAT).
-* If the pData == NULL upon entry the number of entries of the pData array must
-* have in order to be able to hold the data is returned.
-* -- dwPID
-* -- szModule
-* -- pData
-* -- cData
-* -- pcData
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-
-/*
-* Retrieve the virtual address of a given function inside a process/module.
-* -- dwPID
-* -- szModuleName
-* -- szFunctionName
-* -- return = virtual address of function, zero on fail.
-*/
-ULONG64 VMMDLL_ProcessGetProcAddress(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szFunctionName);
-
-/*
-* Retrieve the base address of a given module.
-* -- dwPID
-* -- szModuleName
-* -- return = virtual address of module base, zero on fail.
-*/
-ULONG64 VMMDLL_ProcessGetModuleBase(_In_ DWORD dwPID, _In_ LPSTR szModuleName);
-
-
-
-//-----------------------------------------------------------------------------
-// WINDOWS SPECIFIC UTILITY FUNCTIONS BELOW:
-//-----------------------------------------------------------------------------
-
-typedef struct tdVMMDLL_WIN_THUNKINFO_IAT {
- BOOL fValid;
- BOOL f32; // if TRUE fn is a 32-bit/4-byte entry, otherwise 64-bit/8-byte entry.
- ULONG64 vaThunk; // address of import address table 'thunk'.
- ULONG64 vaFunction; // value if import address table 'thunk' == address of imported function.
- ULONG64 vaNameModule; // address of name string for imported module.
- ULONG64 vaNameFunction; // address of name string for imported function.
-} VMMDLL_WIN_THUNKINFO_IAT, *PVMMDLL_WIN_THUNKINFO_IAT;
-
-typedef struct tdVMMDLL_WIN_THUNKINFO_EAT {
- BOOL fValid;
- DWORD valueThunk; // value of export address table 'thunk'.
- ULONG64 vaThunk; // address of import address table 'thunk'.
- ULONG64 vaNameFunction; // address of name string for exported function.
- ULONG64 vaFunction; // address of exported function (module base + value parameter).
-} VMMDLL_WIN_THUNKINFO_EAT, *PVMMDLL_WIN_THUNKINFO_EAT;
-
-/*
-* Retrieve information about the import address table IAT thunk for an imported
-* function. This includes the virtual address of the IAT thunk which is useful
-* for hooking.
-* -- dwPID
-* -- szModuleName
-* -- szImportModuleName
-* -- szImportFunctionName
-* -- pThunkIAT
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoIAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szImportModuleName, _In_ LPSTR szImportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_IAT pThunkInfoIAT);
-
-/*
-* Retrieve information about the export address table EAT thunk for an exported
-* function. This includes the virtual address of the EAT thunk which is useful
-* for hooking.
-* -- dwPID
-* -- szModuleName
-* -- pThunkEAT
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoEAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szExportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_EAT pThunkInfoEAT);
-
-/*
-* Decompress compressed memory page stored in the MemCompression process.
-* -- vaCompressedData = virtual address in 'MemCompression' to decompress.
-* -- cbCompressedData = length of compressed data in 'MemCompression' to decompress (or zero for auto-detect).
-* -- pbDecompressedPage
-* -- pcbCompressedData = optional ptr to receive length of compressed buffer.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinMemCompression_DecompressPage(
- _In_ ULONG64 vaCompressedData,
- _In_opt_ DWORD cbCompressedData,
- _Out_writes_(4096) PBYTE pbDecompressedPage,
- _Out_opt_ PDWORD pcbCompressedData
-);
-
-
-//-----------------------------------------------------------------------------
-// VMM UTIL FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-/*
-* Fill a human readable hex ascii memory dump into the caller supplied sz buffer.
-* -- pb
-* -- cb
-* -- cbInitialOffset = offset, must be max 0x1000 and multiple of 0x10.
-* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
-* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
-*/
-_Success_(return)
-BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __VMMDLL_H__ */
diff --git a/vmmpyc/vmmpyc.c b/vmmpyc/vmmpyc.c
deleted file mode 100644
index c3d03a5..0000000
--- a/vmmpyc/vmmpyc.c
+++ /dev/null
@@ -1,1002 +0,0 @@
-#ifdef _DEBUG
-#undef _DEBUG
-#include
-#define _DEBUG
-#else
-#include
-#endif
-#include
-#include "vmmdll.h"
-
-//-----------------------------------------------------------------------------
-// INITIALIZATION FUNCTIONALITY BELOW:
-// Choose one way of initialzing the VMM / Memory Process File System.
-//-----------------------------------------------------------------------------
-
-// [STR] -> None
-static PyObject*
-VMMPYC_Initialize(PyObject *self, PyObject *args)
-{
- PyObject *pyList, *pyString;
- BOOL result;
- DWORD i, cDstArgs;
- LPSTR *pszDstArgs;
- if(!PyArg_ParseTuple(args, "O!", &PyList_Type, &pyList)) { return NULL; } // borrowed reference
- cDstArgs = (DWORD)PyList_Size(pyList);
- if(cDstArgs == 0) {
- Py_DECREF(pyList);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_Initialize: Required argument list is empty.");
- }
- // allocate & initialize buffer+basic
- pszDstArgs = (LPSTR*)LocalAlloc(LMEM_ZEROINIT, sizeof(LPSTR) * cDstArgs);
- if(!pszDstArgs) {
- Py_DECREF(pyList);
- return PyErr_NoMemory();
- }
- // iterate over # entries and build argument list
- for(i = 0; i < cDstArgs; i++) {
- pyString = PyList_GetItem(pyList, i); // borrowed reference
- if(!PyUnicode_Check(pyString)) {
- Py_DECREF(pyList);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_Initialize: Argument list contains non string item.");
- }
- pszDstArgs[i] = (char*)PyUnicode_1BYTE_DATA(pyString);
- }
- Py_DECREF(pyList);
- result = VMMDLL_Initialize(cDstArgs, pszDstArgs);
- if(!result) { return PyErr_Format(PyExc_RuntimeError, "VMMPYC_Initialize: Initialization of VMM failed."); }
- return Py_BuildValue("s", NULL); // None returned on success.
-}
-
-// () -> None
-static PyObject*
-VMMPYC_Close(PyObject *self, PyObject *args)
-{
- Py_BEGIN_ALLOW_THREADS;
- VMMDLL_Close();
- Py_END_ALLOW_THREADS;
- return Py_BuildValue("s", NULL); // None returned on success.
-}
-
-// (DWORD) -> None
-static PyObject*
-VMMPYC_Refresh(PyObject *self, PyObject *args)
-{
- BOOL result;
- DWORD dwReserved = 0;
- if(!PyArg_ParseTuple(args, "k", &dwReserved)) { return NULL; }
- Py_BEGIN_ALLOW_THREADS;
- result = VMMDLL_Refresh(dwReserved);
- Py_END_ALLOW_THREADS;
- if(!result) { return PyErr_Format(PyExc_RuntimeError, "VMMPYC_Refresh: Refresh failed."); }
- return Py_BuildValue("s", NULL); // None returned on success.
-}
-
-
-
-//-----------------------------------------------------------------------------
-// CONFIGURATION SETTINGS BELOW:
-// Configure the memory process file system or the underlying memory
-// acquisition devices.
-//-----------------------------------------------------------------------------
-
-// (ULONG64) -> ULONG64
-static PyObject*
-VMMPYC_ConfigGet(PyObject *self, PyObject *args)
-{
- BOOL result;
- ULONG64 fOption, qwValue = 0;
- if(!PyArg_ParseTuple(args, "K", &fOption)) { return NULL; }
- Py_BEGIN_ALLOW_THREADS;
- result = VMMDLL_ConfigGet(fOption, &qwValue);
- Py_END_ALLOW_THREADS;
- if(!result) { return PyErr_Format(PyExc_RuntimeError, "VMMPYC_ConfigGet: Unable to retrieve config value for setting."); }
- return PyLong_FromUnsignedLongLong(qwValue);
-}
-
-// (ULONG64, ULONG64) -> None
-static PyObject*
-VMMPYC_ConfigSet(PyObject *self, PyObject *args)
-{
- BOOL result;
- ULONG64 fOption, qwValue = 0;
- if(!PyArg_ParseTuple(args, "KK", &fOption, &qwValue)) { return NULL; }
- Py_BEGIN_ALLOW_THREADS;
- result = VMMDLL_ConfigSet(fOption, qwValue);
- Py_END_ALLOW_THREADS;
- if(!result) { return PyErr_Format(PyExc_RuntimeError, "VMMPYC_ConfigSet: Unable to set config value for setting."); }
- return Py_BuildValue("s", NULL); // None returned on success.
-}
-
-
-
-//-----------------------------------------------------------------------------
-// VMMPYC C-PYTHON FUNCTIONS BELOW:
-//-----------------------------------------------------------------------------
-
-// (DWORD, [STR], (DWORD)) -> [{...}]
-static PyObject*
-VMMPYC_MemReadScatter(PyObject *self, PyObject *args)
-{
- PyObject *pyListSrc, *pyListItemSrc, *pyListDst, *pyDict;
- BOOL result;
- DWORD dwPID, cMEMs, flags = 0;
- ULONG64 i, qwA;
- PMEM_IO_SCATTER_HEADER pMEM, pMEMs;
- PPMEM_IO_SCATTER_HEADER ppMEMs;
- PBYTE pb, pbDataBuffer;
- if(!PyArg_ParseTuple(args, "kO!|k", &dwPID, &PyList_Type, &pyListSrc, &flags)) { return NULL; } // borrowed reference
- cMEMs = (DWORD)PyList_Size(pyListSrc);
- if(cMEMs == 0) {
- Py_DECREF(pyListSrc);
- return PyList_New(0);
- }
- // allocate & initialize buffer+basic
- pb = LocalAlloc(0, cMEMs * (sizeof(PMEM_IO_SCATTER_HEADER) + sizeof(MEM_IO_SCATTER_HEADER) + 0x1000));
- if(!pb) {
- Py_DECREF(pyListSrc);
- return PyErr_NoMemory();
- }
- ppMEMs = (PPMEM_IO_SCATTER_HEADER)pb;
- pMEMs = (PMEM_IO_SCATTER_HEADER)(pb + cMEMs * sizeof(PMEM_IO_SCATTER_HEADER));
- pbDataBuffer = pb + cMEMs * (sizeof(PMEM_IO_SCATTER_HEADER) + sizeof(MEM_IO_SCATTER_HEADER));
- ZeroMemory(pb, pbDataBuffer - pb);
- // iterate over # entries and build scatter data structure
- for(i = 0; i < cMEMs; i++) {
- pMEM = pMEMs + i;
- pyListItemSrc = PyList_GetItem(pyListSrc, i); // borrowed reference
- if(!pyListItemSrc || !PyLong_Check(pyListItemSrc)) {
- Py_DECREF(pyListSrc);
- LocalFree(pb);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_MemReadScatter: Argument list contains non numeric item.");
- }
- qwA = PyLong_AsUnsignedLongLong(pyListItemSrc);
- if(qwA == (ULONG64)-1) {
- Py_DECREF(pyListSrc);
- LocalFree(pb);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_MemReadScatter: Argument list contains out-of-range numeric item.");
- }
- pMEM->cbMax = 0x1000;
- pMEM->pb = pbDataBuffer + (i << 12);
- pMEM->qwA = qwA;
- ppMEMs[i] = pMEM;
- }
- Py_DECREF(pyListSrc);
- // call c-dll for vmm
- Py_BEGIN_ALLOW_THREADS;
- result = VMMDLL_MemReadScatter(dwPID, ppMEMs, cMEMs, flags);
- Py_END_ALLOW_THREADS;
- if(!result) {
- LocalFree(pb);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_MemReadScatter: Failed.");
- }
- if(!(pyListDst = PyList_New(0))) {
- LocalFree(pb);
- return PyErr_NoMemory();
- }
- for(i = 0; i < cMEMs; i++) {
- pMEM = pMEMs + i;
- if((pyDict = PyDict_New())) {
- PyDict_SetItemString(pyDict, "addr", PyLong_FromUnsignedLongLong(pMEM->qwA));
- PyDict_SetItemString(pyDict, ((dwPID == -1) ? "pa" : "va"), PyLong_FromUnsignedLongLong(pMEM->qwA));
- PyDict_SetItemString(pyDict, "data", PyBytes_FromStringAndSize(pMEM->pb, 0x1000));
- PyDict_SetItemString(pyDict, "size", PyLong_FromUnsignedLong(pMEM->cb));
- PyList_Append(pyListDst, pyDict);
- }
- }
- LocalFree(pb);
- return pyListDst;
-}
-
-// (DWORD, ULONG64, DWORD, (ULONG64)) -> PBYTE
-static PyObject*
-VMMPYC_MemRead(PyObject *self, PyObject *args)
-{
- PyObject *pyBytes;
- BOOL result;
- DWORD dwPID, cb, cbRead = 0;
- ULONG64 qwA, flags = 0;
- PBYTE pb;
- if(!PyArg_ParseTuple(args, "kKk|K", &dwPID, &qwA, &cb, &flags)) { return NULL; }
- if(cb > 0x01000000) { return PyErr_Format(PyExc_RuntimeError, "VMMPYC_MemRead: Read larger than maxium supported (0x01000000) bytes requested."); }
- pb = LocalAlloc(0, cb);
- if(!pb) { return PyErr_NoMemory(); }
- Py_BEGIN_ALLOW_THREADS;
- result = VMMDLL_MemReadEx(dwPID, qwA, pb, cb, &cbRead, flags);
- Py_END_ALLOW_THREADS;
- if(!result) {
- LocalFree(pb);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_MemRead: Failed.");
- }
- pyBytes = PyBytes_FromStringAndSize(pb, cbRead);
- LocalFree(pb);
- return pyBytes;
-}
-
-// (DWORD, ULONG64, PBYTE) -> None
-static PyObject*
-VMMPYC_MemWrite(PyObject *self, PyObject *args)
-{
- Py_buffer pyBuffer;
- BOOL result;
- int iResult;
- DWORD dwPID;
- ULONG64 va;
- PBYTE pb;
- SIZE_T cb;
- if(!PyArg_ParseTuple(args, "kKy*", &dwPID, &va, &pyBuffer)) { return NULL; }
- cb = pyBuffer.len;
- if(cb == 0) {
- PyBuffer_Release(&pyBuffer);
- return Py_BuildValue("s", NULL); // zero-byte write is always successful.
- }
- pb = LocalAlloc(0, cb);
- if(!pb) {
- PyBuffer_Release(&pyBuffer);
- return PyErr_NoMemory();
- }
- iResult = PyBuffer_ToContiguous(pb, &pyBuffer, cb, 'C');
- PyBuffer_Release(&pyBuffer);
- Py_BEGIN_ALLOW_THREADS;
- result = (iResult == 0) && VMMDLL_MemWrite(dwPID, va, pb, (DWORD)cb);
- LocalFree(pb);
- Py_END_ALLOW_THREADS;
- if(!result) { return PyErr_Format(PyExc_RuntimeError, "VMMPYC_MemWrite: Failed."); }
- return Py_BuildValue("s", NULL); // None returned on success.
-}
-
-// (DWORD, ULONG64) -> ULONG64
-static PyObject*
-VMMPYC_MemVirt2Phys(PyObject *self, PyObject *args)
-{
- BOOL result;
- DWORD dwPID;
- ULONG64 va, pa;
- if(!PyArg_ParseTuple(args, "kK", &dwPID, &va)) { return NULL; }
- Py_BEGIN_ALLOW_THREADS;
- result = VMMDLL_MemVirt2Phys(dwPID, va, &pa);
- Py_END_ALLOW_THREADS;
- if(!result) { return PyErr_Format(PyExc_RuntimeError, "VMMPYC_MemVirt2Phys: Failed."); }
- return PyLong_FromUnsignedLongLong(pa);
-}
-
-// (DWORD, (BOOL)) -> [{...}]
-static PyObject*
-VMMPYC_ProcessGetMemoryMap(PyObject *self, PyObject *args)
-{
- PyObject *pyList, *pyDict;
- BOOL result, fIdentifyModules;
- DWORD dwPID, i;
- ULONG64 cMemMapEntries = 0;
- PVMMDLL_MEMMAP_ENTRY pe, pMemMapEntries = NULL;
- CHAR sz[5];
- if(!PyArg_ParseTuple(args, "k|p", &dwPID, &fIdentifyModules)) { return NULL; }
- if(!(pyList = PyList_New(0))) { return PyErr_NoMemory(); }
- Py_BEGIN_ALLOW_THREADS;
- result =
- VMMDLL_ProcessGetMemoryMap(dwPID, NULL, &cMemMapEntries, fIdentifyModules) &&
- cMemMapEntries &&
- (pMemMapEntries = LocalAlloc(0, cMemMapEntries * sizeof(VMMDLL_MEMMAP_ENTRY))) &&
- VMMDLL_ProcessGetMemoryMap(dwPID, pMemMapEntries, &cMemMapEntries, fIdentifyModules);
- Py_END_ALLOW_THREADS;
- if(!result) {
- Py_DECREF(pyList);
- LocalFree(pMemMapEntries);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_ProcessGetMemoryMap: Failed.");
- }
- for(i = 0; i < cMemMapEntries; i++) {
- if((pyDict = PyDict_New())) {
- pe = pMemMapEntries + i;
- PyDict_SetItemString(pyDict, "va", PyLong_FromUnsignedLongLong(pe->AddrBase));
- PyDict_SetItemString(pyDict, "size", PyLong_FromUnsignedLongLong(pe->cPages << 12));
- PyDict_SetItemString(pyDict, "pages", PyLong_FromUnsignedLongLong(pe->cPages));
- PyDict_SetItemString(pyDict, "wow64", PyBool_FromLong((long)pe->fWoW64));
- PyDict_SetItemString(pyDict, "tag", PyUnicode_FromString(pe->szTag));
- PyDict_SetItemString(pyDict, "flags-pte", PyLong_FromUnsignedLongLong(pe->fPage));
- sz[0] = (pe->fPage & VMMDLL_MEMMAP_FLAG_PAGE_NS) ? '-' : 's';
- sz[1] = 'r';
- sz[2] = (pe->fPage & VMMDLL_MEMMAP_FLAG_PAGE_W) ? 'w' : '-';
- sz[3] = (pe->fPage & VMMDLL_MEMMAP_FLAG_PAGE_NX) ? '-' : 'x';
- sz[4] = 0;
- PyDict_SetItemString(pyDict, "flags", PyUnicode_FromString(sz));
- PyList_Append(pyList, pyDict);
- }
- }
- LocalFree(pMemMapEntries);
- return pyList;
-}
-
-// (DWORD, ULONG64, (DWORD)) -> {}
-static PyObject*
-VMMPYC_ProcessGetMemoryMapEntry(PyObject *self, PyObject *args)
-{
- PyObject *pyDict;
- BOOL result, fIdentifyModules;
- DWORD dwPID;
- ULONG64 va;
- VMMDLL_MEMMAP_ENTRY e;
- CHAR sz[5];
- if(!PyArg_ParseTuple(args, "kK|p", &dwPID, &va, &fIdentifyModules)) { return NULL; }
- if(!(pyDict = PyDict_New())) { return PyErr_NoMemory(); }
- Py_BEGIN_ALLOW_THREADS;
- result = VMMDLL_ProcessGetMemoryMapEntry(dwPID, &e, va, fIdentifyModules);
- Py_END_ALLOW_THREADS;
- if(!result) {
- Py_DECREF(pyDict);
- return PyErr_Format(PyExc_RuntimeError, "VMMDLL_ProcessGetMemoryMapEntry: Failed.");
- }
- PyDict_SetItemString(pyDict, "va", PyLong_FromUnsignedLongLong(e.AddrBase));
- PyDict_SetItemString(pyDict, "size", PyLong_FromUnsignedLongLong(e.cPages << 12));
- PyDict_SetItemString(pyDict, "pages", PyLong_FromUnsignedLongLong(e.cPages));
- PyDict_SetItemString(pyDict, "wow64", PyBool_FromLong((long)e.fWoW64));
- PyDict_SetItemString(pyDict, "tag", PyUnicode_FromString(e.szTag));
- PyDict_SetItemString(pyDict, "flags-pte", PyLong_FromUnsignedLongLong(e.fPage));
- sz[0] = (e.fPage & VMMDLL_MEMMAP_FLAG_PAGE_NS) ? '-' : 's';
- sz[1] = 'r';
- sz[2] = (e.fPage & VMMDLL_MEMMAP_FLAG_PAGE_W) ? 'w' : '-';
- sz[3] = (e.fPage & VMMDLL_MEMMAP_FLAG_PAGE_NX) ? '-' : 'x';
- sz[4] = 0;
- PyDict_SetItemString(pyDict, "flags", PyUnicode_FromString(sz));
- return pyDict;
-}
-
-// (DWORD) -> [{...}]
-static PyObject*
-VMMPYC_ProcessGetModuleMap(PyObject *self, PyObject *args)
-{
- PyObject *pyList, *pyDict;
- BOOL result;
- DWORD dwPID;
- ULONG64 i, cModuleEntries = 0;
- PVMMDLL_MODULEMAP_ENTRY pe, pModuleEntries = NULL;
- if(!PyArg_ParseTuple(args, "k", &dwPID)) { return NULL; }
- if(!(pyList = PyList_New(0))) { return PyErr_NoMemory(); }
- Py_BEGIN_ALLOW_THREADS;
- result =
- VMMDLL_ProcessGetModuleMap(dwPID, NULL, &cModuleEntries) &&
- cModuleEntries &&
- (pModuleEntries = LocalAlloc(0, cModuleEntries * sizeof(VMMDLL_MODULEMAP_ENTRY))) &&
- VMMDLL_ProcessGetModuleMap(dwPID, pModuleEntries, &cModuleEntries);
- Py_END_ALLOW_THREADS;
- if(!result) {
- Py_DECREF(pyList);
- LocalFree(pModuleEntries);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_ProcessGetModuleMap: Failed.");
- }
- for(i = 0; i < cModuleEntries; i++) {
- if((pyDict = PyDict_New())) {
- pe = pModuleEntries + i;
- PyDict_SetItemString(pyDict, "va", PyLong_FromUnsignedLongLong(pe->BaseAddress));
- PyDict_SetItemString(pyDict, "va-entry", PyLong_FromUnsignedLongLong(pe->EntryPoint));
- PyDict_SetItemString(pyDict, "size", PyLong_FromUnsignedLong(pe->SizeOfImage));
- PyDict_SetItemString(pyDict, "wow64", PyBool_FromLong((long)pe->fWoW64));
- PyDict_SetItemString(pyDict, "name", PyUnicode_FromString(pe->szName));
- PyList_Append(pyList, pyDict);
- }
- }
- LocalFree(pModuleEntries);
- return pyList;
-}
-
-// (DWORD, STR) -> {...}
-static PyObject*
-VMMPYC_ProcessGetModuleFromName(PyObject *self, PyObject *args)
-{
- PyObject *pyDict;
- BOOL result;
- DWORD dwPID;
- LPSTR szModuleName;
- VMMDLL_MODULEMAP_ENTRY e;
- if(!PyArg_ParseTuple(args, "ks", &dwPID, &szModuleName)) { return NULL; }
- if(!(pyDict = PyDict_New())) { return PyErr_NoMemory(); }
- Py_BEGIN_ALLOW_THREADS;
- ZeroMemory(&e, sizeof(VMMDLL_MODULEMAP_ENTRY));
- result = VMMDLL_ProcessGetModuleFromName(dwPID, szModuleName, &e);
- Py_END_ALLOW_THREADS;
- if(!result) {
- Py_DECREF(pyDict);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_ProcessGetModuleFromName: Failed.");
- }
- PyDict_SetItemString(pyDict, "va", PyLong_FromUnsignedLongLong(e.BaseAddress));
- PyDict_SetItemString(pyDict, "va-entry", PyLong_FromUnsignedLongLong(e.EntryPoint));
- PyDict_SetItemString(pyDict, "wow64", PyBool_FromLong((long)e.fWoW64));
- PyDict_SetItemString(pyDict, "size", PyLong_FromUnsignedLong(e.SizeOfImage));
- PyDict_SetItemString(pyDict, "name", PyUnicode_FromString(e.szName));
- return pyDict;
-}
-
-// (STR) -> DWORD
-static PyObject*
-VMMPYC_PidGetFromName(PyObject *self, PyObject *args)
-{
- BOOL result;
- DWORD dwPID;
- LPSTR szProcessName;
- if(!PyArg_ParseTuple(args, "s", &szProcessName)) { return NULL; }
- Py_BEGIN_ALLOW_THREADS;
- result = VMMDLL_PidGetFromName(szProcessName, &dwPID);
- Py_END_ALLOW_THREADS;
- if(!result) { return PyErr_Format(PyExc_RuntimeError, "VMMPYC_PidGetFromName: Failed."); }
- return PyLong_FromLong(dwPID);
-}
-
-// () -> [DWORD]
-static PyObject*
-VMMPYC_PidList(PyObject *self, PyObject *args)
-{
- PyObject *pyList;
- BOOL result;
- ULONG64 cPIDs = 0;
- DWORD i, *pPIDs = NULL;
- if(!(pyList = PyList_New(0))) { return PyErr_NoMemory(); }
- Py_BEGIN_ALLOW_THREADS;
- result =
- VMMDLL_PidList(NULL, &cPIDs) &&
- (pPIDs = LocalAlloc(LMEM_ZEROINIT, cPIDs * sizeof(DWORD))) &&
- VMMDLL_PidList(pPIDs, &cPIDs);
- Py_END_ALLOW_THREADS;
- if(!result) {
- Py_DECREF(pyList);
- LocalFree(pPIDs);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_PidList: Failed.");
- }
- for(i = 0; i < cPIDs; i++) {
- PyList_Append(pyList, PyLong_FromUnsignedLong(pPIDs[i]));
- }
- LocalFree(pPIDs);
- return pyList;
-}
-
-// (DWORD) -> {...}
-static PyObject*
-VMMPYC_ProcessGetInformation(PyObject *self, PyObject *args)
-{
- PyObject *pyDict;
- BOOL result;
- DWORD dwPID;
- VMMDLL_PROCESS_INFORMATION info;
- SIZE_T cbInfo = sizeof(VMMDLL_PROCESS_INFORMATION);
- if(!PyArg_ParseTuple(args, "k", &dwPID)) { return NULL; }
- if(!(pyDict = PyDict_New())) { return PyErr_NoMemory(); }
- Py_BEGIN_ALLOW_THREADS;
- ZeroMemory(&info, sizeof(VMMDLL_PROCESS_INFORMATION));
- info.magic = VMMDLL_PROCESS_INFORMATION_MAGIC;
- info.wVersion = VMMDLL_PROCESS_INFORMATION_VERSION;
- result = VMMDLL_ProcessGetInformation(dwPID, &info, &cbInfo);
- Py_END_ALLOW_THREADS;
- if(!result) {
- Py_DECREF(pyDict);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_ProcessGetInformation: Failed.");
- }
- PyDict_SetItemString(pyDict, "pid", PyLong_FromUnsignedLong(info.dwPID));
- PyDict_SetItemString(pyDict, "pa-dtb", PyLong_FromUnsignedLongLong(info.paDTB));
- PyDict_SetItemString(pyDict, "pa-dtb-user", PyLong_FromUnsignedLongLong(info.paDTB_UserOpt));
- PyDict_SetItemString(pyDict, "state", PyLong_FromUnsignedLong(info.dwState));
- PyDict_SetItemString(pyDict, "tp-memorymodel", PyLong_FromUnsignedLong(info.tpMemoryModel));
- PyDict_SetItemString(pyDict, "tp-system", PyLong_FromUnsignedLong(info.tpSystem));
- PyDict_SetItemString(pyDict, "usermode", PyBool_FromLong(info.fUserOnly));
- PyDict_SetItemString(pyDict, "name", PyUnicode_FromString(info.szName));
- switch(info.tpSystem) {
- case VMMDLL_SYSTEM_WINDOWS_X64:
- PyDict_SetItemString(pyDict, "wow64", PyBool_FromLong((long)info.os.win.fWow64));
- PyDict_SetItemString(pyDict, "va-entry", PyLong_FromUnsignedLongLong(info.os.win.vaENTRY));
- PyDict_SetItemString(pyDict, "va-eprocess", PyLong_FromUnsignedLongLong(info.os.win.vaEPROCESS));
- PyDict_SetItemString(pyDict, "va-peb", PyLong_FromUnsignedLongLong(info.os.win.vaPEB));
- PyDict_SetItemString(pyDict, "va-peb32", PyLong_FromUnsignedLongLong(info.os.win.vaPEB32));
- break;
- case VMMDLL_SYSTEM_WINDOWS_X86:
- PyDict_SetItemString(pyDict, "va-entry", PyLong_FromUnsignedLongLong(info.os.win.vaENTRY));
- PyDict_SetItemString(pyDict, "va-eprocess", PyLong_FromUnsignedLongLong(info.os.win.vaEPROCESS));
- PyDict_SetItemString(pyDict, "va-peb", PyLong_FromUnsignedLongLong(info.os.win.vaPEB));
- break;
- }
- return pyDict;
-}
-
-// (DWORD, STR) -> [{...}]
-static PyObject*
-VMMPYC_ProcessGetDirectories(PyObject *self, PyObject *args)
-{
- PyObject *pyList, *pyDict;
- BOOL result;
- DWORD i, dwPID, cDirectories;
- PIMAGE_DATA_DIRECTORY pe, pDirectories = NULL;
- LPSTR szModule;
- LPCSTR DIRECTORIES[16] = { "EXPORT", "IMPORT", "RESOURCE", "EXCEPTION", "SECURITY", "BASERELOC", "DEBUG", "ARCHITECTURE", "GLOBALPTR", "TLS", "LOAD_CONFIG", "BOUND_IMPORT", "IAT", "DELAY_IMPORT", "COM_DESCRIPTOR", "RESERVED" };
- if(!PyArg_ParseTuple(args, "ks", &dwPID, &szModule)) { return NULL; }
- if(!(pyList = PyList_New(0))) { return PyErr_NoMemory(); }
- Py_BEGIN_ALLOW_THREADS;
- result =
- (pDirectories = LocalAlloc(0, 16 * sizeof(IMAGE_DATA_DIRECTORY))) &&
- VMMDLL_ProcessGetDirectories(dwPID, szModule, pDirectories, 16, &cDirectories);
- Py_END_ALLOW_THREADS;
- if(!result) {
- Py_DECREF(pyList);
- LocalFree(pDirectories);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_ProcessGetDirectories: Failed.");
- }
- for(i = 0; i < 16; i++) {
- if((pyDict = PyDict_New())) {
- pe = pDirectories + i;
- PyDict_SetItemString(pyDict, "i", PyLong_FromUnsignedLong(i));
- PyDict_SetItemString(pyDict, "size", PyLong_FromUnsignedLong(pe->Size));
- PyDict_SetItemString(pyDict, "offset", PyLong_FromUnsignedLong(pe->VirtualAddress));
- PyDict_SetItemString(pyDict, "name", PyUnicode_FromString(DIRECTORIES[i]));
- PyList_Append(pyList, pyDict);
- }
- }
- LocalFree(pDirectories);
- return pyList;
-}
-
-// (DWORD, STR) -> [{...}]
-static PyObject*
-VMMPYC_ProcessGetSections(PyObject *self, PyObject *args)
-{
- PyObject *pyList, *pyDict;
- BOOL result;
- DWORD i, dwPID, cSections;
- PIMAGE_SECTION_HEADER pe, pSections = NULL;
- LPSTR szModule;
- CHAR szName[9];
- szName[8] = 0;
- if(!PyArg_ParseTuple(args, "ks", &dwPID, &szModule)) { return NULL; }
- if(!(pyList = PyList_New(0))) { return PyErr_NoMemory(); }
- Py_BEGIN_ALLOW_THREADS;
- result =
- VMMDLL_ProcessGetSections(dwPID, szModule, NULL, 0, &cSections) &&
- cSections &&
- (pSections = LocalAlloc(0, cSections * sizeof(IMAGE_SECTION_HEADER))) &&
- VMMDLL_ProcessGetSections(dwPID, szModule, pSections, cSections, &cSections);
- Py_END_ALLOW_THREADS;
- if(!result) {
- Py_DECREF(pyList);
- LocalFree(pSections);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_ProcessGetSections: Failed.");
- }
- for(i = 0; i < cSections; i++) {
- if((pyDict = PyDict_New())) {
- pe = pSections + i;
- PyDict_SetItemString(pyDict, "i", PyLong_FromUnsignedLong(i));
- PyDict_SetItemString(pyDict, "Characteristics", PyLong_FromUnsignedLong(pe->Characteristics));
- PyDict_SetItemString(pyDict, "misc-PhysicalAddress", PyLong_FromUnsignedLong(pe->Misc.PhysicalAddress));
- PyDict_SetItemString(pyDict, "misc-VirtualSize", PyLong_FromUnsignedLong(pe->Misc.VirtualSize));
- *(PULONG64)szName = *(PULONG64)pe->Name;
- PyDict_SetItemString(pyDict, "Name", PyUnicode_FromString(szName));
- PyDict_SetItemString(pyDict, "NumberOfLinenumbers", PyLong_FromUnsignedLong(pe->NumberOfLinenumbers));
- PyDict_SetItemString(pyDict, "NumberOfRelocations", PyLong_FromUnsignedLong(pe->NumberOfRelocations));
- PyDict_SetItemString(pyDict, "PointerToLinenumbers", PyLong_FromUnsignedLong(pe->PointerToLinenumbers));
- PyDict_SetItemString(pyDict, "PointerToRawData", PyLong_FromUnsignedLong(pe->PointerToRawData));
- PyDict_SetItemString(pyDict, "PointerToRelocations", PyLong_FromUnsignedLong(pe->PointerToRelocations));
- PyDict_SetItemString(pyDict, "SizeOfRawData", PyLong_FromUnsignedLong(pe->SizeOfRawData));
- PyDict_SetItemString(pyDict, "VirtualAddress", PyLong_FromUnsignedLong(pe->VirtualAddress));
- PyList_Append(pyList, pyDict);
- }
- }
- LocalFree(pSections);
- return pyList;
-}
-
-// (DWORD, STR) -> [{...}]
-static PyObject*
-VMMPYC_ProcessGetEAT(PyObject *self, PyObject *args)
-{
- PyObject *pyList, *pyDict;
- BOOL result;
- DWORD i, dwPID, cEATs;
- PVMMDLL_EAT_ENTRY pe, pEATs = NULL;
- LPSTR szModule;
- if(!PyArg_ParseTuple(args, "ks", &dwPID, &szModule)) { return NULL; }
- if(!(pyList = PyList_New(0))) { return PyErr_NoMemory(); }
- Py_BEGIN_ALLOW_THREADS;
- result =
- VMMDLL_ProcessGetEAT(dwPID, szModule, NULL, 0, &cEATs) &&
- cEATs &&
- (pEATs = LocalAlloc(0, cEATs * sizeof(VMMDLL_EAT_ENTRY))) &&
- VMMDLL_ProcessGetEAT(dwPID, szModule, pEATs, cEATs, &cEATs);
- Py_END_ALLOW_THREADS;
- if(!result) {
- Py_DECREF(pyList);
- LocalFree(pEATs);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_ProcessGetEAT: Failed.");
- }
- for(i = 0; i < cEATs; i++) {
- if((pyDict = PyDict_New())) {
- pe = pEATs + i;
- PyDict_SetItemString(pyDict, "i", PyLong_FromUnsignedLong(i));
- PyDict_SetItemString(pyDict, "va", PyLong_FromUnsignedLongLong(pe->vaFunction));
- PyDict_SetItemString(pyDict, "offset", PyLong_FromUnsignedLong(pe->vaFunctionOffset));
- PyDict_SetItemString(pyDict, "fn", PyUnicode_FromString(pe->szFunction));
- PyList_Append(pyList, pyDict);
- }
- }
- LocalFree(pEATs);
- return pyList;
-}
-
-// (DWORD, STR) -> [{...}]
-static PyObject*
-VMMPYC_ProcessGetIAT(PyObject *self, PyObject *args)
-{
- PyObject *pyList, *pyDict;
- BOOL result;
- DWORD i, dwPID, cIATs;
- PVMMDLL_IAT_ENTRY pe, pIATs = NULL;
- LPSTR szModule;
- if(!PyArg_ParseTuple(args, "ks", &dwPID, &szModule)) { return NULL; }
- if(!(pyList = PyList_New(0))) { return PyErr_NoMemory(); }
- Py_BEGIN_ALLOW_THREADS;
- result =
- VMMDLL_ProcessGetIAT(dwPID, szModule, NULL, 0, &cIATs) &&
- cIATs &&
- (pIATs = LocalAlloc(0, cIATs * sizeof(VMMDLL_IAT_ENTRY))) &&
- VMMDLL_ProcessGetIAT(dwPID, szModule, pIATs, cIATs, &cIATs);
- Py_END_ALLOW_THREADS;
- if(!result) {
- Py_DECREF(pyList);
- LocalFree(pIATs);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_ProcessGetIAT: Failed.");
- }
- for(i = 0; i < cIATs; i++) {
- if((pyDict = PyDict_New())) {
- pe = pIATs + i;
- PyDict_SetItemString(pyDict, "i", PyLong_FromUnsignedLong(i));
- PyDict_SetItemString(pyDict, "va", PyLong_FromUnsignedLongLong(pe->vaFunction));
- PyDict_SetItemString(pyDict, "fn", PyUnicode_FromString(pe->szFunction));
- PyDict_SetItemString(pyDict, "dll", PyUnicode_FromString(pe->szModule));
- PyList_Append(pyList, pyDict);
- }
- }
- LocalFree(pIATs);
- return pyList;
-}
-
-// (PBYTE, (DWORD)) -> STR
-static PyObject*
-VMMPYC_UtilFillHexAscii(PyObject *self, PyObject *args)
-{
- Py_buffer pyBuffer;
- PyObject *pyString;
- DWORD cb, cbInitialOffset = 0, iResult, csz = 0;
- PBYTE pb;
- LPSTR sz = NULL;
- BOOL result;
- if(!PyArg_ParseTuple(args, "y*|k", &pyBuffer, &cbInitialOffset)) { return NULL; }
- cb = (DWORD)pyBuffer.len;
- if(cb == 0) {
- PyBuffer_Release(&pyBuffer);
- return PyUnicode_FromString("");
- }
- pb = LocalAlloc(0, cb);
- if(!pb) {
- PyBuffer_Release(&pyBuffer);
- return PyErr_NoMemory();
- }
- iResult = PyBuffer_ToContiguous(pb, &pyBuffer, cb, 'C');
- PyBuffer_Release(&pyBuffer);
- Py_BEGIN_ALLOW_THREADS;
- result =
- (iResult == 0) &&
- VMMDLL_UtilFillHexAscii(pb, cb, cbInitialOffset, NULL, &csz) &&
- csz &&
- (sz = (LPSTR)LocalAlloc(0, csz)) &&
- VMMDLL_UtilFillHexAscii(pb, cb, cbInitialOffset, sz, &csz);
- LocalFree(pb);
- Py_END_ALLOW_THREADS;
- if(!result || !sz) {
- LocalFree(sz);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_UtilFillHexAscii: Failed.");
- }
- pyString = PyUnicode_FromString(sz);
- LocalFree(sz);
- return pyString;
-}
-
-// (STR, DWORD, (ULONG64)) -> PBYTE
-static PyObject*
-VMMPYC_VfsRead(PyObject *self, PyObject *args)
-{
- PyObject *pyBytes;
- NTSTATUS nt;
- DWORD i, cb, cbRead = 0;
- ULONG64 cbOffset = 0;
- PBYTE pb;
- LPSTR szFileName;
- WCHAR wszFileName[MAX_PATH];
- if(!PyArg_ParseTuple(args, "sk|K", &szFileName, &cb, &cbOffset)) { return NULL; }
- if(cb > 0x01000000) { return PyErr_Format(PyExc_RuntimeError, "VMMPYC_VfsRead: Read larger than maxium supported (0x01000000) bytes requested."); }
- { // char* -> wchar*
- for(i = 0; i < MAX_PATH - 1; i++) {
- wszFileName[i] = szFileName[i];
- if(0 == szFileName[i]) { break; }
- }
- wszFileName[MAX_PATH - 1] = 0;
- }
- pb = LocalAlloc(0, cb);
- if(!pb) { return PyErr_NoMemory(); }
- Py_BEGIN_ALLOW_THREADS;
- nt = VMMDLL_VfsRead(wszFileName, pb, cb, &cbRead, cbOffset);
- Py_END_ALLOW_THREADS;
- if(nt != VMMDLL_STATUS_SUCCESS) {
- LocalFree(pb);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_VfsRead: Failed.");
- }
- pyBytes = PyBytes_FromStringAndSize(pb, cbRead);
- LocalFree(pb);
- return pyBytes;
-}
-
-// (STR, PBYTE, (ULONG64)) -> None
-static PyObject*
-VMMPYC_VfsWrite(PyObject *self, PyObject *args)
-{
- Py_buffer pyBuffer;
- BOOL result;
- int iResult;
- DWORD i, cb, cbWritten;
- ULONG64 cbOffset;
- PBYTE pb;
- LPSTR szFileName;
- WCHAR wszFileName[MAX_PATH];
- if(!PyArg_ParseTuple(args, "sy*|K", &szFileName, &pyBuffer, &cbOffset)) { return NULL; }
- cb = (DWORD)pyBuffer.len;
- if(cb == 0) {
- PyBuffer_Release(&pyBuffer);
- return Py_BuildValue("s", NULL); // zero-byte write is always successful.
- }
- { // char* -> wchar*
- for(i = 0; i < MAX_PATH - 1; i++) {
- wszFileName[i] = szFileName[i];
- if(0 == szFileName[i]) { break; }
- }
- wszFileName[MAX_PATH - 1] = 0;
- }
- pb = LocalAlloc(0, cb);
- if(!pb) {
- PyBuffer_Release(&pyBuffer);
- return PyErr_NoMemory();
- }
- iResult = PyBuffer_ToContiguous(pb, &pyBuffer, cb, 'C');
- PyBuffer_Release(&pyBuffer);
- Py_BEGIN_ALLOW_THREADS;
- result = (iResult == 0) && (VMMDLL_STATUS_SUCCESS == VMMDLL_VfsWrite(wszFileName, pb, cb, &cbWritten, cbOffset));
- LocalFree(pb);
- Py_END_ALLOW_THREADS;
- if(!result) { return PyErr_Format(PyExc_RuntimeError, "VMMPYC_VfsWrite: Failed."); }
- return Py_BuildValue("s", NULL); // None returned on success.
-}
-
-// (DWORD, STR, STR) -> ULONG64
-static PyObject*
-VMMPYC_ProcessGetProcAddress(PyObject *self, PyObject *args)
-{
- ULONG64 va;
- DWORD dwPID;
- LPSTR szModuleName, szProcName;
- if(!PyArg_ParseTuple(args, "kss", &dwPID, &szModuleName, &szProcName)) { return NULL; }
- Py_BEGIN_ALLOW_THREADS;
- va = VMMDLL_ProcessGetProcAddress(dwPID, szModuleName, szProcName);
- Py_END_ALLOW_THREADS;
- return va ?
- PyLong_FromUnsignedLongLong(va) :
- PyErr_Format(PyExc_RuntimeError, "VMMPYC_ProcessGetProcAddress: Failed.");
-}
-
-// (DWORD, STR) -> ULONG64
-static PyObject*
-VMMPYC_ProcessGetModuleBase(PyObject *self, PyObject *args)
-{
- ULONG64 va;
- DWORD dwPID;
- LPSTR szModuleName;
- if(!PyArg_ParseTuple(args, "ks", &dwPID, &szModuleName)) { return NULL; }
- Py_BEGIN_ALLOW_THREADS;
- va = VMMDLL_ProcessGetModuleBase(dwPID, szModuleName);
- Py_END_ALLOW_THREADS;
- return va ?
- PyLong_FromUnsignedLongLong(va) :
- PyErr_Format(PyExc_RuntimeError, "VMMPYC_ProcessGetModuleBase: Failed.");
-}
-
-// (DWORD, STR, STR) -> {...}
-static PyObject*
-VMMPYC_WinGetThunkInfoEAT(PyObject *self, PyObject *args)
-{
- PyObject *pyDict;
- BOOL result;
- DWORD dwPID;
- VMMDLL_WIN_THUNKINFO_EAT oThunkInfoEAT = { 0 };
- LPSTR szModuleName, szExportFunctionName;
- if(!PyArg_ParseTuple(args, "kss", &dwPID, &szModuleName, &szExportFunctionName)) { return NULL; }
- Py_BEGIN_ALLOW_THREADS;
- result = VMMDLL_WinGetThunkInfoEAT(dwPID, szModuleName, szExportFunctionName, &oThunkInfoEAT);
- Py_END_ALLOW_THREADS;
- if(!result || !oThunkInfoEAT.fValid) {
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_WinGetThunkInfoEAT: Failed.");
- }
- pyDict = PyDict_New();
- if(pyDict) {
- PyDict_SetItemString(pyDict, "vaFunction", PyLong_FromUnsignedLongLong(oThunkInfoEAT.vaFunction));
- PyDict_SetItemString(pyDict, "valueThunk", PyLong_FromUnsignedLong(oThunkInfoEAT.valueThunk));
- PyDict_SetItemString(pyDict, "vaNameFunction", PyLong_FromUnsignedLongLong(oThunkInfoEAT.vaNameFunction));
- PyDict_SetItemString(pyDict, "vaThunk", PyLong_FromUnsignedLongLong(oThunkInfoEAT.vaThunk));
- }
- return pyDict;
-}
-
-// (DWORD, STR, STR, STR) -> {...}
-static PyObject*
-VMMPYC_WinGetThunkInfoIAT(PyObject *self, PyObject *args)
-{
- PyObject *pyDict;
- BOOL result;
- DWORD dwPID;
- VMMDLL_WIN_THUNKINFO_IAT oThunkInfoIAT = { 0 };
- LPSTR szModuleName, szImportModuleName, szImportFunctionName;
- if(!PyArg_ParseTuple(args, "ksss", &dwPID, &szModuleName, &szImportModuleName, &szImportFunctionName)) { return NULL; }
- Py_BEGIN_ALLOW_THREADS;
- result = VMMDLL_WinGetThunkInfoIAT(dwPID, szModuleName, szImportModuleName, szImportFunctionName, &oThunkInfoIAT);
- Py_END_ALLOW_THREADS;
- if(!result || !oThunkInfoIAT.fValid) {
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_WinGetThunkInfoEAT: Failed.");
- }
- pyDict = PyDict_New();
- if(pyDict) {
- PyDict_SetItemString(pyDict, "32", PyBool_FromLong(oThunkInfoIAT.f32 ? 1 : 0));
- PyDict_SetItemString(pyDict, "vaFunction", PyLong_FromUnsignedLongLong(oThunkInfoIAT.vaFunction));
- PyDict_SetItemString(pyDict, "vaNameFunction", PyLong_FromUnsignedLongLong(oThunkInfoIAT.vaNameFunction));
- PyDict_SetItemString(pyDict, "vaNameModule", PyLong_FromUnsignedLongLong(oThunkInfoIAT.vaNameModule));
- PyDict_SetItemString(pyDict, "vaThunk", PyLong_FromUnsignedLongLong(oThunkInfoIAT.vaThunk));
- }
- return pyDict;
-}
-
-// (ULONG64, DWORD) -> {b: PBYTE, c: DWORD}
-static PyObject*
-VMMPYC_WinMemCompression_DecompressPage(PyObject *self, PyObject *args)
-{
- PyObject *pyDict;
- BOOL result;
- DWORD cb, cbCompressed;
- ULONG64 va;
- BYTE pbDecompressed[0x1000] = { 0 };
- if(!PyArg_ParseTuple(args, "Kk", &va, &cb)) { return NULL; }
- Py_BEGIN_ALLOW_THREADS;
- result = VMMDLL_WinMemCompression_DecompressPage(va, cb, pbDecompressed, &cbCompressed);
- Py_END_ALLOW_THREADS;
- if(!result) {
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_WinMemCompression_DecompressPage: Failed.");
- }
- pyDict = PyDict_New();
- if(pyDict) {
- PyDict_SetItemString(pyDict, "c", PyLong_FromUnsignedLong(cbCompressed));
- PyDict_SetItemString(pyDict, "b", PyBytes_FromStringAndSize(pbDecompressed, 0x1000));
- }
- return pyDict;
-}
-
-
-
-typedef struct tdVMMPYC_VFSLIST {
- struct tdVMMPYC_VFSLIST *FLink;
- CHAR szName[MAX_PATH];
- BOOL fIsDir;
- ULONG64 qwSize;
-} VMMPYC_VFSLIST, *PVMMPYC_VFSLIST;
-
-
-VOID VMMPYC_VfsList_AddInternal(_Inout_ HANDLE h, _In_ LPSTR szName, _In_ ULONG64 size, _In_ BOOL fIsDirectory)
-{
- PVMMPYC_VFSLIST *ppE = (PVMMPYC_VFSLIST*)h;
- PVMMPYC_VFSLIST pE;
- if((pE = LocalAlloc(0, sizeof(VMMPYC_VFSLIST)))) {
- strncpy_s(pE->szName, MAX_PATH - 1, szName, _TRUNCATE);
- pE->fIsDir = fIsDirectory;
- pE->qwSize = size;
- pE->FLink = *ppE;
- *ppE = pE;
- }
-}
-
-VOID VMMPYC_VfsList_AddFile(_Inout_ HANDLE h, _In_ LPSTR szName, _In_ ULONG64 size, _In_ PVOID pvReserved)
-{
- VMMPYC_VfsList_AddInternal(h, szName, size, FALSE);
-}
-
-VOID VMMPYC_VfsList_AddDirectory(_Inout_ HANDLE h, _In_ LPSTR szName, _In_ PVOID pvReserved)
-{
- VMMPYC_VfsList_AddInternal(h, szName, 0, TRUE);
-}
-
-
-// (STR) -> {{...}}
-static PyObject*
-VMMPYC_VfsList(PyObject *self, PyObject *args)
-{
- PyObject *pyDict, *PyDict_Attr;
- BOOL result;
- DWORD i;
- LPSTR szPath;
- WCHAR wszPath[MAX_PATH];
- VMMDLL_VFS_FILELIST hFileList;
- PVMMPYC_VFSLIST pE = NULL, pE_Next;
- if(!PyArg_ParseTuple(args, "s", &szPath)) { return NULL; }
- if(!(pyDict = PyDict_New())) { return PyErr_NoMemory(); }
- Py_BEGIN_ALLOW_THREADS;
- { // char* -> wchar*
- for(i = 0; i < MAX_PATH - 1; i++) {
- wszPath[i] = szPath[i];
- if(0 == szPath[i]) { break; }
- }
- wszPath[MAX_PATH - 1] = 0;
- }
- hFileList.h = &pE;
- hFileList.pfnAddFile = VMMPYC_VfsList_AddFile;
- hFileList.pfnAddDirectory = VMMPYC_VfsList_AddDirectory;
- result = VMMDLL_VfsList(wszPath, &hFileList);
- pE = *(PVMMPYC_VFSLIST*)hFileList.h;
- Py_END_ALLOW_THREADS;
- while(pE) {
- if((PyDict_Attr = PyDict_New())) {
- PyDict_SetItemString(PyDict_Attr, "f_isdir", PyBool_FromLong(pE->fIsDir ? 1 : 0));
- PyDict_SetItemString(PyDict_Attr, "size", PyLong_FromUnsignedLongLong(pE->qwSize));
- PyDict_SetItemString(pyDict, pE->szName, PyDict_Attr);
- }
- pE_Next = pE->FLink;
- LocalFree(pE);
- pE = pE_Next;
- }
- if(!result) {
- Py_DECREF(pyDict);
- return PyErr_Format(PyExc_RuntimeError, "VMMPYC_VfsList: Failed.");
- }
- return pyDict;
-}
-
-//-----------------------------------------------------------------------------
-// PY2C common functionality below:
-//-----------------------------------------------------------------------------
-
-static PyMethodDef VMMPYC_EmbMethods[] = {
- {"VMMPYC_Initialize", VMMPYC_Initialize, METH_VARARGS, "Initialize the VMM"},
- {"VMMPYC_Close", VMMPYC_Close, METH_VARARGS, "Try close the VMM"},
- {"VMMPYC_Refresh", VMMPYC_Refresh, METH_VARARGS, "Force refresh the VMM (process listings and caches)."},
- {"VMMPYC_ConfigGet", VMMPYC_ConfigGet, METH_VARARGS, "Get a device specific option value."},
- {"VMMPYC_ConfigSet", VMMPYC_ConfigSet, METH_VARARGS, "Set a device specific option value."},
- {"VMMPYC_MemReadScatter", VMMPYC_MemReadScatter, METH_VARARGS, "Read multiple 4kB page sized and aligned chunks of memory given as an address list."},
- {"VMMPYC_MemRead", VMMPYC_MemRead, METH_VARARGS, "Read memory."},
- {"VMMPYC_MemWrite", VMMPYC_MemWrite, METH_VARARGS, "Write memory."},
- {"VMMPYC_MemVirt2Phys", VMMPYC_MemVirt2Phys, METH_VARARGS, "Translate a virtual address into a physical address."},
- {"VMMPYC_PidGetFromName", VMMPYC_PidGetFromName, METH_VARARGS, "Locate a process by name and return the PID."},
- {"VMMPYC_PidList", VMMPYC_PidList, METH_VARARGS, "List all process PIDs."},
- {"VMMPYC_ProcessGetMemoryMap", VMMPYC_ProcessGetMemoryMap, METH_VARARGS, "Retrieve the memory map for a given process."},
- {"VMMPYC_ProcessGetMemoryMapEntry", VMMPYC_ProcessGetMemoryMapEntry, METH_VARARGS, "Retrieve a single memory map entry for a given process and virtual address."},
- {"VMMPYC_ProcessGetModuleMap", VMMPYC_ProcessGetModuleMap, METH_VARARGS, "Retrieve the module map for a given process."},
- {"VMMPYC_ProcessGetModuleFromName", VMMPYC_ProcessGetModuleFromName, METH_VARARGS, "Locate a module by name and return its information."},
- {"VMMPYC_ProcessGetInformation", VMMPYC_ProcessGetInformation, METH_VARARGS, "Retrieve process information for a specific process."},
- {"VMMPYC_ProcessGetDirectories", VMMPYC_ProcessGetDirectories, METH_VARARGS, "Retrieve the data directories for a specific process and module."},
- {"VMMPYC_ProcessGetSections", VMMPYC_ProcessGetSections, METH_VARARGS, "Retrieve the sections for a specific process and module."},
- {"VMMPYC_ProcessGetEAT", VMMPYC_ProcessGetEAT, METH_VARARGS, "Retrieve the export address table (EAT) for a specific process and module."},
- {"VMMPYC_ProcessGetIAT", VMMPYC_ProcessGetIAT, METH_VARARGS, "Retrieve the import address table (IAT) for a specific process and module."},
- {"VMMPYC_ProcessGetProcAddress", VMMPYC_ProcessGetProcAddress, METH_VARARGS, "Retrieve the proc address of a given module!function."},
- {"VMMPYC_ProcessGetModuleBase", VMMPYC_ProcessGetModuleBase, METH_VARARGS, "Retrieve the module base address given a module."},
- {"VMMPYC_WinGetThunkInfoEAT", VMMPYC_WinGetThunkInfoEAT, METH_VARARGS, "Retrieve information about the export address table (EAT) thunk. (useful for patching)."},
- {"VMMPYC_WinGetThunkInfoIAT", VMMPYC_WinGetThunkInfoIAT, METH_VARARGS, "Retrieve information about the import address table (IAT) thunk. (useful for patching)."},
- {"VMMPYC_VfsRead", VMMPYC_VfsRead, METH_VARARGS, "Read from a file in the virtual file system."},
- {"VMMPYC_VfsWrite", VMMPYC_VfsWrite, METH_VARARGS, "Write to a file in the virtual file system."},
- {"VMMPYC_VfsList", VMMPYC_VfsList, METH_VARARGS, "List files and folder for a specific directory in the Virutal File System."},
- {"VMMPYC_WinMemCompression_DecompressPage", VMMPYC_WinMemCompression_DecompressPage, METH_VARARGS, "Decompress compressed memory in the MemCompression process (if any)."},
- {"VMMPYC_UtilFillHexAscii", VMMPYC_UtilFillHexAscii, METH_VARARGS, "Convert a bytes object into a human readable 'memory dump' style type of string."},
- {NULL, NULL, 0, NULL}
-};
-
-static PyModuleDef VMMPYC_EmbModule = {
- PyModuleDef_HEAD_INIT, "vmmpyc", NULL, -1, VMMPYC_EmbMethods,
- NULL, NULL, NULL, NULL
-};
-
-__declspec(dllexport)
-PyObject* PyInit_vmmpyc(void)
-{
- return PyModule_Create(&VMMPYC_EmbModule);
-}
diff --git a/vmmpyc/vmmpyc.rc b/vmmpyc/vmmpyc.rc
deleted file mode 100644
index c26a624..0000000
Binary files a/vmmpyc/vmmpyc.rc and /dev/null differ
diff --git a/vmmpyc/vmmpyc.vcxproj b/vmmpyc/vmmpyc.vcxproj
deleted file mode 100644
index b9e1ea0..0000000
--- a/vmmpyc/vmmpyc.vcxproj
+++ /dev/null
@@ -1,127 +0,0 @@
-
-
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- 15.0
- {9E47796D-B834-470E-B437-0754BC14DF09}
- vmmpyc
- 10.0.17763.0
-
-
-
- DynamicLibrary
- true
- v141
- Unicode
- false
-
-
- DynamicLibrary
- false
- v141
- true
- Unicode
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(SolutionDir)\files\
- $(SolutionDir)\files\temp\$(ProjectName)\
- .pyd
- $(VC_IncludePath);$(WindowsSDK_IncludePath);$(WindowsSDK_IncludePath);C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\include\;C:\Program Files\Python36\include
- $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\libs;C:\Program Files\Python36\libs;
-
-
- $(SolutionDir)\files\
- $(SolutionDir)\files\temp\$(ProjectName)\
- .pyd
- $(VC_IncludePath);$(WindowsSDK_IncludePath);$(WindowsSDK_IncludePath);C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\include\;C:\Program Files\Python36\include
- $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\libs;C:\Program Files\Python36\libs;
-
-
-
- Level3
- Disabled
- true
- true
-
-
- $(SolutionDir)\files\vmm.lib
-
-
- $(OutDir)\lib\$(TargetName).pdb
- $(OutDir)\lib\$(TargetName).lib
-
-
-
-
-
-
- copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y
-copy $(SolutionDir)\files\vmmdll.h $(ProjectDir)\ /y
-
-
-
-
- Level3
- MaxSpeed
- true
- true
- true
- true
- MultiThreadedDLL
-
-
- true
- true
- $(SolutionDir)\files\vmm.lib
-
-
- $(OutDir)\lib\$(TargetName).pdb
- $(OutDir)\lib\$(TargetName).lib
- UseLinkTimeCodeGeneration
-
-
-
-
-
-
- copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y
-copy $(SolutionDir)\files\vmmdll.h $(ProjectDir)\ /y
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/vmmpyc/vmmpyc.vcxproj.filters b/vmmpyc/vmmpyc.vcxproj.filters
deleted file mode 100644
index 233b995..0000000
--- a/vmmpyc/vmmpyc.vcxproj.filters
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
- {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
-
-
- {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
- rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
-
-
- {e9dc36c3-ddaf-4793-bc7a-ca2ded590236}
-
-
-
-
- Header Files\vmm
-
-
- Header Files\vmm
-
-
- Header Files
-
-
-
-
- Source Files
-
-
-
-
- Resource Files
-
-
-
\ No newline at end of file
diff --git a/vmmpyc/vmmpyc.vcxproj.user b/vmmpyc/vmmpyc.vcxproj.user
deleted file mode 100644
index fa6ed15..0000000
--- a/vmmpyc/vmmpyc.vcxproj.user
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
- WindowsLocalDebugger
-
-
- WindowsLocalDebugger
-
-
\ No newline at end of file
diff --git a/vmmpycplugin/leechcore.h b/vmmpycplugin/leechcore.h
deleted file mode 100644
index 46af16a..0000000
--- a/vmmpycplugin/leechcore.h
+++ /dev/null
@@ -1,471 +0,0 @@
-// leechcore.h : header file for the leechcore module - which purpose is to
-// expose low-level device physical memory functionality.
-//
-// This library is thread-safe in all functions with the notable exceptions of
-// the LeechCore_Open() and LeechCore_Close() functions. Some devices may allow
-// multi-threaded access while in reality most devices are single-threaded and
-// will control synchronization where necessary with locks.
-//
-// The library is initialized by calling LeechCore_Open with a LEECHCORE_CONFIG
-// struct containing the correct configuration paramters. Note that the version
-// and magic values must be set in addition to the szDevice configuration value
-// Also, it may be possible to optionally connect to a remote leechcore service
-// or instance over RPC by specifying a szRemote configuration value.
-//
-// ----------------------------------------------------------------------------
-//
-// Remote instance: szRemote configuration value. Connect to a remote leechcore
-// instance by specifying a configuration value in the szRemote parameter. If a
-// loaded already valid instance exists remotely this will be prioritized above
-// the value in szDevice. If the acquisition device is not yet loaded by the
-// remote instance the value in szDevice will be used. Normally, the connection
-// will take place as a mutually authenticated encrypted connection secured by
-// kerberos. If not possible or desirable the 'insecure' value may be specified
-// to disable authentication and security.
-// Syntax:
-// rpc://:: (port = optional, remote_spn = kerberos)
-// (SPN of remote service or 'insecure' )
-// Examples:
-// rpc://insecure:remotehost.example.com (connect insecure to remote host )
-// rpc://user@ad.domain.com:192.0.0.5 (connect secure to remote host )
-// rpc://insecure:127.0.0.0:6666 (connect insecure non-default port)
-//
-// ----------------------------------------------------------------------------
-//
-// Device to connect to: szDevice contains the device to capture memory from.
-// Supported memory acquisition devices are:
-// USB3380 : hardware, read/write, 32-bit (4GB) addressing only. Requires a
-// PCILeech flashed USB3380 device connected over USB and Google
-// Android WinUSB drivers to be installed. Download and install from:
-// http://developer.android.com/sdk/win-usb.html#download
-// Syntax:
-// USB3380
-// USB3380://USB2 (force USB2 connection speed)
-//
-// FPGA : hardware, read/write - requires a PCILeech FPGA flashed hardware
-// device as shown at: https://github.com/ufrisk/pcileech-fpga
-// Also requires the FTD3XX.DLL from ftdichip to be placed in the
-// same directory as the executable. Download from ftdichip at:
-// http://www.ftdichip.com/Drivers/D3XX/FTD3XXLibrary_v1.2.0.6.zip
-// Syntax:
-// FGPA
-// FPGA://[:[:]] (values are optional)
-//
-// SP605TCP : hardware, read/write - connect to a remote SP605 FPGA over the
-// network using the implementation created by @d_olex.
-// https://github.com/Cr4sh/s6_pcie_microblaze
-// Syntax:
-// SP605TCP://[:] (port is optional)
-//
-// RAWTCP : read/write - connect to a remote raw tcp device - such as HPE iLO
-// that have been patched to support DMA as per blog entry below:
-// https://www.synacktiv.com/posts/exploit/using-your-bmc-as-a-dma-device-plugging-pcileech-to-hpe-ilo-4.html
-// Syntax:
-// RAWTCP://[:] (port is optional)
-//
-// HvSavedState : read-only - connect to a Hyper-V saved state file. In order
-// to do so the .dll file 'vmsavedstatedumpprovider.dll' must be
-// placed in same directory as the executable file.
-//
-// PMEM : load the rekall winpmem driver into the kernel and connect to it
-// to acquire memory. The signed driver `.sys` file may be found at:
-// https://github.com/Velocidex/c-aff4/tree/master/tools/pmem/resources/winpmem
-// Download the driver file `att_winpmem_64.sys` and copy it to the
-// directory of leechcore.dll and run executable as elevated admin
-// using syntax below:
-// Syntax:
-// PMEM (use att_winpmem_64.sys in directory of executable)
-// PMEM://
-//
-// TOTALMELTDOWN : read/write - requires a Windows 7 system vulnerable to the
-// "Total Meltdown" vulnerability - CVE-2018-1038.
-// Syntax:
-// TOTALMELTDOWN
-//
-// FILE : use dump file, either a raw linear memory dump or full crash dump.
-// Which format to use is auto-detected. If it looks like a full cash
-// dump that format will be used, otherwise it will be assumed that a
-// raw linear memory dump is to be used.
-// Syntax:
-// (no device-type prefix - just use the file name)
-// FILE://
-//
-// DumpIt : DumpIt is a "virtual" device. It's only possible to use the DumpIt
-// device if the main process containing LeechCore has been started
-// with DumpIt in LiveKD mode.
-// Example 1:
-// DumpIt.exe /LIVEKD /A MemProcFS.exe
-// Example 2:
-// DumpIt.exe /LIVEKD /A LeechSvc.exe /C "interactive insecure"
-// and then connect to remote service by:
-// MemProcFS.exe -remote rpc://insecure:192.168.x.x -device DumpIt
-//
-// EXISTING : Attach to existing already loaded configuration. This is done
-// instead of the default behaviour of closing any existing devices
-// and initializing the new requested device. If no existing device
-// exists the call to LeechCore_Open will fail.
-// Syntax:
-// EXISTING
-//
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 1.1.0
-//
-#ifndef __LEECHCORE_H__
-#define __LEECHCORE_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// WINDOWS / LINUX COMPATIBILITY BELOW:
-//-----------------------------------------------------------------------------
-
-#ifdef _WIN32
-#include
-typedef unsigned __int64 QWORD, *PQWORD;
-#define DLLEXPORT __declspec(dllexport)
-#endif /* _WIN32 */
-#ifdef LINUX
-#include
-#include
-typedef void VOID, *PVOID, *LPVOID;
-typedef void *HANDLE, **PHANDLE;
-typedef uint32_t BOOL, *PBOOL;
-typedef uint8_t BYTE, *PBYTE;
-typedef char CHAR, *PCHAR, *PSTR, *LPSTR;
-typedef uint16_t WORD, *PWORD, USHORT, *PUSHORT;
-typedef uint32_t DWORD, *PDWORD;
-typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64;
-#define MAX_PATH 260
-#define DLLEXPORT __attribute__((visibility("default")))
-#define _In_
-#define _Out_
-#define _In_z_
-#define _Inout_
-#define _In_opt_
-#define _Out_opt_
-#define _Out_writes_(x)
-#define _Check_return_opt_
-#define _Printf_format_string_
-#define _Inout_updates_bytes_(x)
-#define _In_reads_(cbDataIn)
-#define _Out_writes_opt_(x)
-#define _Success_(return)
-#endif /* LINUX */
-
-//-----------------------------------------------------------------------------
-// GENERAL HEADER DEFINES BELOW:
-//-----------------------------------------------------------------------------
-
-#define MEM_IO_SCATTER_HEADER_MAGIC 0xffff6548
-#define MEM_IO_SCATTER_HEADER_VERSION 0x0003
-
-typedef struct tdMEM_IO_SCATTER_HEADER {
- DWORD magic; // magic
- WORD version; // version
- WORD Future1;
- ULONG64 qwA; // base address.
- DWORD cbMax; // bytes to read (DWORD boundry, max 0x1000); pb must have room for this.
- DWORD cb; // bytes read into result buffer.
- PBYTE pb; // ptr to 0x1000 sized buffer to receive read bytes.
- PVOID pvReserved1; // reserved for use by caller.
- PVOID pvReserved2; // reserved for use by caller.
- PVOID Future2[8];
-} MEM_IO_SCATTER_HEADER, *PMEM_IO_SCATTER_HEADER, **PPMEM_IO_SCATTER_HEADER;
-
-//-----------------------------------------------------------------------------
-// LEECHCORE INITIALIZATION / CLOSE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-typedef enum tdLEECHCORE_DEVICE {
- LEECHCORE_DEVICE_NA = 0,
- LEECHCORE_DEVICE_FILE = 1,
- LEECHCORE_DEVICE_PMEM = 2,
- LEECHCORE_DEVICE_FPGA = 3,
- LEECHCORE_DEVICE_SP605_TCP = 4,
- LEECHCORE_DEVICE_USB3380 = 5,
- LEECHCORE_DEVICE_TOTALMELTDOWN = 6,
- LEECHCORE_DEVICE_HVSAVEDSTATE = 7,
- LEECHCORE_DEVICE_RAWTCP = 8,
-} LEECHCORE_DEVICE;
-
-#define LEECHCORE_CONFIG_MAGIC 0xffff6549
-#define LEECHCORE_CONFIG_VERSION 0x0001
-
-#define LEECHCORE_CONFIG_FLAG_PRINTF 0x0001
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_1 0x0002
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_2 0x0004
-#define LEECHCORE_CONFIG_FLAG_PRINTF_VERBOSE_3 0x0008
-#define LEECHCORE_CONFIG_FLAG_REMOTE_NO_COMPRESS 0x0010
-
-typedef struct tdLEECHCORE_CONFIG {
- DWORD magic; // set by caller.
- WORD version; // set by caller.
- WORD flags; // set by caller, updated by device.
- ULONG64 paMax; // set by caller, updated by device.
- ULONG64 cbMaxSizeMemIo; // set by caller, updated by device.
- ULONG64 paMaxNative; // set by device.
- LEECHCORE_DEVICE tpDevice; // set by device.
- BOOL fWritable; // set by device. (is device writable?)
- BOOL fVolatile; // set by device. (is device volatile / memory may change?)
- BOOL fVolatileMaxAddress; // set by device. (is max address volatile? - poll changes with LEECHCORE_OPT_MEMORYINFO_ADDR_MAX)
- BOOL fRemote; // set by device.
- WORD VersionMajor; // set by device.
- WORD VersionMinor; // set by device.
- WORD VersionRevision; // set by device.
- CHAR szDevice[MAX_PATH]; // set by caller.
- CHAR szRemote[MAX_PATH]; // set by caller.
- // optional 'printf' function pointer. if set to non null value 'printf'
- // calls will be redirected. useful when logging to files.
- _Check_return_opt_ int(*pfn_printf_opt)(_In_z_ _Printf_format_string_ char const* const _Format, ...); // set by caller.
-} LEECHCORE_CONFIG, *PLEECHCORE_CONFIG;
-
-typedef struct tdLEECHCORE_PAGESTAT_MINIMAL {
- HANDLE h;
- VOID(*pfnPageStatUpdate)(HANDLE h, ULONG64 pa, ULONG64 cPageSuccessAdd, ULONG64 cPageFailAdd);
-} LEECHCORE_PAGESTAT_MINIMAL, *PLEECHCORE_PAGESTAT_MINIMAL;
-
-/*
-* Open a connection to the target device. The LeechCore initialization may fail
-* if the underlying device cannot be opened or if the LeechCore is already
-* initialized. If already initialized please connect with device EXISTING or
-* call LeechCore_Close() before opening a new device.
-* -- pInformation
-* -- result
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Open(_Inout_ PLEECHCORE_CONFIG pConfig);
-
-/*
-* Clean up various device related stuff and deallocate memory buffers.
-*/
-DLLEXPORT VOID LeechCore_Close();
-
-
-
-//-----------------------------------------------------------------------------
-// LEECHCORE CORE READ AND WRITE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_FLAG_READ_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_RETRY 0x01
-#define LEECHCORE_FLAG_WRITE_VERIFY 0x02
-
-/*
-* Allocate a scatter buffer containing empty 0x1000-sized ppMEMs with address
-* set to zero. Caller is responsible for calling LocalFree(ppMEMs).
-* -- cMEMs
-* -- pppMEMs = pointer to receive ppMEMs on success.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_AllocScatterEmpty(_In_ DWORD cMEMs, _Out_ PPMEM_IO_SCATTER_HEADER *pppMEMs);
-
-/*
-* Read memory in various non-contigious locations specified by the items in the
-* phDMAs array. Result for each unit of work will be given individually. No upper
-* limit of number of items to read, but no performance boost will be given if
-* above hardware limit. Max size of each unit of work is one 4k page (4096 bytes).
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-*/
-DLLEXPORT VOID LeechCore_ReadScatter(_Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_Read(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb);
-
-/*
-* Try read memory in a fairly optimal way considering device limits. The number
-* of total successfully read bytes is returned. Failed reads will be zeroed out
-* in the returned memory.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_READ_RETRY
-* -- pPageStat = optional minimal statistic struct to update.
-* -- return = the number of bytes successfully read.
-*/
-DLLEXPORT DWORD LeechCore_ReadEx(_In_ ULONG64 pa, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb, _In_ DWORD flags, _In_opt_ PLEECHCORE_PAGESTAT_MINIMAL pPageStat);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Write(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Write data to the target system if supported by the device.
-* -- pa
-* -- pb
-* -- cb
-* -- flags = 0 or LEECHCORE_FLAG_WRITE_*
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_WriteEx(_In_ ULONG64 pa, _In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD flags);
-
-/*
-* Probe the memory of the target system to check whether it's readable or not.
-* Please note that not all devices support this natively.
-* -- pa = address to start probe from.
-* -- cPages = number of 4kB pages to probe.
-* -- pbResultMap = result map, 1 byte represents 1 page, 0 = fail, 1 = success.
-* (individual page elements in pbResultMap must be set to 0 [fail] on call
-* for probe to take place on individual page).
-* -- return = FALSE if not supported by underlying hardware, TRUE if supported.
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_Probe(_In_ QWORD pa, _In_ DWORD cPages, _Inout_updates_bytes_(cPages) PBYTE pbResultMap);
-
-
-
-//-----------------------------------------------------------------------------
-// GET/SET DEVICE OPTIONS BELOW. SOME OPTIONS ARE GENERAL LEECHCORE OPTIONS
-// WHILE OTHER ARE DEVICE SPECIFIC. USE FUNCTIONS:
-// LeechCore_GetOption() AND LeechCore_GetOption() TO GET/SET OPTIONS.
-// FOR DEVICE-SPECIFIC OPTIONS PLEASE SEE INDIVIDUAL DEVICE FILES FOR MORE
-// DETAILED INFORMATION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE 0x80000002 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define LEECHCORE_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-
-#define LEECHCORE_OPT_CORE_VERSION_MAJOR 0x01000001 // R
-#define LEECHCORE_OPT_CORE_VERSION_MINOR 0x01000002 // R
-#define LEECHCORE_OPT_CORE_VERSION_REVISION 0x01000003 // R
-
-#define LEECHCORE_OPT_MEMORYINFO_VALID 0x02000001 // R
-#define LEECHCORE_OPT_MEMORYINFO_ADDR_MAX 0x02000002 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_32BIT 0x02000003 // R
-#define LEECHCORE_OPT_MEMORYINFO_FLAG_PAE 0x02000004 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MINOR 0x02000005 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_VERSION_MAJOR 0x02000006 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_DTB 0x02000007 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PFN 0x02000008 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsLoadedModuleList 0x02000009 // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_PsActiveProcessHead 0x0200000a // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_MACHINE_IMAGE_TP 0x0200000b // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_NUM_PROCESSORS 0x0200000c // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_SYSTEMTIME 0x0200000d // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_UPTIME 0x0200000e // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELBASE 0x0200000f // R
-#define LEECHCORE_OPT_MEMORYINFO_OS_KERNELHINT 0x02000010 // R
-
-#define LEECHCORE_OPT_FPGA_PROBE_MAXPAGES 0x03000001 // RW
-#define LEECHCORE_OPT_FPGA_RX_FLUSH_LIMIT 0x03000002 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_RX 0x03000003 // RW
-#define LEECHCORE_OPT_FPGA_MAX_SIZE_TX 0x03000004 // RW
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_READ 0x03000005 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_PROBE_WRITE 0x03000006 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_WRITE 0x03000007 // RW - uS
-#define LEECHCORE_OPT_FPGA_DELAY_READ 0x03000008 // RW - uS
-#define LEECHCORE_OPT_FPGA_RETRY_ON_ERROR 0x03000009 // RW
-#define LEECHCORE_OPT_FPGA_DEVICE_ID 0x03000080 // R
-#define LEECHCORE_OPT_FPGA_FPGA_ID 0x03000081 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MAJOR 0x03000082 // R
-#define LEECHCORE_OPT_FPGA_VERSION_MINOR 0x03000083 // R
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- pqwValue = pointer to QWORD to receive option value.
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_GetOption(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value.
-* -- fOption
-* -- qwValue
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_SetOption(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// TRANSFER DEVICE DEPENDANT COMMANDS OR DATA TO/FROM UNDERLYING DEVICES AND
-// PERFORM ACTIONS USING THE LeechCore_CommandData() FUNCTION.
-//-----------------------------------------------------------------------------
-
-#define LEECHCORE_COMMANDDATA_FPGA_WRITE_TLP 0x00000101 // R
-#define LEECHCORE_COMMANDDATA_FPGA_LISTEN_TLP 0x00000102 // R
-#define LEECHCORE_COMMANDDATA_STATISTICS_GET 0x80000100 // R
-
-#define LEECHCORE_STATISTICS_MAGIC 0xffff6550
-#define LEECHCORE_STATISTICS_VERSION 0x0001
-#define LEECHCORE_STATISTICS_ID_OPEN 0x00
-#define LEECHCORE_STATISTICS_ID_READSCATTER 0x01
-#define LEECHCORE_STATISTICS_ID_WRITE 0x02
-#define LEECHCORE_STATISTICS_ID_PROBE 0x03
-#define LEECHCORE_STATISTICS_ID_GETOPTION 0x04
-#define LEECHCORE_STATISTICS_ID_SETOPTION 0x05
-#define LEECHCORE_STATISTICS_ID_COMMANDDATA 0x06
-#define LEECHCORE_STATISTICS_ID_MAX 0x06
-
-static const LPSTR LEECHCORE_STATISTICS_NAME[] = {
- "LeechCore_Open",
- "LeechCore_ReadScatter",
- "LeechCore_Write",
- "LeechCore_Probe",
- "LeechCore_GetOption",
- "LeechCore_SetOption",
- "LeechCore_CommandData"
-};
-
-typedef struct tdLEECHCORE_STATISTICS {
- DWORD magic;
- WORD version;
- WORD Reserved0;
- DWORD Reserved1;
- QWORD qwFreq;
- struct {
- QWORD c;
- QWORD tm; // total time in qwFreq ticks
- } Call[0x10];
-} LEECHCORE_STATISTICS, *PLEECHCORE_STATISTICS;
-
-/*
-* Transfer device dependant commands/data to/from the underlying device and
-* perform device dependant actions.
-* -- fOption
-* -- cbDataIn
-* -- pbDataIn
-* -- pbDataOut
-* -- cbDataOut
-* -- pcbDataOut
-* -- return
-*/
-_Success_(return)
-DLLEXPORT BOOL LeechCore_CommandData(
- _In_ ULONG64 fOption,
- _In_reads_(cbDataIn) PBYTE pbDataIn,
- _In_ DWORD cbDataIn,
- _Out_writes_opt_(cbDataOut) PBYTE pbDataOut,
- _In_ DWORD cbDataOut,
- _Out_opt_ PDWORD pcbDataOut
-);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __LEECHCORE_H__ */
diff --git a/vmmpycplugin/version.h b/vmmpycplugin/version.h
deleted file mode 100644
index 997bede..0000000
--- a/vmmpycplugin/version.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#define STRINGIZE2(s) #s
-#define STRINGIZE(s) STRINGIZE2(s)
-
-#define VERSION_MAJOR 2
-#define VERSION_MINOR 2
-#define VERSION_REVISION 1
-#define VERSION_BUILD 0
-
-#define VER_FILE_DESCRIPTION_STR "The Memory Process File System : Python Plugin Manager"
-#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
-#define VER_FILE_VERSION_STR STRINGIZE(VERSION_MAJOR) \
- "." STRINGIZE(VERSION_MINOR) \
- "." STRINGIZE(VERSION_REVISION) \
- "." STRINGIZE(VERSION_BUILD) \
-
-#define VER_COMPANY_NAME_STR ""
-#define VER_PRODUCTNAME_STR "vmmpycplugin"
-#define VER_PRODUCT_VERSION VER_FILE_VERSION
-#define VER_PRODUCT_VERSION_STR VER_FILE_VERSION_STR
-#define VER_ORIGINAL_FILENAME_STR VER_PRODUCTNAME_STR ".dll"
-#define VER_INTERNAL_NAME_STR VER_ORIGINAL_FILENAME_STR
-#define VER_COPYRIGHT_STR "Copyright (c) Ulf Frisk 2018-2019"
diff --git a/vmmpycplugin/vmmdll.h b/vmmpycplugin/vmmdll.h
deleted file mode 100644
index 6b1e71b..0000000
--- a/vmmpycplugin/vmmdll.h
+++ /dev/null
@@ -1,656 +0,0 @@
-// vmmdll.h : header file to include in projects that use vmm.dll either as
-// stand anlone projects or as native plugins to vmm.dll.
-//
-// (c) Ulf Frisk, 2018-2019
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-// Header Version: 2.2
-//
-
-#include
-#include "leechcore.h"
-
-#ifndef __VMMDLL_H__
-#define __VMMDLL_H__
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//-----------------------------------------------------------------------------
-// INITIALIZATION FUNCTIONALITY BELOW:
-// Choose one way of initialzing the VMM / Memory Process File System.
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize VMM.DLL with command line parameters. For a more detailed info
-* about the parameters please see github wiki for Memory Process File System
-* and LeechCore. THIS IS THE PREFERED WAY OF INITIALIZING VMM.DLL
-* Important parameters are:
-* -printf = show printf style outputs)
-* -v -vv -vvv = extra verbosity levels)
-* -device = device as on format for LeechCore - please see leechcore.h or
-* Github documentation for additional information. Some values
-* are: , fpga, usb3380, hvsavedstate, totalmeltdown, pmem
-* -remote = remote LeechCore instance - please see leechcore.h or Github
-* documentation for additional information.
-* -norefresh = disable background refreshes (even if backing memory is
-* volatile memory).
-* -- argc
-* -- argv
-* -- return = success/fail
-*/
-_Success_(return)
-BOOL VMMDLL_Initialize(_In_ DWORD argc, _In_ LPSTR argv[]);
-
-/*
-* Close an initialized instance of VMM.DLL and clean up all allocated resources
-* including plugins, linked PCILeech.DLL and other memory resources.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_Close();
-
-/*
-* Perform a force refresh of all internal caches including:
-* - process listings
-* - memory cache
-* - page table cache
-* WARNING: function may take some time to execute!
-* -- dwReserved = reserved future use - must be zero
-* -- return = sucess/fail
-*/
-_Success_(return)
-BOOL VMMDLL_Refresh(_In_ DWORD dwReserved);
-
-
-//-----------------------------------------------------------------------------
-// CONFIGURATION SETTINGS BELOW:
-// Configure the memory process file system or the underlying memory
-// acquisition devices.
-//-----------------------------------------------------------------------------
-
-/*
-* Options used together with the functions: VMMDLL_GetOption & VMMDLL_SetOption
-* Options are defined with either: VMMDLL_OPT_* in this header file or as
-* MEMDEVICE_OPT_* in memdevice.h
-* For more detailed information check the sources for individual device types.
-*/
-#define VMMDLL_OPT_CORE_PRINTF_ENABLE 0x80000001 // RW
-#define VMMDLL_OPT_CORE_VERBOSE 0x80000002 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA 0x80000003 // RW
-#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x80000004 // RW
-#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x80000005 // R
-#define VMMDLL_OPT_CORE_MAX_NATIVE_IOSIZE 0x80000006 // R
-#define VMMDLL_OPT_CORE_SYSTEM 0x80000007 // R
-#define VMMDLL_OPT_CORE_MEMORYMODEL 0x80000008 // R
-
-#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x40000001 // R - 1/0
-#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x40000002 // RW - base tick period in ms
-#define VMMDLL_OPT_CONFIG_READCACHE_TICKS 0x40000003 // RW - memory cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_TLBCACHE_TICKS 0x40000004 // RW - page table (tlb) cache validity period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_PARTIAL 0x40000005 // RW - process refresh (partial) period (in ticks)
-#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_TOTAL 0x40000006 // RW - process refresh (full) period (in ticks)
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MAJOR 0x40000007 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_MINOR 0x40000008 // R
-#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x40000009 // R
-#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x4000000A // RW - enable function call statistics (.status/statistics_fncall file)
-
-static const LPSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" };
-
-typedef enum tdVMMDLL_MEMORYMODEL_TP {
- VMMDLL_MEMORYMODEL_NA = 0,
- VMMDLL_MEMORYMODEL_X86 = 1,
- VMMDLL_MEMORYMODEL_X86PAE = 2,
- VMMDLL_MEMORYMODEL_X64 = 3
-} VMMDLL_MEMORYMODEL_TP;
-
-typedef enum tdVMMDLL_SYSTEM_TP {
- VMMDLL_SYSTEM_UNKNOWN_X64 = 1,
- VMMDLL_SYSTEM_WINDOWS_X64 = 2,
- VMMDLL_SYSTEM_UNKNOWN_X86 = 3,
- VMMDLL_SYSTEM_WINDOWS_X86 = 4
-} VMMDLL_SYSTEM_TP;
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- pqwValue = pointer to ULONG64 to receive option value.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue);
-
-/*
-* Set a device specific option value. Please see defines VMMDLL_OPT_* for infor-
-* mation about valid option values. Please note that option values may overlap
-* between different device types with different meanings.
-* -- fOption
-* -- qwValue
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue);
-
-
-
-//-----------------------------------------------------------------------------
-// VFS - VIRTUAL FILE SYSTEM FUNCTIONALITY BELOW:
-// This is the core of the memory process file system. All implementation and
-// analysis towards the file system is possible by using functionality below.
-//-----------------------------------------------------------------------------
-
-#define VMMDLL_STATUS_SUCCESS ((NTSTATUS)0x00000000L)
-#define VMMDLL_STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
-#define VMMDLL_STATUS_END_OF_FILE ((NTSTATUS)0xC0000011L)
-#define VMMDLL_STATUS_FILE_INVALID ((NTSTATUS)0xC0000098L)
-#define VMMDLL_STATUS_FILE_SYSTEM_LIMITATION ((NTSTATUS)0xC0000427L)
-
-typedef struct tdVMMDLL_VFS_FILELIST {
- VOID(*pfnAddFile) (_Inout_ HANDLE h, _In_ LPSTR szName, _In_ ULONG64 cb, _In_ PVOID pvReserved);
- VOID(*pfnAddDirectory)(_Inout_ HANDLE h, _In_ LPSTR szName, _In_ PVOID pvReserved);
- HANDLE h;
-} VMMDLL_VFS_FILELIST, *PVMMDLL_VFS_FILELIST;
-
-/*
-* Helper function macros for callbacks into the VMM_VFS_FILELIST structure.
-*/
-#define VMMDLL_VfsList_AddFile(pFileList, szName, cb) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddFile(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, cb, NULL); }
-#define VMMDLL_VfsList_AddDirectory(pFileList, szName) { ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddDirectory(((PVMMDLL_VFS_FILELIST)pFileList)->h, szName, NULL); }
-
-/*
-* List a directory of files in the memory process file system. Directories and
-* files will be listed by callbacks into functions supplied in the pFileList
-* parameter. If information of an individual file is needed it's neccessary
-* to list all files in its directory.
-* -- wcsPath
-* -- pFileList
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList);
-
-/*
-* Read select parts of a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbRead
-* -- cbOffset
-* -- return
-*
-*/
-NTSTATUS VMMDLL_VfsRead(_In_ LPCWSTR wcsFileName, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-
-/*
-* Write select parts to a file in the memory process file system.
-* -- wcsFileName
-* -- pb
-* -- cb
-* -- pcbWrite
-* -- cbOffset
-* -- return
-*/
-NTSTATUS VMMDLL_VfsWrite(_In_ LPCWSTR wcsFileName, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-
-/*
-* Utility functions for memory process file system read/write towards different
-* underlying data representations.
-*/
-NTSTATUS VMMDLL_UtilVfsReadFile_FromPBYTE(_In_ PBYTE pbFile, _In_ ULONG64 cbFile, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromQWORD(_In_ ULONG64 qwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromDWORD(_In_ DWORD dwValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix);
-NTSTATUS VMMDLL_UtilVfsReadFile_FromBOOL(_In_ BOOL fValue, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_BOOL(_Inout_ PBOOL pfTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
-NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset, _In_ DWORD dwMinAllow);
-
-
-//-----------------------------------------------------------------------------
-// PLUGIN MANAGER FUNCTIONALITY BELOW:
-// Function and structures to initialize and use the memory process file system
-// plugin functionality. The plugin manager is started by a call to function:
-// VMM_VfsInitializePlugins. Each built-in plugin and external plugin of which
-// the DLL name matches m_*.dll will receive a call to its InitializeVmmPlugin
-// function. The plugin/module may decide to call pfnPluginManager_Register to
-// register plugins in the form of different names one or more times.
-// Example of registration function in a plugin DLL below:
-// 'VOID InitializeVmmPlugin(_In_ PVMM_PLUGIN_REGINFO pRegInfo)'
-//-----------------------------------------------------------------------------
-
-/*
-* Initialize all potential plugins, both built-in and external, that maps into
-* the memory process file system. Please note that plugins are not loaded by
-* default - they have to be explicitly loaded by calling this function. They
-* will be unloaded on a general close of the vmm dll.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_VfsInitializePlugins();
-
-#define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c
-#define VMMDLL_PLUGIN_CONTEXT_VERSION 2
-#define VMMDLL_PLUGIN_REGINFO_MAGIC 0xc0ffee663df9301d
-#define VMMDLL_PLUGIN_REGINFO_VERSION 3
-
-#define VMMDLL_PLUGIN_EVENT_VERBOSITYCHANGE 0x01
-
-typedef struct tdVMMDLL_PLUGIN_CONTEXT {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- DWORD dwPID;
- PVOID pProcess;
- LPSTR szModule;
- LPSTR szPath;
- PVOID pvReserved1;
- PVOID pvReserved2;
-} VMMDLL_PLUGIN_CONTEXT, *PVMMDLL_PLUGIN_CONTEXT;
-
-typedef struct tdVMMDLL_PLUGIN_REGINFO {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel;
- VMMDLL_SYSTEM_TP tpSystem;
- HMODULE hDLL;
- HMODULE hReservedDll; // not for general use (only used for python).
- BOOL(*pfnPluginManager_Register)(struct tdVMMDLL_PLUGIN_REGINFO *pPluginRegInfo);
- PVOID pvReserved1;
- PVOID pvReserved2;
- // general plugin registration info to be filled out by the plugin below:
- struct {
- CHAR szModuleName[32];
- BOOL fRootModule;
- BOOL fProcessModule;
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_info;
- // function plugin registration info to be filled out by the plugin below:
- struct {
- BOOL(*pfnList)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList);
- NTSTATUS(*pfnRead)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset);
- NTSTATUS(*pfnWrite)(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset);
- VOID(*pfnNotify)(_In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent);
- VOID(*pfnClose)();
- PVOID pvReserved1;
- PVOID pvReserved2;
- } reg_fn;
-} VMMDLL_PLUGIN_REGINFO, *PVMMDLL_PLUGIN_REGINFO;
-
-//-----------------------------------------------------------------------------
-// VMM CORE FUNCTIONALITY BELOW:
-// Vmm core functaionlity such as read (and write) to both virtual and physical
-// memory. NB! writing will only work if the target is supported - i.e. not a
-// memory dump file...
-// To read physical memory specify dwPID as (DWORD)-1
-//-----------------------------------------------------------------------------
-
-// FLAG used to supress the default read cache in calls to VMM_MemReadEx()
-// which will lead to the read being fetched from the target system always.
-// Cached page tables (used for translating virtual2physical) are still used.
-#define VMMDLL_FLAG_NOCACHE 0x0001 // do not use the data cache (force reading from memory acquisition device)
-#define VMMDLL_FLAG_ZEROPAD_ON_FAIL 0x0002 // zero pad failed physical memory reads and report success if read within range of physical memory.
-
-/*
-* Read memory in various non-contigious locations specified by the pointers to
-* the items in the ppDMAs array. Result for each unit of work will be given
-* individually. No upper limit of number of items to read, but no performance
-* boost will be given if above hardware limit. Max size of each unit of work is
-* one 4k page (4096 bytes).
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- ppMEMs = array of scatter read headers.
-* -- cpMEMs = count of ppDMAs.
-* -- pcpDMAsRead = optional count of number of successfully read ppDMAs.
-* -- flags = optional flags as given by VMMDLL_FLAG_*
-* -- return = the number of successfully read items.
-*/
-DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPMEM_IO_SCATTER_HEADER ppMEMs, _In_ DWORD cpMEMs, _In_ DWORD flags);
-
-/*
-* Read a single 4096-byte page of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pbPage
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Inout_bytecount_(4096) PBYTE pbPage);
-
-/*
-* Read a contigious arbitrary amount of memory.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = success/fail (depending if all requested bytes are read or not).
-*/
-_Success_(return)
-BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Read a contigious amount of memory and report the number of bytes read in pcbRead.
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- pcbRead
-* -- flags = flags as in VMMDLL_FLAG_*
-* -- return = success/fail. NB! reads may report as success even if 0 bytes are
-* read - it's recommended to verify pcbReadOpt parameter.
-*/
-_Success_(return)
-BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags);
-
-/*
-* Prefetch a number of addresses (specified in the pA array) into the memory
-* cache. This function is to be used to batch larger known reads into local
-* cache before making multiple smaller reads - which will then happen from
-* the cache. Function exists for performance reasons.
-* -- dwPID = PID of target process, (DWORD)-1 for physical memory.
-* -- pPrefetchAddresses = array of addresses to read into cache.
-* -- cPrefetchAddresses
-*/
-_Success_(return)
-BOOL VMMDLL_MemPrefetchPages(_In_ DWORD dwPID, _In_reads_(cPrefetchAddresses) PULONG64 pPrefetchAddresses, _In_ DWORD cPrefetchAddresses);
-
-/*
-* Write a contigious arbitrary amount of memory. Please note some virtual memory
-* such as pages of executables (such as DLLs) may be shared between different
-* virtual memory over different processes. As an example a write to kernel32.dll
-* in one process is likely to affect kernel32 in the whole system - in all
-* processes. Heaps and Stacks and other memory are usually safe to write to.
-* Please take care when writing to memory!
-* -- dwPID - PID of target process, (DWORD)-1 to read physical memory.
-* -- qwVA
-* -- pb
-* -- cb
-* -- return = TRUE on success, FALSE on partial or zero write.
-*/
-_Success_(return)
-BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb);
-
-/*
-* Translate a virtual address to a physical address by walking the page tables
-* of the specified process.
-* -- dwPID
-* -- qwVA
-* -- pqwPA
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA);
-
-
-
-//-----------------------------------------------------------------------------
-// VMM PROCESS FUNCTIONALITY BELOW:
-// Functionality below is mostly relating to Windows processes.
-//-----------------------------------------------------------------------------
-
-/*
-* Retrieve an active process given it's name. Please note that if multiple
-* processes with the same name exists only one will be returned. If required to
-* parse all processes with the same name please iterate over the PID list by
-* calling VMMDLL_PidList together with VMMDLL_ProcessGetInformation.
-* -- szProcName = process name (truncated max 15 chars) case insensitive.
-* -- pdwPID = pointer that will receive PID on success.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID);
-
-/*
-* List the PIDs in the system.
-* -- pPIDs = DWORD array of at least number of PIDs in system, or NULL.
-* -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_PidList(_Out_opt_ PDWORD pPIDs, _Inout_ PULONG64 pcPIDs);
-
-// flags to check for existence in the fPage field of PCILEECH_VMM_MEMMAP_ENTRY
-#define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002
-#define VMMDLL_MEMMAP_FLAG_PAGE_NS 0x0000000000000004
-#define VMMDLL_MEMMAP_FLAG_PAGE_NX 0x8000000000000000
-#define VMMDLL_MEMMAP_FLAG_PAGE_MASK 0x8000000000000006
-
-typedef struct tdVMMDLL_MEMMAP_ENTRY {
- ULONG64 AddrBase;
- ULONG64 cPages;
- ULONG64 fPage;
- BOOL fWoW64;
- CHAR szTag[32];
-} VMMDLL_MEMMAP_ENTRY, *PVMMDLL_MEMMAP_ENTRY;
-
-/*
-* Retrieve memory map entries from the specified process. Memory map entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries bytes.
-* If the pMemMapEntries is set to NULL the number of memory map entries will be
-* given in the pcMemMapEntries parameter.
-* -- dwPID
-* -- pMemMapEntries = buffer of minimum length sizeof(VMMDLL_MEMMAP_ENTRY)*pcMemMapEntries, or NULL.
-* -- pcMemMapEntries = pointer to number of memory map entries.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MEMMAP_ENTRY pMemMapEntries, _Inout_ PULONG64 pcMemMapEntries, _In_ BOOL fIdentifyModules);
-
-/*
-* Retrieve a single memory map entry given a virtual address within that entrys
-* range.
-* -- dwPID
-* -- pMemMapEntry
-* -- va = virtual address in the memory map entry to retrieve.
-* -- fIdentifyModules = try identify modules as well (= slower)
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetMemoryMapEntry(_In_ DWORD dwPID, _Out_ PVMMDLL_MEMMAP_ENTRY pMemMapEntry, _In_ ULONG64 va, _In_ BOOL fIdentifyModules);
-
-typedef struct tdVMMDLL_MODULEMAP_ENTRY {
- ULONG64 BaseAddress;
- ULONG64 EntryPoint;
- DWORD SizeOfImage;
- BOOL fWoW64;
- CHAR szName[32];
-} VMMDLL_MODULEMAP_ENTRY, *PVMMDLL_MODULEMAP_ENTRY;
-
-/*
-* Retrieve the module entries from the specified process. The module entries
-* are copied into the user supplied buffer that must be at least of size:
-* sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries bytes long. If the
-* pcModuleEntries is set to NULL the number of module entries will be given
-* in the pcModuleEntries parameter.
-* -- dwPID
-* -- pModuleEntries = buffer of minimum length sizeof(VMMDLL_MODULEMAP_ENTRY)*pcModuleEntries, or NULL.
-* -- pcModuleEntries = pointer to number of memory map entries.
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleMap(_In_ DWORD dwPID, _Out_opt_ PVMMDLL_MODULEMAP_ENTRY pModuleEntries, _Inout_ PULONG64 pcModuleEntries);
-
-/*
-* Retrieve a module (.exe or .dll or similar) given a module name.
-* -- dwPID
-* -- szModuleName
-* -- pModuleEntry
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetModuleFromName(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _Out_ PVMMDLL_MODULEMAP_ENTRY pModuleEntry);
-
-#define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e
-#define VMMDLL_PROCESS_INFORMATION_VERSION 2
-
-typedef struct tdVMMDLL_PROCESS_INFORMATION {
- ULONG64 magic;
- WORD wVersion;
- WORD wSize;
- VMMDLL_MEMORYMODEL_TP tpMemoryModel; // as given by VMMDLL_MEMORYMODEL_* enum
- VMMDLL_SYSTEM_TP tpSystem; // as given by VMMDLL_SYSTEM_* enum
- BOOL fUserOnly; // only user mode pages listed
- DWORD dwPID;
- DWORD dwState;
- CHAR szName[16];
- ULONG64 paDTB;
- ULONG64 paDTB_UserOpt; // may not exist
- union {
- struct {
- ULONG64 vaEPROCESS;
- ULONG64 vaPEB;
- ULONG64 vaENTRY;
- BOOL fWow64;
- DWORD vaPEB32; // WoW64 only
- } win;
- } os;
-} VMMDLL_PROCESS_INFORMATION, *PVMMDLL_PROCESS_INFORMATION;
-
-/*
-* Retrieve various process information from a PID. Process information such as
-* name, page directory bases and the process state may be retrieved.
-* -- dwPID
-* -- pProcessInformation = if null, size is given in *pcbProcessInfo
-* -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation);
-
-typedef struct tdVMMDLL_EAT_ENTRY {
- ULONG64 vaFunction;
- DWORD vaFunctionOffset;
- CHAR szFunction[40];
-} VMMDLL_EAT_ENTRY, *PVMMDLL_EAT_ENTRY;
-
-typedef struct tdVMMDLL_IAT_ENTRY {
- ULONG64 vaFunction;
- CHAR szFunction[40];
- CHAR szModule[64];
-} VMMDLL_IAT_ENTRY, *PVMMDLL_IAT_ENTRY;
-
-/*
-* Retrieve information about: Data Directories, Sections, Export Address Table
-* and Import Address Table (IAT).
-* If the pData == NULL upon entry the number of entries of the pData array must
-* have in order to be able to hold the data is returned.
-* -- dwPID
-* -- szModule
-* -- pData
-* -- cData
-* -- pcData
-* -- return = success/fail.
-*/
-_Success_(return)
-BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetEAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_EAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-_Success_(return)
-BOOL VMMDLL_ProcessGetIAT(_In_ DWORD dwPID, _In_ LPSTR szModule, _Out_opt_ PVMMDLL_IAT_ENTRY pData, _In_ DWORD cData, _Out_ PDWORD pcData);
-
-/*
-* Retrieve the virtual address of a given function inside a process/module.
-* -- dwPID
-* -- szModuleName
-* -- szFunctionName
-* -- return = virtual address of function, zero on fail.
-*/
-ULONG64 VMMDLL_ProcessGetProcAddress(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szFunctionName);
-
-/*
-* Retrieve the base address of a given module.
-* -- dwPID
-* -- szModuleName
-* -- return = virtual address of module base, zero on fail.
-*/
-ULONG64 VMMDLL_ProcessGetModuleBase(_In_ DWORD dwPID, _In_ LPSTR szModuleName);
-
-
-
-//-----------------------------------------------------------------------------
-// WINDOWS SPECIFIC UTILITY FUNCTIONS BELOW:
-//-----------------------------------------------------------------------------
-
-typedef struct tdVMMDLL_WIN_THUNKINFO_IAT {
- BOOL fValid;
- BOOL f32; // if TRUE fn is a 32-bit/4-byte entry, otherwise 64-bit/8-byte entry.
- ULONG64 vaThunk; // address of import address table 'thunk'.
- ULONG64 vaFunction; // value if import address table 'thunk' == address of imported function.
- ULONG64 vaNameModule; // address of name string for imported module.
- ULONG64 vaNameFunction; // address of name string for imported function.
-} VMMDLL_WIN_THUNKINFO_IAT, *PVMMDLL_WIN_THUNKINFO_IAT;
-
-typedef struct tdVMMDLL_WIN_THUNKINFO_EAT {
- BOOL fValid;
- DWORD valueThunk; // value of export address table 'thunk'.
- ULONG64 vaThunk; // address of import address table 'thunk'.
- ULONG64 vaNameFunction; // address of name string for exported function.
- ULONG64 vaFunction; // address of exported function (module base + value parameter).
-} VMMDLL_WIN_THUNKINFO_EAT, *PVMMDLL_WIN_THUNKINFO_EAT;
-
-/*
-* Retrieve information about the import address table IAT thunk for an imported
-* function. This includes the virtual address of the IAT thunk which is useful
-* for hooking.
-* -- dwPID
-* -- szModuleName
-* -- szImportModuleName
-* -- szImportFunctionName
-* -- pThunkIAT
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoIAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szImportModuleName, _In_ LPSTR szImportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_IAT pThunkInfoIAT);
-
-/*
-* Retrieve information about the export address table EAT thunk for an exported
-* function. This includes the virtual address of the EAT thunk which is useful
-* for hooking.
-* -- dwPID
-* -- szModuleName
-* -- pThunkEAT
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinGetThunkInfoEAT(_In_ DWORD dwPID, _In_ LPSTR szModuleName, _In_ LPSTR szExportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_EAT pThunkInfoEAT);
-
-/*
-* Decompress compressed memory page stored in the MemCompression process.
-* -- vaCompressedData = virtual address in 'MemCompression' to decompress.
-* -- cbCompressedData = length of compressed data in 'MemCompression' to decompress (or zero for auto-detect).
-* -- pbDecompressedPage
-* -- pcbCompressedData = optional ptr to receive length of compressed buffer.
-* -- return
-*/
-_Success_(return)
-BOOL VMMDLL_WinMemCompression_DecompressPage(
- _In_ ULONG64 vaCompressedData,
- _In_opt_ DWORD cbCompressedData,
- _Out_writes_(4096) PBYTE pbDecompressedPage,
- _Out_opt_ PDWORD pcbCompressedData
-);
-
-
-//-----------------------------------------------------------------------------
-// VMM UTIL FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-/*
-* Fill a human readable hex ascii memory dump into the caller supplied sz buffer.
-* -- pb
-* -- cb
-* -- cbInitialOffset = offset, must be max 0x1000 and multiple of 0x10.
-* -- sz = buffer to fill, NULL to retrieve size in pcsz parameter.
-* -- pcsz = ptr to size of buffer on entry, size of characters on exit.
-*/
-_Success_(return)
-BOOL VMMDLL_UtilFillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Out_ PDWORD pcsz);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* __VMMDLL_H__ */
diff --git a/vmmpycplugin/vmmpycplugin.c b/vmmpycplugin/vmmpycplugin.c
deleted file mode 100644
index a65dbb1..0000000
--- a/vmmpycplugin/vmmpycplugin.c
+++ /dev/null
@@ -1,377 +0,0 @@
-// vmmpycplugin.c : implementation related to the python wrapper native plugin
-// for the memory process file system. NB! this is a special plugin since it's
-// not residing in the plugin directory.
-//
-// (c) Ulf Frisk, 2018
-// Author: Ulf Frisk, pcileech@frizk.net
-//
-#ifdef _DEBUG
-#undef _DEBUG
-#include
-#define _DEBUG
-#else
-#include
-#endif
-#include
-#include
-#include "vmmdll.h"
-
-
-//-----------------------------------------------------------------------------
-// PY2C PYTHON CALLBACK FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-typedef struct tdPY2C_CONTEXT {
- BOOL fPrintf;
- BOOL fVerbose;
- BOOL fVerboseExtra;
- BOOL fVerboseExtraTlp;
- BOOL fInitialized;
- PyObject *fnList;
- PyObject *fnRead;
- PyObject *fnWrite;
- PyObject *fnNotify;
- PyObject *fnClose;
-} PY2C_CONTEXT, *PPY2C_CONTEXT;
-
-PPY2C_CONTEXT ctxPY2C = NULL;
-
-static PyObject*
-PY2C_CallbackRegister(PyObject *self, PyObject *args)
-{
- if(!ctxPY2C->fInitialized) {
- Py_XDECREF(ctxPY2C->fnList);
- Py_XDECREF(ctxPY2C->fnRead);
- Py_XDECREF(ctxPY2C->fnWrite);
- Py_XDECREF(ctxPY2C->fnNotify);
- Py_XDECREF(ctxPY2C->fnClose);
- if(!PyArg_ParseTuple(args, "OOOOO", &ctxPY2C->fnList, &ctxPY2C->fnRead, &ctxPY2C->fnWrite, &ctxPY2C->fnNotify, &ctxPY2C->fnClose)) { return NULL; }
- Py_XINCREF(ctxPY2C->fnList);
- Py_XINCREF(ctxPY2C->fnRead);
- Py_XINCREF(ctxPY2C->fnWrite);
- Py_XINCREF(ctxPY2C->fnNotify);
- Py_XINCREF(ctxPY2C->fnClose);
- ctxPY2C->fInitialized = TRUE;
- }
- return Py_BuildValue("s", NULL); // None returned on success.
-}
-
-BOOL PY2C_Util_TranslatePathDelimiter(_Out_writes_(MAX_PATH) PCHAR dst, LPSTR src)
-{
- DWORD i;
- for(i = 0; i < MAX_PATH; i++) {
- dst[i] = (src[i] == '\\') ? '/' : src[i];
- if(src[i] == 0) { return TRUE; }
- }
- return FALSE;
-}
-
-BOOL PY2C_Callback_List(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Inout_ PHANDLE pFileList)
-{
- BOOL result = FALSE;
- PyObject *args, *pyList = NULL, *pyDict, *pyPid;
- PyObject *pyDict_Name, *pyDict_Size, *pyDict_IsDir;
- PyGILState_STATE gstate;
- SIZE_T i, cList;
- CHAR szPathBuffer[MAX_PATH];
- if(!ctxPY2C->fInitialized) { return FALSE; }
- if(!PY2C_Util_TranslatePathDelimiter(szPathBuffer, ctx->szPath)) { return FALSE; }
- gstate = PyGILState_Ensure();
- // pyPid is "consumed" by Py_BuildValue and does not need to be Py_DECREF'ed.
- if(ctx->dwPID == (DWORD)-1) {
- Py_INCREF(Py_None);
- pyPid = Py_None;
- } else {
- pyPid = PyLong_FromUnsignedLong(ctx->dwPID);
- }
- args = Py_BuildValue("Ns", pyPid, szPathBuffer);
- if(!args) { goto fail; }
- pyList = PyObject_CallObject(ctxPY2C->fnList, args);
- Py_DECREF(args);
- if(!pyList || !PyList_Check(pyList)) { goto fail; }
- cList = PyList_Size(pyList);
- for(i = 0; i < cList; i++) {
- pyDict = PyList_GetItem(pyList, i); // borrowed reference
- if(!PyDict_Check(pyDict)) { continue; }
- pyDict_Name = PyDict_GetItemString(pyDict, "name");
- pyDict_Size = PyDict_GetItemString(pyDict, "size");
- pyDict_IsDir = PyDict_GetItemString(pyDict, "f_isdir");
- if(!pyDict_Name || !PyUnicode_Check(pyDict_Name) || !pyDict_IsDir || !PyBool_Check(pyDict_IsDir)) { continue; }
- if(pyDict_IsDir == Py_True) {
- VMMDLL_VfsList_AddDirectory(pFileList, PyUnicode_AsUTF8AndSize(pyDict_Name, NULL));
- } else {
- if(!pyDict_Size || !PyLong_Check(pyDict_Size)) { continue; }
- VMMDLL_VfsList_AddFile(pFileList, PyUnicode_AsUTF8AndSize(pyDict_Name, NULL), PyLong_AsUnsignedLongLong(pyDict_Size));
- }
- }
- result = TRUE;
- // fall through to cleanup
-fail:
- if(pyList) { Py_DECREF(pyList); }
- PyGILState_Release(gstate);
- return result;
-}
-
-NTSTATUS PY2C_Callback_Read(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _Out_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset)
-{
- NTSTATUS nt = VMMDLL_STATUS_FILE_INVALID;
- PyObject *args, *pyBytes = NULL, *pyPid;
- PyGILState_STATE gstate;
- CHAR szPathBuffer[MAX_PATH];
- if(!ctxPY2C->fInitialized) { return FALSE; }
- if(!PY2C_Util_TranslatePathDelimiter(szPathBuffer, ctx->szPath)) { return FALSE; }
- gstate = PyGILState_Ensure();
- // pyPid is "consumed" by Py_BuildValue and does not need to be Py_DECREF'ed.
- if(ctx->dwPID == (DWORD)-1) {
- Py_INCREF(Py_None);
- pyPid = Py_None;
- } else {
- pyPid = PyLong_FromUnsignedLong(ctx->dwPID);
- }
- args = Py_BuildValue("NskK",
- pyPid,
- szPathBuffer,
- cb,
- cbOffset);
- if(!args) { goto fail; }
- pyBytes = PyObject_CallObject(ctxPY2C->fnRead, args);
- Py_DECREF(args);
- if(!pyBytes || !PyBytes_Check(pyBytes)) { goto fail; }
- *pcbRead = min(cb, (DWORD)PyBytes_Size(pyBytes));
- if(*pcbRead) {
- memcpy(pb, PyBytes_AsString(pyBytes), *pcbRead);
- }
- nt = *pcbRead ? VMMDLL_STATUS_SUCCESS : VMMDLL_STATUS_END_OF_FILE;
- // fall through to cleanup
-fail:
- if(pyBytes) { Py_DECREF(pyBytes); }
- PyGILState_Release(gstate);
- return nt;
-}
-
-NTSTATUS PY2C_Callback_Write(_In_ PVMMDLL_PLUGIN_CONTEXT ctx, _In_ LPVOID pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset)
-{
- NTSTATUS nt = VMMDLL_STATUS_FILE_INVALID;
- PyObject *args, *pyLong = NULL, *pyPid;
- PyGILState_STATE gstate;
- CHAR szPathBuffer[MAX_PATH];
- *pcbWrite = 0;
- if(!ctxPY2C->fInitialized) { return VMMDLL_STATUS_FILE_INVALID; }
- if(!PY2C_Util_TranslatePathDelimiter(szPathBuffer, ctx->szPath)) { return VMMDLL_STATUS_FILE_INVALID; }
- gstate = PyGILState_Ensure();
- // pyPid is "consumed" by Py_BuildValue and does not need to be Py_DECREF'ed.
- if(ctx->dwPID == (DWORD)-1) {
- Py_INCREF(Py_None);
- pyPid = Py_None;
- } else {
- pyPid = PyLong_FromUnsignedLong(ctx->dwPID);
- }
- args = Py_BuildValue("Nsy#K",
- pyPid,
- szPathBuffer,
- pb,
- cb,
- cbOffset);
- if(!args) { goto fail; }
- pyLong = PyObject_CallObject(ctxPY2C->fnWrite, args);
- Py_DECREF(args);
- if(!pyLong || !PyLong_Check(pyLong)) { goto fail; }
- nt = PyLong_AsUnsignedLong(pyLong);
- if(!nt) { *pcbWrite = cb; }
- // fall through to cleanup
-fail:
- if(pyLong) { Py_DECREF(pyLong); }
- PyGILState_Release(gstate);
- return nt;
-}
-
-VOID PY2C_Callback_Notify(_In_ DWORD fEvent, _In_opt_ PVOID pvEvent, _In_opt_ DWORD cbEvent)
-{
- PyObject *args, *pyResult = NULL;
- PyGILState_STATE gstate;
- if(!ctxPY2C->fInitialized) { return; }
- gstate = PyGILState_Ensure();
- args = Py_BuildValue("ky#", fEvent, (char*)pvEvent, cbEvent);
- if(!args) { goto fail; }
- pyResult = PyObject_CallObject(ctxPY2C->fnNotify, args);
- Py_DECREF(args);
- // fall through to cleanup
-fail:
- if(pyResult) { Py_DECREF(pyResult); }
- PyGILState_Release(gstate);
-}
-
-BOOL PY2C_Callback_Close()
-{
- NTSTATUS nt = VMMDLL_STATUS_FILE_INVALID;
- PyObject *args, *pyResult = NULL;
- PyGILState_STATE gstate;
- if(!ctxPY2C->fInitialized) { return FALSE; }
- gstate = PyGILState_Ensure();
- args = Py_BuildValue("");
- if(!args) { goto fail; }
- pyResult = PyObject_CallObject(ctxPY2C->fnClose, args);
- Py_DECREF(args);
- // fall through to cleanup
-fail:
- if(pyResult) { Py_DECREF(pyResult); }
- PyGILState_Release(gstate);
- return nt;
-}
-
-//-----------------------------------------------------------------------------
-// PY2C common functionality below:
-//-----------------------------------------------------------------------------
-
-static PyMethodDef VMMPYCC_EmbMethods[] = {
- {"VMMPYCC_CallbackRegister", PY2C_CallbackRegister, METH_VARARGS, "Register callback functions: List, Read, Write, Close"},
- {NULL, NULL, 0, NULL}
-};
-
-static PyModuleDef VMMPYCC_EmbModule = {
- PyModuleDef_HEAD_INIT, "vmmpycc", NULL, -1, VMMPYCC_EmbMethods,
- NULL, NULL, NULL, NULL
-};
-
-static PyObject* VMMPYCC_PyInit(void)
-{
- return PyModule_Create(&VMMPYCC_EmbModule);
-}
-
-void PY2C_InitializeModuleVMMPYCC()
-{
- PyImport_AppendInittab("vmmpycc", &VMMPYCC_PyInit);
-}
-
-
-//-----------------------------------------------------------------------------
-// CORE NATIVE MODULE FUNCTIONALITY BELOW:
-//-----------------------------------------------------------------------------
-
-VOID Util_GetPathDll(_Out_writes_(MAX_PATH) PWCHAR wszPath, _In_opt_ HMODULE hModule)
-{
- SIZE_T i;
- GetModuleFileNameW(hModule, wszPath, MAX_PATH - 4);
- for(i = wcslen(wszPath) - 1; i > 0; i--) {
- if(wszPath[i] == L'/' || wszPath[i] == L'\\') {
- wszPath[i + 1] = L'\0';
- return;
- }
- }
-}
-
-/*
-* Set the verbosity level of the Python C - plugin.
-* Also set the verbosity level of the Python plugin manager (if already loaded).
-*/
-VOID VmmPyPlugin_UpdateVerbosity()
-{
- ULONG64 f;
- VMMDLL_ConfigGet(VMMDLL_OPT_CORE_PRINTF_ENABLE, &f); ctxPY2C->fPrintf = f ? TRUE : FALSE;
- if(ctxPY2C->fPrintf) {
- VMMDLL_ConfigGet(VMMDLL_OPT_CORE_VERBOSE, &f); ctxPY2C->fVerbose = f ? TRUE : FALSE;
- VMMDLL_ConfigGet(VMMDLL_OPT_CORE_VERBOSE_EXTRA, &f); ctxPY2C->fVerboseExtra = f ? TRUE : FALSE;
- VMMDLL_ConfigGet(VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP, &f); ctxPY2C->fVerboseExtraTlp = f ? TRUE : FALSE;
- } else {
- ctxPY2C->fVerbose = FALSE;
- ctxPY2C->fVerboseExtra = FALSE;
- ctxPY2C->fVerboseExtraTlp = FALSE;
- }
-}
-
-#define PYTHON_PATH_MAX 7*MAX_PATH
-#define PYTHON_PATH_DELIMITER L";"
-BOOL VmmPyPlugin_PythonInitialize(_In_ HMODULE hDllPython)
-{
- PyObject *pName = NULL, *pModule = NULL;
- WCHAR wszPathBaseExe[MAX_PATH], wszPathBasePython[MAX_PATH], wszPathPython[PYTHON_PATH_MAX];
- // 1: Allocate context (if required) and fetch verbosity settings
- if(!ctxPY2C && !(ctxPY2C = LocalAlloc(LMEM_ZEROINIT, sizeof(PY2C_CONTEXT)))) {
- return FALSE;
- }
- VmmPyPlugin_UpdateVerbosity();
- // 2: Construct Python Path
- Util_GetPathDll(wszPathBaseExe, NULL);
- Util_GetPathDll(wszPathBasePython, hDllPython);
- // 2.1: python base directory (where python dll is located)
- wcscpy_s(wszPathPython, PYTHON_PATH_MAX, wszPathBasePython);
- // 2.2: python zip
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, PYTHON_PATH_DELIMITER);
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, wszPathBasePython);
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, L"python36.zip");
- // 2.3: python dlls
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, PYTHON_PATH_DELIMITER);
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, wszPathBasePython);
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, L"DLLs\\");
- // 2.4: python lib
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, PYTHON_PATH_DELIMITER);
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, wszPathBasePython);
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, L"Lib\\");
- // 2.5: python lib\site-packages (python pip)
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, PYTHON_PATH_DELIMITER);
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, wszPathBasePython);
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, L"Lib\\site-packages\\");
- // 2.6: .exe location of this process
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, PYTHON_PATH_DELIMITER);
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, wszPathBaseExe);
- // 2.7: pylib relative to this process
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, PYTHON_PATH_DELIMITER);
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, wszPathBaseExe);
- wcscat_s(wszPathPython, PYTHON_PATH_MAX, L"pylib\\");
- // 3: Initialize (Embedded) Python.
- Py_SetProgramName(L"VmmPyPluginManager");
- Py_SetPath(wszPathPython);
- if(ctxPY2C->fVerboseExtra) {
- wprintf(L"VmmPyPluginManager: Python Path: %s\n", wszPathPython);
- }
- PY2C_InitializeModuleVMMPYCC();
- Py_Initialize();
- PyEval_InitThreads();
- // 4: Import VmmPyPlugin library/file to start the python part of the plugin manager.
- pName = PyUnicode_DecodeFSDefault("vmmpyplugin");
- if(!pName) { goto fail; }
- pModule = PyImport_Import(pName);
- if(!pModule) { goto fail; }
- // 5: Cleanups
- Py_DECREF(pName);
- Py_DECREF(pModule);
- PyEval_ReleaseLock();
- return TRUE;
-fail:
- if(pName) { Py_DECREF(pName); }
- if(pModule) { Py_DECREF(pModule); }
- Py_FinalizeEx();
- return FALSE;
-}
-
-VOID PYTHON_Close()
-{
- PY2C_Callback_Close();
- Py_FinalizeEx();
-}
-
-/*
-* Initialization function for the vmemd native plugin module.
-* It's important that the function is exported in the DLL and that it is
-* declared exactly as below. The plugin manager will call into this function
-* after the DLL is loaded. The DLL then must fill the appropriate information
-* into the supplied struct and call the pfnPluginManager_Register function to
-* register itself with the plugin manager.
-* -- pRegInfo
-*/
-__declspec(dllexport)
-VOID InitializeVmmPlugin(_In_ PVMMDLL_PLUGIN_REGINFO pRegInfo)
-{
- if((pRegInfo->magic != VMMDLL_PLUGIN_REGINFO_MAGIC) || (pRegInfo->wVersion != VMMDLL_PLUGIN_REGINFO_VERSION)) { return; }
- if(VmmPyPlugin_PythonInitialize(pRegInfo->hReservedDll)) {
- strcpy_s(pRegInfo->reg_info.szModuleName, 32, "py"); // module name - 'py'.
- pRegInfo->reg_info.fRootModule = TRUE; // module shows in root directory.
- pRegInfo->reg_info.fProcessModule = TRUE; // module shows in process directory.
- pRegInfo->reg_fn.pfnList = PY2C_Callback_List; // List function supported.
- pRegInfo->reg_fn.pfnRead = PY2C_Callback_Read; // Read function supported.
- pRegInfo->reg_fn.pfnWrite = PY2C_Callback_Write; // Write function supported.
- pRegInfo->reg_fn.pfnNotify = PY2C_Callback_Notify; // Notify function supported.
- pRegInfo->reg_fn.pfnClose = PYTHON_Close; // Close module handle.
- pRegInfo->pfnPluginManager_Register(pRegInfo); // Register with the plugin maanger.
- }
-}
diff --git a/vmmpycplugin/vmmpycplugin.rc b/vmmpycplugin/vmmpycplugin.rc
deleted file mode 100644
index c26a624..0000000
Binary files a/vmmpycplugin/vmmpycplugin.rc and /dev/null differ
diff --git a/vmmpycplugin/vmmpycplugin.vcxproj b/vmmpycplugin/vmmpycplugin.vcxproj
deleted file mode 100644
index fd80a7e..0000000
--- a/vmmpycplugin/vmmpycplugin.vcxproj
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- 15.0
- {283FF01B-31A6-465A-A728-F187F974EFF4}
- vmmpycplugin
- 10.0.17763.0
-
-
-
- DynamicLibrary
- true
- v141
- Unicode
- false
-
-
- DynamicLibrary
- false
- v141
- true
- Unicode
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(SolutionDir)\files\temp\$(ProjectName)\
- $(SolutionDir)\files\
- $(VC_IncludePath);$(WindowsSDK_IncludePath);C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\include\;C:\Program Files\Python36\include;
- $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\libs;C:\Program Files\Python36\libs;
-
-
- $(SolutionDir)\files\temp\$(ProjectName)\
- $(SolutionDir)\files\
- $(VC_IncludePath);$(WindowsSDK_IncludePath);C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\include\;C:\Program Files\Python36\include;
- $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\libs;C:\Program Files\Python36\libs;
-
-
-
- Level3
- Disabled
- true
- true
-
-
-
-
-
-
- $(SolutionDir)\files\vmm.lib
- $(OutDir)\lib\$(TargetName).pdb
- $(OutDir)\lib\$(TargetName).lib
-
-
- copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y
-copy $(SolutionDir)\files\vmmdll.h $(ProjectDir)\ /y
-
-
-
-
- Level3
- MaxSpeed
- true
- true
- true
- true
- MultiThreadedDLL
-
-
- true
- true
- $(SolutionDir)\files\vmm.lib
- $(OutDir)\lib\$(TargetName).pdb
- $(OutDir)\lib\$(TargetName).lib
- UseLinkTimeCodeGeneration
-
-
-
-
-
-
- copy $(SolutionDir)\files\leechcore.h $(ProjectDir)\ /y
-copy $(SolutionDir)\files\vmmdll.h $(ProjectDir)\ /y
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/vmmpycplugin/vmmpycplugin.vcxproj.filters b/vmmpycplugin/vmmpycplugin.vcxproj.filters
deleted file mode 100644
index 8111be1..0000000
--- a/vmmpycplugin/vmmpycplugin.vcxproj.filters
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
- {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
-
-
- {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
- rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
-
-
- {4b74ec91-050e-45ff-95b6-1f4b3d0031e5}
-
-
-
-
- Source Files
-
-
-
-
- Header Files\vmm
-
-
- Header Files\vmm
-
-
- Header Files
-
-
-
-
- Resource Files
-
-
-
\ No newline at end of file
diff --git a/vmmpycplugin/vmmpycplugin.vcxproj.user b/vmmpycplugin/vmmpycplugin.vcxproj.user
deleted file mode 100644
index fa6ed15..0000000
--- a/vmmpycplugin/vmmpycplugin.vcxproj.user
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
- WindowsLocalDebugger
-
-
- WindowsLocalDebugger
-
-
\ No newline at end of file