You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
7.5 KiB
233 lines
7.5 KiB
#include "memory.h"
|
|
|
|
namespace i6
|
|
{
|
|
namespace memory
|
|
{
|
|
CURSOR_PAGE get_cursor()
|
|
{
|
|
const auto cursor =
|
|
ExAllocatePool(
|
|
NonPagedPool,
|
|
0x1000
|
|
);
|
|
|
|
memset(cursor, NULL, 0x1000);
|
|
virt_addr_t addr_t{ cursor };
|
|
|
|
const auto dirbase =
|
|
::cr3{ __readcr3() }.dirbase;
|
|
|
|
const auto pml4 =
|
|
reinterpret_cast<ppml4e>(
|
|
MmGetVirtualForPhysical(
|
|
PHYSICAL_ADDRESS{ (LONGLONG)dirbase << 12 })) + addr_t.pml4_index;
|
|
|
|
if (!MmIsAddressValid(pml4))
|
|
return {};
|
|
|
|
const auto pdpt =
|
|
reinterpret_cast<ppdpte>(
|
|
MmGetVirtualForPhysical(
|
|
PHYSICAL_ADDRESS{ (LONGLONG)pml4->pfn << 12 })) + addr_t.pdpt_index;
|
|
|
|
if (!MmIsAddressValid(pdpt))
|
|
return {};
|
|
|
|
const auto pd =
|
|
reinterpret_cast<ppde>(
|
|
MmGetVirtualForPhysical(
|
|
PHYSICAL_ADDRESS{ (LONGLONG)pdpt->pfn << 12 })) + addr_t.pd_index;
|
|
|
|
if (!MmIsAddressValid(pd))
|
|
return {};
|
|
|
|
const auto pt =
|
|
reinterpret_cast<ppte>(
|
|
MmGetVirtualForPhysical(
|
|
PHYSICAL_ADDRESS{ (LONGLONG)pd->pfn << 12 })) + addr_t.pt_index;
|
|
|
|
if (!MmIsAddressValid(pt))
|
|
return {};
|
|
|
|
return { cursor, pt, (unsigned)pt->pfn };
|
|
}
|
|
|
|
void* virt_to_phys(unsigned pid, void* addr)
|
|
{
|
|
if (!pid || !addr)
|
|
return {};
|
|
|
|
PEPROCESS peproc;
|
|
if (NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)pid, &peproc)) && peproc)
|
|
{
|
|
virt_addr_t addr_t{ addr };
|
|
static const auto cursor = get_cursor();
|
|
|
|
if (!cursor.pte || !cursor.org_pfn || !cursor.page)
|
|
{
|
|
ObDereferenceObject(peproc);
|
|
return {};
|
|
}
|
|
|
|
const auto dirbase = // dirbase is a pfn
|
|
*reinterpret_cast<pte*>(
|
|
reinterpret_cast<ULONGLONG>(peproc) + 0x28);
|
|
|
|
{
|
|
cursor.pte->pfn = dirbase.pfn;
|
|
KeFlushCurrentTbImmediately();
|
|
}
|
|
|
|
if (!MmIsAddressValid(reinterpret_cast<ppml4e>(cursor.page) + addr_t.pml4_index))
|
|
{
|
|
cursor.pte->pfn = cursor.org_pfn;
|
|
KeFlushCurrentTbImmediately();
|
|
ObDereferenceObject(peproc);
|
|
return {};
|
|
}
|
|
|
|
KeFlushCurrentTbImmediately();
|
|
const auto pml4e =
|
|
*reinterpret_cast<::pml4e*>(
|
|
reinterpret_cast<ppml4e>(cursor.page) + addr_t.pml4_index);
|
|
|
|
if (!pml4e.value || !pml4e.present || !pml4e.pfn)
|
|
{
|
|
cursor.pte->pfn = cursor.org_pfn;
|
|
KeFlushCurrentTbImmediately();
|
|
ObDereferenceObject(peproc);
|
|
return {};
|
|
}
|
|
|
|
{
|
|
cursor.pte->pfn = pml4e.pfn;
|
|
KeFlushCurrentTbImmediately();
|
|
}
|
|
|
|
if (!MmIsAddressValid(reinterpret_cast<ppdpte>(cursor.page) + addr_t.pdpt_index))
|
|
{
|
|
cursor.pte->pfn = cursor.org_pfn;
|
|
KeFlushCurrentTbImmediately();
|
|
ObDereferenceObject(peproc);
|
|
return {};
|
|
}
|
|
|
|
KeFlushCurrentTbImmediately();
|
|
const auto pdpte =
|
|
*reinterpret_cast<::pdpte*>(
|
|
reinterpret_cast<ppdpte>(cursor.page) + addr_t.pdpt_index);
|
|
|
|
if (!pdpte.value || !pdpte.present || !pdpte.pfn)
|
|
{
|
|
cursor.pte->pfn = cursor.org_pfn;
|
|
KeFlushCurrentTbImmediately();
|
|
ObDereferenceObject(peproc);
|
|
return {};
|
|
}
|
|
|
|
{
|
|
cursor.pte->pfn = pdpte.pfn;
|
|
KeFlushCurrentTbImmediately();
|
|
}
|
|
|
|
if (!MmIsAddressValid(reinterpret_cast<ppde>(cursor.page) + addr_t.pd_index))
|
|
{
|
|
cursor.pte->pfn = cursor.org_pfn;
|
|
KeFlushCurrentTbImmediately();
|
|
ObDereferenceObject(peproc);
|
|
return {};
|
|
}
|
|
|
|
KeFlushCurrentTbImmediately();
|
|
const auto pde =
|
|
*reinterpret_cast<::pde*>(
|
|
reinterpret_cast<ppde>(cursor.page) + addr_t.pd_index);
|
|
|
|
if (!pde.value || !pde.present || !pde.pfn)
|
|
{
|
|
cursor.pte->pfn = cursor.org_pfn;
|
|
KeFlushCurrentTbImmediately();
|
|
ObDereferenceObject(peproc);
|
|
return {};
|
|
}
|
|
|
|
{
|
|
cursor.pte->pfn = pde.pfn;
|
|
KeFlushCurrentTbImmediately();
|
|
}
|
|
|
|
if (!MmIsAddressValid(reinterpret_cast<ppte>(cursor.page) + addr_t.pt_index))
|
|
{
|
|
cursor.pte->pfn = cursor.org_pfn;
|
|
KeFlushCurrentTbImmediately();
|
|
ObDereferenceObject(peproc);
|
|
return {};
|
|
}
|
|
|
|
KeFlushCurrentTbImmediately();
|
|
const auto pte =
|
|
*reinterpret_cast<::pte*>(
|
|
reinterpret_cast<ppte>(cursor.page) + addr_t.pt_index);
|
|
|
|
if (!pte.value || !pte.present || !pte.pfn)
|
|
{
|
|
cursor.pte->pfn = cursor.org_pfn;
|
|
KeFlushCurrentTbImmediately();
|
|
ObDereferenceObject(peproc);
|
|
return {};
|
|
}
|
|
|
|
//
|
|
// reset pfn
|
|
//
|
|
{
|
|
cursor.pte->pfn = cursor.org_pfn;
|
|
KeFlushCurrentTbImmediately();
|
|
}
|
|
|
|
ObDereferenceObject(peproc);
|
|
return reinterpret_cast<void*>((pte.pfn << 12) + addr_t.offset);
|
|
}
|
|
return {};
|
|
}
|
|
|
|
void read(void* addr, void* buffer, size_t size, unsigned pid)
|
|
{
|
|
if (!addr || !MmIsAddressValid(buffer) || !size || !pid)
|
|
return;
|
|
|
|
const auto virt_addr =
|
|
MmMapIoSpace(
|
|
PHYSICAL_ADDRESS{ (LONGLONG)virt_to_phys(pid, addr) },
|
|
size + 0x1000,
|
|
MmNonCached
|
|
);
|
|
|
|
if (!MmIsAddressValid(virt_addr))
|
|
return;
|
|
|
|
memcpy(buffer, virt_addr, size);
|
|
MmUnmapIoSpace(virt_addr, size + 0x1000);
|
|
}
|
|
|
|
void write(void* addr, void* buffer, size_t size, unsigned pid)
|
|
{
|
|
if (!addr || !MmIsAddressValid(buffer) || !size || !pid)
|
|
return;
|
|
|
|
const auto virt_addr =
|
|
MmMapIoSpace(
|
|
PHYSICAL_ADDRESS{ (LONGLONG)virt_to_phys(pid, addr) },
|
|
size + 0x1000,
|
|
MmNonCached
|
|
);
|
|
|
|
if (!MmIsAddressValid(virt_addr))
|
|
return;
|
|
|
|
memcpy(virt_addr, buffer, size);
|
|
MmUnmapIoSpace(virt_addr, size + 0x1000);
|
|
}
|
|
}
|
|
} |