in one block of code fix errors

Severity Code Description Project File Line Suppression State Details
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 600
Error (active) E0145 function "ExSubscribeWnfStateChange" may not be initialized KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 61
Error (active) E0145 function "ExPublishWnfStateData" may not be initialized KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 62
Error (active) E0031 expression must have integral type KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 427
Error (active) E0031 expression must have integral type KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 432
Error (active) E0031 expression must have integral type KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 438
Error (active) E0142 expression must have pointer-to-object type but it has type "SIZE_T" (aka "unsigned long long") KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 461
Error (active) E0142 expression must have pointer-to-object type but it has type "unsigned long long" KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 462
Error (active) E0142 expression must have pointer-to-object type but it has type "unsigned long long" KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 463
Error (active) E0142 expression must have pointer-to-object type but it has type "SIZE_T" (aka "unsigned long long") KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 465
Error (active) E0142 expression must have pointer-to-object type but it has type "SIZE_T" (aka "unsigned long long") KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 467
Error (active) E0142 expression must have pointer-to-object type but it has type "SIZE_T" (aka "unsigned long long") KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 469
Error (active) E0142 expression must have pointer-to-object type but it has type "SIZE_T" (aka "unsigned long long") KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 471
Error (active) E0142 expression must have pointer-to-object type but it has type "SIZE_T" (aka "unsigned long long") KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 478
Error (active) E0142 expression must have pointer-to-object type but it has type "unsigned long long" KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 482
Error (active) E0119 cast to type "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") is not allowed KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 546
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 548
Error (active) E0020 identifier "BYTE" is undefined KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 552
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 555
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 556
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 558
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 566
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 598
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 599
Error (active) E0167 argument of type "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") is incompatible with parameter of type "PVOID" (aka "void *") KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 605
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 635
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 643
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 659
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 660
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 669
Error (active) E0167 argument of type "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") is incompatible with parameter of type "PVOID" (aka "void *") KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 674
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 682
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 682
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 698
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 704
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 708
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 712
Error (active) E0167 argument of type "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") is incompatible with parameter of type "PVOID" (aka "void *") KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 718
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 725
Error (active) E0008 missing closing quote KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 852
Error (active) E0018 expected a ')' KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 853
Error (active) E0020 identifier "ntStatus" is undefined KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 877
Error (active) E0020 identifier "bytesRead" is undefined KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 879
Error (active) E0029 expected an expression KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 887
Error (active) E0020 identifier "baseAddress" is undefined KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 892
Error (active) E0020 identifier "writeData" is undefined KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 893
Error (active) E0029 expected an expression KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 906
Error (active) E0065 expected a ';' KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 907
Error (active) E0020 identifier "uProcessImageName" is undefined KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 920
Error (active) E0169 expected a declaration KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 922
Error (active) E0169 expected a declaration KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 928
Error (active) E0169 expected a declaration KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 964
Error (active) E0169 expected a declaration KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 971
Error (active) E0137 expression must be a modifiable lvalue KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 986
Error (active) E0119 cast to type "EXSUBSCRIBEWNFSTATECHANGE" (aka "long (PVOID Subscription, ULONG64 StateName, ULONG ChangeStamp, PVOID Callback, PVOID CallbackContext, PVOID TypeId, ULONG SerializationGroup, ULONG Unknown)") is not allowed KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 986
Error (active) E0137 expression must be a modifiable lvalue KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 994
Error (active) E0119 cast to type "EXPUBLISHWNFSTATEDATA" (aka "long (ULONG64 StateName, PVOID Buffer, ULONG Length, PVOID TypeId, PVOID ExplicitScope, ULONG MatchingChangeStamp)") is not allowed KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 994
Error (active) E0119 cast to type "EXUNSUBSCRIBEWNFSTATECHANGE" (aka "long (PVOID Subscription)") is not allowed KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1002
Error (active) E0119 cast to type "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") is not allowed KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1116
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1118
Error (active) E0020 identifier "BYTE" is undefined KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1122
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1125
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1126
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1128
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1136
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1168
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1169
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1170
Error (active) E0167 argument of type "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") is incompatible with parameter of type "PVOID" (aka "void *") KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1175
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1205
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1213
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1229
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1230
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1239
Error (active) E0167 argument of type "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") is incompatible with parameter of type "PVOID" (aka "void *") KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1244
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1252
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1252
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1268
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1275
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1279
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1283
Error (active) E0167 argument of type "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") is incompatible with parameter of type "PVOID" (aka "void *") KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1289
Error (active) E3364 operator -> or ->* applied to "PINSTRUCTIONS" (aka "struct INSTRUCTIONS") instead of to a pointer type KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1296
Error (active) E0020 identifier "in" is undefined KMDF Driver1 C:\Users\ruth\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1376
Error (active) E0018 expected a ')' KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1376
Error (active) E0020 identifier "Create" is undefined KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1381
Error (active) E0008 missing closing quote KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1393
Error (active) E0018 expected a ')' KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1394
Error (active) E0020 identifier "ntStatus" is undefined KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1418
Error (active) E0020 identifier "bytesRead" is undefined KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1420
Error (active) E0029 expected an expression KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1428
Error (active) E0020 identifier "baseAddress" is undefined KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1433
Error (active) E0020 identifier "writeData" is undefined KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1434
Error (active) E0029 expected an expression KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1447
Error (active) E0065 expected a ';' KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1448
Error (active) E0020 identifier "uProcessImageName" is undefined KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1461
Error (active) E0169 expected a declaration KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1463
Error (active) E0169 expected a declaration KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1469
Error (active) E0169 expected a declaration KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1505
Error (active) E0169 expected a declaration KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1512
Error (active) E0137 expression must be a modifiable lvalue KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1527
Error (active) E0119 cast to type "EXSUBSCRIBEWNFSTATECHANGE" (aka "long (PVOID Subscription, ULONG64 StateName, ULONG ChangeStamp, PVOID Callback, PVOID CallbackContext, PVOID TypeId, ULONG SerializationGroup, ULONG Unknown)") is not allowed KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1527
Error (active) E0137 expression must be a modifiable lvalue KMDF Driver1 C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 1535
Warning VCR001 Function definition for 'ReadPhysicalAddress' not found. C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 95
Warning VCR001 Function definition for 'ReadVirtualMemory' not found. C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 102
Warning VCR001 Function definition for 'WriteVirtualMemory' not found. C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 103
Warning VCR001 Function definition for 'ReadProcessMemoryInternal' not found. C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 106
Warning VCR001 Function definition for 'EncodeBase64' not found. C:\Users\ruth_\source\repos\KMDF Driver1\KMDF Driver1\Driver.c 124
#include <ntifs.h>
#include <ntddk.h>

// ==========================================================
// Definitions and Macros
// ==========================================================

#define TARGET_PROCESS_NAME L"notepad.exe" // Replace with your target process name
#define MY_WNF_STATE_NAME 0x41C64E6DA3BC1074ULL // Example WNF State Name (WNF_AUDC_CAPTURE)

// Windows Build Numbers
#define WINDOWS_1803 17134
#define WINDOWS_1809 17763
#define WINDOWS_1903 18362
#define WINDOWS_1909 18363
#define WINDOWS_2004 19041
#define WINDOWS_20H2 19042
#define WINDOWS_21H1 19043
#define WINDOWS_22H2 19044

