NTSTATUS FASTCALL KbReadProcessMemory(IN PIOCTL_INFO RequestInfo, OUT PSIZE_T ResponseLength) { UNREFERENCED_PARAMETER(ResponseLength); if (RequestInfo->InputBufferSize != sizeof(KB_READ_PROCESS_MEMORY_IN)) return STATUS_INFO_LENGTH_MISMATCH; auto Input = static_cast(RequestInfo->InputBuffer); if (!Input) return STATUS_INVALID_PARAMETER; HANDLE ProcessId = Input->ProcessId ? reinterpret_cast(Input->ProcessId) : PsGetCurrentProcessId(); PEPROCESS Process = Processes::Descriptors::GetEPROCESS(ProcessId); if (!Process) return STATUS_UNSUCCESSFUL; NTSTATUS Status = Processes::MemoryManagement::ReadProcessMemory( Process, reinterpret_cast(Input->BaseAddress), reinterpret_cast(Input->Buffer), Input->Size ); ObDereferenceObject(Process); return Status; } NTSTATUS FASTCALL KbWriteProcessMemory(IN PIOCTL_INFO RequestInfo, OUT PSIZE_T ResponseLength) { UNREFERENCED_PARAMETER(ResponseLength); if (RequestInfo->InputBufferSize != sizeof(KB_WRITE_PROCESS_MEMORY_IN)) return STATUS_INFO_LENGTH_MISMATCH; auto Input = static_cast(RequestInfo->InputBuffer); if (!Input) return STATUS_INVALID_PARAMETER; HANDLE ProcessId = Input->ProcessId ? reinterpret_cast(Input->ProcessId) : PsGetCurrentProcessId(); PEPROCESS Process = Processes::Descriptors::GetEPROCESS(ProcessId); if (!Process) return STATUS_UNSUCCESSFUL; PVOID Address = reinterpret_cast(Input->BaseAddress); SIZE_T Size = Input->Size; if (Input->PerformCopyOnWrite) { using namespace Pte; PVOID PageCounter = Address; do { ULONG PageSize = 0; BOOLEAN Status = TriggerCopyOnWrite(Process, PageCounter, &PageSize); if (!Status || !PageSize) { ObDereferenceObject(Process); return STATUS_PARTIAL_COPY; } PageCounter = reinterpret_cast( reinterpret_cast(ALIGN_DOWN_POINTER_BY(PageCounter, PageSize)) + PageSize ); } while (PageCounter < reinterpret_cast(reinterpret_cast(Address) + Size)); } NTSTATUS Status = Processes::MemoryManagement::WriteProcessMemory( Process, Address, reinterpret_cast(Input->Buffer), Input->Size ); ObDereferenceObject(Process); return Status; }