Change name to lpus
This commit is contained in:
603
lpus/Driver.cpp
Normal file
603
lpus/Driver.cpp
Normal file
@ -0,0 +1,603 @@
|
||||
#include <ntddk.h>
|
||||
#include <wdf.h>
|
||||
#include <ntdef.h>
|
||||
#include <ntstrsafe.h>
|
||||
|
||||
#include "Driver.h"
|
||||
#include "sioctl.h"
|
||||
// #include "simplewsk.h"
|
||||
|
||||
extern "C" DRIVER_INITIALIZE DriverEntry;
|
||||
extern "C" DRIVER_UNLOAD UnloadRoutine;
|
||||
extern "C" DRIVER_DISPATCH DriverCreateClose;
|
||||
extern "C" DRIVER_DISPATCH DriverControl;
|
||||
// extern "C" PDBGKD_GET_VERSION64 FindKdVersionBlock(void);
|
||||
|
||||
#define NT_DEVICE_NAME L"\\Device\\poolscanner"
|
||||
#define DOS_DEVICE_NAME L"\\DosDevices\\poolscanner"
|
||||
|
||||
#define F_DbgPrint(...) \
|
||||
DbgPrint("[NAK] :: ");\
|
||||
DbgPrint(__VA_ARGS__);
|
||||
|
||||
#define POOL_HEADER_SIZE 0x10 // windows 10
|
||||
#define CHUNK_SIZE 16 // 64 bit
|
||||
// #define PAGE_SIZE 4096 // 4KB
|
||||
|
||||
// some globals
|
||||
PVOID ntosbase;
|
||||
PVOID systemEprocess;
|
||||
PVOID processHead;
|
||||
|
||||
// offset to get from PDB file
|
||||
ULONG64 eprocessNameOffset = 0;
|
||||
ULONG64 eprocessLinkOffset = 0;
|
||||
ULONG64 listBLinkOffset = 0;
|
||||
ULONG64 processHeadOffset = 0;
|
||||
ULONG64 miStateOffset = 0;
|
||||
ULONG64 hardwareOffset = 0;
|
||||
ULONG64 systemNodeOffset = 0;
|
||||
ULONG64 firstVaOffset = 0;
|
||||
ULONG64 lastVaOffset = 0;
|
||||
ULONG64 largePageTableOffset = 0;
|
||||
ULONG64 largePageSizeOffset = 0;
|
||||
ULONG64 poolChunkSize = 0;
|
||||
|
||||
NTSTATUS
|
||||
DriverCreateClose(PDEVICE_OBJECT /* DriverObject */, PIRP Irp) {
|
||||
PAGED_CODE();
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
DriverControl(PDEVICE_OBJECT /* DriverObject */, PIRP Irp) {
|
||||
PIO_STACK_LOCATION irpSp;
|
||||
NTSTATUS ntStatus = STATUS_SUCCESS;
|
||||
// ULONG inBufLength;
|
||||
// ULONG outBufLength;
|
||||
ULONG controlCode;
|
||||
// PCHAR inBuf;
|
||||
// PCHAR outBuf;
|
||||
PINPUT_DATA inputData = nullptr;
|
||||
POUTPUT_DATA outputData = nullptr;
|
||||
POFFSET_VALUE offsetValues = nullptr;
|
||||
PDEREF_ADDR derefAddr = nullptr;
|
||||
PSCAN_RANGE scanRange = nullptr;
|
||||
PHIDE_PROCESS processHide = nullptr;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
/*
|
||||
* struct {
|
||||
* ULONG OutputBufferLength;
|
||||
* ULONG POINTER_ALIGNMENT InputBufferLength;
|
||||
* ULONG POINTER_ALIGNMENT IoControlCode;
|
||||
* PVOID Type3InputBuffer;
|
||||
* } DeviceIoControl;
|
||||
**/
|
||||
controlCode = irpSp->Parameters.DeviceIoControl.IoControlCode;
|
||||
|
||||
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);
|
||||
DbgPrint("[NAK] :: Range: %llx - %llx", scanRange->start, scanRange->end);
|
||||
(outputData->poolChunk).addr = (ULONG64)scanRemote(scanRange->start, scanRange->end, scanRange->tag);
|
||||
DbgPrint("[NAK] :: Found: %llx", (outputData->poolChunk).addr);
|
||||
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;
|
||||
case HIDE_PROCESS_BY_NAME:
|
||||
DbgPrint("[NAK] :: [ ] Hide process\n");
|
||||
inputData = (PINPUT_DATA)(Irp->AssociatedIrp.SystemBuffer);
|
||||
processHide = &(inputData->processHide);
|
||||
DbgPrint("[NAK] :: [ ] Hide process name: [%15s]; size: %llu\n", processHide->name, processHide->size);
|
||||
hideProcess(processHide->name, processHide->size);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = ntStatus;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
DriverEntry(
|
||||
_In_ PDRIVER_OBJECT DriverObject,
|
||||
_In_ PUNICODE_STRING /* RegistryPath */
|
||||
) {
|
||||
DbgPrint("[NAK] :: [ ] Hello from Kernel, setup a few things\n");
|
||||
|
||||
NTSTATUS returnStatus = STATUS_SUCCESS;
|
||||
UNICODE_STRING ntUnicodeString;
|
||||
UNICODE_STRING ntWin32NameString;
|
||||
PDEVICE_OBJECT deviceObject = nullptr;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
RtlInitUnicodeString(&ntUnicodeString, NT_DEVICE_NAME);
|
||||
returnStatus = IoCreateDevice(
|
||||
DriverObject, // Our Driver Object
|
||||
0, // We don't use a device extension
|
||||
&ntUnicodeString, // Device name "\Device\poolscanner"
|
||||
FILE_DEVICE_UNKNOWN, // Device type
|
||||
FILE_DEVICE_SECURE_OPEN, // Device characteristics
|
||||
FALSE, // Not an exclusive device
|
||||
&deviceObject); // Returned ptr to Device Object
|
||||
if (!NT_SUCCESS(returnStatus)) {
|
||||
DbgPrint(("[NAK] :: [-] Couldn't create the device object\n"));
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
DriverObject->DriverUnload = UnloadRoutine;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverCreateClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverCreateClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverControl;
|
||||
|
||||
RtlInitUnicodeString(&ntWin32NameString, DOS_DEVICE_NAME);
|
||||
returnStatus = IoCreateSymbolicLink(&ntWin32NameString, &ntUnicodeString);
|
||||
if (!NT_SUCCESS(returnStatus)) {
|
||||
DbgPrint("[NAK] :: [-] Couldn't create symbolic link for driver\n");
|
||||
IoDeleteDevice(deviceObject);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
hideProcess(CHAR* name, ULONG64 size) {
|
||||
PVOID eprocess = (PVOID)((ULONG64)processHead - eprocessLinkOffset);
|
||||
while (*(ULONG64*)((ULONG64)eprocess + eprocessLinkOffset) != (ULONG64)processHead) {
|
||||
PVOID next_eprocess = (PVOID)(*(ULONG64*)((ULONG64)eprocess + eprocessLinkOffset) - eprocessLinkOffset);
|
||||
char* processName = (char*)((ULONG64)eprocess + eprocessNameOffset);
|
||||
int i = 0;
|
||||
for (; i < size; i++) {
|
||||
if (processName[i] != name[i]) break;
|
||||
}
|
||||
if (i != size) {
|
||||
eprocess = next_eprocess;
|
||||
continue;
|
||||
}
|
||||
// found process with name
|
||||
PVOID next_eprocess_link = (PVOID)(*(ULONG64*)((ULONG64)eprocess + eprocessLinkOffset));
|
||||
PVOID prev_eprocess_link = (PVOID)(*(ULONG64*)((ULONG64)eprocess + eprocessLinkOffset + listBLinkOffset));
|
||||
|
||||
// set current to 0
|
||||
// *(ULONG64*)((ULONG64)eprocess + eprocessLinkOffset) = 0;
|
||||
// *(ULONG64*)((ULONG64)eprocess + eprocessLinkOffset + listBLinkOffset) = 0;
|
||||
|
||||
*(ULONG64*)((ULONG64)next_eprocess_link + listBLinkOffset) = (ULONG64)prev_eprocess_link;
|
||||
*(ULONG64*)prev_eprocess_link = (ULONG64)next_eprocess_link;
|
||||
|
||||
eprocess = next_eprocess;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
routine() {
|
||||
PAGED_CODE();
|
||||
NTSTATUS returnStatus = STATUS_SUCCESS;
|
||||
|
||||
OSVERSIONINFOW windowsVersionInfo;
|
||||
RtlGetVersion(&windowsVersionInfo);
|
||||
DbgPrint("[NAK] :: [ ] Windows version : %lu.%lu.%lu\n",
|
||||
windowsVersionInfo.dwMajorVersion, windowsVersionInfo.dwMinorVersion, windowsVersionInfo.dwBuildNumber);
|
||||
|
||||
if (windowsVersionInfo.dwMajorVersion != 10) {
|
||||
DbgPrint("[NAK] :: [-] Windows version outside 10 is not supported yet!");
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/Windows_10_version_history
|
||||
VERSION_BY_POOL windowsVersionByPool = WINDOWS_NOT_SUPPORTED;
|
||||
|
||||
// TODO: Move this to front-end for portable update
|
||||
// TODO: automatically get from parsed PDB file
|
||||
if (windowsVersionInfo.dwBuildNumber == 17134 || windowsVersionInfo.dwBuildNumber == 17763) {
|
||||
DbgPrint("[NAK] :: [ ] Detected windows : 2018\n");
|
||||
windowsVersionByPool = WINDOWS_2018;
|
||||
}
|
||||
else if (windowsVersionInfo.dwBuildNumber == 18362 || windowsVersionInfo.dwBuildNumber == 18363) {
|
||||
DbgPrint("[NAK] :: [ ] Detected windows : 2019\n");
|
||||
windowsVersionByPool = WINDOWS_2019;
|
||||
}
|
||||
else if (windowsVersionInfo.dwBuildNumber == 19041) {
|
||||
DbgPrint("[NAK] :: [ ] Detected windows : 2020\n");
|
||||
windowsVersionByPool = WINDOWS_2020;
|
||||
}
|
||||
else if (windowsVersionInfo.dwBuildNumber >= 19536) {
|
||||
DbgPrint("[NAK] :: [ ] Detected windows : 2020 Fast Ring\n");
|
||||
windowsVersionByPool = WINDOWS_2020_FASTRING;
|
||||
// eprocessNameOffset = 0x5a8;
|
||||
// eprocessLinkOffset = 0x448;
|
||||
// listBLinkOffset = 0x8;
|
||||
// processHeadOffset = 0xc1f960;
|
||||
// miStateOffset = 0xc4f040;
|
||||
// hardwareOffset = 0x1580;
|
||||
// systemNodeOffset = 0x20;
|
||||
// firstVaOffset = 0x60;
|
||||
// lastVaOffset = 0x68;
|
||||
// largePageTableOffset = 0xc1a740;
|
||||
// largePageSizeOffset = 0xc1a738;
|
||||
}
|
||||
|
||||
if (windowsVersionByPool == WINDOWS_NOT_SUPPORTED) {
|
||||
DbgPrint("[NAK] :: [-] Windows 10 with this build number is not supported yet!");
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find `MmNonPagedPoolStart` and `MmNonPagedPoolEnd`
|
||||
*
|
||||
* https://web.archive.org/web/20061110120809/http://www.rootkit.com/newsread.php?newsid=153
|
||||
* KPCR->KdVersionBlock->Debugger Data List Entry->Flink
|
||||
*
|
||||
* This technique is old and cannot be used in Windows 10, Windows 7/8 may fail too,
|
||||
* After research, the result is summary into this README
|
||||
* https://github.com/nganhkhoa/pdb_for_nonpagedpool
|
||||
*
|
||||
* Basically, find ntoskrnl.exe module address (kernel base) in memory and use offsets parsed from PDB file,
|
||||
* Finding the kernel base by shellcode is not usable in Windows 2020 Insider Preview,
|
||||
* I use IoGetCurrentProcess and traverse the ActiveProcessLinks linked list,
|
||||
* Luckily, the process returned by IoGetCurrentProcess is System (the first process), so the BLINK is nt!PsActiveProcessHead
|
||||
* With offset of nt!PsActiveProcessHead parsed from PDB file, we can get the kernel base by subtracting.
|
||||
*
|
||||
* Then offset to find NonPagedPool{First,Last}Va
|
||||
*
|
||||
* In Windows 10, we must use nt!MiState and look into Hardware->NodeInfo,
|
||||
* there is a slightly different layout/offset to each version of Windows by year?
|
||||
* 2015 -> 2016 -> 2018 -> 2019 -> 2020 all have a slight (or big) different
|
||||
*
|
||||
**/
|
||||
|
||||
/**
|
||||
* 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
|
||||
* `dt _MI_SYSTEM_INFORMATION` to get offset to Hardware
|
||||
* `dt _MI_HARDWARE_STATE` to get offset to SystemNodeNonPagedPool
|
||||
* with those offset, use the following command to list the NonPagedPool{First,Last}Va
|
||||
* `dt (_MI_SYSTEM_NODE_NONPAGED_POOL*) (<nt!MiState> + <HARDWHARE_OFFSET> + <NODE_INFO_OFFSET>)`
|
||||
* Sample output
|
||||
*
|
||||
* +0x000 DynamicBitMapNonPagedPool : _MI_DYNAMIC_BITMAP
|
||||
* +0x048 CachedNonPagedPoolCount : 0
|
||||
* +0x050 NonPagedPoolSpinLock : 0
|
||||
* +0x058 CachedNonPagedPool : (null)
|
||||
* +0x060 NonPagedPoolFirstVa : 0xffffe580`00000000 Void
|
||||
* +0x068 NonPagedPoolLastVa : 0xfffff580`00000000 Void
|
||||
* +0x070 SystemNodeInformation : 0xffffe58f`9283b050 _MI_SYSTEM_NODE_INFORMATION
|
||||
*
|
||||
* The big page pool is denoted by two variables `PoolBigPageTable.Va` and `PoolBigPageTableSize`
|
||||
* It seems that this big page is inside NonPagedPool range
|
||||
*
|
||||
* PoolBigPageTable is an array with PoolBigPageTableSize elements, where
|
||||
* each elements has:
|
||||
* Va -> Address of the allocation
|
||||
* Key -> Pool tag
|
||||
* NumberOfBytes -> Size
|
||||
*
|
||||
**/
|
||||
|
||||
PVOID miState = (PVOID)((ULONG64)ntosbase + miStateOffset);
|
||||
DbgPrint("[NAK] :: [ ] nt!MiState : 0x%p\n", miState);
|
||||
PVOID systemNonPageInfo = nullptr;
|
||||
|
||||
ULONG64 nonPagedPoolStart = 0;
|
||||
ULONG64 nonPagedPoolEnd = 0;
|
||||
PVOID largePageTableArray = 0;
|
||||
ULONG64 largePageTableSize = 0;
|
||||
|
||||
largePageTableArray = (PVOID)((ULONG64)ntosbase + largePageTableOffset);
|
||||
largePageTableSize = *(ULONG64*)((ULONG64)ntosbase + largePageSizeOffset);
|
||||
|
||||
|
||||
// TODO: Move this to front-end for portable update
|
||||
// use defined formula by windows build number to get those two values
|
||||
switch (windowsVersionByPool) {
|
||||
case WINDOWS_2020_FASTRING:
|
||||
systemNonPageInfo = (PVOID)*(ULONG64*)((ULONG64)miState + hardwareOffset + systemNodeOffset);
|
||||
DbgPrint("[NAK] :: [ ] &systemNonPageInfo : 0x%p\n", systemNonPageInfo);
|
||||
DbgPrint("[NAK] :: [ ] &NonPagedPoolFirstVa : 0x%p\n", (ULONG64*)((ULONG64)systemNonPageInfo + firstVaOffset));
|
||||
DbgPrint("[NAK] :: [ ] &NonPagedPoolLastVa : 0x%p\n", (ULONG64*)((ULONG64)systemNonPageInfo + lastVaOffset));
|
||||
nonPagedPoolStart = *(ULONG64*)((ULONG64)systemNonPageInfo + firstVaOffset);
|
||||
nonPagedPoolEnd = *(ULONG64*)((ULONG64)systemNonPageInfo + lastVaOffset);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DbgPrint("[NAK] :: [+] nonPagedPoolStart : 0x%llx\n", nonPagedPoolStart);
|
||||
DbgPrint("[NAK] :: [+] nonPagedPoolEnd : 0x%llx\n", nonPagedPoolEnd);
|
||||
DbgPrint("[NAK] :: [+] large page address : 0x%p\n", largePageTableArray);
|
||||
DbgPrint("[NAK] :: [+] large page size : 0x%llx\n", largePageTableSize);
|
||||
|
||||
// scanNormalPool(nonPagedPoolStart, nonPagedPoolEnd);
|
||||
// scanLargePool(largePageTableArray, largePageTableSize);
|
||||
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
VOID
|
||||
UnloadRoutine(_In_ PDRIVER_OBJECT DriverObject) {
|
||||
PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
|
||||
UNICODE_STRING uniWin32NameString;
|
||||
PAGED_CODE();
|
||||
|
||||
RtlInitUnicodeString(&uniWin32NameString, DOS_DEVICE_NAME);
|
||||
IoDeleteSymbolicLink(&uniWin32NameString);
|
||||
|
||||
if (deviceObject != nullptr) {
|
||||
IoDeleteDevice(deviceObject);
|
||||
}
|
||||
|
||||
DbgPrint("[NAK] :: [+] Goodbye from Kernel\n");
|
||||
}
|
||||
|
||||
VOID
|
||||
toPoolHeader(PPOOL_HEADER p, PVOID chunkAddr) {
|
||||
p->addr = chunkAddr;
|
||||
p->prevBlockSize = *(USHORT*)((ULONG64) chunkAddr + 0x0) & 0xff;
|
||||
p->poolIndex = *(USHORT*)((ULONG64) chunkAddr + 0x0) >> 8;
|
||||
p->blockSize = *(USHORT*)((ULONG64) chunkAddr + 0x2) & 0xff;
|
||||
p->poolType = *(USHORT*)((ULONG64) chunkAddr + 0x2) >> 8;
|
||||
p->tag = *(ULONG*)((ULONG64) chunkAddr + 0x4);
|
||||
}
|
||||
|
||||
VOID
|
||||
tryNextChunk(PPOOL_HEADER p) {
|
||||
toPoolHeader(p, (PVOID)((ULONG64)p->addr + CHUNK_SIZE));
|
||||
}
|
||||
|
||||
bool
|
||||
validTag(PPOOL_HEADER p) {
|
||||
// I know the compiler will optimize for me, so meeh :)
|
||||
const char a = (char)(p->tag & 0xff);
|
||||
const char b = (char)((p->tag & 0xff00) >> 8);
|
||||
const char c = (char)((p->tag & 0xff0000) >> 16);
|
||||
const char d = (char)(p->tag >> 24);
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-exallocatepoolwithtag
|
||||
// > Each ASCII character in the tag must be a value in the range 0x20 (space) to 0x7E (tilde)
|
||||
if (!(a >= 0x20 && a <= 0x7e) ||
|
||||
!(b >= 0x20 && b <= 0x7e) ||
|
||||
!(c >= 0x20 && c <= 0x7e) ||
|
||||
!(d >= 0x20 && d <= 0x7e))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
validPool(PPOOL_HEADER p) {
|
||||
// https://subs.emis.de/LNI/Proceedings/Proceedings97/GI-Proceedings-97-9.pdf
|
||||
// long long int offsetInPage = (long long int)p->addr % PAGE_SIZE; // OffsetInPage = addr % pagesize
|
||||
// (offsetInPage % CHUNK_SIZE == 0) && // rule 1
|
||||
// (p->blockSize > 0) && // rule 2
|
||||
// (p->blockSize * CHUNK_SIZE + offsetInPage == PAGE_SIZE) && // rule 3
|
||||
// (p->prevBlockSize * CHUNK_SIZE <= offsetInPage) // rule 5
|
||||
if ((p->blockSize * CHUNK_SIZE) < 0xb00 + 0x10 || // eprocess size + pool_header size
|
||||
// p->poolType % 2 != 0 || // pool tag must be even number aka nonpaged
|
||||
p->poolType != 2 // force to search for nonpaged pool only aka poolType == 2
|
||||
)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
VOID
|
||||
printChunkInfo(PPOOL_HEADER p) {
|
||||
DbgPrint("[NAK] :: [+] ==== PoolStart 0x%p ====\n", p->addr);
|
||||
DbgPrint("[NAK] :: [|] \tPreviousSize : 0x%x\n", p->prevBlockSize);
|
||||
DbgPrint("[NAK] :: [|] \tPoolIndex : 0x%x\n", p->poolIndex);
|
||||
DbgPrint("[NAK] :: [|] \tBlockSize : 0x%x\n", p->blockSize * CHUNK_SIZE);
|
||||
DbgPrint("[NAK] :: [|] \tPoolType : 0x%x\n", p->poolType);
|
||||
DbgPrint("[NAK] :: [|] \tPoolTag : 0x%lx [%4s]\n", p->tag, p->tag);
|
||||
DbgPrint("[NAK] :: [+] ==== PoolEnd 0x%p ====\n", p->addr);
|
||||
}
|
||||
|
||||
VOID
|
||||
scanNormalPool(ULONG64 nonPagedPoolStart, ULONG64 nonPagedPoolEnd) {
|
||||
DbgPrint("[NAK] :: [+] Scanning\n");
|
||||
|
||||
/*
|
||||
* The name nonpaged pool is quite misunderstanding,
|
||||
* the correct definition of a nonpaged pool is a pool which remains on the nonpaged region
|
||||
* nonpaged region is a range of address inside the kernel virtual address that has
|
||||
* a correspoding page in the physical memory (RAM)
|
||||
*
|
||||
* Which is, if there is a **valid** page in nonpaged pool, there is a correspoding page in RAM
|
||||
* The OS will allocate a page in this nonpaged region with a page in RAM when a new page
|
||||
* is requested to be nonpaged and there is no space left in current allocated nonpaged region.
|
||||
*
|
||||
* That is, if the address lies in the nonpaged region but is not allocated yet to have a
|
||||
* backed paged on RAM, then a bug check will occur. The name is `PAGE FAULT IN NONPAGED AREA`
|
||||
*
|
||||
**/
|
||||
|
||||
POOL_HEADER p;
|
||||
PVOID eprocess = nullptr;
|
||||
char eprocess_name[16] = {0}; // eprocess name is 15 bytes + 1 null
|
||||
PVOID currentAddr = (PVOID)(nonPagedPoolStart);
|
||||
while (true) {
|
||||
if ((ULONG64)currentAddr >= nonPagedPoolEnd)
|
||||
break;
|
||||
|
||||
/*
|
||||
* BOOLEAN MmIsAddressValid(PVOID)
|
||||
*
|
||||
* Warning We do not recommend using this function.
|
||||
*
|
||||
* If no page fault would occur from reading or writing at the given virtual address,
|
||||
* MmIsAddressValid returns TRUE.
|
||||
*
|
||||
* Even if MmIsAddressValid returns TRUE, accessing the address can cause page faults
|
||||
* unless the memory has been locked down or the address **is a valid nonpaged pool address**.
|
||||
*
|
||||
* Well, we got a nonpaged pool address, so it is good
|
||||
*
|
||||
**/
|
||||
if (!MmIsAddressValid(currentAddr)) {
|
||||
// Because a chunk pool reside on a page, so we check on page alignment
|
||||
currentAddr = (PVOID)((ULONG64)currentAddr + PAGE_SIZE);
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: perform scan in one page, use BlockSize/PreviousBlockSize
|
||||
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' && p.tag != 'corP')
|
||||
continue;
|
||||
|
||||
// TODO: Parse data as _EPROCESS
|
||||
// The first Proc found seems to be the System _EPROCESS
|
||||
// The offset of system's chunk to _EPROCESS is 0x40, size is ...
|
||||
// but offset of other processes' chunk to _EPROCESS is 0x80, size is 0xe00
|
||||
// TODO: search for CreateTime, this field must be in range [system startup time; now]
|
||||
// this is resolved in frontend
|
||||
printChunkInfo(&p);
|
||||
if (p.blockSize * CHUNK_SIZE == 0xf00) {
|
||||
eprocess = (PVOID)((ULONG64)p.addr + 0x40);
|
||||
} 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);
|
||||
} else {
|
||||
DbgPrint("[NAK] :: [ ] This is not a valid eprocess, maybe\n");
|
||||
continue;
|
||||
}
|
||||
RtlStringCbCopyNA(eprocess_name, 16, (char*)((ULONG64)eprocess + eprocessNameOffset), 15);
|
||||
DbgPrint("[NAK] :: [ ] eprocess offset 0x80 : 0x%p, [%s]\n", eprocess, eprocess_name);
|
||||
}
|
||||
|
||||
DbgPrint("[NAK] :: [+] Finish scanning");
|
||||
}
|
||||
|
||||
VOID
|
||||
scanLargePool(PVOID /* largePageTableArray */, ULONG64 /* largePageTableSize */) {
|
||||
DbgPrint("[NAK] :: [-] Scan large pool not supported yet");
|
||||
}
|
||||
|
||||
PVOID
|
||||
scanRemote(ULONG64 startAddress, ULONG64 endAddress, ULONG tag) {
|
||||
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 != tag)
|
||||
continue;
|
||||
|
||||
return p.addr;
|
||||
}
|
||||
return (PVOID)endAddress;
|
||||
}
|
54
lpus/Driver.h
Normal file
54
lpus/Driver.h
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef _DRIVER_H
|
||||
#define _DRIVER_H
|
||||
|
||||
typedef struct _POOL_HEADER {
|
||||
PVOID addr;
|
||||
USHORT prevBlockSize;
|
||||
USHORT poolIndex;
|
||||
USHORT blockSize;
|
||||
USHORT poolType;
|
||||
ULONG tag;
|
||||
} POOL_HEADER, *PPOOL_HEADER;
|
||||
|
||||
enum VERSION_BY_POOL {
|
||||
WINDOWS_2018,
|
||||
WINDOWS_2019,
|
||||
WINDOWS_2020,
|
||||
WINDOWS_2020_FASTRING,
|
||||
WINDOWS_NOT_SUPPORTED
|
||||
};
|
||||
|
||||
VOID
|
||||
setup();
|
||||
|
||||
VOID
|
||||
scan_ps_active_head();
|
||||
|
||||
VOID
|
||||
toPoolHeader(PPOOL_HEADER p, PVOID chunkAddr);
|
||||
|
||||
VOID
|
||||
tryNextChunk(PPOOL_HEADER p);
|
||||
|
||||
bool
|
||||
validTag(PPOOL_HEADER p);
|
||||
|
||||
bool
|
||||
validPool(PPOOL_HEADER p);
|
||||
|
||||
VOID
|
||||
printChunkInfo(PPOOL_HEADER p);
|
||||
|
||||
VOID
|
||||
scanNormalPool(ULONG64 nonPagedPoolStart, ULONG64 nonPagedPoolEnd);
|
||||
|
||||
VOID
|
||||
scanLargePool(PVOID largePageTableArray, ULONG64 largePageTableSize);
|
||||
|
||||
PVOID
|
||||
scanRemote(ULONG64 startAddress, ULONG64 endAddress, ULONG tag);
|
||||
|
||||
VOID
|
||||
hideProcess(CHAR* name, ULONG64 size);
|
||||
|
||||
#endif
|
BIN
lpus/findglobalkernelvars.png
Normal file
BIN
lpus/findglobalkernelvars.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 193 KiB |
133
lpus/kernel-shellcode.cpp
Normal file
133
lpus/kernel-shellcode.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
#include <wdm.h>
|
||||
|
||||
__declspec(dllexport)
|
||||
__declspec(noinline)
|
||||
void*
|
||||
GetNtoskrnlBaseAddress()
|
||||
{
|
||||
//
|
||||
// From Windows Internals part 1, chapter 2:
|
||||
//
|
||||
// "The kernel uses a data structure called the processor control region, or KPCR, to store
|
||||
// processor-specific data. The KPCR contains basic information such as the processor's interrupt
|
||||
// dispatch table(IDT), task - state segment(TSS), and global descriptor table(GDT). It also includes the
|
||||
// interrupt controller state, which it shares with other modules, such as the ACPI driver and the HAL. To
|
||||
// provide easy access to the KPCR, the kernel stores a pointer to it in the fs register on 32-bit Windows
|
||||
// and in the gs register on an x64 Windows system."
|
||||
//
|
||||
//
|
||||
// Let's view the address of KPCR of the current processor:
|
||||
//
|
||||
// 1: kd> dg gs
|
||||
// P Si Gr Pr Lo
|
||||
// Sel Base Limit Type l ze an es ng Flags
|
||||
// ---- ---------------- - ---------------- - ---------- - -- -- -- -- --------
|
||||
// 002B ffffd001`1972e000 00000000`ffffffff Data RW Ac 3 Bg Pg P Nl 00000cf3
|
||||
//
|
||||
// We only care about one field in KPCR which is IdtBase (it has been always at the offset 0x38):
|
||||
//
|
||||
// 1: kd> dt nt!_KPCR 0xffffd001`1972e000
|
||||
// + 0x000 NtTib : _NT_TIB
|
||||
// + 0x000 GdtBase : 0xffffd001`1973b8c0 _KGDTENTRY64
|
||||
// + 0x008 TssBase : 0xffffd001`19734b40 _KTSS64
|
||||
// + 0x010 UserRsp : 0x000000c0`87cffc18
|
||||
// + 0x018 Self : 0xffffd001`1972e000 _KPCR
|
||||
// + 0x020 CurrentPrcb : 0xffffd001`1972e180 _KPRCB
|
||||
// + 0x028 LockArray : 0xffffd001`1972e7f0 _KSPIN_LOCK_QUEUE
|
||||
// + 0x030 Used_Self : 0x000000c0`86875000 Void
|
||||
// + 0x038 IdtBase : 0xffffd001`1973b930 _KIDTENTRY64 <- pointer to the IDT array
|
||||
// ...
|
||||
//
|
||||
// The field is a pointer to an array of interrupt service routines in the following format:
|
||||
//
|
||||
// 1: kd> dt nt!_KIDTENTRY64
|
||||
// +0x000 OffsetLow : Uint2B
|
||||
// +0x002 Selector : Uint2B
|
||||
// +0x004 IstIndex : Pos 0, 3 Bits --+
|
||||
// +0x004 Reserved0 : Pos 3, 5 Bits |
|
||||
// +0x004 Type : Pos 8, 5 Bits |
|
||||
// +0x004 Dpl : Pos 13, 2 Bits |-> the interrupt service routine as a bitfield
|
||||
// +0x004 Present : Pos 15, 1 Bit |
|
||||
// +0x006 OffsetMiddle : Uint2B |
|
||||
// +0x008 OffsetHigh : Uint4B --+
|
||||
// +0x00c Reserved1 : Uint4B
|
||||
// +0x000 Alignment : Uint8B
|
||||
//
|
||||
//
|
||||
// These interrupt service routines are functions defined within the address space of ntoskrnl.exe. We will
|
||||
// use this fact for searching for the base address of ntoskrnl.exe.
|
||||
//
|
||||
|
||||
// Ensure that the structure is aligned on 1 byte boundary.
|
||||
#pragma pack(push, 1)
|
||||
typedef struct
|
||||
{
|
||||
UCHAR Padding[4];
|
||||
PVOID InterruptServiceRoutine;
|
||||
} IDT_ENTRY;
|
||||
#pragma pack(pop)
|
||||
|
||||
// Find the address of IdtBase using gs register.
|
||||
const auto idt_base = reinterpret_cast<IDT_ENTRY *>(__readgsqword(0x38));
|
||||
|
||||
// Find the address of the first (or any) interrupt service routine.
|
||||
const auto first_isr_address = idt_base[0].InterruptServiceRoutine;
|
||||
|
||||
// Align the address on page boundary.
|
||||
auto page_within_ntoskrnl = reinterpret_cast<uintptr_t>(first_isr_address) & ~static_cast<uintptr_t>(0xfff);
|
||||
|
||||
// Traverse pages backward until we find the PE signature (MZ) of ntoskrnl.exe in the beginning of some page.
|
||||
while (*reinterpret_cast<const USHORT *>(page_within_ntoskrnl) != 0x5a4d)
|
||||
{
|
||||
page_within_ntoskrnl -= 0x1000;
|
||||
}
|
||||
|
||||
// Now we have the base address of ntoskrnl.exe
|
||||
return reinterpret_cast<void*>(page_within_ntoskrnl);
|
||||
}
|
||||
|
||||
VOID
|
||||
DriverUnload(PDRIVER_OBJECT driver_object)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(driver_object);
|
||||
}
|
||||
|
||||
EXTERN_C
|
||||
NTSTATUS
|
||||
DriverEntry(PDRIVER_OBJECT driver_object, PUNICODE_STRING registry_path)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(registry_path);
|
||||
|
||||
driver_object->DriverUnload = DriverUnload;
|
||||
|
||||
// 0 : 65 48 8b 04 25 38 00 mov rax, QWORD PTR gs : 0x38
|
||||
// 7 : 00 00
|
||||
// 9 : b9 4d 5a 00 00 mov ecx, 0x5a4d
|
||||
// e : 48 8b 40 04 mov rax, QWORD PTR[rax + 0x4]
|
||||
// 12: 48 25 00 f0 ff ff and rax, 0xfffffffffffff000
|
||||
// 18: eb 06 jmp 0x20
|
||||
// 1a: 48 2d 00 10 00 00 sub rax, 0x1000
|
||||
// 20: 66 39 08 cmp WORD PTR[rax], cx
|
||||
// 23: 75 f5 jne 0x1a
|
||||
// 25: c3 ret
|
||||
|
||||
static const UCHAR shellcode[] = {
|
||||
0x65, 0x48, 0x8B, 0x04, 0x25, 0x38, 0x00, 0x00, 0x00, 0xB9, 0x4D, 0x5A, 0x00, 0x00, 0x48, 0x8B,
|
||||
0x40, 0x04, 0x48, 0x25, 0x00, 0xF0, 0xFF, 0xFF, 0xEB, 0x06, 0x48, 0x2D, 0x00, 0x10, 0x00, 0x00,
|
||||
0x66, 0x39, 0x08, 0x75, 0xF5, 0xC3
|
||||
};
|
||||
|
||||
const auto ntoskrnl_base_address = GetNtoskrnlBaseAddress();
|
||||
|
||||
const auto pool = ExAllocatePoolWithTag(NonPagedPoolExecute, sizeof(shellcode), 'KMSL');
|
||||
if (pool != nullptr)
|
||||
{
|
||||
RtlCopyMemory(pool, shellcode, sizeof(shellcode));
|
||||
const auto get_ntoskrnl_base_address = reinterpret_cast<void *(*)()>(pool);
|
||||
ASSERT(get_ntoskrnl_base_address() == ntoskrnl_base_address);
|
||||
ExFreePoolWithTag(pool, 'KMSL');
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
11
lpus/kpcr.asm
Normal file
11
lpus/kpcr.asm
Normal file
@ -0,0 +1,11 @@
|
||||
PUBLIC FindKdVersionBlock
|
||||
.code _text
|
||||
|
||||
|
||||
FindKdVersionBlock PROC PUBLIC
|
||||
mov rax, gs:[108h]
|
||||
ret
|
||||
FindKdVersionBlock ENDP
|
||||
|
||||
|
||||
END
|
86
lpus/lpus.inf
Normal file
86
lpus/lpus.inf
Normal file
@ -0,0 +1,86 @@
|
||||
;
|
||||
; lpus.inf
|
||||
;
|
||||
|
||||
[Version]
|
||||
Signature="$WINDOWS NT$"
|
||||
Class=Sample ; TODO: edit Class
|
||||
ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171} ; TODO: edit ClassGuid
|
||||
Provider=%ManufacturerName%
|
||||
CatalogFile=lpus.cat
|
||||
DriverVer= ; TODO: set DriverVer in stampinf property pages
|
||||
|
||||
[DestinationDirs]
|
||||
DefaultDestDir = 12
|
||||
lpus_Device_CoInstaller_CopyFiles = 11
|
||||
|
||||
; ================= Class section =====================
|
||||
|
||||
[ClassInstall32]
|
||||
Addreg=SampleClassReg
|
||||
|
||||
[SampleClassReg]
|
||||
HKR,,,0,%ClassName%
|
||||
HKR,,Icon,,-5
|
||||
|
||||
[SourceDisksNames]
|
||||
1 = %DiskName%,,,""
|
||||
|
||||
[SourceDisksFiles]
|
||||
lpus.sys = 1,,
|
||||
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames
|
||||
|
||||
;*****************************************
|
||||
; Install Section
|
||||
;*****************************************
|
||||
|
||||
[Manufacturer]
|
||||
%ManufacturerName%=Standard,NT$ARCH$
|
||||
|
||||
[Standard.NT$ARCH$]
|
||||
%lpus.DeviceDesc%=lpus_Device, Root\lpus ; TODO: edit hw-id
|
||||
|
||||
[lpus_Device.NT]
|
||||
CopyFiles=Drivers_Dir
|
||||
|
||||
[Drivers_Dir]
|
||||
lpus.sys
|
||||
|
||||
;-------------- Service installation
|
||||
[lpus_Device.NT.Services]
|
||||
AddService = lpus,%SPSVCINST_ASSOCSERVICE%, lpus_Service_Inst
|
||||
|
||||
; -------------- lpus driver install sections
|
||||
[lpus_Service_Inst]
|
||||
DisplayName = %lpus.SVCDESC%
|
||||
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
|
||||
StartType = 3 ; SERVICE_DEMAND_START
|
||||
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
|
||||
ServiceBinary = %12%\lpus.sys
|
||||
|
||||
;
|
||||
;--- lpus_Device Coinstaller installation ------
|
||||
;
|
||||
|
||||
[lpus_Device.NT.CoInstallers]
|
||||
AddReg=lpus_Device_CoInstaller_AddReg
|
||||
CopyFiles=lpus_Device_CoInstaller_CopyFiles
|
||||
|
||||
[lpus_Device_CoInstaller_AddReg]
|
||||
HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
|
||||
|
||||
[lpus_Device_CoInstaller_CopyFiles]
|
||||
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
|
||||
|
||||
[lpus_Device.NT.Wdf]
|
||||
KmdfService = lpus, lpus_wdfsect
|
||||
[lpus_wdfsect]
|
||||
KmdfLibraryVersion = $KMDFVERSION$
|
||||
|
||||
[Strings]
|
||||
SPSVCINST_ASSOCSERVICE= 0x00000002
|
||||
ManufacturerName="<Your manufacturer name>" ;TODO: Replace with your manufacturer name
|
||||
ClassName="Samples" ; TODO: edit ClassName
|
||||
DiskName = "lpus Installation Disk"
|
||||
lpus.DeviceDesc = "lpus Device"
|
||||
lpus.SVCDESC = "lpus Service"
|
168
lpus/lpus.vcxproj
Normal file
168
lpus/lpus.vcxproj
Normal file
@ -0,0 +1,168 @@
|
||||
<?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>{905D3C7D-3EAD-4977-975E-B1FFD3E6FBE4}</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>lpus</RootNamespace>
|
||||
<ProjectName>lpus</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>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
</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>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
</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|x64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>$(DDK_LIB_PATH)\netio.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Inf Include="lpus.inf" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FilesToPackage Include="$(TargetPath)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Driver.cpp" />
|
||||
<ClCompile Include="simplewsk.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Driver.h" />
|
||||
<ClInclude Include="simplewsk.h" />
|
||||
<ClInclude Include="sioctl.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
45
lpus/lpus.vcxproj.filters
Normal file
45
lpus/lpus.vcxproj.filters
Normal file
@ -0,0 +1,45 @@
|
||||
<?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>
|
||||
<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>
|
||||
<Filter Include="Driver Files">
|
||||
<UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
|
||||
<Extensions>inf;inv;inx;mof;mc;</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Inf Include="lpus.inf">
|
||||
<Filter>Driver Files</Filter>
|
||||
</Inf>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Driver.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="simplewsk.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="sioctl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Driver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="simplewsk.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
53
lpus/note.md
Normal file
53
lpus/note.md
Normal file
@ -0,0 +1,53 @@
|
||||
Scanning the memory is not working well, we go with Pool tag quick scanning
|
||||
|
||||
[address in kernel space](https://www.codemachine.com/article_x64kvas.html)
|
||||
|
||||
find `MmNonPagedPoolStart` and `MmNonPagedPoolEnd` values in kernel variable.
|
||||
|
||||
These two variables located inside `KdDebuggerDataBlock` of type `_KDDEBUGGER_DATA64`. `KdDebuggerDataBlock` can be found somewhere in `KdVersionBlock`. `KdVersionBlock` is a member of `KPCR`. `KPCR` pointer can be get through `gs:[0x0]`
|
||||
|
||||
> Unfortunately this method stopped working in recent versions of Windows. Recently the KdVersionBlock member is always 0 and does not link to the kernel debugger block.
|
||||
|
||||
[kdbg.c](https://raw.githubusercontent.com/libvmi/libvmi/master/libvmi/os/windows/kdbg.c)
|
||||
|
||||
[KPCR at gs:[0x0]](https://sizzop.github.io/2016/07/07/kernel-hacking-with-hevd-part-3.html)
|
||||
|
||||
[finding kdbg](http://scudette.blogspot.com/2012/11/finding-kernel-debugger-block.html)
|
||||
|
||||
[finding kernel variables](http://moyix.blogspot.com/2008/04/finding-kernel-global-variables-in.html)
|
||||
|
||||
[get kernel shellcode](https://github.com/FuzzySecurity/PSKernel-Primitives/blob/master/Get-KernelShellCode.ps1)
|
||||
|
||||
[www.rootkit.com artifacts](https://github.com/fdiskyou/www.rootkit.com)
|
||||
- GetVarXP.pdf
|
||||
|
||||
[ghidra on fs/gs and kdbg](https://github.com/NationalSecurityAgency/ghidra/issues/1339)
|
||||
|
||||
[big ram kdbg](https://laserkittens.com/big-ram-kernel-debugger-data-block/)
|
||||
|
||||
[](blackstormsecurity.com/docs/NO_HAT_2019.pdf)
|
||||
|
||||
> KPCR -> KdVersionBlock -> `_DBGKD_GET_VERSION64` -> `LIST_ENTRY _KDDEBUGGER_DATA64` (`GetDebuggerData()`) -> `_KDDEBUGGER_DATA64 KdDebuggerDataBlock` -> kernel variables
|
||||
|
||||
|
||||
|
||||
> `_KPCR gs:[0]` -> `_DBGKD_GET_VERSION64 KdVersionBlock` -> `PLIST_ENTRY DebuggerDataList` -> `PLIST_ENTRY Flink` -> `Debugger block`
|
||||
|
||||
This only works with windows x86, x64 Windows KdVersionBlock is always null.
|
||||
|
||||
[KdVersionBlock](https://web.archive.org/web/20061110120809/http://www.rootkit.com/newsread.php?newsid=153)
|
||||
|
||||
```
|
||||
_DBGKD_GET_VERSION64* KdVersionBlock;
|
||||
__asm {
|
||||
mov eax, gs:[0x108]
|
||||
mov KdVersionBlock, eax
|
||||
}
|
||||
PLIST_ENTRY dbglist = KdVersionBlock->DebuggerDataList;
|
||||
DebuggerBlock dbgBlock = (DebuggerBlock)*(dbglist->Flink);
|
||||
```
|
||||
|
||||
|
||||
|
||||
`AuxKlibQueryModuleInformation` to get all `PsActiveProcessModules`
|
||||
[Sample](https://correy.webs.com/articles/computer/c/AuxKlibQueryModuleInformation.C.txt)
|
209
lpus/peformat.h
Normal file
209
lpus/peformat.h
Normal file
@ -0,0 +1,209 @@
|
||||
// Copyright Ric Vieler, 2006
|
||||
// Support header for hookManager.c
|
||||
// Contains required PE file format data structures used by GetFunctionAddress()
|
||||
|
||||
#ifndef _PE_FORMAT_HEADER_
|
||||
#define _PE_FORMAT_HEADER_
|
||||
|
||||
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned long DWORD;
|
||||
typedef long LONG;
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned long ULONG;
|
||||
typedef unsigned short USHORT;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef unsigned __int64 ULONGLONG;
|
||||
|
||||
|
||||
//
|
||||
// Image Format
|
||||
//
|
||||
|
||||
#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
|
||||
#define IMAGE_NT_SIGNATURE 0x00004550 // PE00
|
||||
|
||||
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
|
||||
WORD e_magic; // Magic number
|
||||
WORD e_cblp; // Bytes on last page of file
|
||||
WORD e_cp; // Pages in file
|
||||
WORD e_crlc; // Relocations
|
||||
WORD e_cparhdr; // Size of header in paragraphs
|
||||
WORD e_minalloc; // Minimum extra paragraphs needed
|
||||
WORD e_maxalloc; // Maximum extra paragraphs needed
|
||||
WORD e_ss; // Initial (relative) SS value
|
||||
WORD e_sp; // Initial SP value
|
||||
WORD e_csum; // Checksum
|
||||
WORD e_ip; // Initial IP value
|
||||
WORD e_cs; // Initial (relative) CS value
|
||||
WORD e_lfarlc; // File address of relocation table
|
||||
WORD e_ovno; // Overlay number
|
||||
WORD e_res[4]; // Reserved words
|
||||
WORD e_oemid; // OEM identifier (for e_oeminfo)
|
||||
WORD e_oeminfo; // OEM information; e_oemid specific
|
||||
WORD e_res2[10]; // Reserved words
|
||||
LONG e_lfanew; // File address of new exe header
|
||||
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
|
||||
|
||||
|
||||
//
|
||||
// File header format.
|
||||
//
|
||||
|
||||
typedef struct _IMAGE_FILE_HEADER {
|
||||
WORD Machine;
|
||||
WORD NumberOfSections;
|
||||
DWORD TimeDateStamp;
|
||||
DWORD PointerToSymbolTable;
|
||||
DWORD NumberOfSymbols;
|
||||
WORD SizeOfOptionalHeader;
|
||||
WORD Characteristics;
|
||||
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
|
||||
|
||||
|
||||
//
|
||||
// Directory format.
|
||||
//
|
||||
|
||||
typedef struct _IMAGE_DATA_DIRECTORY {
|
||||
DWORD VirtualAddress;
|
||||
DWORD Size;
|
||||
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
|
||||
|
||||
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
|
||||
|
||||
//
|
||||
// Optional header format.
|
||||
//
|
||||
|
||||
typedef struct _IMAGE_OPTIONAL_HEADER {
|
||||
//
|
||||
// Standard fields.
|
||||
//
|
||||
|
||||
WORD Magic;
|
||||
BYTE MajorLinkerVersion;
|
||||
BYTE MinorLinkerVersion;
|
||||
DWORD SizeOfCode;
|
||||
DWORD SizeOfInitializedData;
|
||||
DWORD SizeOfUninitializedData;
|
||||
DWORD AddressOfEntryPoint;
|
||||
DWORD BaseOfCode;
|
||||
DWORD BaseOfData;
|
||||
|
||||
//
|
||||
// NT additional fields.
|
||||
//
|
||||
|
||||
DWORD ImageBase;
|
||||
DWORD SectionAlignment;
|
||||
DWORD FileAlignment;
|
||||
WORD MajorOperatingSystemVersion;
|
||||
WORD MinorOperatingSystemVersion;
|
||||
WORD MajorImageVersion;
|
||||
WORD MinorImageVersion;
|
||||
WORD MajorSubsystemVersion;
|
||||
WORD MinorSubsystemVersion;
|
||||
DWORD Win32VersionValue;
|
||||
DWORD SizeOfImage;
|
||||
DWORD SizeOfHeaders;
|
||||
DWORD CheckSum;
|
||||
WORD Subsystem;
|
||||
WORD DllCharacteristics;
|
||||
DWORD SizeOfStackReserve;
|
||||
DWORD SizeOfStackCommit;
|
||||
DWORD SizeOfHeapReserve;
|
||||
DWORD SizeOfHeapCommit;
|
||||
DWORD LoaderFlags;
|
||||
DWORD NumberOfRvaAndSizes;
|
||||
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
|
||||
|
||||
typedef struct _IMAGE_OPTIONAL_HEADER64 {
|
||||
WORD Magic;
|
||||
BYTE MajorLinkerVersion;
|
||||
BYTE MinorLinkerVersion;
|
||||
DWORD SizeOfCode;
|
||||
DWORD SizeOfInitializedData;
|
||||
DWORD SizeOfUninitializedData;
|
||||
DWORD AddressOfEntryPoint;
|
||||
DWORD BaseOfCode;
|
||||
ULONGLONG ImageBase;
|
||||
DWORD SectionAlignment;
|
||||
DWORD FileAlignment;
|
||||
WORD MajorOperatingSystemVersion;
|
||||
WORD MinorOperatingSystemVersion;
|
||||
WORD MajorImageVersion;
|
||||
WORD MinorImageVersion;
|
||||
WORD MajorSubsystemVersion;
|
||||
WORD MinorSubsystemVersion;
|
||||
DWORD Win32VersionValue;
|
||||
DWORD SizeOfImage;
|
||||
DWORD SizeOfHeaders;
|
||||
DWORD CheckSum;
|
||||
WORD Subsystem;
|
||||
WORD DllCharacteristics;
|
||||
ULONGLONG SizeOfStackReserve;
|
||||
ULONGLONG SizeOfStackCommit;
|
||||
ULONGLONG SizeOfHeapReserve;
|
||||
ULONGLONG SizeOfHeapCommit;
|
||||
DWORD LoaderFlags;
|
||||
DWORD NumberOfRvaAndSizes;
|
||||
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
|
||||
|
||||
typedef struct _IMAGE_NT_HEADERS {
|
||||
ULONG Signature;
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
IMAGE_OPTIONAL_HEADER OptionalHeader;
|
||||
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
|
||||
|
||||
typedef struct _IMAGE_NT_HEADER64 {
|
||||
DWORD Signature;
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
|
||||
} IMAGE_NT_HEADER64, *PIMAGE_NT_HEADER64;
|
||||
|
||||
#define IMAGE_SIZEOF_SHORT_NAME 8
|
||||
|
||||
typedef struct _IMAGE_SECTION_HEADER {
|
||||
UCHAR Name[IMAGE_SIZEOF_SHORT_NAME];
|
||||
union {
|
||||
ULONG PhysicalAddress;
|
||||
ULONG VirtualSize;
|
||||
} Misc;
|
||||
ULONG VirtualAddress;
|
||||
ULONG SizeOfRawData;
|
||||
ULONG PointerToRawData;
|
||||
ULONG PointerToRelocations;
|
||||
ULONG PointerToLinenumbers;
|
||||
USHORT NumberOfRelocations;
|
||||
USHORT NumberOfLinenumbers;
|
||||
ULONG Characteristics;
|
||||
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
|
||||
|
||||
//
|
||||
// Export Format
|
||||
//
|
||||
|
||||
typedef struct _IMAGE_EXPORT_DIRECTORY {
|
||||
DWORD Characteristics;
|
||||
DWORD TimeDateStamp;
|
||||
WORD MajorVersion;
|
||||
WORD MinorVersion;
|
||||
DWORD Name;
|
||||
DWORD Base;
|
||||
DWORD NumberOfFunctions;
|
||||
DWORD NumberOfNames;
|
||||
DWORD AddressOfFunctions; // RVA from base of image
|
||||
DWORD AddressOfNames; // RVA from base of image
|
||||
DWORD AddressOfNameOrdinals; // RVA from base of image
|
||||
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
|
||||
|
||||
// Directory Entries
|
||||
|
||||
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory
|
||||
|
||||
#endif
|
||||
|
||||
|
479
lpus/simplewsk.c
Normal file
479
lpus/simplewsk.c
Normal file
@ -0,0 +1,479 @@
|
||||
/*++
|
||||
|
||||
Module Name:
|
||||
|
||||
simplewsk.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Wrapper library for WSK functions
|
||||
|
||||
Author:
|
||||
|
||||
MaD, 12-May-2009
|
||||
|
||||
--*/
|
||||
|
||||
#include "simplewsk.h"
|
||||
|
||||
static WSK_REGISTRATION g_WskRegistration;
|
||||
static WSK_PROVIDER_NPI g_WskProvider;
|
||||
static WSK_CLIENT_DISPATCH g_WskDispatch = {MAKE_WSK_VERSION(1, 0), 0, NULL};
|
||||
|
||||
enum { DEINITIALIZED, DEINITIALIZING, INITIALIZING, INITIALIZED };
|
||||
|
||||
static LONG g_SocketsState = DEINITIALIZED;
|
||||
|
||||
static NTSTATUS NTAPI CompletionRoutine(__in PDEVICE_OBJECT DeviceObject,
|
||||
__in PIRP Irp,
|
||||
__in PKEVENT CompletionEvent) {
|
||||
ASSERT(CompletionEvent);
|
||||
|
||||
UNREFERENCED_PARAMETER(Irp);
|
||||
UNREFERENCED_PARAMETER(DeviceObject);
|
||||
|
||||
KeSetEvent(CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
static NTSTATUS InitWskData(__out PIRP* pIrp, __out PKEVENT CompletionEvent) {
|
||||
ASSERT(pIrp);
|
||||
ASSERT(CompletionEvent);
|
||||
|
||||
*pIrp = IoAllocateIrp(1, FALSE);
|
||||
if (!*pIrp) {
|
||||
KdPrint(("InitWskData(): IoAllocateIrp() failed\n"));
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
KeInitializeEvent(CompletionEvent, SynchronizationEvent, FALSE);
|
||||
IoSetCompletionRoutine(*pIrp, CompletionRoutine, CompletionEvent, TRUE, TRUE,
|
||||
TRUE);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS InitWskBuffer(__in PVOID Buffer, __in ULONG BufferSize,
|
||||
__out PWSK_BUF WskBuffer) {
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
ASSERT(Buffer);
|
||||
ASSERT(BufferSize);
|
||||
ASSERT(WskBuffer);
|
||||
|
||||
WskBuffer->Offset = 0;
|
||||
WskBuffer->Length = BufferSize;
|
||||
|
||||
WskBuffer->Mdl = IoAllocateMdl(Buffer, BufferSize, FALSE, FALSE, NULL);
|
||||
if (!WskBuffer->Mdl) {
|
||||
KdPrint(("InitWskBuffer(): IoAllocateMdl() failed\n"));
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
__try {
|
||||
MmProbeAndLockPages(WskBuffer->Mdl, KernelMode, IoWriteAccess);
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
KdPrint(("InitWskBuffer(): MmProbeAndLockPages(%p) failed\n", Buffer));
|
||||
IoFreeMdl(WskBuffer->Mdl);
|
||||
Status = STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static VOID FreeWskBuffer(__in PWSK_BUF WskBuffer) {
|
||||
ASSERT(WskBuffer);
|
||||
|
||||
MmUnlockPages(WskBuffer->Mdl);
|
||||
IoFreeMdl(WskBuffer->Mdl);
|
||||
}
|
||||
|
||||
//
|
||||
// Library initialization routine
|
||||
//
|
||||
|
||||
NTSTATUS NTAPI WSKStartup() {
|
||||
WSK_CLIENT_NPI WskClient = {0};
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (InterlockedCompareExchange(&g_SocketsState, INITIALIZING,
|
||||
DEINITIALIZED) != DEINITIALIZED)
|
||||
return STATUS_ALREADY_REGISTERED;
|
||||
|
||||
WskClient.ClientContext = NULL;
|
||||
WskClient.Dispatch = &g_WskDispatch;
|
||||
|
||||
Status = WskRegister(&WskClient, &g_WskRegistration);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(("WskRegister() failed with status 0x%08X\n", Status));
|
||||
InterlockedExchange(&g_SocketsState, DEINITIALIZED);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status =
|
||||
WskCaptureProviderNPI(&g_WskRegistration, WSK_NO_WAIT, &g_WskProvider);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(("WskCaptureProviderNPI() failed with status 0x%08X\n", Status));
|
||||
WskDeregister(&g_WskRegistration);
|
||||
InterlockedExchange(&g_SocketsState, DEINITIALIZED);
|
||||
return Status;
|
||||
}
|
||||
|
||||
InterlockedExchange(&g_SocketsState, INITIALIZED);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Library deinitialization routine
|
||||
//
|
||||
|
||||
VOID NTAPI WSKCleanup() {
|
||||
if (InterlockedCompareExchange(&g_SocketsState, INITIALIZED,
|
||||
DEINITIALIZING) != INITIALIZED)
|
||||
return;
|
||||
|
||||
WskReleaseProviderNPI(&g_WskRegistration);
|
||||
WskDeregister(&g_WskRegistration);
|
||||
|
||||
InterlockedExchange(&g_SocketsState, DEINITIALIZED);
|
||||
}
|
||||
|
||||
PWSK_SOCKET
|
||||
NTAPI
|
||||
CreateSocket(__in ADDRESS_FAMILY AddressFamily, __in USHORT SocketType,
|
||||
__in ULONG Protocol, __in ULONG Flags) {
|
||||
KEVENT CompletionEvent = {0};
|
||||
PIRP Irp = NULL;
|
||||
PWSK_SOCKET WskSocket = NULL;
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (g_SocketsState != INITIALIZED) return NULL;
|
||||
|
||||
Status = InitWskData(&Irp, &CompletionEvent);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(
|
||||
("CreateSocket(): InitWskData() failed with status 0x%08X\n", Status));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Status = g_WskProvider.Dispatch->WskSocket(
|
||||
g_WskProvider.Client, AddressFamily, SocketType, Protocol, Flags, NULL,
|
||||
NULL, NULL, NULL, NULL, Irp);
|
||||
if (Status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
WskSocket =
|
||||
NT_SUCCESS(Status) ? (PWSK_SOCKET)Irp->IoStatus.Information : NULL;
|
||||
|
||||
IoFreeIrp(Irp);
|
||||
return (PWSK_SOCKET)WskSocket;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CloseSocket(__in PWSK_SOCKET WskSocket) {
|
||||
KEVENT CompletionEvent = {0};
|
||||
PIRP Irp = NULL;
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (g_SocketsState != INITIALIZED || !WskSocket)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
Status = InitWskData(&Irp, &CompletionEvent);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(
|
||||
("CloseSocket(): InitWskData() failed with status 0x%08X\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ((PWSK_PROVIDER_BASIC_DISPATCH)WskSocket->Dispatch)
|
||||
->WskCloseSocket(WskSocket, Irp);
|
||||
if (Status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
IoFreeIrp(Irp);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
Connect(__in PWSK_SOCKET WskSocket, __in PSOCKADDR RemoteAddress) {
|
||||
KEVENT CompletionEvent = {0};
|
||||
PIRP Irp = NULL;
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (g_SocketsState != INITIALIZED || !WskSocket || !RemoteAddress)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
Status = InitWskData(&Irp, &CompletionEvent);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(("Connect(): InitWskData() failed with status 0x%08X\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH)WskSocket->Dispatch)
|
||||
->WskConnect(WskSocket, RemoteAddress, 0, Irp);
|
||||
if (Status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
IoFreeIrp(Irp);
|
||||
return Status;
|
||||
}
|
||||
|
||||
PWSK_SOCKET
|
||||
NTAPI
|
||||
SocketConnect(__in USHORT SocketType, __in ULONG Protocol,
|
||||
__in PSOCKADDR RemoteAddress, __in PSOCKADDR LocalAddress) {
|
||||
KEVENT CompletionEvent = {0};
|
||||
PIRP Irp = NULL;
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
PWSK_SOCKET WskSocket = NULL;
|
||||
|
||||
if (g_SocketsState != INITIALIZED || !RemoteAddress || !LocalAddress)
|
||||
return NULL;
|
||||
|
||||
Status = InitWskData(&Irp, &CompletionEvent);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(("InitWskData() failed with status 0x%08X\n", Status));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Status = g_WskProvider.Dispatch->WskSocketConnect(
|
||||
g_WskProvider.Client, SocketType, Protocol, LocalAddress, RemoteAddress,
|
||||
0, NULL, NULL, NULL, NULL, NULL, Irp);
|
||||
if (Status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
WskSocket =
|
||||
NT_SUCCESS(Status) ? (PWSK_SOCKET)Irp->IoStatus.Information : NULL;
|
||||
|
||||
IoFreeIrp(Irp);
|
||||
return WskSocket;
|
||||
}
|
||||
|
||||
LONG NTAPI Send(__in PWSK_SOCKET WskSocket, __in PVOID Buffer,
|
||||
__in ULONG BufferSize, __in ULONG Flags) {
|
||||
KEVENT CompletionEvent = {0};
|
||||
PIRP Irp = NULL;
|
||||
WSK_BUF WskBuffer = {0};
|
||||
LONG BytesSent = SOCKET_ERROR;
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || !BufferSize)
|
||||
return SOCKET_ERROR;
|
||||
|
||||
Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(("Send(): InitWskData() failed with status 0x%08X\n", Status));
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
Status = InitWskData(&Irp, &CompletionEvent);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(("Send(): InitWskData() failed with status 0x%08X\n", Status));
|
||||
FreeWskBuffer(&WskBuffer);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH)WskSocket->Dispatch)
|
||||
->WskSend(WskSocket, &WskBuffer, Flags, Irp);
|
||||
if (Status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
BytesSent =
|
||||
NT_SUCCESS(Status) ? (LONG)Irp->IoStatus.Information : SOCKET_ERROR;
|
||||
|
||||
IoFreeIrp(Irp);
|
||||
FreeWskBuffer(&WskBuffer);
|
||||
return BytesSent;
|
||||
}
|
||||
|
||||
LONG NTAPI SendTo(__in PWSK_SOCKET WskSocket, __in PVOID Buffer,
|
||||
__in ULONG BufferSize, __in_opt PSOCKADDR RemoteAddress) {
|
||||
KEVENT CompletionEvent = {0};
|
||||
PIRP Irp = NULL;
|
||||
WSK_BUF WskBuffer = {0};
|
||||
LONG BytesSent = SOCKET_ERROR;
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || !BufferSize)
|
||||
return SOCKET_ERROR;
|
||||
|
||||
Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(("SendTo(): InitWskData() failed with status 0x%08X\n", Status));
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
Status = InitWskData(&Irp, &CompletionEvent);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(("SendTo(): InitWskData() failed with status 0x%08X\n", Status));
|
||||
FreeWskBuffer(&WskBuffer);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
Status =
|
||||
((PWSK_PROVIDER_DATAGRAM_DISPATCH)WskSocket->Dispatch)
|
||||
->WskSendTo(WskSocket, &WskBuffer, 0, RemoteAddress, 0, NULL, Irp);
|
||||
if (Status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
BytesSent =
|
||||
NT_SUCCESS(Status) ? (LONG)Irp->IoStatus.Information : SOCKET_ERROR;
|
||||
|
||||
IoFreeIrp(Irp);
|
||||
FreeWskBuffer(&WskBuffer);
|
||||
return BytesSent;
|
||||
}
|
||||
|
||||
LONG NTAPI Receive(__in PWSK_SOCKET WskSocket, __out PVOID Buffer,
|
||||
__in ULONG BufferSize, __in ULONG Flags) {
|
||||
KEVENT CompletionEvent = {0};
|
||||
PIRP Irp = NULL;
|
||||
WSK_BUF WskBuffer = {0};
|
||||
LONG BytesReceived = SOCKET_ERROR;
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || !BufferSize)
|
||||
return SOCKET_ERROR;
|
||||
|
||||
Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(("Receive(): InitWskData() failed with status 0x%08X\n", Status));
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
Status = InitWskData(&Irp, &CompletionEvent);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(("Receive(): InitWskData() failed with status 0x%08X\n", Status));
|
||||
FreeWskBuffer(&WskBuffer);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH)WskSocket->Dispatch)
|
||||
->WskReceive(WskSocket, &WskBuffer, Flags, Irp);
|
||||
if (Status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
BytesReceived =
|
||||
NT_SUCCESS(Status) ? (LONG)Irp->IoStatus.Information : SOCKET_ERROR;
|
||||
|
||||
IoFreeIrp(Irp);
|
||||
FreeWskBuffer(&WskBuffer);
|
||||
return BytesReceived;
|
||||
}
|
||||
|
||||
LONG NTAPI ReceiveFrom(__in PWSK_SOCKET WskSocket, __out PVOID Buffer,
|
||||
__in ULONG BufferSize, __out_opt PSOCKADDR RemoteAddress,
|
||||
__out_opt PULONG ControlFlags) {
|
||||
KEVENT CompletionEvent = {0};
|
||||
PIRP Irp = NULL;
|
||||
WSK_BUF WskBuffer = {0};
|
||||
LONG BytesReceived = SOCKET_ERROR;
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || !BufferSize)
|
||||
return SOCKET_ERROR;
|
||||
|
||||
Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(
|
||||
("ReceiveFrom(): InitWskData() failed with status 0x%08X\n", Status));
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
Status = InitWskData(&Irp, &CompletionEvent);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(
|
||||
("ReceiveFrom(): InitWskData() failed with status 0x%08X\n", Status));
|
||||
FreeWskBuffer(&WskBuffer);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
Status = ((PWSK_PROVIDER_DATAGRAM_DISPATCH)WskSocket->Dispatch)
|
||||
->WskReceiveFrom(WskSocket, &WskBuffer, 0, RemoteAddress, 0,
|
||||
NULL, ControlFlags, Irp);
|
||||
if (Status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
BytesReceived =
|
||||
NT_SUCCESS(Status) ? (LONG)Irp->IoStatus.Information : SOCKET_ERROR;
|
||||
|
||||
IoFreeIrp(Irp);
|
||||
FreeWskBuffer(&WskBuffer);
|
||||
return BytesReceived;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
Bind(__in PWSK_SOCKET WskSocket, __in PSOCKADDR LocalAddress) {
|
||||
KEVENT CompletionEvent = {0};
|
||||
PIRP Irp = NULL;
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (g_SocketsState != INITIALIZED || !WskSocket || !LocalAddress)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
Status = InitWskData(&Irp, &CompletionEvent);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(("Bind(): InitWskData() failed with status 0x%08X\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH)WskSocket->Dispatch)
|
||||
->WskBind(WskSocket, LocalAddress, 0, Irp);
|
||||
if (Status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
IoFreeIrp(Irp);
|
||||
return Status;
|
||||
}
|
||||
|
||||
PWSK_SOCKET
|
||||
NTAPI
|
||||
Accept(__in PWSK_SOCKET WskSocket, __out_opt PSOCKADDR LocalAddress,
|
||||
__out_opt PSOCKADDR RemoteAddress) {
|
||||
KEVENT CompletionEvent = {0};
|
||||
PIRP Irp = NULL;
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
PWSK_SOCKET AcceptedSocket = NULL;
|
||||
|
||||
if (g_SocketsState != INITIALIZED || !WskSocket) return NULL;
|
||||
|
||||
Status = InitWskData(&Irp, &CompletionEvent);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
KdPrint(("Accept(): InitWskData() failed with status 0x%08X\n", Status));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Status = ((PWSK_PROVIDER_LISTEN_DISPATCH)WskSocket->Dispatch)
|
||||
->WskAccept(WskSocket, 0, NULL, NULL, LocalAddress,
|
||||
RemoteAddress, Irp);
|
||||
if (Status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
AcceptedSocket =
|
||||
NT_SUCCESS(Status) ? (PWSK_SOCKET)Irp->IoStatus.Information : NULL;
|
||||
|
||||
IoFreeIrp(Irp);
|
||||
return AcceptedSocket;
|
||||
}
|
55
lpus/simplewsk.h
Normal file
55
lpus/simplewsk.h
Normal file
@ -0,0 +1,55 @@
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201) // nameless struct/union
|
||||
#pragma warning(disable : 4214) // bit field types other than int
|
||||
|
||||
#pragma once
|
||||
#include <ntddk.h>
|
||||
#include <wsk.h>
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#define SOCKET_ERROR -1
|
||||
|
||||
NTSTATUS NTAPI WSKStartup();
|
||||
VOID NTAPI WSKCleanup();
|
||||
|
||||
PWSK_SOCKET
|
||||
NTAPI
|
||||
CreateSocket(__in ADDRESS_FAMILY AddressFamily, __in USHORT SocketType,
|
||||
__in ULONG Protocol, __in ULONG Flags);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CloseSocket(__in PWSK_SOCKET WskSocket);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
Connect(__in PWSK_SOCKET WskSocket, __in PSOCKADDR RemoteAddress);
|
||||
|
||||
PWSK_SOCKET
|
||||
NTAPI
|
||||
SocketConnect(__in USHORT SocketType, __in ULONG Protocol,
|
||||
__in PSOCKADDR RemoteAddress, __in PSOCKADDR LocalAddress);
|
||||
|
||||
LONG NTAPI Send(__in PWSK_SOCKET WskSocket, __in PVOID Buffer,
|
||||
__in ULONG BufferSize, __in ULONG Flags);
|
||||
|
||||
LONG NTAPI SendTo(__in PWSK_SOCKET WskSocket, __in PVOID Buffer,
|
||||
__in ULONG BufferSize, __in_opt PSOCKADDR RemoteAddress);
|
||||
|
||||
LONG NTAPI Receive(__in PWSK_SOCKET WskSocket, __out PVOID Buffer,
|
||||
__in ULONG BufferSize, __in ULONG Flags);
|
||||
|
||||
LONG NTAPI ReceiveFrom(__in PWSK_SOCKET WskSocket, __out PVOID Buffer,
|
||||
__in ULONG BufferSize, __out_opt PSOCKADDR RemoteAddress,
|
||||
__out_opt PULONG ControlFlags);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
Bind(__in PWSK_SOCKET WskSocket, __in PSOCKADDR LocalAddress);
|
||||
|
||||
PWSK_SOCKET
|
||||
NTAPI
|
||||
Accept(__in PWSK_SOCKET WskSocket, __out_opt PSOCKADDR LocalAddress,
|
||||
__out_opt PSOCKADDR RemoteAddress);
|
103
lpus/sioctl.h
Normal file
103
lpus/sioctl.h
Normal file
@ -0,0 +1,103 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 1997 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
SIOCTL.H
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
Defines the IOCTL codes that will be used by this driver. The IOCTL code
|
||||
contains a command identifier, plus other information about the device,
|
||||
the type of access with which the file must have been opened,
|
||||
and the type of buffering.
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _IOCTL_PROTOCOL_H
|
||||
#define _IOCTL_PROTOCOL_H
|
||||
|
||||
// Device type
|
||||
#define SIOCTL_TYPE 40000 // 32768 to 65535
|
||||
|
||||
// The IOCTL function codes from 0x800 to 0xFFF are for customer use.
|
||||
#define IOCTL_SETUP_OFFSETS \
|
||||
CTL_CODE(SIOCTL_TYPE, 0x900, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
|
||||
#define GET_KERNEL_BASE \
|
||||
CTL_CODE(SIOCTL_TYPE, 0x901, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
|
||||
#define SCAN_PS_ACTIVE_HEAD \
|
||||
CTL_CODE(SIOCTL_TYPE, 0x902, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
|
||||
#define SCAN_POOL \
|
||||
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 HIDE_PROCESS_BY_NAME \
|
||||
CTL_CODE(SIOCTL_TYPE, 0xA01, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
|
||||
#define DRIVER_FUNC_INSTALL 0x01
|
||||
#define DRIVER_FUNC_REMOVE 0x02
|
||||
|
||||
#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;
|
||||
ULONG tag;
|
||||
} SCAN_RANGE, *PSCAN_RANGE;
|
||||
|
||||
typedef struct _HIDE_PROCESS {
|
||||
CHAR name[15];
|
||||
ULONG64 size;
|
||||
} HIDE_PROCESS, *PHIDE_PROCESS;
|
||||
|
||||
typedef union _INPUT_DATA {
|
||||
OFFSET_VALUES offsetValues;
|
||||
DEREF_ADDR derefAddr;
|
||||
SCAN_RANGE scanRange;
|
||||
HIDE_PROCESS processHide;
|
||||
} 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
|
Reference in New Issue
Block a user