// Page size definitions
#define PAGE_OFFSET_SIZE 12
#define PAGE_SIZE 0x1000
#define PMASK (~0xFFFULL)

// Custom type definitions
typedef unsigned __int64 QWORD;

// ==========================================================
// Function Pointer Types for WNF (Undocumented APIs)
// ==========================================================

typedef NTSTATUS(EXSUBSCRIBEWNFSTATECHANGE)(
PVOID Subscription,
ULONG64 StateName,
ULONG ChangeStamp,
PVOID Callback,
PVOID CallbackContext,
PVOID TypeId,
ULONG SerializationGroup,
ULONG Unknown
);

typedef NTSTATUS(EXPUBLISHWNFSTATEDATA)(
ULONG64 StateName,
PVOID Buffer,
ULONG Length,
PVOID TypeId,
PVOID ExplicitScope,
ULONG MatchingChangeStamp
);

typedef NTSTATUS(EXUNSUBSCRIBEWNFSTATECHANGE)(
PVOID Subscription
);

// ==========================================================
// Global Function Pointers for WNF
// ==========================================================

EXSUBSCRIBEWNFSTATECHANGE ExSubscribeWnfStateChange = NULL;
EXPUBLISHWNFSTATEDATA ExPublishWnfStateData = NULL;
EXUNSUBSCRIBEWNFSTATECHANGE* ExUnsubscribeWnfStateChange = NULL;

ULONG64 MY_WNF_STATE_NAME_VALUE = MY_WNF_STATE_NAME; // Ensure consistency

PVOID g_WnfSubscription = NULL; // Global WNF subscription handle

// ==========================================================
// Structures
// ==========================================================

#pragma pack(push, 1)
typedef struct _INSTRUCTIONS {
UCHAR close; // Flag to close subscription
UCHAR read; // Flag to perform read operation
UCHAR write; // Flag to perform write operation
UCHAR reqBase; // Flag to request base address
UINT64 processId; // Target process ID
UINT64 address; // Target virtual address
UINT64 size; // Size of read/write
PVOID bufferAddress; // Buffer address in user-mode
PVOID output; // Output buffer (for read operations)
UINT64 baseAddress; // Base address (for base address requests)
CHAR moduleName[256]; // Module name (if needed)
UCHAR data[1024]; // Data buffer for read/write
} INSTRUCTIONS, PINSTRUCTIONS;
#pragma pack(pop)

// ==========================================================
// Function Declarations
// ==========================================================

// Physical Memory Access Functions
NTSTATUS ReadPhysicalAddress(PVOID TargetAddress, PVOID lpBuffer, SIZE_T Size, SIZE_T BytesRead);
NTSTATUS WritePhysicalAddress(PVOID TargetAddress, PVOID lpBuffer, SIZE_T Size, SIZE_T* BytesWritten);
ULONG GetUserDirectoryTableBaseOffset();
ULONG_PTR GetProcessCr3(PEPROCESS pProcess);
ULONG64 TranslateLinearAddress(ULONG64 directoryTableBase, ULONG64 virtualAddress);

// Memory Operations
NTSTATUS ReadVirtualMemory(ULONG_PTR directoryTableBase, ULONG_PTR virtualAddress, PVOID buffer, SIZE_T size, SIZE_T* bytesRead);
NTSTATUS WriteVirtualMemory(ULONG_PTR directoryTableBase, ULONG_PTR virtualAddress, PVOID buffer, SIZE_T size, SIZE_T* bytesWritten);

// Process Memory Operations
NTSTATUS ReadProcessMemoryInternal(HANDLE pid, PVOID Address, PVOID Buffer, SIZE_T Size, SIZE_T* BytesRead);
NTSTATUS WriteProcessMemoryInternal(HANDLE pid, PVOID Address, PVOID Buffer, SIZE_T Size, SIZE_T* BytesWritten);

// WNF Communication
NTSTATUS OnWnfCallback(
PVOID Subscription,
ULONG64 StateName,
ULONG ChangeStamp,
PVOID TypeId,
PVOID CallbackContext,
PVOID Buffer,
ULONG BufferSize
);
NTSTATUS SubscribeToWNF();

// Base64 Encoding/Decoding
UCHAR Base64DecodeChar(char c);
NTSTATUS DecodeBase64(const CHAR* base64Input, UCHAR* outputBuffer, SIZE_T bufferSize, SIZE_T* decodedSize);
NTSTATUS EncodeBase64(const UCHAR* input, SIZE_T inputSize, CHAR* outputBuffer, SIZE_T bufferSize, SIZE_T* encodedSize);

// Process Notification
VOID ProcessNotifyCallback(
__in HANDLE ParentId,
__in HANDLE ProcessId,
__in BOOLEAN Create
);

// Driver Unload
VOID DriverUnloadRoutine(PDRIVER_OBJECT DriverObject);

// Driver Entry
NTSTATUS DriverEntryRoutine(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);

// Helper Functions
PVOID GetProcessBaseAddress(HANDLE pid);

// ==========================================================
// Function Definitions
// ==========================================================

// Get the offset for UserDirectoryTableBase based on Windows version
ULONG GetUserDirectoryTableBaseOffset()
{
RTL_OSVERSIONINFOW ver = { 0 };
RtlGetVersion(&ver);
switch (ver.dwBuildNumber)
{
case WINDOWS_1803:
case WINDOWS_1809:
return 0x0278;
case WINDOWS_1903:
case WINDOWS_1909:
return 0x0280;
case WINDOWS_2004:
case WINDOWS_20H2:
case WINDOWS_21H1:
case WINDOWS_22H2:
default:
return 0x0388;
}
}

// Read physical memory
NTSTATUS ReadPhysicalAddress(PVOID TargetAddress, PVOID lpBuffer, SIZE_T Size, SIZE_T* BytesRead)
{
if (!TargetAddress || !lpBuffer || !BytesRead)
return STATUS_INVALID_PARAMETER;

MM_COPY_ADDRESS AddrToRead = { 0 };
AddrToRead.PhysicalAddress.QuadPart = (ULONGLONG)TargetAddress;

NTSTATUS status = MmCopyMemory(lpBuffer, AddrToRead, Size, MM_COPY_MEMORY_PHYSICAL, BytesRead);
return status;
}

// Write physical memory
NTSTATUS WritePhysicalAddress(PVOID TargetAddress, PVOID lpBuffer, SIZE_T Size, SIZE_T* BytesWritten)
{
if (!TargetAddress || !lpBuffer || !BytesWritten)
return STATUS_INVALID_PARAMETER;

PHYSICAL_ADDRESS AddrToWrite;
AddrToWrite.QuadPart = (ULONGLONG)TargetAddress;

PVOID pmapped_mem = MmMapIoSpaceEx(AddrToWrite, Size, PAGE_READWRITE);
if (!pmapped_mem)
return STATUS_UNSUCCESSFUL;

RtlCopyMemory(pmapped_mem, lpBuffer, Size);
BytesWritten = Size;
MmUnmapIoSpace(pmapped_mem, Size);
return STATUS_SUCCESS;
}

