using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace test_cs
{
public static class Driver
{
private static SafeFileHandle Handle = null;
private static string SymLink = "\\\\.\\DRVTEST";
private static string SvcName = "DRVTEST";
private static uint ReadMemCtlCode = Native.CTL_CODE(0x00008008, 0x0800, 0, 3);
public static Native.NTSTATUS EnsureLoaded(string path = "")
{
if (Driver.Handle != null && Driver.Handle.IsInvalid == false)
{
return Native.NTSTATUS.Success;
}
Driver.Handle = Native.CreateFile(Driver.SymLink,FileAccess.ReadWrite,FileShare.ReadWrite,
IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
if (Driver.Handle == null || Driver.Handle.IsInvalid)
{
return Driver.Reload(path);
}
return Native.NTSTATUS.Success;
}
public static Native.NTSTATUS Unload()
{
if (Driver.Handle != null && Driver.Handle.IsInvalid == false)
{
Driver.Handle.Close();
Driver.Handle = null;
}
return Driver.UnloadDriver(Driver.SvcName);
}
struct COPY_MEM
{
public Int64 localbuf;
public Int64 targetPtr;
public Int64 size;
public uint pid;
public byte write;
};
public static Native.NTSTATUS ReadMemory(int pid, Int64 addr, Int64 size, object buffer)
{
if (Driver.Handle == null || Driver.Handle.IsInvalid)
{
return Native.NTSTATUS.DeviceDoesNotExist;
}
var info = new COPY_MEM();
var pinned = GCHandle.Alloc(buffer, GCHandleType.Pinned);
info.pid = (uint)pid;
info.size = size;
info.write = 0;
info.localbuf = pinned.AddrOfPinnedObject().ToInt64();
info.targetPtr = addr;
int bytes = 0;
if (!Native.DeviceIoControl(Driver.Handle, ReadMemCtlCode, info, (uint)Marshal.SizeOf(info), null, 0, ref bytes, IntPtr.Zero))
{
return (Native.NTSTATUS)Marshal.GetLastWin32Error();
}
return Native.NTSTATUS.Success;
}
private static Native.NTSTATUS LoadDriver(string svcName, string path)
{
string regPath = "CurrentControlSet\\Services\\" + svcName;
RegistryKey svcKey = Registry.LocalMachine.CreateSubKey("SYSTEM\\" + regPath);
svcKey.SetValue("ImagePath", "\\??\\" + path);
svcKey.SetValue("Type", 1);
Native.UNICODE_STRING uRegPath = new Native.UNICODE_STRING();
bool enabled;
var status = Native.RtlAdjustPrivilege(Native.SeLoadDriverPrivilege, true,
Native.ADJUST_PRIVILEGE_TYPE.AdjustCurrentProcess, out enabled);
Native.RtlInitUnicodeString(ref uRegPath, "\\Registry\\Machine\\SYSTEM\\" + regPath);
return Native.NtLoadDriver(ref uRegPath);
}
private static Native.NTSTATUS UnloadDriver(string svcName)
{
string regPath = "CurrentControlSet\\Services\\" + svcName;
Native.UNICODE_STRING uRegPath = new Native.UNICODE_STRING();
bool enabled;
Native.NTSTATUS status = Native.RtlAdjustPrivilege(Native.SeLoadDriverPrivilege, true,
Native.ADJUST_PRIVILEGE_TYPE.AdjustCurrentProcess, out enabled);
Native.RtlInitUnicodeString(ref uRegPath, "\\Registry\\Machine\\SYSTEM\\" + regPath);
status = Native.NtUnloadDriver(ref uRegPath);
Registry.LocalMachine.DeleteSubKeyTree("SYSTEM\\" + regPath, false);
return status;
}
private static Native.NTSTATUS Reload(string path)
{
Driver.Unload();
if (String.IsNullOrWhiteSpace(path))
{
// TODO: Guess the driver file path
return Native.NTSTATUS.ObjectPathNotFound;
}
Native.NTSTATUS status = Driver.LoadDriver(Driver.SvcName, path);
if( status >= 0 )
{
Driver.Handle = Native.CreateFile(Driver.SymLink, FileAccess.ReadWrite, FileShare.ReadWrite,
IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
if (Driver.Handle == null || Driver.Handle.IsInvalid)
{
return (Native.NTSTATUS)Marshal.GetLastWin32Error();
}
}
return Native.NTSTATUS.Success;
}
}
}