diff options
-rw-r--r-- | .gitattributes | 63 | ||||
-rw-r--r-- | .gitignore | 261 | ||||
-rw-r--r-- | KMemDriver.sln | 33 | ||||
-rw-r--r-- | KMemDriver/Driver.c | 805 | ||||
-rw-r--r-- | KMemDriver/Imports.h | 112 | ||||
-rw-r--r-- | KMemDriver/KMemDriver.vcxproj | 185 | ||||
-rw-r--r-- | KMemDriver/KMemDriver.vcxproj.filters | 29 | ||||
-rw-r--r-- | KMemDriver/Native.h | 82 | ||||
-rw-r--r-- | KTest-Only.bat | 5 | ||||
-rw-r--r-- | KTest/KInterface.cpp | 326 | ||||
-rw-r--r-- | KTest/KInterface.h | 120 | ||||
-rw-r--r-- | KTest/KTest.cpp | 400 | ||||
-rw-r--r-- | KTest/KTest.vcxproj | 193 | ||||
-rw-r--r-- | KTest/KTest.vcxproj.filters | 39 | ||||
-rw-r--r-- | KTest/pch.cpp | 5 | ||||
-rw-r--r-- | KTest/pch.h | 14 | ||||
-rw-r--r-- | PastDSE-Manual-Map-Debug.bat | 13 | ||||
-rw-r--r-- | PastDSE-Manual-Map-Release.bat | 13 | ||||
-rw-r--r-- | include/Driver.h | 131 |
19 files changed, 2829 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c4efe2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,261 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc
\ No newline at end of file diff --git a/KMemDriver.sln b/KMemDriver.sln new file mode 100644 index 0000000..3d32609 --- /dev/null +++ b/KMemDriver.sln @@ -0,0 +1,33 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.421 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KMemDriver", "KMemDriver\KMemDriver.vcxproj", "{5B65BD0E-C43C-41E3-A016-1CD0B092998F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KTest", "KTest\KTest.vcxproj", "{8661069D-CE09-4A70-8C75-8F33E77732E6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5B65BD0E-C43C-41E3-A016-1CD0B092998F}.Debug|x64.ActiveCfg = Debug|x64 + {5B65BD0E-C43C-41E3-A016-1CD0B092998F}.Debug|x64.Build.0 = Debug|x64 + {5B65BD0E-C43C-41E3-A016-1CD0B092998F}.Debug|x64.Deploy.0 = Debug|x64 + {5B65BD0E-C43C-41E3-A016-1CD0B092998F}.Release|x64.ActiveCfg = Release|x64 + {5B65BD0E-C43C-41E3-A016-1CD0B092998F}.Release|x64.Build.0 = Release|x64 + {5B65BD0E-C43C-41E3-A016-1CD0B092998F}.Release|x64.Deploy.0 = Release|x64 + {8661069D-CE09-4A70-8C75-8F33E77732E6}.Debug|x64.ActiveCfg = Debug|x64 + {8661069D-CE09-4A70-8C75-8F33E77732E6}.Debug|x64.Build.0 = Debug|x64 + {8661069D-CE09-4A70-8C75-8F33E77732E6}.Release|x64.ActiveCfg = Release|x64 + {8661069D-CE09-4A70-8C75-8F33E77732E6}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8F34A429-695E-48D4-A0EF-9840BABAE3BF} + EndGlobalSection +EndGlobal diff --git a/KMemDriver/Driver.c b/KMemDriver/Driver.c new file mode 100644 index 0000000..12af90d --- /dev/null +++ b/KMemDriver/Driver.c @@ -0,0 +1,805 @@ +#include "Driver.h" +#include "Imports.h" +#include "Native.h" + +#include <ntddk.h> +#include <Ntstrsafe.h> + +#define CHEAT_EXE L"KTest.exe" + +#ifdef _DEBUG_ +#define KDBG(fmt, ...) DbgPrint("KMemDriver[%01d]: " fmt, KeGetCurrentIrql(), __VA_ARGS__) +#else +#define KDBG(fmt, ...) +#endif + +#ifndef _DEBUG_ +#define FNZERO_MARKER() \ + do { \ + volatile UINT32 marker = 0xDEADC0DE;\ + UNREFERENCED_PARAMETER(marker); \ + } while (0) +#define FNZERO_FN(fn_start) \ + do { fn_zero_text((PVOID)fn_start); } while (0) +#define FNZERO(fn_start) \ + FNZERO_MARKER(); \ + FNZERO_FN(fn_start) +#else +#define FNZERO_MARKER() +#define FNZERO_FN(fn_start) +#define FNZERO(fn_start) +#endif + +#define WAIT_OBJECT_0 ((STATUS_WAIT_0 ) + 0 ) + +DRIVER_INITIALIZE DriverEntry; +#pragma alloc_text(INIT, DriverEntry) +void OnImageLoad( + PUNICODE_STRING FullImageName, + HANDLE ProcessId, + PIMAGE_INFO ImageInfo +); +#pragma alloc_text(PAGE, OnImageLoad) + +NTSTATUS WaitForControlProcess(OUT PEPROCESS *ppEProcess); +NTSTATUS VerifyControlProcess(IN PEPROCESS pEProcess); +NTSTATUS InitSharedMemory(IN PEPROCESS pEProcess); +NTSTATUS WaitForHandshake(IN PEPROCESS pEProcess, + OUT HANDLE *pKEvent, OUT HANDLE *pUEvent); +NTSTATUS OpenEventReference(IN PEPROCESS pEProcess, + IN KAPC_STATE *pKAPCState, IN HANDLE hEvent, + OUT PKEVENT *pPKEvent); +NTSTATUS UpdatePPEPIfRequired(IN HANDLE wantedPID, + IN HANDLE lastPID, OUT HANDLE *lastPROC, + OUT PEPROCESS *lastPEP); +NTSTATUS GetPages(IN PEPROCESS Process, + OUT MEMORY_BASIC_INFORMATION *mbiArr, + IN SIZE_T mbiArrLen, OUT SIZE_T *mbiUsed, + IN PVOID start_addr); +NTSTATUS GetModules(IN PEPROCESS pEProcess, + OUT PMODULE_DATA pmod, IN OUT SIZE_T *psiz, + IN SIZE_T start_index); +NTSTATUS KeReadVirtualMemory(IN PEPROCESS pEProcess, + IN PVOID SourceAddress, + IN PVOID TargetAddress, IN PSIZE_T Size); +NTSTATUS KeWriteVirtualMemory(IN PEPROCESS pEProcess, + IN PVOID SourceAddress, + IN PVOID TargetAddress, IN PSIZE_T Size); +NTSTATUS KeProtectVirtualMemory(IN HANDLE hProcess, + IN PVOID addr, IN SIZE_T siz, + IN ULONG new_prot, OUT ULONG *old_prot); +NTSTATUS KeRestoreProtectVirtualMemory(IN HANDLE hProcess, + IN PVOID addr, IN SIZE_T siz, + IN ULONG old_prot); +NTSTATUS GetDriverObject(PDRIVER_OBJECT *lpObj, WCHAR* DriverDirName); +NTSTATUS KRThread(IN PVOID pArg); + +#pragma alloc_text(PAGE, WaitForControlProcess) +#pragma alloc_text(PAGE, VerifyControlProcess) +#pragma alloc_text(PAGE, InitSharedMemory) +#pragma alloc_text(PAGE, WaitForHandshake) +#pragma alloc_text(PAGE, OpenEventReference) +#pragma alloc_text(PAGE, UpdatePPEPIfRequired) +#pragma alloc_text(PAGE, GetPages) +#pragma alloc_text(PAGE, GetModules) +#pragma alloc_text(PAGE, KeReadVirtualMemory) +#pragma alloc_text(PAGE, KeWriteVirtualMemory) +#pragma alloc_text(PAGE, KeProtectVirtualMemory) +#pragma alloc_text(PAGE, KeRestoreProtectVirtualMemory) +#pragma alloc_text(PAGE, GetDriverObject) +#pragma alloc_text(PAGE, KRThread) + +static void fn_zero_text(PVOID fn_start); +static HANDLE ctrlPID; +static PVOID imageBase; + +static PVOID mmapedBase = NULL; +static INT hijacked = 0; +static PDRIVER_OBJECT hijackedDriver = NULL; +static DRIVER_OBJECT hijackedDriverOriginal; + + +NTSTATUS DriverEntry( + _In_ DRIVER_OBJECT *DriverObject, + _In_ PUNICODE_STRING RegistryPath +) +{ + NTSTATUS status; + HANDLE hThread = NULL; + CLIENT_ID clientID = { 0 }; + OBJECT_ATTRIBUTES obAttr = { 0 }; + + UNREFERENCED_PARAMETER(DriverObject); + UNREFERENCED_PARAMETER(RegistryPath); + + KDBG("Driver Loaded\n"); + if (!DriverObject && RegistryPath) { + /* assume that we are manual mapped by PastDSE */ + mmapedBase = RegistryPath; + KDBG("Manual mapped image base: 0x%p\n", mmapedBase); + } + InitializeObjectAttributes(&obAttr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); + status = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, &obAttr, NULL, &clientID, &KRThread, NULL); + if (!NT_SUCCESS(status)) + { + KDBG("Failed to create worker thread. Status: 0x%X\n", status); + return status; + } + + FNZERO(DriverEntry); + return status; +} + +void OnImageLoad( + PUNICODE_STRING FullImageName, + HANDLE ProcessId, + PIMAGE_INFO ImageInfo +) +{ + UNREFERENCED_PARAMETER(ImageInfo); +#if 0 + KDBG("ProcessID: 0x%X\n", ProcessId); + KDBG("FullImage: %wZ\n", FullImageName); +#endif + if (wcsstr(FullImageName->Buffer, CHEAT_EXE)) { + ctrlPID = ProcessId; + imageBase = ImageInfo->ImageBase; + KDBG("Found Target !!!\n"); + } +} + +NTSTATUS WaitForControlProcess(OUT PEPROCESS *ppEProcess) +{ + NTSTATUS status; + + if (!ppEProcess) + return STATUS_INVALID_ADDRESS; + + imageBase = NULL; + ctrlPID = NULL; + + status = PsSetLoadImageNotifyRoutine(OnImageLoad); + if (!NT_SUCCESS(status)) { + KDBG("PsSetLoadImageNotifyRoutine failed with 0x%X\n", status); + return status; + } + + while (!ctrlPID) { + LARGE_INTEGER wait = { .QuadPart = -1000000 }; + KeDelayExecutionThread(KernelMode, TRUE, &wait); + } + + status = PsRemoveLoadImageNotifyRoutine(OnImageLoad); + if (!NT_SUCCESS(status)) { + KDBG("PsRemoveLoadImageNotifyRoutine failed with 0x%X\n", status); + return status; + } + + status = PsLookupProcessByProcessId(ctrlPID, ppEProcess); + if (!NT_SUCCESS(status)) { + KDBG("PsLookupProcessByProcessId failed with 0x%X\n", status); + return status; + } + + KDBG("Got Ctrl Process PID: 0x%X (%d)\n", + ctrlPID, ctrlPID); + + return STATUS_SUCCESS; +} + +NTSTATUS VerifyControlProcess(IN PEPROCESS pEProcess) +{ + NTSTATUS status; + UCHAR pefile[4] = { 0 }; + SIZE_T pesiz = sizeof pefile; + + status = KeReadVirtualMemory(pEProcess, + imageBase, pefile, &pesiz); + if (!NT_SUCCESS(status) || pesiz != sizeof pefile) { + KDBG("KeReadVirtualMemory failed with 0x%X\n", status); + return status; + } + if (pefile[0] != 0x4D || pefile[1] != 0x5A || + pefile[2] != 0x90 || pefile[3] != 0x00) + { + KDBG("Invalid PE file\n"); + return status; + } + + return status; +} + +NTSTATUS InitSharedMemory(IN PEPROCESS pEProcess) +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; + SIZE_T maxWaits = 20; + + KDBG("Init Shmem ..\n"); + while (--maxWaits) { + UCHAR buf[4] = { 0 }; + SIZE_T bufsiz = sizeof buf; + LARGE_INTEGER wait = { .QuadPart = -5000000 }; + status = KeReadVirtualMemory(pEProcess, + (PVOID)SHMEM_ADDR, buf, &bufsiz); + if (NT_SUCCESS(status) && bufsiz == sizeof buf) + break; + KDBG("Waiting until 0x%X alloc'd by user space app ..\n", SHMEM_ADDR); + KeDelayExecutionThread(KernelMode, TRUE, &wait); + } + + return status; +} + +NTSTATUS WaitForHandshake(IN PEPROCESS pEProcess, + OUT HANDLE *pKEvent, OUT HANDLE *pUEvent) +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; + SIZE_T maxWaits = 20; + + KDBG("Wait for Handshake ..\n"); + while (--maxWaits) { + KERNEL_HANDSHAKE hnds; + SIZE_T siz = sizeof hnds; + LARGE_INTEGER wait = { .QuadPart = -5000000 }; + status = KeReadVirtualMemory(pEProcess, (PVOID)SHMEM_ADDR, &hnds, &siz); + if (NT_SUCCESS(status) && siz == sizeof hnds && + hnds.kevent) + { + if (validateRequest(&hnds) != MEM_HANDSHAKE) { + KDBG("Invalid Handshake received: 0x%X\n", hnds.hdr.magic); + return STATUS_INVALID_CONNECTION; + } + *pKEvent = hnds.kevent; + *pUEvent = hnds.uevent; + KDBG("Got Event Handle 0x%X (Kernel) and 0x%X (User)\n", + *pKEvent, *pUEvent); + break; + } + KDBG("Waiting for handshake at 0x%X ..\n", SHMEM_ADDR); + KeDelayExecutionThread(KernelMode, TRUE, &wait); + } + + return status; +} + +NTSTATUS OpenEventReference(IN PEPROCESS pEProcess, + IN KAPC_STATE *pKAPCState, IN HANDLE hEvent, + OUT PKEVENT *pPKEvent) +{ + NTSTATUS status; + + KeStackAttachProcess((PRKPROCESS)pEProcess, pKAPCState); + status = ObReferenceObjectByHandle( + hEvent, SYNCHRONIZE | EVENT_MODIFY_STATE, + *ExEventObjectType, UserMode, pPKEvent, NULL + ); + KeUnstackDetachProcess(pKAPCState); + if (!NT_SUCCESS(status)) + KDBG("ObReferenceObjectByHandle for Handle 0x%X failed with 0x%X\n", + hEvent, status); + + return status; +} + +NTSTATUS KRThread(IN PVOID pArg) +{ + NTSTATUS status; + INT reinit; + HANDLE kevent, uevent; + PEPROCESS ctrlPEP; + KAPC_STATE apcstate; + PKEVENT pk_kevent, pk_uevent; + + UNREFERENCED_PARAMETER(pArg); + + do { + reinit = 0; + ctrlPEP = NULL; + pk_kevent = pk_uevent = NULL; + + KeLowerIrql(0); + KDBG("Init ..\n"); + + if (mmapedBase && !hijackedDriver && + NT_SUCCESS(GetDriverObject(&hijackedDriver, L"\\Driver\\ahcache"))) + { + if (hijackedDriver) { +#ifdef _DEBUG_ + KDBG("Got DriverObject at 0x%p\n", hijackedDriver); + PKLDR_DATA_TABLE_ENTRY drv_section = hijackedDriver->DriverSection; + KDBG("PDrvObj: base -> 0x%p , name -> '%wZ' , flags -> 0x%X\n", + drv_section->DllBase, drv_section->BaseDllName, drv_section->Flags); +#endif + /* !!! EXPERIMENTAL !!! */ +#if 0 + hijacked = 1; + /* the following lines are known to cause a bugcheck */ + hijackedDriverOriginal = *hijackedDriver; + hijackedDriver->DriverStart = mmapedBase; + //hijackedDriver->DriverSection = (PVOID)((ULONG_PTR)mmapedBase + 100); +#endif +#if 0 + /* the following lines are known to not work with ahcache driver */ + hijackedDriver->DriverInit = (PDRIVER_INITIALIZE)DriverEntry; + hijackedDriver->DriverStartIo = NULL; + hijackedDriver->DriverUnload = NULL; + SIZE_T funcs = sizeof hijackedDriver->MajorFunction / sizeof hijackedDriver->MajorFunction[0]; + for (SIZE_T i = 0; i < funcs; ++i) { + hijackedDriver->MajorFunction[i] = NULL; + } +#endif + } + } + + status = WaitForControlProcess(&ctrlPEP); + if (!NT_SUCCESS(status)) + goto finish; + + if (hijackedDriver && hijacked) { + *hijackedDriver = hijackedDriverOriginal; + } + + status = VerifyControlProcess(ctrlPEP); + if (!NT_SUCCESS(status)) + goto finish_ctrlpep; + + status = InitSharedMemory(ctrlPEP); + if (!NT_SUCCESS(status)) + goto finish_ctrlpep; + + status = WaitForHandshake(ctrlPEP, + &kevent, &uevent); + if (!NT_SUCCESS(status)) + goto finish_ctrlpep; + + status = OpenEventReference(ctrlPEP, + &apcstate, kevent, &pk_kevent); + if (!NT_SUCCESS(status)) + goto finish_ctrlpep; + + status = OpenEventReference(ctrlPEP, + &apcstate, uevent, &pk_uevent); + if (!NT_SUCCESS(status)) + goto finish_kevent; + + KeClearEvent(pk_kevent); + KeClearEvent(pk_uevent); + + PVOID shm_buf = MmAllocateNonCachedMemory(SHMEM_SIZE); + if (!shm_buf) { + KDBG("MmAllocateNonCachedMemory with size 0x%X failed\n", SHMEM_SIZE); + goto nomem; + } + + reinit = 1; + KeSetEvent(pk_uevent, FILE_DEVICE_MOUSE, TRUE); + HANDLE lastPID = NULL, lastPROC = NULL; + PEPROCESS lastPEP = NULL; + INT running = 1; + SIZE_T maxWaits = 20; + do { + LARGE_INTEGER wait = { .QuadPart = -10000000 }; + status = KeWaitForSingleObject(pk_kevent, Executive, UserMode, FALSE, &wait); + if (NT_SUCCESS(status) && status == WAIT_OBJECT_0) { + maxWaits = 20; + /* parse memory request */ + SIZE_T siz = SHMEM_SIZE; + status = KeReadVirtualMemory(ctrlPEP, (PVOID)SHMEM_ADDR, shm_buf, &siz); + + if (NT_SUCCESS(status) && siz == SHMEM_SIZE) { + switch (validateRequest(shm_buf)) + { + case MEM_HANDSHAKE: + KDBG("Invalid Request MEM_HANDSHAKE\n"); + break; + case MEM_PING: { + PKERNEL_PING ping = (PKERNEL_PING)shm_buf; + KDBG("Got a PING with rng 0x%X, sending PONG !\n", + ping->rnd_user); + ping->rnd_kern = ping->rnd_user; + siz = sizeof *ping; + KeWriteVirtualMemory(ctrlPEP, ping, (PVOID)SHMEM_ADDR, &siz); + break; + } + case MEM_PAGES: { + PKERNEL_PAGE pages = (PKERNEL_PAGE)shm_buf; + KDBG("Got a PAGES request for process 0x%X start at address 0x%p\n", + pages->ProcessId, pages->StartAddress); + if (!NT_SUCCESS(UpdatePPEPIfRequired(pages->ProcessId, + lastPID, &lastPROC, &lastPEP))) + { + running = 0; + break; + } + siz = (SHMEM_SIZE - sizeof *pages + sizeof pages->pages_start) + / sizeof pages->pages_start; + pages->StatusRes = GetPages(lastPEP, &pages->pages_start, siz, + &pages->pages, pages->StartAddress); + siz = (sizeof *pages - sizeof pages->pages_start) + + sizeof pages->pages_start * pages->pages; + KeWriteVirtualMemory(ctrlPEP, pages, (PVOID)SHMEM_ADDR, &siz); + break; + } + case MEM_MODULES: { + PKERNEL_MODULES mods = (PKERNEL_MODULES)shm_buf; + KDBG("Got a MODULES request for process 0x%X start at index 0x%X\n", + mods->ProcessId, mods->StartIndex); + if (!NT_SUCCESS(UpdatePPEPIfRequired(mods->ProcessId, + lastPID, &lastPROC, &lastPEP))) + { + running = 0; + break; + } + siz = (SHMEM_SIZE - sizeof *mods + sizeof mods->modules_start) + / sizeof mods->modules_start; + PMODULE_DATA entries = &mods->modules_start; + KDBG("GetModules max entries: %u\n", siz); + KeStackAttachProcess((PRKPROCESS)lastPEP, &apcstate); + mods->StatusRes = GetModules(lastPEP, entries, &siz, mods->StartIndex); + KeUnstackDetachProcess(&apcstate); + mods->modules = siz; + siz = (sizeof *mods - sizeof mods->modules_start) + + sizeof mods->modules_start * mods->modules; + KeWriteVirtualMemory(ctrlPEP, mods, (PVOID)SHMEM_ADDR, &siz); + break; + } + case MEM_RPM: { + PKERNEL_READ_REQUEST rr = (PKERNEL_READ_REQUEST)shm_buf; + KDBG("Got a RPM to process 0x%X, address 0x%p with size 0x%lX\n", + rr->ProcessId, rr->Address, rr->SizeReq); + if (!NT_SUCCESS(UpdatePPEPIfRequired(rr->ProcessId, + lastPID, &lastPROC, &lastPEP))) + { + running = 0; + break; + } + if (rr->SizeReq > SHMEM_SIZE - sizeof *rr) { + siz = SHMEM_SIZE - sizeof *rr; + } + else { + siz = rr->SizeReq; + } + ULONG new_prot = PAGE_EXECUTE_READWRITE, old_prot = 0; + KeProtectVirtualMemory(lastPROC, rr->Address, rr->SizeReq, new_prot, &old_prot); + KDBG("RPM to 0x%p size 0x%X bytes (protection before/after: 0x%X/0x%X)\n", + rr->Address, rr->SizeReq, old_prot, new_prot); + rr->StatusRes = KeReadVirtualMemory(lastPEP, (PVOID)rr->Address, + (PVOID)((ULONG_PTR)shm_buf + sizeof *rr), &siz); + KeRestoreProtectVirtualMemory(lastPROC, rr->Address, rr->SizeReq, old_prot); + if (NT_SUCCESS(rr->StatusRes)) { + rr->SizeRes = siz; + siz += sizeof *rr; + } + else { + rr->SizeRes = 0; + siz = sizeof *rr; + } + KeWriteVirtualMemory(ctrlPEP, rr, (PVOID)SHMEM_ADDR, &siz); + break; + } + case MEM_WPM: { + PKERNEL_WRITE_REQUEST wr = (PKERNEL_WRITE_REQUEST)shm_buf; + KDBG("Got a WPM to process 0x%X, address 0x%p with size 0x%lX\n", + wr->ProcessId, wr->Address, wr->SizeReq); + if (!NT_SUCCESS(UpdatePPEPIfRequired(wr->ProcessId, + lastPID, &lastPROC, &lastPEP))) + { + running = 0; + break; + } + if (wr->SizeReq > SHMEM_SIZE - sizeof *wr) { + siz = SHMEM_SIZE - sizeof *wr; + } + else { + siz = wr->SizeReq; + } + ULONG new_prot = PAGE_EXECUTE_READWRITE, old_prot = 0; + KeProtectVirtualMemory(lastPEP, wr->Address, wr->SizeReq, new_prot, &old_prot); + KDBG("WPM to 0x%p size 0x%X bytes (protection before/after: 0x%X/0x%X)\n", + wr->Address, wr->SizeReq, old_prot, new_prot); + wr->StatusRes = KeWriteVirtualMemory(lastPEP, (PVOID)((ULONG_PTR)shm_buf + sizeof *wr), + (PVOID)wr->Address, &siz); + KeRestoreProtectVirtualMemory(lastPROC, wr->Address, wr->SizeReq, old_prot); + if (NT_SUCCESS(wr->StatusRes)) { + wr->SizeRes = siz; + siz += sizeof *wr; + } + else { + wr->SizeRes = 0; + siz = sizeof *wr; + } + KeWriteVirtualMemory(ctrlPEP, wr, (PVOID)SHMEM_ADDR, &siz); + break; + } + case MEM_EXIT: + KDBG("Gracefully exiting ..\n"); + KeClearEvent(pk_kevent); + KeClearEvent(pk_uevent); + running = 0; + reinit = 0; + break; + default: + KDBG("Invalid Request\n"); + running = 0; + reinit = 0; + break; + } + } + + if (KeSetEvent(pk_uevent, FILE_DEVICE_MOUSE, TRUE)) { + KDBG("Previous signal state wasn't consumed!?\n"); + } + } + else { + if (!maxWaits--) { + KDBG("No activity, abort ..\n"); + running = 0; + } + } + } while (running); + KeSetEvent(pk_uevent, FILE_DEVICE_MOUSE, TRUE); + + if (lastPEP) + ObDereferenceObject(lastPEP); + if (lastPROC) + ZwClose(lastPROC); + MmFreeNonCachedMemory(shm_buf, SHMEM_SIZE); + nomem: + ObDereferenceObject(pk_uevent); + finish_kevent: + ObDereferenceObject(pk_kevent); + finish_ctrlpep: + ObDereferenceObject(ctrlPEP); + finish: + if (reinit) { + LARGE_INTEGER wait = { .QuadPart = -50000000 }; + KeDelayExecutionThread(KernelMode, TRUE, &wait); + } + } while (reinit); + + KDBG("Terminating ..\n"); + PsTerminateSystemThread(status); + return status; +} + +NTSTATUS UpdatePPEPIfRequired(IN HANDLE wantedPID, + IN HANDLE lastPID, OUT HANDLE *lastPROC, + OUT PEPROCESS *lastPEP) +{ + NTSTATUS status = STATUS_SUCCESS; + + if (wantedPID != lastPID) { + if (lastPID) { + ObDereferenceObject(*lastPEP); + *lastPEP = NULL; + ZwClose(*lastPROC); + *lastPROC = NULL; + } + status = PsLookupProcessByProcessId(wantedPID, lastPEP); + if (!NT_SUCCESS(status)) { + KDBG("PsLookupProcessByProcessId failed with 0x%X\n", status); + } + else { + status = ObOpenObjectByPointer(*lastPEP, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, GENERIC_ALL, + *PsProcessType, KernelMode, lastPROC + ); + if (!NT_SUCCESS(status)) { + KDBG("ObOpenObjectByPointer failed with 0x%X\n", status); + } + } + } + return status; +} + +NTSTATUS GetPages(IN PEPROCESS Process, + OUT MEMORY_BASIC_INFORMATION *mbiArr, + IN SIZE_T mbiArrLen, OUT SIZE_T *mbiUsed, + IN PVOID start_addr) +{ + NTSTATUS status; + HANDLE procHandle; + SIZE_T i, mbiLength, mbiReturn; + ULONG_PTR baseAddr = (ULONG_PTR)start_addr; + + status = ObOpenObjectByPointer(Process, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, GENERIC_ALL, + *PsProcessType, KernelMode, &procHandle + ); + if (!NT_SUCCESS(status)) { + KDBG("ObOpenObjectByPointer failed with 0x%X\n", status); + return status; + } + + KDBG("ZwQueryVirtualMemory max entries: %u\n", mbiArrLen); + *mbiUsed = 0; + do { + mbiReturn = 0; + status = ZwQueryVirtualMemory(procHandle, (PVOID)baseAddr, + MemoryBasicInformation, mbiArr, sizeof *mbiArr * mbiArrLen, &mbiReturn); + mbiLength = mbiReturn / sizeof *mbiArr; + if (!NT_SUCCESS(status)) { + if (status == STATUS_INVALID_PARAMETER) + status = STATUS_SUCCESS; + else + KDBG("ZwQueryVirtualMemory failed with 0x%X\n", status); + break; + } + else { + for (i = 0; i < mbiLength; ++i) + KDBG("Page #%03u: base -> %p, prot -> 0x%02X, size -> 0x%X\n", + (*mbiUsed) + i, (*(mbiArr + i)).BaseAddress, (*(mbiArr + i)).Protect, + (*(mbiArr + i)).RegionSize); + } + baseAddr += (SIZE_T)(mbiArr + mbiLength - 1)->RegionSize; + *mbiUsed += mbiLength; + mbiArr += mbiLength; + } while (*mbiUsed < mbiArrLen && mbiReturn > 0); + + ZwClose(procHandle); + return status; +} + +NTSTATUS GetModules(IN PEPROCESS Process, + OUT PMODULE_DATA pmod, IN OUT SIZE_T *psiz, + IN SIZE_T start_index) +{ + SIZE_T used = 0, index = 0; + INT waitCount = 0; + + PPEB peb = PsGetProcessPeb(Process); + if (!peb) { + KDBG("PsGetProcessPeb failed"); + return STATUS_UNSUCCESSFUL; + } + + PPEB_LDR_DATA ldr = peb->Ldr; + + if (!ldr) { + KDBG("peb->Ldr is invalid"); + return STATUS_UNSUCCESSFUL; + } + + if (!ldr->Initialized) { + while (!ldr->Initialized && waitCount++ < 4) { + LARGE_INTEGER wait = { .QuadPart = -2500 }; + KeDelayExecutionThread(KernelMode, TRUE, &wait); + } + + if (!ldr->Initialized) { + KDBG("ldr->Initialized is 0"); + return STATUS_UNSUCCESSFUL; + } + } + + for (PLIST_ENTRY listEntry = (PLIST_ENTRY)ldr->InLoadOrderModuleList.Flink; + listEntry != &ldr->InLoadOrderModuleList && used < *psiz; + listEntry = (PLIST_ENTRY)listEntry->Flink, ++pmod, ++index) { + if (index < start_index) + continue; + used++; + + PLDR_DATA_TABLE_ENTRY ldrEntry = CONTAINING_RECORD(listEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + ANSI_STRING name; + if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&name, &ldrEntry->BaseDllName, sizeof pmod->BaseDllName))) { + RtlCopyMemory(pmod->BaseDllName, name.Buffer, + (name.Length > sizeof pmod->BaseDllName ? + sizeof pmod->BaseDllName : name.Length) + ); + } + pmod->DllBase = ldrEntry->DllBase; + pmod->SizeOfImage = ldrEntry->SizeOfImage; + KDBG("DLL #%02lu: base -> 0x%p, size -> 0x%06X, name -> '%s'\n", used, + pmod->DllBase, pmod->SizeOfImage, pmod->BaseDllName); + } + + *psiz = used; + return STATUS_SUCCESS; +} + +NTSTATUS KeReadVirtualMemory(IN PEPROCESS Process, + IN PVOID SourceAddress, + IN PVOID TargetAddress, IN PSIZE_T Size) +{ + NTSTATUS status; + SIZE_T Bytes = 0; + + status = MmCopyVirtualMemory(Process, SourceAddress, PsGetCurrentProcess(), + TargetAddress, *Size, KernelMode, &Bytes); + if (NT_SUCCESS(status)) + { + *Size = Bytes; + return STATUS_SUCCESS; + } + else { + return status; + } +} + +NTSTATUS KeWriteVirtualMemory(IN PEPROCESS Process, + IN PVOID SourceAddress, + IN PVOID TargetAddress, IN PSIZE_T Size) +{ + NTSTATUS status; + SIZE_T Bytes = 0; + + status = MmCopyVirtualMemory(PsGetCurrentProcess(), SourceAddress, Process, + TargetAddress, *Size, KernelMode, &Bytes); + if (NT_SUCCESS(status)) + { + *Size = Bytes; + return STATUS_SUCCESS; + } + else { + return status; + } +} + +NTSTATUS KeProtectVirtualMemory(IN HANDLE hProcess, + IN PVOID addr, IN SIZE_T siz, IN ULONG new_prot, + OUT ULONG *old_prot) +{ + NTSTATUS status; + PVOID prot_addr = addr; + SIZE_T prot_size = siz; + ULONG prot = 0; + + status = ZwProtectVirtualMemory(hProcess, &prot_addr, + &prot_size, new_prot, &prot); + if (NT_SUCCESS(status)) { + *old_prot = prot; + } + return status; +} + +NTSTATUS KeRestoreProtectVirtualMemory(IN HANDLE hProcess, + IN PVOID addr, IN SIZE_T siz, + IN ULONG old_prot) +{ + NTSTATUS status; + PVOID prot_addr = addr; + SIZE_T prot_size = siz; + ULONG prot = 0; + + status = ZwProtectVirtualMemory(hProcess, &prot_addr, + &prot_size, old_prot, &prot); + return status; +} + +static void fn_zero_text(PVOID fn_start) +{ + SIZE_T i; + UINT32 marker = 0xDEADC0DE; + PUCHAR fnbuf = (PUCHAR)fn_start; + + KDBG("Fn: %p\n", fn_start); + for (i = 0; i < 0x1000; ++i && fnbuf++) { + if (*(UINT32 *)fnbuf == marker) { + KDBG("Marker: 0x%X\n", i); + RtlSecureZeroMemory(fn_start, i + 4); + } + } +} + +NTSTATUS GetDriverObject(PDRIVER_OBJECT *lpObj, WCHAR* DriverDirName) +{ + NTSTATUS status = STATUS_SUCCESS; + PDRIVER_OBJECT pBeepObj = NULL; + UNICODE_STRING DevName = { 0 }; + + if (!MmIsAddressValid(lpObj)) + return STATUS_INVALID_ADDRESS; + + RtlInitUnicodeString(&DevName, DriverDirName); + + status = ObReferenceObjectByName(&DevName, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType, KernelMode, NULL, &pBeepObj); + + if (NT_SUCCESS(status)) + *lpObj = pBeepObj; + else + { + *lpObj = NULL; + } + + return status; +}
\ No newline at end of file diff --git a/KMemDriver/Imports.h b/KMemDriver/Imports.h new file mode 100644 index 0000000..44f53cc --- /dev/null +++ b/KMemDriver/Imports.h @@ -0,0 +1,112 @@ +#pragma once + +#include <ntddk.h> +#include <wdm.h> + + +extern POBJECT_TYPE* IoDriverObjectType; + +NTKERNELAPI +NTSTATUS +NTAPI +MmCopyVirtualMemory +( + PEPROCESS SourceProcess, + PVOID SourceAddress, + PEPROCESS TargetProcess, + PVOID TargetAddress, + SIZE_T BufferSize, + KPROCESSOR_MODE PreviousMode, + PSIZE_T ReturnSize +); + +NTKERNELAPI +NTSTATUS +NTAPI +PsLookupProcessByProcessId( + _In_ HANDLE ProcessId, + _Outptr_ PEPROCESS *Process +); + +typedef struct _KAPC_STATE +{ + LIST_ENTRY ApcListHead[2]; + PKPROCESS Process; + UCHAR KernelApcInProgress; + UCHAR KernelApcPending; + UCHAR UserApcPending; +} KAPC_STATE, *PKAPC_STATE, *PRKAPC_STATE; + +NTKERNELAPI +VOID +NTAPI +KeStackAttachProcess( + PRKPROCESS PROCESS, + PRKAPC_STATE ApcState +); + +NTKERNELAPI +VOID +NTAPI +KeUnstackDetachProcess( + PRKAPC_STATE ApcState +); + +NTKERNELAPI +PPEB +NTAPI +PsGetProcessPeb(PEPROCESS Process); + +NTKERNELAPI +NTSTATUS +NTAPI +ObOpenObjectByPointer( + PVOID Object, + ULONG HandleAttributes, + PACCESS_STATE PassedAccessState, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, + PHANDLE Handle +); + +typedef enum _MEMORY_INFORMATION_CLASS { + MemoryBasicInformation +} MEMORY_INFORMATION_CLASS; + +NTKERNELAPI +NTSTATUS +NTAPI +ZwQueryVirtualMemory( + _In_ HANDLE ProcessHandle, + _In_opt_ PVOID BaseAddress, + _In_ MEMORY_INFORMATION_CLASS MemoryInformationClass, + _Out_ PVOID MemoryInformation, + _In_ SIZE_T MemoryInformationLength, + _Out_opt_ PSIZE_T ReturnLength +); + +NTKERNELAPI +NTSTATUS +NTAPI +ZwProtectVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID* BaseAddress, /* THIS IS ACTUALLY AN IN_OUT */ + IN SIZE_T* NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection +); + +NTKERNELAPI +NTSTATUS +NTAPI +ObReferenceObjectByName( + PUNICODE_STRING ObjectName, + ULONG Attributes, + PACCESS_STATE Passed, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE Access, + PVOID ParseContext, + PVOID* ObjectPtr +);
\ No newline at end of file diff --git a/KMemDriver/KMemDriver.vcxproj b/KMemDriver/KMemDriver.vcxproj new file mode 100644 index 0000000..1c84ef0 --- /dev/null +++ b/KMemDriver/KMemDriver.vcxproj @@ -0,0 +1,185 @@ +<?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>{5B65BD0E-C43C-41E3-A016-1CD0B092998F}</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>KMemDriver</RootNamespace> + <ProjectName>KMemDriver</ProjectName> + </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> + <SpectreMitigation>false</SpectreMitigation> + </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> + <SpectreMitigation>false</SpectreMitigation> + </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> + <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>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <SpectreMitigation>false</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> + </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)'=='Debug|Win32'"> + <ClCompile> + <PreprocessorDefinitions>_DEBUG_;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PreprocessorDefinitions>_DEBUG_;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PreprocessorDefinitions>KERNEL_MODULE;_DEBUG_;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)$(SolutionName);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile /> + <ClCompile> + <AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)$(SolutionName);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>KERNEL_MODULE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="Driver.c" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\include\Driver.h" /> + <ClInclude Include="Imports.h" /> + <ClInclude Include="Native.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/KMemDriver/KMemDriver.vcxproj.filters b/KMemDriver/KMemDriver.vcxproj.filters new file mode 100644 index 0000000..99f5bcc --- /dev/null +++ b/KMemDriver/KMemDriver.vcxproj.filters @@ -0,0 +1,29 @@ +<?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> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="Driver.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="Imports.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="Native.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\Driver.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/KMemDriver/Native.h b/KMemDriver/Native.h new file mode 100644 index 0000000..e421bda --- /dev/null +++ b/KMemDriver/Native.h @@ -0,0 +1,82 @@ +#pragma once + +#include <ntddk.h> + +typedef struct _PEB_LDR_DATA +{ + ULONG Length; + UCHAR Initialized; + PVOID SsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; +} PEB_LDR_DATA, *PPEB_LDR_DATA; + +typedef struct _LDR_DATA_TABLE_ENTRY +{ + LIST_ENTRY InLoadOrderLinks; + LIST_ENTRY InMemoryOrderLinks; + LIST_ENTRY InInitializationOrderLinks; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + USHORT LoadCount; + USHORT TlsIndex; + LIST_ENTRY HashLinks; + ULONG TimeDateStamp; +} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; + +typedef struct _PEB +{ + UCHAR InheritedAddressSpace; + UCHAR ReadImageFileExecOptions; + UCHAR BeingDebugged; + UCHAR BitField; + PVOID Mutant; + PVOID ImageBaseAddress; + PPEB_LDR_DATA Ldr; + PVOID ProcessParameters; + PVOID SubSystemData; + PVOID ProcessHeap; + PVOID FastPebLock; + PVOID AtlThunkSListPtr; + PVOID IFEOKey; + PVOID CrossProcessFlags; + PVOID KernelCallbackTable; + ULONG SystemReserved; + ULONG AtlThunkSListPtr32; + PVOID ApiSetMap; +} PEB, *PPEB; + +typedef struct _MEMORY_BASIC_INFORMATION { + PVOID BaseAddress; + PVOID AllocationBase; + ULONG AllocationProtect; + SIZE_T RegionSize; + ULONG State; + ULONG Protect; + ULONG Type; +} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; + +typedef struct _KLDR_DATA_TABLE_ENTRY { + LIST_ENTRY InLoadOrderLinks; + PVOID ExceptionTable; + ULONG ExceptionTableSize; + PVOID GpValue; + PVOID NonPagedDebugInfo; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + USHORT LoadCount; + USHORT __Unused; + PVOID SectionPointer; + ULONG CheckSum; + PVOID LoadedImports; + PVOID PatchInformation; +} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
\ No newline at end of file diff --git a/KTest-Only.bat b/KTest-Only.bat new file mode 100644 index 0000000..9dadcbe --- /dev/null +++ b/KTest-Only.bat @@ -0,0 +1,5 @@ +@echo off + +REM fsutil usn deleteJournal /D C: +%~dp0\x64\Release\KTest.exe +timeout /t 3
\ No newline at end of file diff --git a/KTest/KInterface.cpp b/KTest/KInterface.cpp new file mode 100644 index 0000000..dae57e3 --- /dev/null +++ b/KTest/KInterface.cpp @@ -0,0 +1,326 @@ +#include "pch.h" +#include "KInterface.h" +#include "Driver.h" + +#include <sstream> +#include <ctime> +#include <stdexcept> + + +KInterface::KInterface() +{ +} + +bool KInterface::Init() +{ + std::srand((unsigned int)std::time(nullptr)); + m_shmem = VirtualAlloc((PVOID)SHMEM_ADDR, SHMEM_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + m_kevent = CreateEvent(NULL, FALSE, FALSE, NULL); + m_uevent = CreateEvent(NULL, FALSE, FALSE, NULL); + return m_shmem && m_kevent != INVALID_HANDLE_VALUE && m_uevent != INVALID_HANDLE_VALUE; +} + +bool KInterface::Handshake() +{ + PKERNEL_HANDSHAKE hnds = (PKERNEL_HANDSHAKE)getBuffer(); + hnds->kevent = m_kevent; + hnds->uevent = m_uevent; + m_last_ntstatus = INVALID_NTSTATUS; + return SendRecvWait(MEM_HANDSHAKE) == SRR_SIGNALED; +} + +bool KInterface::Ping() +{ + SendRecvReturn srr; + PKERNEL_PING ping = (PKERNEL_PING)getBuffer(); + m_last_ping_value = ping->rnd_user = (std::rand() << 16) | std::rand(); + std::srand(m_last_ping_value); + m_last_ntstatus = INVALID_NTSTATUS; + srr = SendRecvWait(MEM_PING); + if (ping->rnd_kern != getLastPingValue()) + return false; + return srr == SRR_SIGNALED; +} + +bool KInterface::Pages(HANDLE targetPID, + std::vector<MEMORY_BASIC_INFORMATION>& dest, + PVOID start_address) +{ + PKERNEL_PAGE pages = (PKERNEL_PAGE)getBuffer(); + const ULONGLONG max_pages = (SHMEM_SIZE - sizeof *pages + + sizeof pages->pages_start) / sizeof pages->pages_start; + SendRecvReturn srr; + bool success = false; + + do { + m_last_ntstatus = INVALID_NTSTATUS; + pages->pages = 0; + pages->ProcessId = targetPID; + pages->StartAddress = start_address; + srr = SendRecvWait(MEM_PAGES); + if (srr == SRR_SIGNALED) { + m_last_ntstatus = pages->StatusRes; + if (validateRespone(getBuffer()) == MEM_PAGES && + !pages->StatusRes && + pages->pages * sizeof(pages->pages_start) <= SHMEM_SIZE) + { + for (SIZE_T i = 0; i < pages->pages; ++i) { + dest.push_back((&pages->pages_start)[i]); + start_address = (PVOID) + ((ULONG_PTR)((&pages->pages_start)[i].BaseAddress) + + (&pages->pages_start)[i].RegionSize); + } + success = true; + } + else { + success = false; + break; + } + } + } while (srr == SRR_SIGNALED && pages->pages == max_pages && pages->pages); + return success && srr == SRR_SIGNALED;; +} + +bool KInterface::Modules(HANDLE targetPID, + std::vector<MODULE_DATA>& dest) +{ + PKERNEL_MODULES mods = (PKERNEL_MODULES)getBuffer(); + SIZE_T start_index = 0; + const ULONGLONG max_mods = (SHMEM_SIZE - sizeof *mods + + sizeof mods->modules_start) / sizeof mods->modules_start; + SendRecvReturn srr; + bool success = false; + + do { + m_last_ntstatus = INVALID_NTSTATUS; + mods->modules = 0; + mods->ProcessId = targetPID; + mods->StartIndex = start_index; + srr = SendRecvWait(MEM_MODULES); + if (srr == SRR_SIGNALED) { + m_last_ntstatus = mods->StatusRes; + if (validateRespone(getBuffer()) == MEM_MODULES && + !mods->StatusRes && + mods->modules * sizeof(mods->modules_start) <= SHMEM_SIZE) + { + for (SIZE_T i = 0; i < mods->modules; ++i) { + dest.push_back((&mods->modules_start)[i]); + start_index++; + } + success = true; + } + else { + success = false; + break; + } + } + } while (srr == SRR_SIGNALED && mods->modules == max_mods && mods->modules); + return success && srr == SRR_SIGNALED; +} + +bool KInterface::Exit() +{ + m_last_ntstatus = INVALID_NTSTATUS; + return SendRecvWait(MEM_EXIT, INFINITE) == SRR_SIGNALED; +} + +bool KInterface::RPM(HANDLE targetPID, PVOID address, BYTE *buf, SIZE_T size, + PKERNEL_READ_REQUEST result) +{ + PKERNEL_READ_REQUEST rr = (PKERNEL_READ_REQUEST)getBuffer(); + m_last_ntstatus = INVALID_NTSTATUS; + if (size > SHMEM_SIZE - sizeof *rr) + return false; + rr->ProcessId = targetPID; + rr->Address = address; + rr->SizeReq = size; + rr->SizeRes = (SIZE_T)-1; + rr->StatusRes = (NTSTATUS)-1; + if (SendRecvWait(MEM_RPM) == SRR_SIGNALED) { + m_last_ntstatus = rr->StatusRes; + if (rr->StatusRes || + rr->SizeRes != size) + { + std::stringstream err_str; + err_str << "Call RPM(0x" << std::hex << address + << "," << std::dec << size + << ") failed with 0x" + << std::hex << rr->StatusRes + << " (Size Req/Res: " + << std::dec << rr->SizeReq << "/" << (SSIZE_T)rr->SizeRes + << ")"; + throw std::runtime_error(err_str.str()); + } + memcpy(buf, (BYTE *)rr + sizeof *rr, size); + if (result) + *result = *rr; + return true; + } + return false; +} + +bool KInterface::WPM(HANDLE targetPID, PVOID address, BYTE *buf, SIZE_T size, + PKERNEL_WRITE_REQUEST result) +{ + PKERNEL_WRITE_REQUEST wr = (PKERNEL_WRITE_REQUEST)getBuffer(); + m_last_ntstatus = INVALID_NTSTATUS; + if (size > SHMEM_SIZE - sizeof *wr) + return false; + wr->ProcessId = targetPID; + wr->Address = address; + wr->SizeReq = size; + wr->SizeRes = (SIZE_T)-1; + wr->StatusRes = (NTSTATUS)-1; + memcpy((BYTE *)wr + sizeof *wr, buf, size); + if (SendRecvWait(MEM_WPM) == SRR_SIGNALED) { + m_last_ntstatus = wr->StatusRes; + if (wr->StatusRes || + wr->SizeRes != size) + { + std::stringstream err_str; + err_str << "Call WPM(0x" << std::hex << address + << "," << std::dec << size + << ") failed with 0x" + << std::hex << wr->StatusRes + << " (Size Req/Res: " + << std::dec << wr->SizeReq << "/" << (SSIZE_T)wr->SizeRes + << ")"; + throw std::runtime_error(err_str.str()); + } + if (result) + *result = *wr; + return true; + } + return false; +} + +PVOID KInterface::getBuffer() { + if (!m_shmem) + throw std::runtime_error("Call Init() before.."); + return m_shmem; +} + +HANDLE KInterface::getKHandle() { + if (!m_kevent) + throw std::runtime_error("Call Init() before.."); + return m_kevent; +} + +HANDLE KInterface::getUHandle() { + if (!m_uevent) + throw std::runtime_error("Call Init() before.."); + return m_uevent; +} + +UINT32 KInterface::getLastPingValue() { + return m_last_ping_value; +} + +UINT32 KInterface::getLastNtStatus() { + return m_last_ntstatus; +} + +SendRecvReturn KInterface::SendRecvWait(UINT32 type, DWORD timeout) +{ + prepareRequest(getBuffer(), type); + if (!SetEvent(m_kevent)) + return SRR_ERR_KEVENT; + return RecvWait(timeout); +} + +SendRecvReturn KInterface::RecvWait(DWORD timeout) +{ + switch (WaitForSingleObject(m_uevent, timeout)) { + case WAIT_OBJECT_0: + return validateRespone(getBuffer()) != INVALID_REQUEST ? SRR_SIGNALED : SRR_ERR_HEADER; + case WAIT_TIMEOUT: + return SRR_TIMEOUT; + } + return SRR_ERR_UEVENT; +} + +SSIZE_T KScan::KScanSimple(HANDLE targetPID, PVOID start_address, SIZE_T max_scansize, + PVOID scanbuf, SIZE_T scanbuf_size) +{ + ULONG_PTR max_addr; + ULONG_PTR cur_addr = (ULONG_PTR)start_address; + BYTE tmp_rpmbuf[SHMEM_SIZE]; + SIZE_T scan_index, processed, real_size, diff_size; + std::vector<MEMORY_BASIC_INFORMATION> mbis; + KERNEL_READ_REQUEST rr = { 0 }; + + if (max_scansize < scanbuf_size) + return -1; + if (!KInterface::getInstance().Pages(targetPID, mbis, start_address)) + return -1; + + diff_size = (ULONG_PTR)start_address - (ULONG_PTR)mbis.at(0).BaseAddress; + real_size = (mbis.at(0).RegionSize - diff_size > max_scansize ? + max_scansize : (ULONG_PTR)mbis.at(0).RegionSize - diff_size); + max_addr = (ULONG_PTR)start_address + real_size; + + while (cur_addr < max_addr) { + if (!KInterface::getInstance().RPM(targetPID, (PVOID)cur_addr, + tmp_rpmbuf, (sizeof tmp_rpmbuf > real_size ? real_size : sizeof tmp_rpmbuf), &rr)) + { + break; + } + + if (rr.StatusRes || rr.SizeRes < scanbuf_size) + break; + + for (processed = 0, scan_index = 0; processed < rr.SizeRes; ++processed) { + if (tmp_rpmbuf[processed] != *((BYTE*)scanbuf + scan_index)) { + scan_index = 0; + } + else { + scan_index++; + if (scan_index == scanbuf_size) { + return cur_addr + processed - scanbuf_size + 1; + } + } + } + cur_addr += processed; + real_size -= processed; + } + return -1; +} + +SSIZE_T KScan::KBinDiffSimple(HANDLE targetPID, PVOID start_address, + BYTE *curbuf, BYTE *oldbuf, SIZE_T siz, std::vector<std::pair<SIZE_T, SIZE_T>> *diffs) +{ + SSIZE_T scanned, diff_start; + SIZE_T diff_size; + KERNEL_READ_REQUEST rr = { 0 }; + + if (!KInterface::getInstance().RPM(targetPID, start_address, + curbuf, siz, &rr)) + { + scanned = -1; + } + else scanned = rr.SizeRes; + + if (scanned > 0) { + diffs->clear(); + diff_start = -1; + diff_size = 0; + for (SIZE_T i = 0; i < (SIZE_T)scanned; ++i) { + if (curbuf[i] != oldbuf[i]) { + if (diff_start < 0) + diff_start = i; + diff_size++; + } + else if (diff_start >= 0) { + diffs->push_back(std::pair<SIZE_T, SIZE_T> + (diff_start, diff_size)); + diff_start = -1; + diff_size = 0; + } + } + memcpy(oldbuf, curbuf, scanned); + if ((SIZE_T)scanned < siz) + memset(oldbuf + scanned, 0, siz - scanned); + } + + return scanned; +}
\ No newline at end of file diff --git a/KTest/KInterface.h b/KTest/KInterface.h new file mode 100644 index 0000000..a8a7ee2 --- /dev/null +++ b/KTest/KInterface.h @@ -0,0 +1,120 @@ +#pragma once + +#include "Driver.h" + +#include <vector> +#include <Windows.h> + +#define DEFAULT_TIMEOUT 2500 +#define INVALID_NTSTATUS (UINT32)-1 + +typedef enum SendRecvReturn { + SRR_INVALID = 0, SRR_SIGNALED, SRR_TIMEOUT, SRR_ERR_UEVENT, SRR_ERR_KEVENT, SRR_ERR_HEADER +} SendRecvReturn; + +class KInterface +{ +public: + static KInterface& getInstance() + { + static KInterface instance; + return instance; + } + KInterface(); + KInterface(KInterface const&) = delete; + void operator=(KInterface const&) = delete; + + bool Init(); + bool Handshake(); + bool Ping(); + bool Pages(HANDLE targetPID, + std::vector<MEMORY_BASIC_INFORMATION>& dest, + PVOID start_address = NULL); + bool Modules(HANDLE targetPID, + std::vector<MODULE_DATA>& dest); + bool Exit(); + bool RPM(HANDLE targetPID, PVOID address, BYTE *buf, SIZE_T size, + PKERNEL_READ_REQUEST result); + bool WPM(HANDLE targetPID, PVOID address, BYTE *buf, SIZE_T size, + PKERNEL_WRITE_REQUEST result); + + PVOID getBuffer(); + HANDLE getKHandle(); + HANDLE getUHandle(); + UINT32 getLastPingValue(); + UINT32 getLastNtStatus(); + SendRecvReturn RecvWait(DWORD timeout = DEFAULT_TIMEOUT); + +private: + SendRecvReturn SendRecvWait(UINT32 type, DWORD timeout = DEFAULT_TIMEOUT); + + PVOID m_shmem = NULL; + HANDLE m_kevent = NULL, m_uevent = NULL; + + UINT32 m_last_ping_value = 0; + UINT32 m_last_ntstatus = INVALID_NTSTATUS; +}; + +class KMemory +{ +public: + template <class T> + static T Rpm(HANDLE targetPID, PVOID address) { + T buf; + if (!KInterface::getInstance().RPM(targetPID, address, (BYTE*)&buf, sizeof buf, NULL)) + throw std::runtime_error("KMemory RPM failed"); + return buf; + } + template <class T> + static void Wpm(HANDLE targetPID, PVOID address, T *buf) { + if (!KInterface::getInstance().WPM(targetPID, address, (BYTE*)buf, sizeof *buf, NULL)) + throw std::runtime_error("KMemory WPM failed"); + } +}; + +class KMemoryBuf +{ +public: + template <size_t SIZE> + static SSIZE_T Rpm(HANDLE targetPID, PVOID address, BYTE *dest) { + KERNEL_READ_REQUEST rr = { 0 }; + if (!KInterface::getInstance().RPM(targetPID, address, &dest[0], SIZE, &rr)) + return -1; + return rr.SizeRes; + } + template <size_t SIZE> + static SSIZE_T Wpm(HANDLE targetPID, PVOID address, BYTE *dest) { + KERNEL_WRITE_REQUEST wr = { 0 }; + if (!KInterface::getInstance().WPM(targetPID, address, &dest[0], SIZE, &wr)) + return -1; + return wr.SizeRes; + } +}; + +template <SIZE_T SIZE> +struct Diff { + BYTE current_buffer[SIZE]; + BYTE old_buffer[SIZE]; + std::vector<std::pair<SIZE_T, SIZE_T>> diffs; +}; + +class KScan +{ +public: + template <typename T, SIZE_T SIZE> + static SSIZE_T ScanSimple(HANDLE targetPID, PVOID start_address, SIZE_T max_scansize, T(&a)[SIZE]) + { + return KScanSimple(targetPID, start_address, max_scansize, a, sizeof T * SIZE); + } + template <SIZE_T SIZE> + static SSIZE_T BinDiffSimple(HANDLE targetPID, PVOID start_address, Diff<SIZE> *diff) + { + return KBinDiffSimple(targetPID, start_address, diff->current_buffer, + diff->old_buffer, SIZE, &diff->diffs); + } +private: + static SSIZE_T KScanSimple(HANDLE targetPID, PVOID start_address, SIZE_T max_scansize, + PVOID scanbuf, SIZE_T scanbuf_size); + static SSIZE_T KBinDiffSimple(HANDLE targetPid, PVOID start_address, + BYTE *curbuf, BYTE *oldbuf, SIZE_T siz, std::vector<std::pair<SIZE_T, SIZE_T>> *diffs); +};
\ No newline at end of file diff --git a/KTest/KTest.cpp b/KTest/KTest.cpp new file mode 100644 index 0000000..4dad138 --- /dev/null +++ b/KTest/KTest.cpp @@ -0,0 +1,400 @@ +#include "pch.h" +#include "Driver.h" +#include "KInterface.h" + +#include <iostream> +#include <iomanip> +#include <windows.h> + +#pragma comment(lib, "User32.lib") + +#define WHEXOUT std::setfill(L'0') << std::setw(16) << std::hex + +BOOL running = false; +const wchar_t *wName = L"HUNT"; + +typedef struct SSystemGlobalEnvironment +{ + PVOID pDialogSystem; + PVOID p3DEngine; + PVOID pNetwork; + PVOID pNetContext; + PVOID pLobby; + PVOID pScriptSystem; + PVOID pPhysicalWorld; + PVOID pFlowSystem; + PVOID pInput; + PVOID pStatoscope; + PVOID pCryPak; + PVOID pFileChangeMonitor; + PVOID pProfileLogSystem; + PVOID pParticleManager; + PVOID pOpticsManager; + PVOID pFrameProfileSystem; + PVOID pTimer; + PVOID pCryFont; + PVOID pGameFramework; + PVOID pLocalMemoryUsage; + PVOID pEntitySystem; + PVOID pConsole; + PVOID pAudioSystem; + PVOID pSystem; + PVOID pCharacterManager; + PVOID pAISystem; + PVOID pLog; + PVOID pCodeCheckpointMgr; + PVOID pMovieSystem; + PVOID pNameTable; + PVOID pRenderer; + PVOID pAuxGeomRenderer; + PVOID pHardwareMouse; + PVOID pMaterialEffects; + PVOID pJobManager; + PVOID pOverloadSceneManager; + PVOID pFlashUI; + PVOID pUIFramework; + PVOID pServiceNetwork; + PVOID pRemoteCommandManager; + PVOID pDynamicResponseSystem; + PVOID pThreadManager; + PVOID pScaleformHelper; // nullptr when Scaleform support is not enabled + PVOID pSchematyc; + PVOID pSchematyc2; + PVOID pReflection; + + PVOID pLiveCreateManager; + PVOID pLiveCreateHost; + PVOID pMonoRuntime; + UINT32 mMainThreadId; //!< The main thread ID is used in multiple systems so should be stored globally. + UINT32 nMainFrameID; + const char* szCmdLine = ""; //!< Startup command line. + + //! Generic debug string which can be easily updated by any system and output by the debug handler + enum { MAX_DEBUG_STRING_LENGTH = 128 }; + char szDebugStatus[MAX_DEBUG_STRING_LENGTH]; + + //! Used to tell if this is a server/multiplayer instance + bool bServer; + bool bMultiplayer; + bool bHostMigrating; + int bDeepProfiling; + bool bBootProfilerEnabledFrames; + PVOID callbackStartSection; + PVOID callbackEndSection; + ////////////////////////////////////////////////////////////////////////// + + //! Whether we are running unattended, disallows message boxes and other blocking events that require human intervention + bool bUnattendedMode; + //! Whether we are unit testing + bool bTesting; + + bool bNoRandomSeed; +} SSystemGlobalEnvironment; + + + +bool consoleHandler(int signal) { + if (signal == CTRL_C_EVENT) { + if (!running) + exit(EXIT_FAILURE); + running = false; + std::wcout << L"Waiting for graceful shutdown .." << std::endl; + } + return true; +} + +void printBuf(UCHAR *buf, SIZE_T siz, SIZE_T bytesBeforeNewline) { + unsigned int i, j; + const unsigned char colors[] = { 10,11,12,13,14,15 }; + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + + for (i = 0, j = 0; i < siz; ++i) { + if (i % bytesBeforeNewline == 0) { + SetConsoleTextAttribute(hConsole, colors[j++ % (sizeof colors)]); + wprintf(L"\n0x%04X: ", i); + } + wprintf(L"%02X ", buf[i]); + } + wprintf(L"\n"); + SetConsoleTextAttribute(hConsole, 15); +} + +BOOL CALLBACK enumWindowsProc(HWND hWnd, LPARAM lParam) +{ + int length = GetWindowTextLength(hWnd); + TCHAR* buffer; + buffer = new TCHAR[length + 1]; + memset(buffer, 0, (length + 1) * sizeof(TCHAR)); + GetWindowText(hWnd, buffer, length + 1); + if (!wcscmp(buffer, wName)) + *(HWND *)lParam = hWnd; + delete[] buffer; + return TRUE; +} + +int wmain(int argc, wchar_t **argv) +{ + HANDLE targetPID = 0; + PVOID buf; + HANDLE kevent; + HANDLE uevent; + + KInterface &ki = KInterface::getInstance(); + std::vector<MEMORY_BASIC_INFORMATION> pages; + std::vector<MODULE_DATA> modules; + + if (argc > 1 && !wcscmp(argv[1], L"test")) { + return 0; + } + + if (argc > 1 && !wcscmp(argv[1], L"wnd")) { + if (argc < 3) { + std::wcout << L"Window title required!" << std::endl; + return 1; + } + wName = argv[2]; + std::wcout << L"Waiting for window title: '" << wName << L"'" << std::endl; + + HWND targetHWND = NULL; + while (1) { + if (!EnumWindows(enumWindowsProc, (LPARAM)&targetHWND)) { + return 1; + } + if (targetHWND) { + std::wcout << L"Found window '" << wName << L"' with Handle 0x" + << std::hex << targetHWND << std::endl; + break; + } + Sleep(1000); + } + GetWindowThreadProcessId(targetHWND, (LPDWORD)&targetPID); + } + + SetConsoleCtrlHandler((PHANDLER_ROUTINE)consoleHandler, TRUE); + + if (!ki.Init()) { + std::wcout << L"Kernel Interface Init() failed" << std::endl; + return 1; + } + + try { + buf = ki.getBuffer(); + kevent = ki.getKHandle(); + uevent = ki.getUHandle(); + } + catch (std::runtime_error& err) { + std::wcout << err.what() << std::endl; + return 1; + } + + std::wcout << L"Buffer.: " << buf << std::endl; + std::wcout << L"KHandle: " << kevent << std::endl; + std::wcout << L"UHandle: " << uevent << std::endl; + + if (!ki.Handshake()) { + std::wcout << L"Kernel Interface Handshake() failed" << std::endl; + return 1; + } + if (targetPID) { + if (!ki.Modules(targetPID, modules)) + std::wcout << L"Kernel Interface Modules() failed with 0x" + << std::hex << ki.getLastNtStatus() << std::endl; + else std::wcout << L"Got " << std::dec << modules.size() << L" modules for pid 0x" + << std::hex << targetPID << std::endl; + if (!ki.Pages(targetPID, pages)) + std::wcout << L"Kernel Interface Pages() failed with 0x" + << std::hex << ki.getLastNtStatus() << std::endl; + else std::wcout << L"Got " << std::dec << pages.size() << L" mapped pages for pid 0x" + << std::hex << targetPID << std::endl; + } + + running = TRUE; + do { + if (ki.RecvWait() == SRR_TIMEOUT) { + std::wcout << L"Ping -> "; + if (!ki.Ping()) { + std::wcout << L"Got no valid PONG, abort!" << std::endl; + running = FALSE; + } + else std::wcout << L"PONG!" << std::endl; + } + + if (!running) + break; + + try { + if (targetPID) { + for (MODULE_DATA& md : modules) { + if (!strncmp(md.BaseDllName, "CrySystem.dll", + sizeof md.BaseDllName)) + { + std::wcout << L"CrySystem.dll......: 0x" << WHEXOUT << md.DllBase << std::endl; + UINT64 g_pEnv = KMemory::Rpm<UINT64>(targetPID, + (PVOID)((UINT64)md.DllBase + 0xA37708)); + + std::wcout << L"g_pEnv.............: 0x" << WHEXOUT << g_pEnv << std::endl; + } + else + if (!strncmp(md.BaseDllName, "CryEntitySystem.dll", + sizeof md.BaseDllName)) + { + std::wcout << L"CryEntitySystem.dll: 0x" << std::hex << md.DllBase << std::endl; +#if 1 + /* Found: void CEntitySystem::LoadInternalState(IDataReadStream& reader) */ + UINT64 g_pEnv = KMemory::Rpm<UINT64>(targetPID, + (PVOID)((UINT64)md.DllBase + 0x28C400)); + + std::wcout << L"g_pEnv.............: 0x" << WHEXOUT << g_pEnv << std::endl; +#if 1 + BYTE tmp[sizeof SSystemGlobalEnvironment * 2] = { 0 }; + SSIZE_T siz = KMemoryBuf::Rpm<sizeof tmp>(targetPID, (PVOID)(g_pEnv), tmp); + + SSystemGlobalEnvironment *gEnv = (SSystemGlobalEnvironment *)&tmp[0]; + std::wcout << std::hex + << gEnv->p3DEngine << ", " + << gEnv->pEntitySystem << ", " + << gEnv->bMultiplayer << ", " + << gEnv->mMainThreadId << ", " + << gEnv->nMainFrameID << ", " + << gEnv->szDebugStatus << ", " + << gEnv->pMonoRuntime << ", " + << gEnv->callbackStartSection << ", " + << gEnv->callbackEndSection << ", " + << gEnv->bUnattendedMode << ", " + << gEnv->bTesting << ", " + << gEnv->bNoRandomSeed << ", " + << gEnv->bDeepProfiling << ", " + << std::endl; + + /* Found: void CEntitySystem::LoadInternalState(IDataReadStream& reader) + * search for String "ExistingEntity: '%s' '%s'" + */ + UINT64 m_EntityArray = KMemory::Rpm<UINT64>(targetPID, + (PVOID)((UINT64)gEnv->pEntitySystem + 0x40078)); + //m_EntityArray += 0x40078; + std::wcout << WHEXOUT + << m_EntityArray + << std::endl; + + USHORT nops; + nops = KMemory::Rpm<USHORT>(targetPID, + (PVOID)((UINT64)md.DllBase + 0x12C3C7)); + std::wcout << std::hex << "+++ " << nops << std::endl; + nops = 0x9090; + KMemory::Wpm<USHORT>(targetPID, + (PVOID)((UINT64)md.DllBase + 0x12C3C7), &nops); +#if 0 + UINT64 tmp2[1024]; + SSIZE_T siz2 = KMemoryBuf::Rpm<sizeof tmp2>(targetPID, (PVOID)(m_EntityArray), (PBYTE)tmp2); + SIZE_T i = 0; + for (UINT64 val : tmp2) { + if (val) + std::wcout << WHEXOUT << val << ", "; + if (++i % 16 == 0) + std::wcout << std::endl; + } + /* + if (siz2 > 0) + printBuf(tmp2, sizeof tmp2, 64); + */ +#endif +#endif +#if 0 + SSIZE_T siz3; + static Diff<65535> diff = { 0 }; + siz3 = KScan::BinDiffSimple(targetPID, (PVOID)(m_EntityArray), &diff); + if (siz3 > 0) { + std::wcout << L"Got " << std::dec << diff.diffs.size() << L" diffs" << std::endl; + for (auto& e : diff.diffs) { + std::wcout << std::dec << L"0x" + << std::hex << (PVOID)(/*(ULONG_PTR)(m_EntityArray)+*/e.first) + << " - " << std::hex << e.second + << L": "; + printBuf((UCHAR *)((ULONG_PTR)(diff.current_buffer) + e.first), e.second, e.second); + } + } +#endif +#if 0 +#if 1 + //UCHAR scan[1024] = { 0 }; + UCHAR scan[] = "anti_alles"; + SSIZE_T found = KScan::ScanSimple<UCHAR, sizeof scan>(targetPID, + (PVOID)(m_EntityArray), 65535, scan); +#else + SSIZE_T found = (SSIZE_T)(pIEntitySystem)+8192; +#endif + if (found >= 0) { + std::wcout << "FOUND: 0x" << std::hex << (PVOID)found << std::endl; + UCHAR tmp[4096] = { 0 }; + SSIZE_T siz = KMemoryBuf::Rpm<UCHAR, sizeof tmp>(targetPID, (PVOID)found, tmp); + if (siz > 0) { + printBuf(tmp, sizeof tmp, 64); +#if 0 + UINT64 i; + for (i = 0; i < sizeof tmp; i += 8) { + UINT64 value = *(UINT64 *)&tmp[i]; + if (value) + printf("0x%p ", (PVOID)value); + } + printf("\nGot %llu entities ..\n", i); +#endif + } + } +#endif +#endif + } +#if 0 + else if (!strncmp(md.BaseDllName, "CryRenderD3D11.dll", + sizeof md.BaseDllName)) + { + UINT32 displayWidth = KMemory::Rpm<UINT32>(targetPID, + (PVOID)((ULONGLONG)md.DllBase + /* 0x19F0FE */ 0x5EA870)); + UINT32 displayHeight = KMemory::Rpm<UINT32>(targetPID, + (PVOID)((ULONGLONG)md.DllBase + /* 0x19F0F0 */ 0x5EA9DC)); + std::wcout << L"Display.........: " << std::dec << displayWidth + << " x " << displayHeight << std::endl; + } +#endif +#if 0 + else if (!strncmp(md.BaseDllName, "ntdll.dll", + sizeof md.BaseDllName)) + { + UCHAR tmp[8192] = { 0 }; + SSIZE_T siz = KMemoryBuf::Rpm<UCHAR, sizeof tmp>(targetPID, (PVOID)((ULONGLONG)md.DllBase), tmp); + /* + if (siz > 0) + printBuf(tmp, sizeof tmp, 64); + + UCHAR scan[] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }; + SSIZE_T found = KScan::ScanSimple<UCHAR, sizeof scan>(targetPID, + (PVOID)((ULONGLONG)md.DllBase), sizeof tmp, scan); + std::wcout << "FOUND: 0x" << std::hex << (found - (ULONGLONG)md.DllBase) << std::endl; + */ + static Diff<10> diff = { 0 }; + siz = KScan::BinDiffSimple(targetPID, (PVOID)((ULONGLONG)md.DllBase), &diff); + if (siz > 0) { + std::wcout << L"Got " << std::dec << diff.diffs.size() << L" diffs" << std::endl; + for (auto& e : diff.diffs) { + printBuf((UCHAR *)((ULONGLONG)md.DllBase + e.first), e.second, e.second); + /* + std::wcout << std::dec << L" addr: " << e.first + << std::endl << L" size: " << e.second + << std::endl; + */ + } + } + } +#endif + } + } + } + catch (std::runtime_error& err) { + std::wcout << err.what() << std::endl; + } + } while (running); + + std::wcout << L"Driver shutdown .." << std::endl; + ki.Exit(); + + return 0; +}
\ No newline at end of file diff --git a/KTest/KTest.vcxproj b/KTest/KTest.vcxproj new file mode 100644 index 0000000..952a888 --- /dev/null +++ b/KTest/KTest.vcxproj @@ -0,0 +1,193 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.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> + </ItemGroup> + <PropertyGroup Label="Globals"> + <VCProjectVersion>15.0</VCProjectVersion> + <ProjectGuid>{8661069D-CE09-4A70-8C75-8F33E77732E6}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>KTest</RootNamespace> + <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + <SpectreMitigation>false</SpectreMitigation> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <SpectreMitigation>false</SpectreMitigation> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + <SpectreMitigation>false</SpectreMitigation> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <SpectreMitigation>false</SpectreMitigation> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + <ExceptionHandling>SyncCThrow</ExceptionHandling> + <BufferSecurityCheck>true</BufferSecurityCheck> + <AdditionalIncludeDirectories>$(SolutionDir)include</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>$(VCToolsInstallDir)lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <ExceptionHandling>SyncCThrow</ExceptionHandling> + <BufferSecurityCheck>false</BufferSecurityCheck> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <ExceptionHandling>Sync</ExceptionHandling> + <BufferSecurityCheck>false</BufferSecurityCheck> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <ExceptionHandling>Sync</ExceptionHandling> + <BufferSecurityCheck>false</BufferSecurityCheck> + <AdditionalIncludeDirectories>$(SolutionDir)include</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalLibraryDirectories>$(VCToolsInstallDir)lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="..\include\Driver.h" /> + <ClInclude Include="KInterface.h" /> + <ClInclude Include="pch.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="KInterface.cpp" /> + <ClCompile Include="KTest.cpp" /> + <ClCompile Include="pch.cpp"> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> + </ClCompile> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/KTest/KTest.vcxproj.filters b/KTest/KTest.vcxproj.filters new file mode 100644 index 0000000..80c6481 --- /dev/null +++ b/KTest/KTest.vcxproj.filters @@ -0,0 +1,39 @@ +<?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> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="pch.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="KInterface.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\Driver.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="pch.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="KTest.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="KInterface.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/KTest/pch.cpp b/KTest/pch.cpp new file mode 100644 index 0000000..3a3d12b --- /dev/null +++ b/KTest/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: source file corresponding to pre-compiled header; necessary for compilation to succeed + +#include "pch.h" + +// In general, ignore this file, but keep it around if you are using pre-compiled headers. diff --git a/KTest/pch.h b/KTest/pch.h new file mode 100644 index 0000000..b04e71e --- /dev/null +++ b/KTest/pch.h @@ -0,0 +1,14 @@ +// Tips for Getting Started: +// 1. Use the Solution Explorer window to add/manage files +// 2. Use the Team Explorer window to connect to source control +// 3. Use the Output window to see build output and other messages +// 4. Use the Error List window to view errors +// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project +// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file + +#ifndef PCH_H +#define PCH_H + +// TODO: add headers that you want to pre-compile here + +#endif //PCH_H diff --git a/PastDSE-Manual-Map-Debug.bat b/PastDSE-Manual-Map-Debug.bat new file mode 100644 index 0000000..316075b --- /dev/null +++ b/PastDSE-Manual-Map-Debug.bat @@ -0,0 +1,13 @@ +@echo off + +set PDSECTRL="%~dp0\..\PastDSE\x64\Debug\PastDSECtrl.exe" +if not exist %PDSECTRL% set PDSECTRL="%~dp0\..\PastDSE\bin\x64\Debug\PastDSECtrl.exe" + +call %~dp0\..\PastDSE\driver-start.bat +%PDSECTRL% %~dp0\x64\Debug\KMemDriver.sys +call %~dp0\..\PastDSE\driver-stop.bat +REM fsutil usn deleteJournal /D C: + +REM set /p wndtitle="Enter Window Title: " +REM IF [%wndtitle%] == [] (%~dp0\x64\Release\KTest.exe) ELSE (%~dp0\x64\Release\KTest.exe wnd "%wndtitle%") +timeout /t 3
\ No newline at end of file diff --git a/PastDSE-Manual-Map-Release.bat b/PastDSE-Manual-Map-Release.bat new file mode 100644 index 0000000..2276725 --- /dev/null +++ b/PastDSE-Manual-Map-Release.bat @@ -0,0 +1,13 @@ +@echo off + +set PDSECTRL="%~dp0\..\PastDSE\x64\Debug\PastDSECtrl.exe" +if not exist %PDSECTRL% set PDSECTRL="%~dp0\..\PastDSE\bin\x64\Debug\PastDSECtrl.exe" + +call %~dp0\..\PastDSE\driver-start.bat +%PDSECTRL% %~dp0\x64\Release\KMemDriver.sys +call %~dp0\..\PastDSE\driver-stop.bat +REM fsutil usn deleteJournal /D C: + +REM set /p wndtitle="Enter Window Title: " +REM IF [%wndtitle%] == [] (%~dp0\x64\Release\KTest.exe) ELSE (%~dp0\x64\Release\KTest.exe wnd "%wndtitle%") +timeout /t 3
\ No newline at end of file diff --git a/include/Driver.h b/include/Driver.h new file mode 100644 index 0000000..6a41fe2 --- /dev/null +++ b/include/Driver.h @@ -0,0 +1,131 @@ +#pragma once + +#ifdef KERNEL_MODULE +#include "Native.h" +#else +#include <windows.h> +#endif + +#define HDR_MAGIC 0xDEADC0DE +#define SHMEM_ADDR 0x60000000 +#define SHMEM_SIZE 8192*8*2 +#define INVALID_REQUEST (UINT32)-1 + +#define MEM_HANDSHAKE 0x800 +#define MEM_PING 0x801 +#define MEM_MODULES 0x802 +#define MEM_PAGES 0x803 +#define MEM_RPM 0x804 +#define MEM_WPM 0x805 +#define MEM_EXIT 0x806 + +typedef struct _KERNEL_HEADER +{ + UINT32 magic; + UINT32 type; +} KERNEL_HEADER, *PKERNEL_HEADER; + +typedef struct _KERNEL_HANDSHAKE +{ + KERNEL_HEADER hdr; + HANDLE kevent; + HANDLE uevent; +} KERNEL_HANDSHAKE, *PKERNEL_HANDSHAKE; + +typedef struct _KERNEL_PING +{ + KERNEL_HEADER hdr; + UINT32 rnd_user; + UINT32 rnd_kern; +} KERNEL_PING, *PKERNEL_PING; + +typedef struct _KERNEL_PAGE +{ + KERNEL_HEADER hdr; + HANDLE ProcessId; + PVOID StartAddress; + + NTSTATUS StatusRes; + SIZE_T pages; + MEMORY_BASIC_INFORMATION pages_start; +} KERNEL_PAGE, *PKERNEL_PAGE; + +typedef struct _MODULE_DATA +{ + PVOID DllBase; + ULONG SizeOfImage; + CHAR BaseDllName[64]; +} MODULE_DATA, *PMODULE_DATA; + +typedef struct _KERNEL_MODULES +{ + KERNEL_HEADER hdr; + HANDLE ProcessId; + SIZE_T StartIndex; + + NTSTATUS StatusRes; + SIZE_T modules; + MODULE_DATA modules_start; +} KERNEL_MODULES, *PKERNEL_MODULES; + +typedef struct _KERNEL_EXIT +{ + KERNEL_HEADER hdr; +} KERNEL_EXIT, *PKERNEL_EXIT; + +typedef struct _KERNEL_READ_REQUEST +{ + KERNEL_HEADER hdr; + HANDLE ProcessId; + PVOID Address; + SIZE_T SizeReq; + + NTSTATUS StatusRes; + SIZE_T SizeRes; +} KERNEL_READ_REQUEST, *PKERNEL_READ_REQUEST; + +typedef struct _KERNEL_WRITE_REQUEST +{ + KERNEL_HEADER hdr; + HANDLE ProcessId; + PVOID Address; + SIZE_T SizeReq; + + NTSTATUS StatusRes; + SIZE_T SizeRes; +} KERNEL_WRITE_REQUEST, *PKERNEL_WRITE_REQUEST; + + +#ifndef KERNEL_MODULE +static inline VOID prepareRequest(PVOID buf, UINT32 type) +{ + PKERNEL_HEADER hdr = (PKERNEL_HEADER)buf; + hdr->magic = HDR_MAGIC; + hdr->type = type; +} +#endif + +static inline UINT32 +#ifndef KERNEL_MODULE +validateRespone +#else +validateRequest +#endif +(PVOID buf) +{ + PKERNEL_HEADER hdr = (PKERNEL_HEADER)buf; + if (hdr->magic != HDR_MAGIC) + return INVALID_REQUEST; + switch (hdr->type) { + case MEM_HANDSHAKE: + case MEM_PING: + case MEM_PAGES: + case MEM_MODULES: + case MEM_RPM: + case MEM_WPM: + case MEM_EXIT: + return hdr->type; + default: + return INVALID_REQUEST; + } +}
\ No newline at end of file |