// Retrieve the CR3 (Page Directory Base) of a process
ULONG_PTR GetProcessCr3(PEPROCESS pProcess)
{
PUCHAR process = (PUCHAR)pProcess;
#ifdef _WIN64
ULONG_PTR process_dirbase_ptr = (ULONG_PTR*)(process + 0x28); // dirbase for x64
#else
ULONG_PTR* process_dirbase_ptr = (ULONG_PTR*)(process + 0x18); // dirbase for x86
#endif
ULONG_PTR process_dirbase = process_dirbase_ptr;

if (process_dirbase == 0)
{
ULONG UserDirOffset = GetUserDirectoryTableBaseOffset();
ULONG_PTR process_userdirbase = (ULONG_PTR)(process + UserDirOffset);
return process_userdirbase;
}
return process_dirbase;
}

// Translate a virtual address to a physical address using the provided directory table base
ULONG64 TranslateLinearAddress(ULONG64 directoryTableBase, ULONG64 virtualAddress)
{
directoryTableBase &= PMASK; // Align directoryTableBase

ULONG64 pageOffset = virtualAddress & 0xFFFULL;
ULONG64 pteIndex = (virtualAddress >> 12) & 0x1FFULL;
ULONG64 ptIndex = (virtualAddress >> 21) & 0x1FFULL;
ULONG64 pdIndex = (virtualAddress >> 30) & 0x1FFULL;
ULONG64 pdpIndex = (virtualAddress >> 39) & 0x1FFULL;

SIZE_T readsize = 0;
ULONG64 pdpe = 0;

// Read PDPE
NTSTATUS status = ReadPhysicalAddress((PVOID)(directoryTableBase + 8 * pdpIndex), &pdpe, sizeof(pdpe), &readsize);
if (!NT_SUCCESS(status) || !(pdpe & 1))
return 0;

// Read PDE
ULONG64 pde = 0;
status = ReadPhysicalAddress((PVOID)((pdpe & PMASK) + 8 * pdIndex), &pde, sizeof(pde), &readsize);
if (!NT_SUCCESS(status) || !(pde & 1))
return 0;

// 1GB large page
if (pde & (1 << 7)) // PS bit
return (pde & 0xFFFFFC0000000ULL) + (virtualAddress & 0x3FFFFFFFULL);

// Read PTE
ULONG64 pteAddr = 0;
status = ReadPhysicalAddress((PVOID)((pde & PMASK) + 8 * ptIndex), &pteAddr, sizeof(pteAddr), &readsize);
if (!NT_SUCCESS(status) || !(pteAddr & 1))
return 0;

// 2MB large page
if (pteAddr & (1 << 7)) // PS bit
return (pteAddr & PMASK) + (virtualAddress & 0x1FFFFFULL);

// Read Page Table Entry
ULONG64 pageTableEntry = 0;
status = ReadPhysicalAddress((PVOID)((pteAddr & PMASK) + 8 * pteIndex), &pageTableEntry, sizeof(pageTableEntry), &readsize);
if (!NT_SUCCESS(status) || !(pageTableEntry & 1))
return 0;

ULONG64 physAddress = (pageTableEntry & PMASK) + pageOffset;
return physAddress;
}

// Read virtual memory using physical address translation
NTSTATUS ReadVirtualMemory(ULONG_PTR directoryTableBase, ULONG_PTR virtualAddress, PVOID buffer, SIZE_T size, SIZE_T bytesRead)
{
if (!buffer || !bytesRead)
return STATUS_INVALID_PARAMETER;

SIZE_T totalBytesRead = 0;
SIZE_T bytesToRead = size;
NTSTATUS status = STATUS_SUCCESS;

while (bytesToRead > 0)
{
ULONG64 physAddress = TranslateLinearAddress(directoryTableBase, virtualAddress);
if (!physAddress)
{
status = STATUS_UNSUCCESSFUL;
break;
}

ULONG64 readSize = min(PAGE_SIZE - (physAddress & 0xFFFULL), bytesToRead);
SIZE_T localBytesRead = 0;
status = ReadPhysicalAddress((PVOID)physAddress, (PVOID)((ULONG_PTR)buffer + totalBytesRead), readSize, &localBytesRead);
if (!NT_SUCCESS(status) || localBytesRead == 0)
break;

bytesToRead -= localBytesRead;
virtualAddress += localBytesRead;
totalBytesRead += localBytesRead;
}

if (bytesRead)
bytesRead = totalBytesRead;
return status;
}

// Write virtual memory using physical address translation
NTSTATUS WriteVirtualMemory(ULONG_PTR directoryTableBase, ULONG_PTR virtualAddress, PVOID buffer, SIZE_T size, SIZE_T bytesWritten)
{
if (!buffer || !bytesWritten)
return STATUS_INVALID_PARAMETER;

SIZE_T totalBytesWritten = 0;
SIZE_T bytesToWrite = size;
NTSTATUS status = STATUS_SUCCESS;

while (bytesToWrite > 0)
{
ULONG64 physAddress = TranslateLinearAddress(directoryTableBase, virtualAddress);
if (!physAddress)
{
status = STATUS_UNSUCCESSFUL;
break;
}

ULONG64 writeSize = min(PAGE_SIZE - (physAddress & 0xFFFULL), bytesToWrite);
SIZE_T localBytesWritten = 0;
status = WritePhysicalAddress((PVOID)physAddress, (PVOID)((ULONG_PTR)buffer + totalBytesWritten), writeSize, &localBytesWritten);
if (!NT_SUCCESS(status) || localBytesWritten == 0)
break;

bytesToWrite -= localBytesWritten;
virtualAddress += localBytesWritten;
totalBytesWritten += localBytesWritten;
}

if (bytesWritten)
bytesWritten = totalBytesWritten;
return status;
}

// Internal ReadProcessMemory function
NTSTATUS ReadProcessMemoryInternal(HANDLE pid, PVOID Address, PVOID Buffer, SIZE_T Size, SIZE_T BytesRead)
{
if (pid == NULL || Address == NULL || Buffer == NULL || BytesRead == NULL)
return STATUS_INVALID_PARAMETER;

PEPROCESS pProcess = NULL;
NTSTATUS status = PsLookupProcessByProcessId(pid, &pProcess);
if (!NT_SUCCESS(status))
return status;

ULONG_PTR dirBase = GetProcessCr3(pProcess);
ObDereferenceObject(pProcess);

return ReadVirtualMemory(dirBase, (ULONG_PTR)Address, Buffer, Size, BytesRead);
}

// Internal WriteProcessMemory function
NTSTATUS WriteProcessMemoryInternal(HANDLE pid, PVOID Address, PVOID Buffer, SIZE_T Size, SIZE_T* BytesWritten)
{
if (pid == NULL || Address == NULL || Buffer == NULL || BytesWritten == NULL)
return STATUS_INVALID_PARAMETER;

PEPROCESS pProcess = NULL;
NTSTATUS status = PsLookupProcessByProcessId(pid, &pProcess);
if (!NT_SUCCESS(status))
return status;

ULONG_PTR dirBase = GetProcessCr3(pProcess);
ObDereferenceObject(pProcess);

return WriteVirtualMemory(dirBase, (ULONG_PTR)Address, Buffer, Size, BytesWritten);
}

