device io complete

This commit is contained in:
nganhkhoa 2020-02-27 03:28:26 +07:00
parent 87a61a625a
commit a40950812b
3 changed files with 240 additions and 67 deletions

View File

@ -3,9 +3,9 @@
#include <ntdef.h> #include <ntdef.h>
#include <ntstrsafe.h> #include <ntstrsafe.h>
#include "sioctl.h"
#include "Driver.h" #include "Driver.h"
#include "simplewsk.h" #include "sioctl.h"
// #include "simplewsk.h"
extern "C" DRIVER_INITIALIZE DriverEntry; extern "C" DRIVER_INITIALIZE DriverEntry;
extern "C" DRIVER_UNLOAD UnloadRoutine; extern "C" DRIVER_UNLOAD UnloadRoutine;
@ -24,6 +24,11 @@ extern "C" DRIVER_DISPATCH DriverControl;
#define CHUNK_SIZE 16 // 64 bit #define CHUNK_SIZE 16 // 64 bit
// #define PAGE_SIZE 4096 // 4KB // #define PAGE_SIZE 4096 // 4KB
// some globals
PVOID ntosbase;
PVOID systemEprocess;
PVOID processHead;
// offset to get from PDB file // offset to get from PDB file
ULONG64 eprocessNameOffset = 0; ULONG64 eprocessNameOffset = 0;
ULONG64 eprocessLinkOffset = 0; ULONG64 eprocessLinkOffset = 0;
@ -36,6 +41,7 @@ ULONG64 firstVaOffset = 0;
ULONG64 lastVaOffset = 0; ULONG64 lastVaOffset = 0;
ULONG64 largePageTableOffset = 0; ULONG64 largePageTableOffset = 0;
ULONG64 largePageSizeOffset = 0; ULONG64 largePageSizeOffset = 0;
ULONG64 poolChunkSize = 0;
NTSTATUS NTSTATUS
DriverCreateClose(PDEVICE_OBJECT /* DriverObject */, PIRP Irp) { DriverCreateClose(PDEVICE_OBJECT /* DriverObject */, PIRP Irp) {
@ -58,6 +64,11 @@ DriverControl(PDEVICE_OBJECT /* DriverObject */, PIRP Irp) {
ULONG controlCode; ULONG controlCode;
// PCHAR inBuf; // PCHAR inBuf;
// PCHAR outBuf; // PCHAR outBuf;
PINPUT_DATA inputData = nullptr;
POUTPUT_DATA outputData = nullptr;
POFFSET_VALUE offsetValues = nullptr;
PDEREF_ADDR derefAddr = nullptr;
PSCAN_RANGE scanRange = nullptr;
PAGED_CODE(); PAGED_CODE();
@ -74,6 +85,60 @@ DriverControl(PDEVICE_OBJECT /* DriverObject */, PIRP Irp) {
DbgPrint("[NAK] :: [ ] Control Code : %lu\n", controlCode); DbgPrint("[NAK] :: [ ] Control Code : %lu\n", controlCode);
switch (controlCode) {
case IOCTL_SETUP_OFFSETS:
DbgPrint("[NAK] :: [ ] Setup offsets\n");
inputData = (PINPUT_DATA)(Irp->AssociatedIrp.SystemBuffer);
offsetValues = &(inputData->offsetValues);
eprocessNameOffset = offsetValues->eprocessNameOffset;
eprocessLinkOffset = offsetValues->eprocessLinkOffset;
listBLinkOffset = offsetValues->listBLinkOffset;
processHeadOffset = offsetValues->processHeadOffset;
miStateOffset = offsetValues->miStateOffset;
hardwareOffset = offsetValues->hardwareOffset;
systemNodeOffset = offsetValues->systemNodeOffset;
firstVaOffset = offsetValues->firstVaOffset;
lastVaOffset = offsetValues->lastVaOffset;
largePageTableOffset = offsetValues->largePageTableOffset;
largePageSizeOffset = offsetValues->largePageSizeOffset;
poolChunkSize = offsetValues->poolChunkSize;
setup();
break;
case GET_KERNEL_BASE:
DbgPrint("[NAK] :: [ ] Get kernel base\n");
outputData = (POUTPUT_DATA)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority | MdlMappingNoExecute);
// TODO: check for safety outputData address null
outputData->ulong64Value = (ULONG64)ntosbase;
Irp->IoStatus.Information = sizeof(ULONG64);
break;
case SCAN_PS_ACTIVE_HEAD:
DbgPrint("[NAK] :: [ ] Scan ps active head\n");
scan_ps_active_head();
break;
case SCAN_POOL:
DbgPrint("[NAK] :: [ ] Scan pool\n");
inputData = (PINPUT_DATA)(Irp->AssociatedIrp.SystemBuffer);
scanRange = &(inputData->scanRange);
DbgPrint("[NAK] :: Range: %llx - %llx", scanRange->start, scanRange->end);
scanNormalPool(scanRange->start, scanRange->end);
break;
case SCAN_POOL_REMOTE:
inputData = (PINPUT_DATA)(Irp->AssociatedIrp.SystemBuffer);
outputData = (POUTPUT_DATA)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority | MdlMappingNoExecute);
scanRange = &(inputData->scanRange);
(outputData->poolChunk).addr = (ULONG64)scanRemote(scanRange->start, scanRange->end);
break;
case DEREFERENCE_ADDRESS:
DbgPrint("[NAK] :: [ ] Deref address\n");
inputData = (PINPUT_DATA)(Irp->AssociatedIrp.SystemBuffer);
derefAddr = &(inputData->derefAddr);
outputData = (POUTPUT_DATA)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority | MdlMappingNoExecute);
DbgPrint("[NAK] :: [ ] Deref %llu bytes from %llx\n", derefAddr->size, derefAddr->addr);
RtlCopyBytes((PVOID)outputData, (PVOID)derefAddr->addr, (SIZE_T)derefAddr->size);
break;
default:
break;
}
Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Status = ntStatus;
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
@ -92,6 +157,8 @@ DriverEntry(
UNICODE_STRING ntWin32NameString; UNICODE_STRING ntWin32NameString;
PDEVICE_OBJECT deviceObject = nullptr; PDEVICE_OBJECT deviceObject = nullptr;
PAGED_CODE();
RtlInitUnicodeString(&ntUnicodeString, NT_DEVICE_NAME); RtlInitUnicodeString(&ntUnicodeString, NT_DEVICE_NAME);
returnStatus = IoCreateDevice( returnStatus = IoCreateDevice(
DriverObject, // Our Driver Object DriverObject, // Our Driver Object
@ -118,7 +185,55 @@ DriverEntry(
IoDeleteDevice(deviceObject); IoDeleteDevice(deviceObject);
} }
DbgPrint("[NAK] :: [+] Setup completed, GO GO GO !!!!\n"); systemEprocess = IoGetCurrentProcess();
DbgPrint("[NAK] :: [+] Setup completed, waiting for command on DeviceIo\n");
return returnStatus;
}
VOID
setup() {
PAGED_CODE();
// TODO: Exception?????
PVOID eprocess = systemEprocess;
DbgPrint("[NAK] :: [ ] System eprocess : 0x%p, [%15s]\n",
eprocess, (char*)((ULONG64)eprocess + eprocessNameOffset));
processHead = (PVOID)(*(ULONG64*)((ULONG64)eprocess + eprocessLinkOffset + listBLinkOffset));
DbgPrint("[NAK] :: [ ] PsActiveProcessHead : 0x%p\n", processHead);
ntosbase = (PVOID)((ULONG64)processHead - processHeadOffset);
DbgPrint("[NAK] :: [ ] ntoskrnl.exe : 0x%p\n", ntosbase);
// TODO: Check if ntosbase is a PE, and the name is ntoskrnl.exe
// https://stackoverflow.com/a/4316804
// https://stackoverflow.com/a/47898643
// https://github.com/Reetus/RazorRE/blob/42f441093bd85443b39fcff5d2a02069b524b114/Crypt/Misc.cpp#L63
// if (ntosbase->e_magic == IMAGE_DOS_SIGNATURE) {
// DbgPrint("[NAK] :: [ ] DOS Signature (MZ) Matched \n");
// const PIMAGE_NT_HEADERS32 peHeader = (PIMAGE_NT_HEADERS32) ((unsigned char*)ntosbase+ntosbase->e_lfanew);
// if(peHeader->Signature == IMAGE_NT_SIGNATURE) {
// DbgPrint("[NAK] :: [ ] PE Signature (PE) Matched \n");
// // yeah we really got ntoskrnl.exe base
// }
// }
}
VOID
scan_ps_active_head() {
PVOID eprocess = (PVOID)((ULONG64)processHead - eprocessLinkOffset);
DbgPrint("[NAK] :: [ ] Scan the PsActiveProcessHead linked-list\n");
while (*(ULONG64*)((ULONG64)eprocess + eprocessLinkOffset) != (ULONG64)processHead) {
eprocess = (PVOID)(*(ULONG64*)((ULONG64)eprocess + eprocessLinkOffset) - eprocessLinkOffset);
DbgPrint("[NAK] :: [ ] eprocess : 0x%p, [%15s]\n",
eprocess, (char*)((ULONG64)eprocess + eprocessNameOffset));
}
}
NTSTATUS
routine() {
PAGED_CODE();
NTSTATUS returnStatus = STATUS_SUCCESS;
OSVERSIONINFOW windowsVersionInfo; OSVERSIONINFOW windowsVersionInfo;
RtlGetVersion(&windowsVersionInfo); RtlGetVersion(&windowsVersionInfo);
@ -150,17 +265,17 @@ DriverEntry(
else if (windowsVersionInfo.dwBuildNumber >= 19536) { else if (windowsVersionInfo.dwBuildNumber >= 19536) {
DbgPrint("[NAK] :: [ ] Detected windows : 2020 Fast Ring\n"); DbgPrint("[NAK] :: [ ] Detected windows : 2020 Fast Ring\n");
windowsVersionByPool = WINDOWS_2020_FASTRING; windowsVersionByPool = WINDOWS_2020_FASTRING;
eprocessNameOffset = 0x5a8; // eprocessNameOffset = 0x5a8;
eprocessLinkOffset = 0x448; // eprocessLinkOffset = 0x448;
listBLinkOffset = 0x8; // listBLinkOffset = 0x8;
processHeadOffset = 0xc1f960; // processHeadOffset = 0xc1f960;
miStateOffset = 0xc4f040; // miStateOffset = 0xc4f040;
hardwareOffset = 0x1580; // hardwareOffset = 0x1580;
systemNodeOffset = 0x20; // systemNodeOffset = 0x20;
firstVaOffset = 0x60; // firstVaOffset = 0x60;
lastVaOffset = 0x68; // lastVaOffset = 0x68;
largePageTableOffset = 0xc1a740; // largePageTableOffset = 0xc1a740;
largePageSizeOffset = 0xc1a738; // largePageSizeOffset = 0xc1a738;
} }
if (windowsVersionByPool == WINDOWS_NOT_SUPPORTED) { if (windowsVersionByPool == WINDOWS_NOT_SUPPORTED) {
@ -192,35 +307,6 @@ DriverEntry(
* *
**/ **/
// TODO: Exception?????
PVOID eprocess = (PVOID)IoGetCurrentProcess();
DbgPrint("[NAK] :: [ ] System eprocess : 0x%p, [%15s]\n",
eprocess, (char*)((ULONG64)eprocess + eprocessNameOffset));
PVOID processHead = (PVOID)(*(ULONG64*)((ULONG64)eprocess + eprocessLinkOffset + listBLinkOffset));
DbgPrint("[NAK] :: [ ] PsActiveProcessHead : 0x%p\n", processHead);
PVOID ntosbase = (PVOID)((ULONG64)processHead - processHeadOffset);
DbgPrint("[NAK] :: [ ] ntoskrnl.exe : 0x%p\n", ntosbase);
DbgPrint("[NAK] :: [ ] Scan the PsActiveProcessHead linked-list\n");
while (*(ULONG64*)((ULONG64)eprocess + eprocessLinkOffset) != (ULONG64)processHead) {
eprocess = (PVOID)(*(ULONG64*)((ULONG64)eprocess + eprocessLinkOffset) - eprocessLinkOffset);
DbgPrint("[NAK] :: [ ] eprocess : 0x%p, [%15s]\n",
eprocess, (char*)((ULONG64)eprocess + eprocessNameOffset));
}
// TODO: Check if ntosbase is a PE, and the name is ntoskrnl.exe
// https://stackoverflow.com/a/4316804
// https://stackoverflow.com/a/47898643
// https://github.com/Reetus/RazorRE/blob/42f441093bd85443b39fcff5d2a02069b524b114/Crypt/Misc.cpp#L63
// if (ntosbase->e_magic == IMAGE_DOS_SIGNATURE) {
// DbgPrint("[NAK] :: [ ] DOS Signature (MZ) Matched \n");
// const PIMAGE_NT_HEADERS32 peHeader = (PIMAGE_NT_HEADERS32) ((unsigned char*)ntosbase+ntosbase->e_lfanew);
// if(peHeader->Signature == IMAGE_NT_SIGNATURE) {
// DbgPrint("[NAK] :: [ ] PE Signature (PE) Matched \n");
// // yeah we really got ntoskrnl.exe base
// }
// }
/** /**
* In Windows 10 Insider Preview Feb 2020, the global debug is MiState, try this in windbg and see * In Windows 10 Insider Preview Feb 2020, the global debug is MiState, try this in windbg and see
* `x nt!MiState` to get address of MiState * `x nt!MiState` to get address of MiState
@ -292,6 +378,7 @@ VOID
UnloadRoutine(_In_ PDRIVER_OBJECT DriverObject) { UnloadRoutine(_In_ PDRIVER_OBJECT DriverObject) {
PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject; PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
UNICODE_STRING uniWin32NameString; UNICODE_STRING uniWin32NameString;
PAGED_CODE();
RtlInitUnicodeString(&uniWin32NameString, DOS_DEVICE_NAME); RtlInitUnicodeString(&uniWin32NameString, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&uniWin32NameString); IoDeleteSymbolicLink(&uniWin32NameString);
@ -385,7 +472,6 @@ scanNormalPool(ULONG64 nonPagedPoolStart, ULONG64 nonPagedPoolEnd) {
POOL_HEADER p; POOL_HEADER p;
PVOID eprocess; PVOID eprocess;
char eprocess_name[16] = {0}; // eprocess name is 15 bytes + 1 null char eprocess_name[16] = {0}; // eprocess name is 15 bytes + 1 null
const ULONG64 headerSize = 0x10;
PVOID currentAddr = (PVOID)(nonPagedPoolStart); PVOID currentAddr = (PVOID)(nonPagedPoolStart);
while (true) { while (true) {
if ((ULONG64)currentAddr >= nonPagedPoolEnd) if ((ULONG64)currentAddr >= nonPagedPoolEnd)
@ -413,23 +499,27 @@ scanNormalPool(ULONG64 nonPagedPoolStart, ULONG64 nonPagedPoolEnd) {
// TODO: perform scan in one page, use BlockSize/PreviousBlockSize // TODO: perform scan in one page, use BlockSize/PreviousBlockSize
toPoolHeader(&p, (PVOID)currentAddr); toPoolHeader(&p, (PVOID)currentAddr);
currentAddr = (PVOID)((ULONG64)currentAddr + headerSize); currentAddr = (PVOID)((ULONG64)currentAddr + poolChunkSize);
if (p.tag == 0) continue; if (p.tag == 0) continue;
if (!validTag(&p)) continue; if (!validTag(&p)) continue;
if (!validPool(&p)) continue; if (!validPool(&p)) continue;
if (p.tag != 'Proc' && p.tag != 'corP') if (p.tag != 'Proc')
continue; continue;
// TODO: Parse data as _EPROCESS // TODO: Parse data as _EPROCESS
// The first Proc found seems to be the EPROCESS from IoGetCurrentProcess // The first Proc found seems to be the System _EPROCESS
// But it was offset 0x40 // The offset of system's chunk to _EPROCESS is 0x40, size is ...
// printChunkInfo(&p); // but offset of other processes' chunk to _EPROCESS is 0x80, size is 0xe00
// eprocess = (PVOID)((ULONG64)p.addr + 0x40); printChunkInfo(&p);
// RtlStringCbCopyNA(eprocess_name, 16, (char*)((ULONG64)eprocess + eprocessNameOffset), 15); if (p->blockSize * CHUNK_SIZE == 0xf00) {
// DbgPrint("[NAK] :: [ ] eprocess offset 0x40 : 0x%p, [%s]\n", eprocess, eprocess_name); eprocess = (PVOID)((ULONG64)p.addr + 0x40);
eprocess = (PVOID)((ULONG64)p.addr + 0x80); } else if (p->blockSize * CHUNK_SIZE == 0xd80) {
eprocess = (PVOID)((ULONG64)p.addr + 0x70);
} else if (p->blockSize * CHUNK_SIZE == 0xe00) {
eprocess = (PVOID)((ULONG64)p.addr + 0x80);
}
RtlStringCbCopyNA(eprocess_name, 16, (char*)((ULONG64)eprocess + eprocessNameOffset), 15); RtlStringCbCopyNA(eprocess_name, 16, (char*)((ULONG64)eprocess + eprocessNameOffset), 15);
DbgPrint("[NAK] :: [ ] eprocess offset 0x80 : 0x%p, [%s]\n", eprocess, eprocess_name); DbgPrint("[NAK] :: [ ] eprocess offset 0x80 : 0x%p, [%s]\n", eprocess, eprocess_name);
} }
@ -441,3 +531,31 @@ VOID
scanLargePool(PVOID /* largePageTableArray */, ULONG64 /* largePageTableSize */) { scanLargePool(PVOID /* largePageTableArray */, ULONG64 /* largePageTableSize */) {
DbgPrint("[NAK] :: [-] Scan large pool not supported yet"); DbgPrint("[NAK] :: [-] Scan large pool not supported yet");
} }
PVOID
scanRemote(ULONG64 startAddress, ULONG64 endAddress) {
POOL_HEADER p;
PVOID currentAddr = (PVOID)startAddress;
while (true) {
if ((ULONG64)currentAddr >= endAddress)
break;
if (!MmIsAddressValid(currentAddr)) {
currentAddr = (PVOID)((ULONG64)currentAddr + PAGE_SIZE);
continue;
}
toPoolHeader(&p, (PVOID)currentAddr);
currentAddr = (PVOID)((ULONG64)currentAddr + poolChunkSize);
if (p.tag == 0) continue;
if (!validTag(&p)) continue;
if (!validPool(&p)) continue;
if (p.tag != 'Proc')
continue;
return p.addr;
}
return (PVOID)endAddress;
}

View File

@ -18,6 +18,12 @@ enum VERSION_BY_POOL {
WINDOWS_NOT_SUPPORTED WINDOWS_NOT_SUPPORTED
}; };
VOID
setup();
VOID
scan_ps_active_head();
VOID VOID
toPoolHeader(PPOOL_HEADER p, PVOID chunkAddr); toPoolHeader(PPOOL_HEADER p, PVOID chunkAddr);
@ -39,4 +45,7 @@ scanNormalPool(ULONG64 nonPagedPoolStart, ULONG64 nonPagedPoolEnd);
VOID VOID
scanLargePool(PVOID largePageTableArray, ULONG64 largePageTableSize); scanLargePool(PVOID largePageTableArray, ULONG64 largePageTableSize);
PVOID
scanRemote(ULONG64 startAddress, ULONG64 endAddress);
#endif #endif

View File

@ -20,28 +20,74 @@ Environment:
--*/ --*/
// #ifndef _IOCTL_PROTOCOL_H
// Device type -- in the "User Defined" range." #define _IOCTL_PROTOCOL_H
//
#define SIOCTL_TYPE 40000 // Device type
// #define SIOCTL_TYPE 40000 // 32768 to 65535
// The IOCTL function codes from 0x800 to 0xFFF are for customer use. // The IOCTL function codes from 0x800 to 0xFFF are for customer use.
// #define IOCTL_SETUP_OFFSETS \
#define IOCTL_SIOCTL_METHOD_IN_DIRECT \ CTL_CODE(SIOCTL_TYPE, 0x900, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
CTL_CODE( SIOCTL_TYPE, 0x900, METHOD_IN_DIRECT, FILE_ANY_ACCESS )
#define IOCTL_SIOCTL_METHOD_OUT_DIRECT \ #define GET_KERNEL_BASE \
CTL_CODE( SIOCTL_TYPE, 0x901, METHOD_OUT_DIRECT , FILE_ANY_ACCESS ) CTL_CODE(SIOCTL_TYPE, 0x901, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_SIOCTL_METHOD_BUFFERED \ #define SCAN_PS_ACTIVE_HEAD \
CTL_CODE( SIOCTL_TYPE, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS ) CTL_CODE(SIOCTL_TYPE, 0x902, METHOD_NEITHER, FILE_ANY_ACCESS)
#define IOCTL_SIOCTL_METHOD_NEITHER \ #define SCAN_POOL \
CTL_CODE( SIOCTL_TYPE, 0x903, METHOD_NEITHER , FILE_ANY_ACCESS ) CTL_CODE(SIOCTL_TYPE, 0x903, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define SCAN_POOL_REMOTE \
CTL_CODE(SIOCTL_TYPE, 0x904, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define DEREFERENCE_ADDRESS \
CTL_CODE(SIOCTL_TYPE, 0xA00, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define DRIVER_FUNC_INSTALL 0x01 #define DRIVER_FUNC_INSTALL 0x01
#define DRIVER_FUNC_REMOVE 0x02 #define DRIVER_FUNC_REMOVE 0x02
#define DRIVER_NAME "poolscanner" #define DRIVER_NAME "poolscanner"
typedef struct _OFFSET_VALUE {
ULONG64 eprocessNameOffset;
ULONG64 eprocessLinkOffset;
ULONG64 listBLinkOffset;
ULONG64 processHeadOffset;
ULONG64 miStateOffset;
ULONG64 hardwareOffset;
ULONG64 systemNodeOffset;
ULONG64 firstVaOffset;
ULONG64 lastVaOffset;
ULONG64 largePageTableOffset;
ULONG64 largePageSizeOffset;
ULONG64 poolChunkSize;
} OFFSET_VALUES, *POFFSET_VALUE;
typedef struct _DEREF_ADDR {
ULONG64 addr;
ULONG64 size; // bytes
} DEREF_ADDR, *PDEREF_ADDR;
typedef struct _SCAN_RANGE {
ULONG64 start;
ULONG64 end;
} SCAN_RANGE, *PSCAN_RANGE;
typedef union _INPUT_DATA {
OFFSET_VALUES offsetValues;
DEREF_ADDR derefAddr;
SCAN_RANGE scanRange;
} INPUT_DATA, *PINPUT_DATA;
typedef struct _POOL_CHUNK {
ULONG64 addr;
} POOL_CHUNK, *PPOOL_CHUNK;
typedef union _OUTPUT_DATA {
ULONG64 ulong64Value; // for gereral addresses, value fit in 64 bit
POOL_CHUNK poolChunk;
} OUTPUT_DATA, *POUTPUT_DATA;
#endif