#include <ntifs.h>
#include <ntddk.h>
#include <intrin.h>
#include <ntdef.h>
#define WIN10_21H1_EPROCESS2DIRBASE_OFFSET 0x28
#define kprintf(...) \
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, __VA_ARGS__))
NTSTATUS GetDirBaseByEprocess(IN
UINT64
, OUT
PUINT64
);
NTSTATUS TranslateAddress(IN
UINT64
, _Inout_
PUINT64
);
NTSTATUS ReadPhysicalAddress(IN PVOID64, OUT PVOID64, IN
SIZE_T
, OUT
SIZE_T
*);
NTSTATUS WritePhysicalAddress(IN PVOID64, IN PVOID64, IN
SIZE_T
, OUT
SIZE_T
*);
NTKERNELAPI PPEB NTAPI PsGetProcessPeb(IN PEPROCESS Process);
NTKERNELAPI
PVOID
NTAPI PsGetProcessWow64Process(IN PEPROCESS Process);
VOID
DriverUnload(PDRIVER_OBJECT pDriver)
{
kprintf(
"驱动已卸载.\r\n"
);
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING path)
{
NTSTATUS status;
UINT64
pid, uAddr, uDirBase;
SIZE_T
BytesTransferred;
UCHAR
charArry[40] = {0};
UCHAR
example[40] = {
"Yes I change memory by physical"
};
pid = 10276;
uAddr = 0x3629FAFB80;
pDriver->DriverUnload = DriverUnload;
status = GetDirBaseByEprocess(pid, &uDirBase);
if
(!NT_SUCCESS(status)) {
kprintf(
"[!] Get DirBase address failed!\r\n"
);
return
STATUS_UNSUCCESSFUL;
}
status = TranslateAddress(uDirBase, &uAddr);
if
(!NT_SUCCESS(status)) {
kprintf(
"[!] Translate address failed!\r\n"
);
return
STATUS_UNSUCCESSFUL;
}
ReadPhysicalAddress((PVOID64)uAddr, charArry, 40, &BytesTransferred);
kprintf(
"[+] data is %s\r\n"
, charArry);
WritePhysicalAddress((PVOID64)uAddr, example, 40, &BytesTransferred);
kprintf(
"[+] Write end\r\n"
);
return
STATUS_SUCCESS;
}
NTSTATUS ReadPhysicalAddress(IN PVOID64 address, OUT PVOID64 buffer,
IN
SIZE_T
size, OUT
SIZE_T
* BytesTransferred)
{
MM_COPY_ADDRESS Read = {0};
Read.PhysicalAddress.QuadPart = (
LONG64
)address;
return
MmCopyMemory(
buffer, Read, size, MM_COPY_MEMORY_PHYSICAL, BytesTransferred);
}
NTSTATUS WritePhysicalAddress(IN PVOID64 address, IN PVOID64 buffer,
IN
SIZE_T
size, OUT
SIZE_T
* BytesTransferred)
{
PVOID
map;
PHYSICAL_ADDRESS Write = {0};
if
(!address) {
kprintf(
"Address value error. \r\n"
);
return
STATUS_UNSUCCESSFUL;
}
Write.QuadPart = (
LONG64
)address;
map = MmMapIoSpaceEx(Write, size, PAGE_READWRITE);
if
(!map) {
kprintf(
"Write Memory faild.\r\n"
);
return
STATUS_UNSUCCESSFUL;
}
RtlCopyMemory(map, buffer, size);
*BytesTransferred = size;
MmUnmapIoSpace(map, size);
return
STATUS_SUCCESS;
}
NTSTATUS GetDirBaseByEprocess(IN
UINT64
pid, OUT
PUINT64
pDirbase)
{
PEPROCESS pEprocess;
NTSTATUS status;
status = PsLookupProcessByProcessId((
HANDLE
)pid, &pEprocess);
if
(!NT_SUCCESS(status)) {
kprintf(
"[!] Get Pid=%d _EPROCESS failed!"
, pid);
return
STATUS_UNSUCCESSFUL;
}
*pDirbase =
*(
PUINT64
)((
PUCHAR
)pEprocess + WIN10_21H1_EPROCESS2DIRBASE_OFFSET);
kprintf(
"[+] uDirBase ==> %llx\r\n"
, *pDirbase);
return
STATUS_SUCCESS;
}
NTSTATUS TranslateAddress(IN
UINT64
DirBase, _Inout_
PUINT64
addr)
{
UINT16 PML4, PDPE, PDE, PTE, offset;
UINT64
mask = 0x7fffff000;
UINT64
uTmp;
SIZE_T
BytesTransferred;
NTSTATUS status;
offset = *addr & 0xfff;
PTE = (*addr >> 12) & 0x1ff;
PDE = (*addr >> (12 + 9)) & 0x1ff;
PDPE = (*addr >> (9 * 2 + 12)) & 0x1ff;
PML4 = (*addr >> (9 * 3 + 12)) & 0x1ff;
status = ReadPhysicalAddress(
(PVOID64)(DirBase + PML4 * 8), &uTmp,
sizeof
(uTmp), &BytesTransferred);
uTmp &= mask;
kprintf(
"[+] PML4(%x) ==> %llx\r\n"
, PML4, uTmp);
status = ReadPhysicalAddress(
(PVOID64)(uTmp + PDPE * 8), &uTmp,
sizeof
(uTmp), &BytesTransferred);
uTmp &= mask;
kprintf(
"[+] PDPE(%x) ==> %llx\r\n"
, PDPE, uTmp);
status = ReadPhysicalAddress(
(PVOID64)(uTmp + PDE * 8), &uTmp,
sizeof
(uTmp), &BytesTransferred);
uTmp &= mask;
kprintf(
"[+] PDE(%x) ==> %llx\r\n"
, PDE, uTmp);
status = ReadPhysicalAddress(
(PVOID64)(uTmp + PTE * 8), &uTmp,
sizeof
(uTmp), &BytesTransferred);
uTmp &= mask;
kprintf(
"[+] PTE(%x) ==> %llx\r\n"
, PTE, uTmp);
*addr = uTmp + offset;
kprintf(
"[+] physical address: %llx\r\n"
, *addr);
return
STATUS_SUCCESS;
}