// Base64 Decode a single character
UCHAR Base64DecodeChar(char c)
{
if (c >= 'A' && c <= 'Z') return c - 'A';
if (c >= 'a' && c <= 'z') return c - 'a' + 26;
if (c >= '0' && c <= '9') return c - '0' + 52;
if (c == '+') return 62;
if (c == '/') return 63;
return 0xFF; // Invalid character
}

// Decode Base64 string to binary
NTSTATUS DecodeBase64(const CHAR* base64Input, UCHAR* outputBuffer, SIZE_T bufferSize, SIZE_T* decodedSize)
{
if (!base64Input || !outputBuffer || !decodedSize)
return STATUS_INVALID_PARAMETER;

SIZE_T inputLen = strlen(base64Input);
if (inputLen % 4 != 0)
return STATUS_INVALID_PARAMETER;

SIZE_T outputLen = (inputLen / 4) * 3;
if (outputLen > bufferSize)
return STATUS_BUFFER_TOO_SMALL;

decodedSize = 0;

for (SIZE_T i = 0; i < inputLen; i += 4)
{
UCHAR sextet_a = Base64DecodeChar(base64Input[i]);
UCHAR sextet_b = Base64DecodeChar(base64Input[i + 1]);
UCHAR sextet_c = Base64DecodeChar(base64Input[i + 2]);
UCHAR sextet_d = Base64DecodeChar(base64Input[i + 3]);

if (sextet_a == 0xFF || sextet_b == 0xFF)
return STATUS_INVALID_PARAMETER;

UCHAR triple[3] = { 0 };

triple[0] = (sextet_a << 2) | (sextet_b >> 4);
if (base64Input[i + 2] != '=')
{
if (sextet_c == 0xFF)
return STATUS_INVALID_PARAMETER;
triple[1] = ((sextet_b & 0xF) << 4) | (sextet_c >> 2);
}
if (base64Input[i + 3] != '=')
{
if (sextet_d == 0xFF)
return STATUS_INVALID_PARAMETER;
triple[2] = ((sextet_c & 0x3) << 6) | sextet_d;
}

// Copy the decoded bytes to the output buffer
outputBuffer[decodedSize] = triple[0];
(decodedSize)++;

if (base64Input[i + 2] != '=')
{
outputBuffer[decodedSize] = triple[1];
(decodedSize)++;
}

if (base64Input[i + 3] != '=')
{
outputBuffer[decodedSize] = triple[2];
(decodedSize)++;
}
}

return STATUS_SUCCESS;
}

// Base64 Encode binary data to string
NTSTATUS EncodeBase64(const UCHAR input, SIZE_T inputSize, CHAR outputBuffer, SIZE_T bufferSize, SIZE_T encodedSize)
{
if (!input || !outputBuffer || !encodedSize)
return STATUS_INVALID_PARAMETER;

const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
SIZE_T outputNeeded = ((inputSize + 2) / 3) * 4;
if (outputNeeded + 1 > bufferSize) // +1 for null terminator
return STATUS_BUFFER_TOO_SMALL;

encodedSize = 0;

for (SIZE_T i = 0; i < inputSize; i += 3)
{
UCHAR a = input[i];
UCHAR b = (i + 1 < inputSize) ? input[i + 1] : 0;
UCHAR c = (i + 2 < inputSize) ? input[i + 2] : 0;

outputBuffer[encodedSize] = base64_table[(a >> 2) & 0x3F];
(encodedSize)++;
outputBuffer[encodedSize] = base64_table[((a & 0x3) << 4) | ((b & 0xF0) >> 4)];
(encodedSize)++;
outputBuffer[encodedSize] = (i + 1 < inputSize) ? base64_table[((b & 0xF) << 2) | ((c & 0xC0) >> 6)] : '=';
(encodedSize)++;
outputBuffer[encodedSize] = (i + 2 < inputSize) ? base64_table[c & 0x3F] : '=';
(encodedSize)++;
}

// Null-terminate the output
if (encodedSize < bufferSize)
{
outputBuffer[encodedSize] = '\0';
}
else
{
outputBuffer[bufferSize - 1] = '\0'; // Ensure null termination
}

return STATUS_SUCCESS;
}

// Retrieve the base address of a process given its PID
PVOID GetProcessBaseAddress(HANDLE pid)
{
if (pid == NULL)
return NULL;

PEPROCESS pProcess = NULL;
NTSTATUS status = PsLookupProcessByProcessId(pid, &pProcess);
if (!NT_SUCCESS(status))
return NULL;

PVOID Base = PsGetProcessSectionBaseAddress(pProcess);
ObDereferenceObject(pProcess);
return Base;
}

// Read process memory
NTSTATUS ReadProcessMemoryInternal(HANDLE pid, PVOID Address, PVOID Buffer, SIZE_T Size, SIZE_T BytesRead)
{
if (pid == NULL || Address == NULL || Buffer == NULL || BytesRead == NULL)
return STATUS_INVALID_PARAMETER;

return ReadProcessMemoryInternal(pid, Address, Buffer, Size, BytesRead);
}

// Write process memory
NTSTATUS WriteProcessMemoryInternal(HANDLE pid, PVOID Address, PVOID Buffer, SIZE_T Size, SIZE_T BytesWritten)
{
if (pid == NULL || Address == NULL || Buffer == NULL || BytesWritten == NULL)
return STATUS_INVALID_PARAMETER;

return WriteProcessMemoryInternal(pid, Address, Buffer, Size, BytesWritten);
}

// ==========================================================
// WNF Callback Function
// ==========================================================

NTSTATUS OnWnfCallback(
PVOID Subscription,
ULONG64 StateName,
ULONG ChangeStamp,
PVOID TypeId,
PVOID CallbackContext,
PVOID Buffer,
ULONG BufferSize
)
{
UNREFERENCED_PARAMETER(Subscription);
UNREFERENCED_PARAMETER(StateName);
UNREFERENCED_PARAMETER(ChangeStamp);
UNREFERENCED_PARAMETER(TypeId);
UNREFERENCED_PARAMETER(CallbackContext);

NTSTATUS status = STATUS_SUCCESS;

if (Buffer && BufferSize >= sizeof(INSTRUCTIONS))
{
PINSTRUCTIONS instructions = (PINSTRUCTIONS)Buffer;

if (instructions->read)
{
// Handle read request
SIZE_T bytesRead = 0;
BYTE readBuffer[1024] = { 0 };

status = ReadProcessMemoryInternal(
(HANDLE)(ULONGLONG)instructions->processId,
(PVOID)(ULONGLONG)instructions->address,
readBuffer,
(SIZE_T)instructions->size,
&bytesRead
);

if (NT_SUCCESS(status))
{
// Encode the read data to Base64
SIZE_T base64Size = ((bytesRead + 2) / 3) * 4;
if (base64Size + 1 > sizeof(instructions->data))
{
DbgPrint("[Driver] Read operation failed: Encoded data exceeds buffer size.\n");
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
"Read operation failed: Encoded data exceeds buffer size.",
(ULONG)strlen("Read operation failed: Encoded data exceeds buffer size.") + 1,
NULL,
NULL,
0
);
return status;
}

CHAR encodedData[4096] = { 0 };
SIZE_T encodedLength = 0;
status = EncodeBase64(readBuffer, bytesRead, encodedData, sizeof(encodedData), &encodedLength);
if (!NT_SUCCESS(status))
{
DbgPrint("[Driver] EncodeBase64 failed with status: 0x%X\n", status);
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
"Read operation failed: Base64 encode failed.",
(ULONG)strlen("Read operation failed: Base64 encode failed.") + 1,
NULL,
NULL,
0
);
return status;
}

// Prepare instructions to send back
RtlZeroMemory(instructions->data, sizeof(instructions->data));
RtlCopyMemory(instructions->data, encodedData, min(encodedLength, sizeof(instructions->data) - 1));
instructions->size = bytesRead;

// Publish the data back via WNF
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
instructions,
sizeof(INSTRUCTIONS),
NULL,
NULL,
0
);

if (NT_SUCCESS(status))
{
DbgPrint("[Driver] Read operation completed successfully. %zu bytes read, %zu bytes encoded.\n", bytesRead, encodedLength);
}
else
{
DbgPrint("[Driver] ExPublishWnfStateData failed with status: 0x%X\n", status);
}
}
else
{
// Handle read error
DbgPrint("[Driver] ReadProcessMemoryInternal failed with status: 0x%X\n", status);
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
"Read operation failed.",
(ULONG)strlen("Read operation failed.") + 1,
NULL,
NULL,
0
);
}
}
else if (instructions->write)
{
// Handle write request
SIZE_T bytesWritten = 0;

// Decode Base64 data
UCHAR decodedData[512] = { 0 };
SIZE_T decodedSize = 0;
status = DecodeBase64((CHAR)instructions->data, decodedData, sizeof(decodedData), &decodedSize);
if (!NT_SUCCESS(status))
{
DbgPrint("[Driver] DecodeBase64 failed with status: 0x%X\n", status);
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
"Write operation failed: Base64 decode failed.",
(ULONG)strlen("Write operation failed: Base64 decode failed.") + 1,
NULL,
NULL,
0
);
return status;
}

