mirror of
https://github.com/WithSecureLabs/ModuleStomping
synced 2026-06-06 17:00:48 +00:00
Add materials for final part of series, part 3
This commit is contained in:
+395
@@ -0,0 +1,395 @@
|
||||
#include <Ntifs.h>
|
||||
#include <Ntddk.h>
|
||||
//#include <aux_klib.h>
|
||||
#include "driver.h"
|
||||
#include "public.h"
|
||||
|
||||
_Use_decl_annotations_ DRIVER_INITIALIZE DriverEntry;
|
||||
_Use_decl_annotations_ DRIVER_UNLOAD DriverUnload;
|
||||
_Dispatch_type_(IRP_MJ_CREATE) DRIVER_DISPATCH irp_mj_create;
|
||||
_Dispatch_type_(IRP_MJ_CLOSE) DRIVER_DISPATCH irp_mj_close;
|
||||
_Dispatch_type_(IRP_MJ_DEVICE_CONTROL) DRIVER_DISPATCH irp_mj_device_control;
|
||||
|
||||
NTSTATUS queryVA(getPageInfoRequest* params, getPageInfoResponse* response);
|
||||
NTSTATUS queryVAFromIRP(PIRP Irp);
|
||||
NTSTATUS setPFNDatabase(setPFNDatabaseRequest* req);
|
||||
NTSTATUS setPFNDatabaseFromIRP(PIRP Irp);
|
||||
int isTableEntryValid(unsigned long long entry);
|
||||
unsigned long long getChildTableFromTableEntry(unsigned long long entry);
|
||||
__drv_requiresIRQL(APC_LEVEL) NTSTATUS readMemoryFromPhysical(unsigned long long address, char* errMsg, void* tableOut);
|
||||
|
||||
privateInfo prv;
|
||||
|
||||
// TODO: Get PFN structure info via PDBs instead of hardcoding it here.
|
||||
struct PFN
|
||||
{
|
||||
// 0x00
|
||||
unsigned long long padding1;
|
||||
// 0x08
|
||||
unsigned long long PTEAddress;
|
||||
// 0x10
|
||||
unsigned long long OriginalPte;
|
||||
// 0x18
|
||||
unsigned long long u2;
|
||||
// 0x20 - u3
|
||||
unsigned short referenceCount;
|
||||
unsigned char e1;
|
||||
unsigned char e3;
|
||||
unsigned long e4; // or e2
|
||||
// 0x28
|
||||
unsigned long long u4;
|
||||
};
|
||||
|
||||
_Use_decl_annotations_ NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT *DriverObject, _In_ PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
NTSTATUS s;
|
||||
UNICODE_STRING deviceName;
|
||||
UNICODE_STRING DOSDeviceName;
|
||||
|
||||
UNREFERENCED_PARAMETER(RegistryPath);
|
||||
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = irp_mj_create;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = irp_mj_close;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = irp_mj_device_control;
|
||||
|
||||
// Initialise our 'private' data, shared throughout the driver
|
||||
memset(&prv, 0, sizeof(privateInfo));
|
||||
|
||||
// Create our device and the DOS symlink to it, as usual
|
||||
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
|
||||
s = IoCreateDevice(DriverObject, 0, &deviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &prv.deviceObject);
|
||||
if (!NT_SUCCESS(s))
|
||||
{
|
||||
DbgPrint("Failed IoCreateDevice: 0x%08lx\n", s);
|
||||
return s;
|
||||
}
|
||||
RtlInitUnicodeString(&DOSDeviceName, DOS_DEVICE_NAME);
|
||||
|
||||
s = IoCreateSymbolicLink(&DOSDeviceName, &deviceName);
|
||||
if (!NT_SUCCESS(s))
|
||||
{
|
||||
IoDeleteDevice(prv.deviceObject);
|
||||
DbgPrint("Failed IoCreateSymbolicLink: 0x%08lx\n", s);
|
||||
return s;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID DriverUnload(_In_ struct _DRIVER_OBJECT *DriverObject)
|
||||
{
|
||||
UNICODE_STRING DOSDeviceName;
|
||||
|
||||
UNREFERENCED_PARAMETER(DriverObject);
|
||||
|
||||
RtlInitUnicodeString(&DOSDeviceName, DOS_DEVICE_NAME);
|
||||
IoDeleteSymbolicLink(&DOSDeviceName);
|
||||
IoDeleteDevice(prv.deviceObject);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_ NTSTATUS irp_mj_create(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(DeviceObject);
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_ NTSTATUS irp_mj_close(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(DeviceObject);
|
||||
|
||||
// FIXME: Make sure all pending requests on this handle are complete
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS setPFNDatabaseFromIRP(PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION irpStack;
|
||||
setPFNDatabaseRequest inputBuffer;
|
||||
int bytesReturned;
|
||||
NTSTATUS s;
|
||||
|
||||
bytesReturned = 0;
|
||||
|
||||
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(setPFNDatabaseRequest))
|
||||
{
|
||||
s = STATUS_BUFFER_TOO_SMALL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(&inputBuffer, Irp->AssociatedIrp.SystemBuffer, sizeof(setPFNDatabaseRequest));
|
||||
|
||||
s = setPFNDatabase(&inputBuffer);
|
||||
|
||||
out:
|
||||
Irp->IoStatus.Status = s;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return s;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_ NTSTATUS irp_mj_device_control(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION irpStack;
|
||||
unsigned long functionCode;
|
||||
|
||||
UNREFERENCED_PARAMETER(DeviceObject);
|
||||
|
||||
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
functionCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
|
||||
|
||||
switch (functionCode)
|
||||
{
|
||||
case IOCTL_DRIVER_QUERY_VA:
|
||||
return queryVAFromIRP(Irp);
|
||||
case IOCTL_DRIVER_SET_PFN_DATABASE:
|
||||
return setPFNDatabaseFromIRP(Irp);
|
||||
default:
|
||||
DbgPrint("IRP_MJ_DEVICE_CONTROL: Unrecognised function code 0x%08lx\n", functionCode);
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = STATUS_ILLEGAL_FUNCTION;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS setPFNDatabase(setPFNDatabaseRequest* req)
|
||||
{
|
||||
PVOID MmPfnDatabaseUnsafe;
|
||||
unsigned long long MmPfnDatabase;
|
||||
MM_COPY_ADDRESS src;
|
||||
SIZE_T bytesRead;
|
||||
NTSTATUS s;
|
||||
int didExcept;
|
||||
|
||||
unsigned long numberOfPFNs = 0x2000; // FIXME
|
||||
|
||||
// Since we don't know the base address of ntdll (and don't want to call any undocumented stuff to get it), we accept an offset to MmPfnDatabase
|
||||
// from an exported entry (ExAllocatePoolWithTag). Since this comes from userspace, we still need to santise it as best we can. We can't make it
|
||||
// foolproof but we can do some basic checks. Since we only ever read the PFN database via MmCopyMemory, it should be safe for userspace to give
|
||||
// us a bad address, anyway.
|
||||
MmPfnDatabaseUnsafe = (PVOID)( ((unsigned long long)ExAllocatePoolWithTag) - req->offsetToMmPfnDatabaseInNtDllFromExAllocatePoolWithTag );
|
||||
|
||||
// We now have a pointer to MmPfnDatabase, which is itself a pointer to the first PFN. We should try to read it, and find the PFN DB base.
|
||||
src.VirtualAddress = MmPfnDatabaseUnsafe;
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 6001 ) // VS things 'MmPfnDatabase' can be uninitialized in this call. It cannot.
|
||||
s = MmCopyMemory(&MmPfnDatabase, src, sizeof(PVOID), MM_COPY_MEMORY_VIRTUAL, &bytesRead);
|
||||
#pragma warning( pop )
|
||||
if (!NT_SUCCESS(s))
|
||||
{
|
||||
DbgPrint("Cannot read MmPfnDatabase pointer %p as provided by userspace\n", MmPfnDatabaseUnsafe);
|
||||
return s;
|
||||
}
|
||||
if (bytesRead != sizeof(PVOID))
|
||||
{
|
||||
DbgPrint("Short read of read MmPfnDatabase pointer %p as provided by userspace (read %llu of %llu bytes)\n", MmPfnDatabaseUnsafe, bytesRead, sizeof(PVOID));
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
// Now we have the PFN database pointer, and we can do some basic checks on it.
|
||||
// It should be aligned on a 4K boundary (I think?). This is totally from observation
|
||||
// and may be incorrect.
|
||||
if ((MmPfnDatabase & 0x0000000000000fff) != 0)
|
||||
{
|
||||
DbgPrint("Dereferenced MmPfnDatabase pointer is not correctly aligned?\n");
|
||||
return STATUS_BAD_DATA;
|
||||
}
|
||||
|
||||
// This should not be in a user-space buffer
|
||||
__try
|
||||
{
|
||||
ProbeForRead((PVOID)MmPfnDatabase, sizeof(struct PFN) * numberOfPFNs, 1);
|
||||
didExcept = FALSE;
|
||||
}
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 6320 ) // "warning C6320: Exception-filter expression is the constant EXCEPTION_EXECUTE_HANDLER. This might mask exceptions that were not intended to be handled."
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
#pragma warning( pop )
|
||||
{
|
||||
didExcept = TRUE;
|
||||
}
|
||||
if (!didExcept)
|
||||
{
|
||||
DbgPrint("Dereferenced MmPfnDatabase pointer is in userspace\n");
|
||||
return STATUS_BAD_DATA;
|
||||
}
|
||||
|
||||
// TODO: more checks. We're giving userspace the ability to give kernel space a pointer here
|
||||
// so we should be as careful as we possibly can be.
|
||||
|
||||
// OK, all our checks passed!
|
||||
prv.PFNDatabase = MmPfnDatabase;
|
||||
DbgPrint("MmPfnDatabase is 0x%016llx\n", prv.PFNDatabase);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS queryVAFromIRP(PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION irpStack;
|
||||
getPageInfoRequest inputBuffer;
|
||||
getPageInfoResponse* outputBuffer;
|
||||
int bytesReturned;
|
||||
NTSTATUS s;
|
||||
|
||||
bytesReturned = 0;
|
||||
|
||||
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(getPageInfoRequest))
|
||||
{
|
||||
s = STATUS_BUFFER_TOO_SMALL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(&inputBuffer, Irp->AssociatedIrp.SystemBuffer, sizeof(getPageInfoRequest));
|
||||
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(getPageInfoResponse) * inputBuffer.numberOfPagesToCheck)
|
||||
{
|
||||
s = STATUS_BUFFER_TOO_SMALL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
outputBuffer = (getPageInfoResponse*)Irp->AssociatedIrp.SystemBuffer;
|
||||
memset(outputBuffer, 0, sizeof(getPageInfoResponse) * inputBuffer.numberOfPagesToCheck);
|
||||
|
||||
s = queryVA(&inputBuffer, outputBuffer);
|
||||
|
||||
if (NT_SUCCESS(s))
|
||||
bytesReturned = sizeof(getPageInfoResponse) * inputBuffer.numberOfPagesToCheck;
|
||||
|
||||
out:
|
||||
Irp->IoStatus.Status = s;
|
||||
Irp->IoStatus.Information = bytesReturned;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return s;
|
||||
}
|
||||
|
||||
NTSTATUS queryVA(getPageInfoRequest* params, getPageInfoResponse* response)
|
||||
{
|
||||
PMDL mdl;
|
||||
PPFN_NUMBER pfnArray;
|
||||
unsigned int pfnArrayCount;
|
||||
unsigned int pfnIdx;
|
||||
struct PFN* MmPfnDatabase = (struct PFN*)prv.PFNDatabase;
|
||||
struct PFN ourPFN;
|
||||
unsigned long long pte;
|
||||
KAPC_STATE state;
|
||||
PEPROCESS eprocess;
|
||||
NTSTATUS s;
|
||||
MM_COPY_ADDRESS srcAddress;
|
||||
PHYSICAL_ADDRESS phys;
|
||||
SIZE_T numRead;
|
||||
|
||||
UNREFERENCED_PARAMETER(response);
|
||||
|
||||
if (params->numberOfPagesToCheck == 0)
|
||||
{
|
||||
DbgPrint("Asked to scan 0 pages\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
mdl = IoAllocateMdl((PVOID)params->pageToCheck, 0x1000 * params->numberOfPagesToCheck, FALSE, FALSE, NULL);
|
||||
if (!mdl)
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
s = PsLookupProcessByProcessId((HANDLE)params->targetPID, &eprocess);
|
||||
if (!NT_SUCCESS(s))
|
||||
{
|
||||
IoFreeMdl(mdl);
|
||||
DbgPrint("PsLookupProcesByProcessId failed for PID 0x%04lx: 0x%08lx\n", params->targetPID, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
KeStackAttachProcess(eprocess, &state);
|
||||
|
||||
__try
|
||||
{
|
||||
MmProbeAndLockPages(mdl, UserMode, IoReadAccess);
|
||||
}
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 6320 ) // "warning C6320: Exception-filter expression is the constant EXCEPTION_EXECUTE_HANDLER. This might mask exceptions that were not intended to be handled."
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
#pragma warning( pop )
|
||||
{
|
||||
s = STATUS_BAD_DATA;
|
||||
goto out;
|
||||
}
|
||||
pfnArray = MmGetMdlPfnArray(mdl);
|
||||
pfnArrayCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(mdl), MmGetMdlByteCount(mdl));
|
||||
// Read the PTE from the PFN database using MmCopyMemory, in case we have the pfn database base address wrong.
|
||||
// MmCopyMemory won't let me read us the memory by VA - not 100% sure why but I suspect because it is checked
|
||||
// against the PFN table and no mapping is found (?) - so we just translate to physical address and read that
|
||||
// instead.
|
||||
for (pfnIdx = 0; pfnIdx < pfnArrayCount; pfnIdx++)
|
||||
{
|
||||
phys = MmGetPhysicalAddress(&MmPfnDatabase[pfnArray[pfnIdx]]);
|
||||
srcAddress.PhysicalAddress.QuadPart = phys.QuadPart;
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 6001 ) // VS things 'ourPFN' can be uninitialized in this call. It cannot.
|
||||
s = MmCopyMemory(&ourPFN, srcAddress, sizeof(struct PFN), MM_COPY_MEMORY_PHYSICAL, &numRead);
|
||||
#pragma warning( pop )
|
||||
if (!NT_SUCCESS(s) || numRead != sizeof(struct PFN))
|
||||
{
|
||||
DbgPrint("Failed to read PFN from PFN database at %p (%p[0x%16llx]): NTSTATUS 0x%08lx, transferred %llu of %llu bytes\n", srcAddress.VirtualAddress, MmPfnDatabase, pfnArray[pfnIdx], s, numRead, sizeof(struct PFN));
|
||||
if (NT_SUCCESS(s))
|
||||
s = STATUS_PARTIAL_COPY;
|
||||
goto out;
|
||||
}
|
||||
pte = ourPFN.PTEAddress;
|
||||
|
||||
// DbgPrint("VA 0x%016llx PFN %p\n", params->pageToCheck, &MmPfnDatabase[pfn[0]]);
|
||||
|
||||
response[pfnIdx].isValid = TRUE; // TODO
|
||||
response[pfnIdx].isDirty = (ourPFN.e1 >> 4) & 0x01;
|
||||
}
|
||||
s = STATUS_SUCCESS;
|
||||
|
||||
out:
|
||||
MmUnlockPages(mdl);
|
||||
IoFreeMdl(mdl);
|
||||
KeUnstackDetachProcess(&state);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
__drv_requiresIRQL(APC_LEVEL)
|
||||
NTSTATUS readMemoryFromPhysical(unsigned long long address, char* errMsg, void* tableOut)
|
||||
{
|
||||
NTSTATUS s;
|
||||
MM_COPY_ADDRESS srcAddress;
|
||||
SIZE_T numRead;
|
||||
SIZE_T bytesToRead = 0x200 * sizeof(unsigned long long);
|
||||
|
||||
srcAddress.PhysicalAddress.QuadPart = address;
|
||||
s = MmCopyMemory(tableOut, srcAddress, bytesToRead, MM_COPY_MEMORY_PHYSICAL, &numRead);
|
||||
|
||||
if (!NT_SUCCESS(s) || numRead != bytesToRead)
|
||||
{
|
||||
DbgPrint("Failed to MmCopyMemory table '%s' from physical location 0x%08llx: 0x%08lx (read 0x%08llx of 0x%08llx bytes)\n", errMsg, srcAddress.PhysicalAddress.QuadPart, s, numRead, bytesToRead);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
unsigned long long getChildTableFromTableEntry(unsigned long long entry)
|
||||
{
|
||||
// TODO/FIXME: We should honour the size of the child table pointer here, which is set as
|
||||
// M-12 (M being set in the sillicon I think). Bit 63 is XD, and 62-52 is ignored, but 51
|
||||
// through M is reserved by the sillicon so we should ignore it..
|
||||
return ((unsigned long long)((entry & ~(0xfff0'0000'0000'0FFF)) ));
|
||||
}
|
||||
|
||||
int isTableEntryValid(unsigned long long entry)
|
||||
{
|
||||
return (entry & 0x01) != 0;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
struct privateInfo
|
||||
{
|
||||
PDEVICE_OBJECT deviceObject;
|
||||
unsigned long long PFNDatabase;
|
||||
}; typedef struct privateInfo privateInfo;
|
||||
|
||||
extern privateInfo prv;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
;
|
||||
; driver.inf
|
||||
;
|
||||
|
||||
[Version]
|
||||
Signature="$WINDOWS NT$"
|
||||
Class=System
|
||||
ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}
|
||||
Provider=%ManufacturerName%
|
||||
DriverVer=1
|
||||
CatalogFile=driver.cat
|
||||
|
||||
[DestinationDirs]
|
||||
DefaultDestDir = 12
|
||||
|
||||
|
||||
[SourceDisksNames]
|
||||
1 = %DiskName%,,,""
|
||||
|
||||
[SourceDisksFiles]
|
||||
|
||||
|
||||
[Manufacturer]
|
||||
%ManufacturerName%=Standard,NT$ARCH$
|
||||
|
||||
[Standard.NT$ARCH$]
|
||||
|
||||
|
||||
[Strings]
|
||||
ManufacturerName="<Your manufacturer name>" ;TODO: Replace with your manufacturer name
|
||||
ClassName=""
|
||||
DiskName="driver Source Disk"
|
||||
@@ -0,0 +1,95 @@
|
||||
<?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|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{65A559E4-6946-4252-BFBE-C3B5D1B8108C}</ProjectGuid>
|
||||
<TemplateGuid>{dd38f7fc-d7bd-488b-9242-7d8754cde80d}</TemplateGuid>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
|
||||
<RootNamespace>driver</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>WDM</DriverType>
|
||||
<SpectreMitigation>false</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>WDM</DriverType>
|
||||
<SpectreMitigation>false</SpectreMitigation>
|
||||
</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|x64'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>Aux_klib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<EnablePREfast>true</EnablePREfast>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>Aux_klib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<EnablePREfast>true</EnablePREfast>
|
||||
<PreprocessorDefinitions>_PFT_SHOULD_CHECK_RETURN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Inf Include="driver.inf" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FilesToPackage Include="$(TargetPath)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="driver.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="driver.h" />
|
||||
<ClInclude Include="public.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#define DOS_DEVICE_NAME L"\\DosDevices\\cowspot"
|
||||
#define DEVICE_NAME L"\\Device\\cowspot"
|
||||
|
||||
struct getPageInfoResponse
|
||||
{
|
||||
unsigned char isValid;
|
||||
unsigned char isDirty;
|
||||
}; typedef struct getPageInfoResponse getPageInfoResponse;
|
||||
|
||||
struct getPageInfoRequest
|
||||
{
|
||||
unsigned long targetPID;
|
||||
unsigned long numberOfPagesToCheck;
|
||||
unsigned long long pageToCheck;
|
||||
}; typedef struct getPageInfoRequest getPageInfoRequest;
|
||||
|
||||
#define IOCTL_DRIVER_QUERY_VA CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
|
||||
struct setPFNDatabaseRequest
|
||||
{
|
||||
unsigned long long offsetToMmPfnDatabaseInNtDllFromExAllocatePoolWithTag;
|
||||
}; typedef struct setPFNDatabaseRequest setPFNDatabaseRequest;
|
||||
|
||||
#define IOCTL_DRIVER_SET_PFN_DATABASE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
|
||||
Reference in New Issue
Block a user