using System;
using NtApiDotNet;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;

namespace WnfSubscriber
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct INSTRUCTIONS
{
public byte close;
public byte read;
public byte reqBase;
public IntPtr bufferAddress;
public UIntPtr address;
public ulong size;
public IntPtr output;
public ulong baseAddress;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string moduleName;
}

public class KernelCom : IDisposable
{
private const ulong MY_WNF_STATE_NAME = 0x41C64E6DA3BC1074;
private readonly WnfClient _client;
private bool _initialized = false;

public KernelCom()
{
_client = new WnfClient();
}

public void Initialize()
{
if (_initialized)
return;

_client.SubscribeState(new WnfStateName(MY_WNF_STATE_NAME), OnWnfStateChange);
Console.WriteLine("[+] Subscribed to WNF state.");
_initialized = true;
}

public void SendMessage(string message)
{
byte[] dataToSend = Encoding.ASCII.GetBytes(message);
NtWnf.PublishStateData(new WnfStateName(MY_WNF_STATE_NAME), dataToSend);
Console.WriteLine("[+] Sent message to kernel-mode: " + message);
}

public void SendInstructions(INSTRUCTIONS instructions)
{
int size = Marshal.SizeOf(instructions);
byte[] dataToSend = new byte[size];

IntPtr ptr = Marshal.AllocHGlobal(size);
try
{
Marshal.StructureToPtr(instructions, ptr, false);
Marshal.Copy(ptr, dataToSend, 0, size);
}
finally
{
Marshal.FreeHGlobal(ptr);
}

NtWnf.PublishStateData(new WnfStateName(MY_WNF_STATE_NAME), dataToSend);
Console.WriteLine("[+] Sent instructions to kernel-mode.");
}

private void OnWnfStateChange(WnfStateChange change)
{
Console.WriteLine("[] WNF State Changed!");

            if (change.Data == null || change.Data.Length == 0)
            {
                Console.WriteLine("[!] Received empty data.");
                return;
            }

            string receivedMessage = Encoding.ASCII.GetString(change.Data);
            Console.WriteLine("[] Received message from kernel-mode: " + receivedMessage);

            if (receivedMessage == "Hi")
            {
                Console.WriteLine("[] Received 'Hi' from kernel-mode. Sending instructions...");

                INSTRUCTIONS instructions = new INSTRUCTIONS
                {
                    close = 0,
                    read = 1,
                    reqBase = 0,
                    bufferAddress = IntPtr.Zero,
                    address = UIntPtr.Zero,
                    size = 0,
                    output = IntPtr.Zero,
                    baseAddress = 0,
                    moduleName = "ExampleModule"
                };

                SendInstructions(instructions);
            }
            else if (receivedMessage == "Read operation completed")
            {
                Console.WriteLine("[] Kernel-mode has completed the read operation.");
                // Process the results if any
                // ...
            }
            else
            {
                // Handle other messages or results
                Console.WriteLine("[] Received data: " + receivedMessage);
            }
        }

        public void CloseDriver()
        {
            INSTRUCTIONS instructions = new INSTRUCTIONS
            {
                close = 1,
                read = 0,
                reqBase = 0,
                bufferAddress = IntPtr.Zero,
                address = UIntPtr.Zero,
                size = 0,
                output = IntPtr.Zero,
                baseAddress = 0,
                moduleName = string.Empty
            };

            SendInstructions(instructions);
        }

        public void GetModuleBaseAddress(string moduleName)
        {
            INSTRUCTIONS instructions = new INSTRUCTIONS
            {
                close = 0,
                read = 0,
                reqBase = 1,
                bufferAddress = IntPtr.Zero,
                address = UIntPtr.Zero,
                size = 0,
                output = IntPtr.Zero,
                baseAddress = 0,
                moduleName = moduleName
            };

            SendInstructions(instructions);
        }

        public void Dispose()
        {
            _client.Dispose();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (KernelCom kernelCom = new KernelCom())
            {
                // Initialize WNF subscription
                kernelCom.Initialize();

                Console.WriteLine("[>] Subscribed to WNF state. Sending 'Hi' to kernel-mode.");

                // Send 'Hi' message to kernel-mode
                kernelCom.SendMessage("Hi");

                Console.WriteLine("[>] Waiting for kernel-mode responses...");

                // Keep the application running to receive WNF notifications
                while (true)
                {
                    Thread.Sleep(1000);
                }

                // Example of sending additional instructions
                // kernelCom.GetModuleBaseAddress("Notepad.exe");
                // kernelCom.CloseDriver();
            }
        }
    }
}
i want something similar to read and write process memory on this program