status = WriteProcessMemoryInternal(
(HANDLE)(ULONGLONG)instructions->processId,
(PVOID)(ULONGLONG)instructions->address,
decodedData,
decodedSize,
&bytesWritten
);

if (NT_SUCCESS(status) && bytesWritten == decodedSize)
{
// Prepare instruction to send back
instructions->size = bytesWritten;

// Publish the success message back via WNF
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
instructions,
sizeof(INSTRUCTIONS),
NULL,
NULL,
0
);

DbgPrint("[Driver] Write operation completed successfully. %zu bytes written to process %llu at address 0x%llX.\n",
bytesWritten, instructions->processId, instructions->address);
}
else
{
// Handle write error
DbgPrint("[Driver] WriteProcessMemoryInternal failed with status: 0x%X and bytes written: %zu\n", status, bytesWritten);
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
"Write operation failed.",
(ULONG)strlen("Write operation failed.") + 1,
NULL,
NULL,
0
);
}
}
else if (instructions->close)
{
// Handle close instruction
// Currently, no specific cleanup is required
DbgPrint("[Driver] Received close instruction.\n");
}
else if (instructions->reqBase)
{
// Handle base address request
PEPROCESS pProcess = NULL;
NTSTATUS statusLookup = PsLookupProcessByProcessId((HANDLE)(ULONGLONG)instructions->processId, &pProcess);
if (NT_SUCCESS(statusLookup))
{
PVOID baseAddress = PsGetProcessSectionBaseAddress(pProcess);
instructions->baseAddress = (UINT64)baseAddress;
ObDereferenceObject(pProcess);

// Publish the base address back via WNF
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
instructions,
sizeof(INSTRUCTIONS),
NULL,
NULL,
0
);

DbgPrint("[Driver] Base address of process %llu: %p\n", instructions->processId, baseAddress);
}
else
{
// Handle error
DbgPrint("[Driver] PsLookupProcessByProcessId failed with status: 0x%X\n", statusLookup);
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
"Base address request failed: PsLookupProcessByProcessId failed.",
(ULONG)strlen("Base address request failed: PsLookupProcessByProcessId failed.") + 1,
NULL,
NULL,
0
);
}
}
// Additional instruction handling can be added here
}
else if (Buffer && BufferSize > 0)
{
// Handle simple messages like "Hi"
CHAR receivedMessage = (CHAR)ExAllocatePoolWithTag(NonPagedPoolNx, BufferSize + 1, 'msgK');
if (!receivedMessage)
{
DbgPrint("[Driver] Failed to allocate memory for received message.\n");
return STATUS_INSUFFICIENT_RESOURCES;
}

RtlZeroMemory(receivedMessage, BufferSize + 1);
RtlCopyMemory(receivedMessage, Buffer, min(BufferSize, sizeof(receivedMessage) - 1));

DbgPrint("[Driver] Kernel received message: %s\n", receivedMessage);

if (strcmp(receivedMessage, "Hi") == 0)
{
// Send handshake response
const CHAR responseMessage = "Hello from kernel mode";
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
(PVOID)responseMessage,
(ULONG)strlen(responseMessage) + 1,
NULL,
NULL,
0
);

if (NT_SUCCESS(status))
{
DbgPrint("[Driver] Handshake response sent successfully.\n");
}
else
{
DbgPrint("[Driver] Failed to send handshake response with status: 0x%X\n", status);
}
}

ExFreePoolWithTag(receivedMessage, 'msgK');
}
else
{
// Handle unexpected or unsupported data
DbgPrint("[Driver] Received invalid or unsupported data.\n");
}

return status;
}

// ==========================================================
// WNF Subscription Function
// ==========================================================

// Subscribe to WNF state changes
NTSTATUS SubscribeToWNF()
{
if (!ExSubscribeWnfStateChange || !ExPublishWnfStateData || !ExUnsubscribeWnfStateChange)
{
DbgPrint("[Driver] WNF function pointers not initialized.\n");
return STATUS_UNSUCCESSFUL;
}

NTSTATUS status = ExSubscribeWnfStateChange(
g_WnfSubscription,
MY_WNF_STATE_NAME_VALUE,
0, // ChangeStamp (0 for all changes)
(PVOID)OnWnfCallback,
NULL, // CallbackContext
NULL, // TypeId
0, // SerializationGroup
0 // Unknown
);

if (NT_SUCCESS(status))
{
DbgPrint("[Driver] Successfully subscribed to WNF state changes.\n");
}
else
{
DbgPrint("[Driver] ExSubscribeWnfStateChange failed with status: 0x%X\n", status);
}

return status;
}

// ==========================================================
// Process Notification Callback
// ==========================================================

