NTSTATUS AddHiddenPageRecord(ULONG64 CR3, PVOID pHiddenPageBase, PHIDDEN_PAGE_RECORD pHiddenPageRecord)
{
KIRQL EntryIrql;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
//prevent mulit-thread change the page record count
KeAcquireSpinLock(&pHiddenPageRecord->SpinLock, &EntryIrql);
//check count
MyPrint(_TitleAndFunc"pHiddenPageRecord->Count:%16IX\n", pHiddenPageRecord->Count);
if (pHiddenPageRecord->Count == MAX_HIDDEN_PAGE_COUNT)
goto Lable_Error;
//add pPTE record
PSPECIFIC_HIDDEN_PAGE_RECORD pCurrentRecord = &pHiddenPageRecord->Record[pHiddenPageRecord->Count];
pCurrentRecord->pPTE = pGetSpecificAddresspPTEPhysical(CR3, pHiddenPageBase);
MyPrint(_TitleAndFunc"pCurrentRecord->pPTE:%16IX\n", pCurrentRecord->pPTE);
if (pCurrentRecord->pPTE == NULL)
goto Lable_Error;
//add hidden virtual address record
pCurrentRecord->pHiddenBase = pHiddenPageBase;
MyPrint(_TitleAndFunc"pCurrentRecord->pHiddenBase:%16IX\n", pCurrentRecord->pHiddenBase);
//add original pfn record
ContextVirtualToPhysical(&g_PhysicalOpCR3);
pCurrentRecord->OriginalPfn = pCurrentRecord->pPTE->PageFrameNumber;
ContextPhysicalToVirtual(&g_PhysicalOpCR3);
MyPrint(_TitleAndFunc"pCurrentRecord->OriginalPfn:%16IX\n", pCurrentRecord->OriginalPfn);
//add hidden pfn record
//allocate memory
//record the physical address
//then free the memory and mark it as bad
PVOID TemporaryVirtual = MmAllocateNonCachedMemory(PAGE_SIZE);
if (TemporaryVirtual == NULL)
goto Lable_Error;
PHYSICAL_ADDRESS TemporaryPhysical = MmGetPhysicalAddress(TemporaryVirtual);
LARGE_INTEGER PhysicalLength = { 0 };
PhysicalLength.QuadPart = PAGE_SIZE;
pCurrentRecord->HiddenPfn = pPhysicalAddresstoPTEPFN((PVOID)(TemporaryPhysical.QuadPart));
MyPrint(_TitleAndFunc"pCurrentRecord->HiddenPfn:%16IX\n", pCurrentRecord->HiddenPfn);
MmFreeNonCachedMemory(TemporaryVirtual, PAGE_SIZE);
Status = MmMarkPhysicalMemoryAsBad(&TemporaryPhysical, &PhysicalLength);
//copy codes to the new non-mapped physical address
ContextVirtualToPhysical(&g_PhysicalOpCR3);
RtlCopyMemory((PVOID)(TemporaryPhysical.QuadPart),
pCurrentRecord->pHiddenBase,
PAGE_SIZE
);
ContextPhysicalToVirtual(&g_PhysicalOpCR3);
//check the mark state
if (!NT_SUCCESS(Status))
goto Lable_Error;
//the last step:count +1
pHiddenPageRecord->Count++;
//release spin lock
KeReleaseSpinLock(&pHiddenPageRecord->SpinLock, EntryIrql);
return STATUS_SUCCESS;
Lable_Error:
KeReleaseSpinLock(&pHiddenPageRecord->SpinLock, EntryIrql);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS RemoveAndRestoreAllHiddenPageRecord(PHIDDEN_PAGE_RECORD pHiddenPageRecord)
{
KIRQL EntryIrql;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
//prevent mulit-thread change the page record count
KeAcquireSpinLock(&pHiddenPageRecord->SpinLock, &EntryIrql);
//assert we have elements
if (pHiddenPageRecord->Count == 0)
goto Lable_Error;
//restore all records and mark all the hidden physical memory as good
PSPECIFIC_HIDDEN_PAGE_RECORD pCurrentRecord = NULL;
PHYSICAL_ADDRESS CurrentHiddenPhysical = { 0 };
LARGE_INTEGER PhysicalLength = { 0 };
PhysicalLength.QuadPart = PAGE_SIZE;
for (int i = 0; i < pHiddenPageRecord->Count; i++)
{
pCurrentRecord = &pHiddenPageRecord->Record[i];
CurrentHiddenPhysical.QuadPart = (ULONG64)pPTEPFNtoPhysicalAddress(pCurrentRecord->HiddenPfn);
//mark it as good
MmMarkPhysicalMemoryAsGood(&CurrentHiddenPhysical, &PhysicalLength);
//restore all page mapping relations
ContextVirtualToPhysical(&g_PhysicalOpCR3);
pCurrentRecord->pPTE->PageFrameNumber = pCurrentRecord->OriginalPfn;
ContextPhysicalToVirtual(&g_PhysicalOpCR3);
//invalid the TLB of current hidden address
__invlpg(pCurrentRecord->pHiddenBase);
}
//set count to zero
pHiddenPageRecord->Count = 0;
//release spin lock
KeReleaseSpinLock(&pHiddenPageRecord->SpinLock, EntryIrql);
return STATUS_SUCCESS;
Lable_Error:
KeReleaseSpinLock(&pHiddenPageRecord->SpinLock, EntryIrql);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS AddHiddenPageRecord(ULONG64 CR3, PVOID pHiddenPageBase, PHIDDEN_PAGE_RECORD pHiddenPageRecord)
{
KIRQL EntryIrql;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
//prevent mulit-thread change the page record count
KeAcquireSpinLock(&pHiddenPageRecord->SpinLock, &EntryIrql);
//check count
MyPrint(_TitleAndFunc"pHiddenPageRecord->Count:%16IX\n", pHiddenPageRecord->Count);
if (pHiddenPageRecord->Count == MAX_HIDDEN_PAGE_COUNT)
goto Lable_Error;
//add pPTE record
PSPECIFIC_HIDDEN_PAGE_RECORD pCurrentRecord = &pHiddenPageRecord->Record[pHiddenPageRecord->Count];
pCurrentRecord->pPTE = pGetSpecificAddresspPTEPhysical(CR3, pHiddenPageBase);
MyPrint(_TitleAndFunc"pCurrentRecord->pPTE:%16IX\n", pCurrentRecord->pPTE);
if (pCurrentRecord->pPTE == NULL)
goto Lable_Error;
//add hidden virtual address record
pCurrentRecord->pHiddenBase = pHiddenPageBase;
MyPrint(_TitleAndFunc"pCurrentRecord->pHiddenBase:%16IX\n", pCurrentRecord->pHiddenBase);
//add original pfn record
ContextVirtualToPhysical(&g_PhysicalOpCR3);
pCurrentRecord->OriginalPfn = pCurrentRecord->pPTE->PageFrameNumber;
ContextPhysicalToVirtual(&g_PhysicalOpCR3);
MyPrint(_TitleAndFunc"pCurrentRecord->OriginalPfn:%16IX\n", pCurrentRecord->OriginalPfn);
//add hidden pfn record
//allocate memory
//record the physical address
//then free the memory and mark it as bad
PVOID TemporaryVirtual = MmAllocateNonCachedMemory(PAGE_SIZE);
if (TemporaryVirtual == NULL)
goto Lable_Error;
PHYSICAL_ADDRESS TemporaryPhysical = MmGetPhysicalAddress(TemporaryVirtual);
LARGE_INTEGER PhysicalLength = { 0 };
PhysicalLength.QuadPart = PAGE_SIZE;
pCurrentRecord->HiddenPfn = pPhysicalAddresstoPTEPFN((PVOID)(TemporaryPhysical.QuadPart));
MyPrint(_TitleAndFunc"pCurrentRecord->HiddenPfn:%16IX\n", pCurrentRecord->HiddenPfn);
MmFreeNonCachedMemory(TemporaryVirtual, PAGE_SIZE);
Status = MmMarkPhysicalMemoryAsBad(&TemporaryPhysical, &PhysicalLength);
//copy codes to the new non-mapped physical address
ContextVirtualToPhysical(&g_PhysicalOpCR3);
RtlCopyMemory((PVOID)(TemporaryPhysical.QuadPart),
pCurrentRecord->pHiddenBase,
PAGE_SIZE
);
ContextPhysicalToVirtual(&g_PhysicalOpCR3);
//check the mark state
if (!NT_SUCCESS(Status))
goto Lable_Error;
//the last step:count +1
pHiddenPageRecord->Count++;
//release spin lock
KeReleaseSpinLock(&pHiddenPageRecord->SpinLock, EntryIrql);
return STATUS_SUCCESS;
Lable_Error:
KeReleaseSpinLock(&pHiddenPageRecord->SpinLock, EntryIrql);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS RemoveAndRestoreAllHiddenPageRecord(PHIDDEN_PAGE_RECORD pHiddenPageRecord)
{
KIRQL EntryIrql;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
//prevent mulit-thread change the page record count
KeAcquireSpinLock(&pHiddenPageRecord->SpinLock, &EntryIrql);
//assert we have elements
if (pHiddenPageRecord->Count == 0)
goto Lable_Error;
//restore all records and mark all the hidden physical memory as good
PSPECIFIC_HIDDEN_PAGE_RECORD pCurrentRecord = NULL;
PHYSICAL_ADDRESS CurrentHiddenPhysical = { 0 };
LARGE_INTEGER PhysicalLength = { 0 };
PhysicalLength.QuadPart = PAGE_SIZE;
for (int i = 0; i < pHiddenPageRecord->Count; i++)
{
pCurrentRecord = &pHiddenPageRecord->Record[i];
CurrentHiddenPhysical.QuadPart = (ULONG64)pPTEPFNtoPhysicalAddress(pCurrentRecord->HiddenPfn);
//mark it as good
MmMarkPhysicalMemoryAsGood(&CurrentHiddenPhysical, &PhysicalLength);
//restore all page mapping relations
ContextVirtualToPhysical(&g_PhysicalOpCR3);
pCurrentRecord->pPTE->PageFrameNumber = pCurrentRecord->OriginalPfn;
ContextPhysicalToVirtual(&g_PhysicalOpCR3);
//invalid the TLB of current hidden address
__invlpg(pCurrentRecord->pHiddenBase);
}
//set count to zero
pHiddenPageRecord->Count = 0;
//release spin lock
KeReleaseSpinLock(&pHiddenPageRecord->SpinLock, EntryIrql);
return STATUS_SUCCESS;
Lable_Error:
KeReleaseSpinLock(&pHiddenPageRecord->SpinLock, EntryIrql);
return STATUS_UNSUCCESSFUL;
}
彩蛋:
NTSTATUS AddHiddenPageRecord(ULONG64 CR3, PVOID pHiddenPageBase, PHIDDEN_PAGE_RECORD pHiddenPageRecord)
{
KIRQL EntryIrql;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
//prevent mulit-thread change the page record count
KeAcquireSpinLock(&pHiddenPageRecord->SpinLock, &EntryIrql);
//check count
MyPrint(_TitleAndFunc"pHiddenPageRecord->Count:%16IX\n", pHiddenPageRecord->Count);
if (pHiddenPageRecord->Count == MAX_HIDDEN_PAGE_COUNT)
goto Lable_Error;
//add pPTE record
PSPECIFIC_HIDDEN_PAGE_RECORD pCurrentRecord = &pHiddenPageRecord->Record[pHiddenPageRecord->Count];
pCurrentRecord->pPTE = pGetSpecificAddresspPTEPhysical(CR3, pHiddenPageBase);
MyPrint(_TitleAndFunc"pCurrentRecord->pPTE:%16IX\n", pCurrentRecord->pPTE);
if (pCurrentRecord->pPTE == NULL)
goto Lable_Error;
//add hidden virtual address record
pCurrentRecord->pHiddenBase = pHiddenPageBase;
MyPrint(_TitleAndFunc"pCurrentRecord->pHiddenBase:%16IX\n", pCurrentRecord->pHiddenBase);
//add original pfn record
ContextVirtualToPhysical(&g_PhysicalOpCR3);
pCurrentRecord->OriginalPfn = pCurrentRecord->pPTE->PageFrameNumber;
ContextPhysicalToVirtual(&g_PhysicalOpCR3);
MyPrint(_TitleAndFunc"pCurrentRecord->OriginalPfn:%16IX\n", pCurrentRecord->OriginalPfn);
//add hidden pfn record
//allocate memory
//record the physical address
//then free the memory and mark it as bad
PVOID TemporaryVirtual = MmAllocateNonCachedMemory(PAGE_SIZE);
if (TemporaryVirtual == NULL)
goto Lable_Error;
PHYSICAL_ADDRESS TemporaryPhysical = MmGetPhysicalAddress(TemporaryVirtual);
LARGE_INTEGER PhysicalLength = { 0 };
PhysicalLength.QuadPart = PAGE_SIZE;
pCurrentRecord->HiddenPfn = pPhysicalAddresstoPTEPFN((PVOID)(TemporaryPhysical.QuadPart));
MyPrint(_TitleAndFunc"pCurrentRecord->HiddenPfn:%16IX\n", pCurrentRecord->HiddenPfn);
MmFreeNonCachedMemory(TemporaryVirtual, PAGE_SIZE);
Status = MmMarkPhysicalMemoryAsBad(&TemporaryPhysical, &PhysicalLength);
//copy codes to the new non-mapped physical address
ContextVirtualToPhysical(&g_PhysicalOpCR3);
RtlCopyMemory((PVOID)(TemporaryPhysical.QuadPart),
pCurrentRecord->pHiddenBase,
PAGE_SIZE
);
ContextPhysicalToVirtual(&g_PhysicalOpCR3);
//check the mark state
if (!NT_SUCCESS(Status))
goto Lable_Error;
//the last step:count +1
pHiddenPageRecord->Count++;
//release spin lock
KeReleaseSpinLock(&pHiddenPageRecord->SpinLock, EntryIrql);
return STATUS_SUCCESS;
Lable_Error:
KeReleaseSpinLock(&pHiddenPageRecord->SpinLock, EntryIrql);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS RemoveAndRestoreAllHiddenPageRecord(PHIDDEN_PAGE_RECORD pHiddenPageRecord)
{
KIRQL EntryIrql;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
//prevent mulit-thread change the page record count
KeAcquireSpinLock(&pHiddenPageRecord->SpinLock, &EntryIrql);
//assert we have elements
if (pHiddenPageRecord->Count == 0)
goto Lable_Error;
//restore all records and mark all the hidden physical memory as good
PSPECIFIC_HIDDEN_PAGE_RECORD pCurrentRecord = NULL;
PHYSICAL_ADDRESS CurrentHiddenPhysical = { 0 };
LARGE_INTEGER PhysicalLength = { 0 };
PhysicalLength.QuadPart = PAGE_SIZE;
for (int i = 0; i < pHiddenPageRecord->Count; i++)
{
pCurrentRecord = &pHiddenPageRecord->Record[i];
CurrentHiddenPhysical.QuadPart = (ULONG64)pPTEPFNtoPhysicalAddress(pCurrentRecord->HiddenPfn);
//mark it as good
MmMarkPhysicalMemoryAsGood(&CurrentHiddenPhysical, &PhysicalLength);
//restore all page mapping relations
ContextVirtualToPhysical(&g_PhysicalOpCR3);
pCurrentRecord->pPTE->PageFrameNumber = pCurrentRecord->OriginalPfn;
ContextPhysicalToVirtual(&g_PhysicalOpCR3);
//invalid the TLB of current hidden address
__invlpg(pCurrentRecord->pHiddenBase);
}
//set count to zero
pHiddenPageRecord->Count = 0;
//release spin lock
KeReleaseSpinLock(&pHiddenPageRecord->SpinLock, EntryIrql);
return STATUS_SUCCESS;
Lable_Error:
KeReleaseSpinLock(&pHiddenPageRecord->SpinLock, EntryIrql);
return STATUS_UNSUCCESSFUL;
}