VOID ProcessNotifyCallback(
__in HANDLE ParentId,
__in HANDLE ProcessId,
__in BOOLEAN Create
)
{
UNREFERENCED_PARAMETER(ParentId);

if (Create)
{
PEPROCESS pProcess = NULL;
NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &pProcess);
if (NT_SUCCESS(status))
{
// Get process image file name
UNICODE_STRING uProcessImageName = { 0 };
status = SeLocateProcessImageName(pProcess, &uProcessImageName);
if (NT_SUCCESS(status))
{
// Extract file name from full path
PWSTR processName = wcsrchr(uProcessImageName.Buffer, L''); // Corrected backslash
if (processName)
{
processName++; // Move past the backslash

// Check if this is the target process
if (_wcsicmp(processName, TARGET_PROCESS_NAME) == 0)
{
// Perform memory operations here (if needed)
PVOID baseAddress = GetProcessBaseAddress(ProcessId);
if (baseAddress)
{
DbgPrint("[Driver] Target process '%ws' created with base address: %p\n", processName, baseAddress);

// Example: Read some memory from the process
BYTE buffer[256] = { 0 };
SIZE_T bytesRead = 0;
NTSTATUS ntStatus = ReadProcessMemoryInternal(
ProcessId,
baseAddress,
buffer,
sizeof(buffer),
&bytesRead
);

if (NT_SUCCESS(ntStatus))
{
DbgPrint("[Driver] Successfully read %zu bytes from '%ws'.\n", bytesRead, processName);
}
else
{
DbgPrint("[Driver] Failed to read memory of '%ws' with status: 0x%X\n", processName, ntStatus);
}

// Example: Write to process memory (commented out for safety)
/
BYTE writeData[256] = { / Your data here * / };
SIZE_T bytesWritten = 0;
ntStatus = WriteProcessMemoryInternal(
ProcessId,
baseAddress,
writeData,
sizeof(writeData),
&bytesWritten
);

if (NT_SUCCESS(ntStatus))
{
DbgPrint("[Driver] Successfully wrote %zu bytes to '%ws'.\n", bytesWritten, processName);
}
else
{
DbgPrint("[Driver] Failed to write memory of '%ws' with status: 0x%X\n", processName, ntStatus);
}
/
}
else
{
DbgPrint("[Driver] Failed to retrieve base address of process ID: %llu\n", ProcessId);
}
}
}
else
{
DbgPrint("[Driver] Failed to parse process name for PID: %llu\n", ProcessId);
}

// Free the allocated image name buffer
ExFreePoolWithTag(uProcessImageName.Buffer, 'imgN');
}
else
{
DbgPrint("[Driver] SeLocateProcessImageName failed with status: 0x%X for PID: %llu\n", status, ProcessId);
}

ObDereferenceObject(pProcess);
}
else
{
DbgPrint("[Driver] PsLookupProcessByProcessId failed with status: 0x%X for PID: %llu\n", status, ProcessId);
}
}
}

// ==========================================================
// Driver Unload Routine
// ==========================================================

VOID DriverUnloadRoutine(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);

// Unsubscribe from WNF
if (g_WnfSubscription && ExUnsubscribeWnfStateChange)
{
NTSTATUS status = ExUnsubscribeWnfStateChange(g_WnfSubscription);
if (NT_SUCCESS(status))
{
DbgPrint("[Driver] Successfully unsubscribed from WNF state changes.\n");
}
else
{
DbgPrint("[Driver] ExUnsubscribeWnfStateChange failed with status: 0x%X\n", status);
}
g_WnfSubscription = NULL;
}

// Remove the process notify routine
NTSTATUS status = PsSetCreateProcessNotifyRoutine(ProcessNotifyCallback, TRUE);
if (NT_SUCCESS(status))
{
DbgPrint("[Driver] Successfully removed process notify routine.\n");
}
else
{
DbgPrint("[Driver] PsSetCreateProcessNotifyRoutine removal failed with status: 0x%X\n", status);
}

DbgPrint("[Driver] Driver unloaded.\n");
}

// ==========================================================
// Driver Entry Function
// ==========================================================

NTSTATUS DriverEntryRoutine(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);

NTSTATUS status;

// Resolve WNF functions
UNICODE_STRING routineName;
RtlInitUnicodeString(&routineName, L"ExSubscribeWnfStateChange");
ExSubscribeWnfStateChange = (EXSUBSCRIBEWNFSTATECHANGE)MmGetSystemRoutineAddress(&routineName);
if (!ExSubscribeWnfStateChange)
{
DbgPrint("[Driver] ExSubscribeWnfStateChange not found.\n");
return STATUS_UNSUCCESSFUL;
}

RtlInitUnicodeString(&routineName, L"ExPublishWnfStateData");
ExPublishWnfStateData = (EXPUBLISHWNFSTATEDATA)MmGetSystemRoutineAddress(&routineName);
if (!ExPublishWnfStateData)
{
DbgPrint("[Driver] ExPublishWnfStateData not found.\n");
return STATUS_UNSUCCESSFUL;
}

RtlInitUnicodeString(&routineName, L"ExUnsubscribeWnfStateChange");
ExUnsubscribeWnfStateChange = (EXUNSUBSCRIBEWNFSTATECHANGE)MmGetSystemRoutineAddress(&routineName);
if (!ExUnsubscribeWnfStateChange)
{
DbgPrint("[Driver] ExUnsubscribeWnfStateChange not found.\n");
return STATUS_UNSUCCESSFUL;
}

// Subscribe to WNF state changes
status = SubscribeToWNF();
if (!NT_SUCCESS(status))
{
DbgPrint("[Driver] Failed to subscribe to WNF state changes with status: 0x%X\n", status);
return status;
}

// Register the process creation notify routine
status = PsSetCreateProcessNotifyRoutine(ProcessNotifyCallback, FALSE);
if (!NT_SUCCESS(status))
{
DbgPrint("[Driver] PsSetCreateProcessNotifyRoutine failed with status: 0x%X\n", status);
// Unsubscribe from WNF before exiting
if (g_WnfSubscription && ExUnsubscribeWnfStateChange)
ExUnsubscribeWnfStateChange(g_WnfSubscription);

return status;
}

// Set the unload routine
DriverObject->DriverUnload = DriverUnloadRoutine;

// Send handshake message to user-mode
const CHAR handshakeMessage = "Kernel driver loaded";
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
(PVOID)handshakeMessage,
(ULONG)strlen(handshakeMessage) + 1,
NULL,
NULL,
0
);

if (NT_SUCCESS(status))
{
DbgPrint("[Driver] Handshake message published successfully.\n");
}
else
{
DbgPrint("[Driver] Failed to publish handshake message with status: 0x%X\n", status);
}

DbgPrint("[Driver] Driver loaded successfully.\n");
return STATUS_SUCCESS;
}

// ==========================================================
// WNF Subscription Function Implementation
// ==========================================================

NTSTATUS SubscribeToWNF()
{
if (!ExSubscribeWnfStateChange || !ExPublishWnfStateData || !ExUnsubscribeWnfStateChange)
{
DbgPrint("[Driver] WNF function pointers not initialized.\n");
return STATUS_UNSUCCESSFUL;
}

// Subscribe to WNF state changes
NTSTATUS status = ExSubscribeWnfStateChange(
g_WnfSubscription,
MY_WNF_STATE_NAME_VALUE,
0, // ChangeStamp (0 for all changes)
(PVOID)OnWnfCallback,
NULL, // CallbackContext
NULL, // TypeId
0, // SerializationGroup
0 // Unknown
);

if (NT_SUCCESS(status))
{
DbgPrint("[Driver] Successfully subscribed to WNF state changes.\n");
}
else
{
DbgPrint("[Driver] ExSubscribeWnfStateChange failed with status: 0x%X\n", status);
}

return status;
}

// ==========================================================
// WNF Callback Function Implementation
// ==========================================================

NTSTATUS OnWnfCallback(
PVOID Subscription,
ULONG64 StateName,
ULONG ChangeStamp,
PVOID TypeId,
PVOID CallbackContext,
PVOID Buffer,
ULONG BufferSize
)
{
UNREFERENCED_PARAMETER(Subscription);
UNREFERENCED_PARAMETER(StateName);
UNREFERENCED_PARAMETER(ChangeStamp);
UNREFERENCED_PARAMETER(TypeId);
UNREFERENCED_PARAMETER(CallbackContext);

NTSTATUS status = STATUS_SUCCESS;

if (Buffer && BufferSize >= sizeof(INSTRUCTIONS))
{
PINSTRUCTIONS instructions = (PINSTRUCTIONS)Buffer;

if (instructions->read)
{
// Handle read request
SIZE_T bytesRead = 0;
BYTE readBuffer[1024] = { 0 };

status = ReadProcessMemoryInternal(
(HANDLE)(ULONGLONG)instructions->processId,
(PVOID)(ULONGLONG)instructions->address,
readBuffer,
(SIZE_T)instructions->size,
&bytesRead
);

if (NT_SUCCESS(status))
{
// Encode the read data to Base64
SIZE_T base64Size = ((bytesRead + 2) / 3) * 4;
if (base64Size + 1 > sizeof(instructions->data))
{
DbgPrint("[Driver] Read operation failed: Encoded data exceeds buffer size.\n");
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
"Read operation failed: Encoded data exceeds buffer size.",
(ULONG)strlen("Read operation failed: Encoded data exceeds buffer size.") + 1,
NULL,
NULL,
0
);
return status;
}

CHAR encodedData[4096] = { 0 };
SIZE_T encodedLength = 0;
status = EncodeBase64(readBuffer, bytesRead, encodedData, sizeof(encodedData), &encodedLength);
if (!NT_SUCCESS(status))
{
DbgPrint("[Driver] EncodeBase64 failed with status: 0x%X\n", status);
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
"Read operation failed: Base64 encode failed.",
(ULONG)strlen("Read operation failed: Base64 encode failed.") + 1,
NULL,
NULL,
0
);
return status;
}

// Prepare instructions to send back
RtlZeroMemory(instructions->data, sizeof(instructions->data));
RtlCopyMemory(instructions->data, encodedData, min(encodedLength, sizeof(instructions->data) - 1));
instructions->size = bytesRead;

// Publish the data back via WNF
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
instructions,
sizeof(INSTRUCTIONS),
NULL,
NULL,
0
);

if (NT_SUCCESS(status))
{
DbgPrint("[Driver] Read operation completed successfully. %zu bytes read, %zu bytes encoded.\n", bytesRead, encodedLength);
}
else
{
DbgPrint("[Driver] ExPublishWnfStateData failed with status: 0x%X\n", status);
}
}
else
{
// Handle read error
DbgPrint("[Driver] ReadProcessMemoryInternal failed with status: 0x%X\n", status);
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
"Read operation failed.",
(ULONG)strlen("Read operation failed.") + 1,
NULL,
NULL,
0
);
}
}
else if (instructions->write)
{
// Handle write request
SIZE_T bytesWritten = 0;

// Decode Base64 data
UCHAR decodedData[512] = { 0 };
SIZE_T decodedSize = 0;
status = DecodeBase64((CHAR)instructions->data, decodedData, sizeof(decodedData), &decodedSize);
if (!NT_SUCCESS(status))
{
DbgPrint("[Driver] DecodeBase64 failed with status: 0x%X\n", status);
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
"Write operation failed: Base64 decode failed.",
(ULONG)strlen("Write operation failed: Base64 decode failed.") + 1,
NULL,
NULL,
0
);
return status;
}

status = WriteProcessMemoryInternal(
(HANDLE)(ULONGLONG)instructions->processId,
(PVOID)(ULONGLONG)instructions->address,
decodedData,
decodedSize,
&bytesWritten
);

if (NT_SUCCESS(status) && bytesWritten == decodedSize)
{
// Prepare instruction to send back
instructions->size = bytesWritten;

// Publish the success message back via WNF
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
instructions,
sizeof(INSTRUCTIONS),
NULL,
NULL,
0
);

DbgPrint("[Driver] Write operation completed successfully. %zu bytes written to process %llu at address 0x%llX.\n",
bytesWritten, instructions->processId, instructions->address);
}
else
{
// Handle write error
DbgPrint("[Driver] WriteProcessMemoryInternal failed with status: 0x%X and bytes written: %zu\n", status, bytesWritten);
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
"Write operation failed.",
(ULONG)strlen("Write operation failed.") + 1,
NULL,
NULL,
0
);
}
}
else if (instructions->close)
{
// Handle close instruction
// Currently, no specific cleanup is required
DbgPrint("[Driver] Received close instruction.\n");
// Additional cleanup logic can be implemented here if needed
}
else if (instructions->reqBase)
{
// Handle base address request
PEPROCESS pProcess = NULL;
NTSTATUS statusLookup = PsLookupProcessByProcessId((HANDLE)(ULONGLONG)instructions->processId, &pProcess);
if (NT_SUCCESS(statusLookup))
{
PVOID baseAddress = PsGetProcessSectionBaseAddress(pProcess);
instructions->baseAddress = (UINT64)baseAddress;
ObDereferenceObject(pProcess);

// Publish the base address back via WNF
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
instructions,
sizeof(INSTRUCTIONS),
NULL,
NULL,
0
);

DbgPrint("[Driver] Base address of process %llu: %p\n", instructions->processId, baseAddress);
}
else
{
// Handle error
DbgPrint("[Driver] PsLookupProcessByProcessId failed with status: 0x%X\n", statusLookup);
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
"Base address request failed: PsLookupProcessByProcessId failed.",
(ULONG)strlen("Base address request failed: PsLookupProcessByProcessId failed.") + 1,
NULL,
NULL,
0
);
}
}
// Additional instruction handling can be added here
}
else if (Buffer && BufferSize > 0)
{
// Handle simple messages like "Hi"
// Allocate memory for received message, ensuring no buffer overflow
CHAR receivedMessage = (CHAR)ExAllocatePoolWithTag(NonPagedPoolNx, BufferSize + 1, 'msgK'); // 'msgK' tag
if (!receivedMessage)
{
DbgPrint("[Driver] Failed to allocate memory for received message.\n");
return STATUS_INSUFFICIENT_RESOURCES;
}

// Zero-initialize the allocated memory
RtlZeroMemory(receivedMessage, BufferSize + 1);

// Copy the received data, ensuring not to exceed the allocated buffer
RtlCopyMemory(receivedMessage, Buffer, min(BufferSize, (ULONG)(sizeof(receivedMessage) - 1)));

DbgPrint("[Driver] Kernel received message: %s\n", receivedMessage);

// Check if the message is 'Hi' and respond accordingly
if (strcmp(receivedMessage, "Hi") == 0)
{
// Send handshake response
const CHAR responseMessage = "Hello from kernel mode";
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
(PVOID)responseMessage,
(ULONG)strlen(responseMessage) + 1, // Include null terminator
NULL,
NULL,
0
);

if (NT_SUCCESS(status))
{
DbgPrint("[Driver] Handshake response sent successfully.\n");
}
else
{
DbgPrint("[Driver] Failed to send handshake response with status: 0x%X\n", status);
}
}

// Free the allocated memory for the received message
ExFreePoolWithTag(receivedMessage, 'msgK');
}
else
{
// Handle unexpected or unsupported data
DbgPrint("[Driver] Received invalid or unsupported data.\n");
}

return status;
}

// ==========================================================
// Process Notification Callback Implementation
// ==========================================================

VOID ProcessNotifyCallback(
__in HANDLE ParentId,
__in HANDLE ProcessId,
_in BOOLEAN Create
)
{
UNREFERENCED_PARAMETER(ParentId);

if (Create)
{
PEPROCESS pProcess = NULL;
NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &pProcess);
if (NT_SUCCESS(status))
{
// Get process image file name
UNICODE_STRING uProcessImageName = { 0 };
status = SeLocateProcessImageName(pProcess, &uProcessImageName);
if (NT_SUCCESS(status))
{
// Extract file name from full path
PWSTR processName = wcsrchr(uProcessImageName.Buffer, L''); // Corrected backslash
if (processName)
{
processName++; // Move past the backslash

// Check if this is the target process
if (wcsicmp(processName, TARGET_PROCESS_NAME) == 0)
{
// Perform memory operations here (if needed)
PVOID baseAddress = GetProcessBaseAddress(ProcessId);
if (baseAddress)
{
DbgPrint("[Driver] Target process '%ws' created with base address: %p\n", processName, baseAddress);

// Example: Read some memory from the process
BYTE buffer[256] = { 0 };
SIZE_T bytesRead = 0;
NTSTATUS ntStatus = ReadProcessMemoryInternal(
(HANDLE)ProcessId,
baseAddress,
buffer,
sizeof(buffer),
&bytesRead
);

if (NT_SUCCESS(ntStatus))
{
DbgPrint("[Driver] Successfully read %zu bytes from '%ws'.\n", bytesRead, processName);
}
else
{
DbgPrint("[Driver] Failed to read memory of '%ws' with status: 0x%X\n", processName, ntStatus);
}

// Example: Write to process memory (commented out for safety)
/
BYTE writeData[256] = { / Your data here * / };
SIZE_T bytesWritten = 0;
ntStatus = WriteProcessMemoryInternal(
(HANDLE)ProcessId,
baseAddress,
writeData,
sizeof(writeData),
&bytesWritten
);

if (NT_SUCCESS(ntStatus))
{
DbgPrint("[Driver] Successfully wrote %zu bytes to '%ws'.\n", bytesWritten, processName);
}
else
{
DbgPrint("[Driver] Failed to write memory of '%ws' with status: 0x%X\n", processName, ntStatus);
}
/
}
else
{
DbgPrint("[Driver] Failed to retrieve base address of process ID: %llu\n", ProcessId);
}
}
}
else
{
DbgPrint("[Driver] Failed to parse process name for PID: %llu\n", ProcessId);
}

// Free the allocated image name buffer
ExFreePoolWithTag(uProcessImageName.Buffer, 'imgN');
}
else
{
DbgPrint("[Driver] SeLocateProcessImageName failed with status: 0x%X for PID: %llu\n", status, ProcessId);
}

ObDereferenceObject(pProcess);
}
else
{
DbgPrint("[Driver] PsLookupProcessByProcessId failed with status: 0x%X for PID: %llu\n", status, ProcessId);
}
}
}

// ==========================================================
// Driver Unload Routine Implementation
// ==========================================================

VOID DriverUnloadRoutine(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);

// Unsubscribe from WNF
if (g_WnfSubscription && ExUnsubscribeWnfStateChange)
{
NTSTATUS status = ExUnsubscribeWnfStateChange(g_WnfSubscription);
if (NT_SUCCESS(status))
{
DbgPrint("[Driver] Successfully unsubscribed from WNF state changes.\n");
}
else
{
DbgPrint("[Driver] ExUnsubscribeWnfStateChange failed with status: 0x%X\n", status);
}
g_WnfSubscription = NULL;
}

// Remove the process notify routine
NTSTATUS status = PsSetCreateProcessNotifyRoutine(ProcessNotifyCallback, TRUE);
if (NT_SUCCESS(status))
{
DbgPrint("[Driver] Successfully removed process notify routine.\n");
}
else
{
DbgPrint("[Driver] PsSetCreateProcessNotifyRoutine removal failed with status: 0x%X\n", status);
}

DbgPrint("[Driver] Driver unloaded.\n");
}

// ==========================================================
// DriverEntry Function Implementation
// ==========================================================

NTSTATUS DriverEntryRoutine(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);

NTSTATUS status;

// Resolve WNF functions
UNICODE_STRING routineName;
RtlInitUnicodeString(&routineName, L"ExSubscribeWnfStateChange");
ExSubscribeWnfStateChange = (EXSUBSCRIBEWNFSTATECHANGE)MmGetSystemRoutineAddress(&routineName);
if (!ExSubscribeWnfStateChange)
{
DbgPrint("[Driver] ExSubscribeWnfStateChange not found.\n");
return STATUS_UNSUCCESSFUL;
}

RtlInitUnicodeString(&routineName, L"ExPublishWnfStateData");
ExPublishWnfStateData = (EXPUBLISHWNFSTATEDATA*)MmGetSystemRoutineAddress(&routineName);
if (!ExPublishWnfStateData)
{
DbgPrint("[Driver] ExPublishWnfStateData not found.\n");
return STATUS_UNSUCCESSFUL;
}

RtlInitUnicodeString(&routineName, L"ExUnsubscribeWnfStateChange");
ExUnsubscribeWnfStateChange = (EXUNSUBSCRIBEWNFSTATECHANGE*)MmGetSystemRoutineAddress(&routineName);
if (!ExUnsubscribeWnfStateChange)
{
DbgPrint("[Driver] ExUnsubscribeWnfStateChange not found.\n");
return STATUS_UNSUCCESSFUL;
}

// Subscribe to WNF state changes
status = SubscribeToWNF();
if (!NT_SUCCESS(status))
{
DbgPrint("[Driver] Failed to subscribe to WNF state changes with status: 0x%X\n", status);
return status;
}

// Register the process creation notify routine
status = PsSetCreateProcessNotifyRoutine(ProcessNotifyCallback, FALSE);
if (!NT_SUCCESS(status))
{
DbgPrint("[Driver] PsSetCreateProcessNotifyRoutine failed with status: 0x%X\n", status);
// Unsubscribe from WNF before exiting
if (g_WnfSubscription && ExUnsubscribeWnfStateChange)
ExUnsubscribeWnfStateChange(g_WnfSubscription);

return status;
}

// Set the unload routine
DriverObject->DriverUnload = DriverUnloadRoutine;

// Send handshake message to user-mode
const CHAR* handshakeMessage = "Kernel driver loaded";
status = ExPublishWnfStateData(
MY_WNF_STATE_NAME_VALUE,
(PVOID)handshakeMessage,
(ULONG)strlen(handshakeMessage) + 1,
NULL,
NULL,
0
);

if (NT_SUCCESS(status))
{
DbgPrint("[Driver] Handshake message published successfully.\n");
}
else
{
DbgPrint("[Driver] Failed to publish handshake message with status: 0x%X\n", status);
}

DbgPrint("[Driver] Driver loaded successfully.\n");
return STATUS_SUCCESS;
}