20 #define for_each_pfn_lock(_var_name) list_for_each (gWinPfns, WIN_PFN_LOCK, _var_name) 39 QWORD pteAddress, pfnAddress;
53 ERROR(
"[ERROR] IntTranslateVirtualAddressEx: 0x%08x\n", status);
83 if (pfnSize >
sizeof(pPfn))
85 ERROR(
"[ERROR] The PFN size is too large: %d bytes!", pfnSize);
113 if (pfnSize >
sizeof(pPfn))
115 ERROR(
"[ERROR] The PFN size is too large: %d bytes!", pfnSize);
119 for (
DWORD page = 0; page < 100; page++)
122 WORD refCount, pageLocation;
127 ERROR(
"[ERROR] IntTranslateVirtualAddressEx failed for 0x%016llx (kernel at 0x%016llx): 0x%08x\n",
156 pteAddress == 0xffffffff ||
162 if (refCount > 0xff || refCount == 0 ||
180 for (
DWORD j = 8; j < pfnSize; j++)
184 ERROR(
"[ERROR] NULL page pfn 0x%016llx should be NULL!\n", MmPfnDatabase);
224 WORD pageLocation, initialFlags, initialRefCount;
246 ERROR(
"[ERROR] Failed to get _MMPFN.u3 from address 0x%016llx for GPA 0x%016llx: 0x%08x\n",
247 pfnGva, PhysicalAddress, status);
251 pageLocation = ((0xFFFF0000 & *(
DWORD *)pPfnMap) >> 16) & 7;
252 initialFlags = (0xffff0000 & *(
DWORD *)pPfnMap) >> 16;
253 initialRefCount = 0x0000ffff & *(
DWORD *)pPfnMap;
254 refCount = initialRefCount;
264 WARNING(
"[WARNING] Cannot lock a page that isn't active. u3=0x%08x, pageLocation=%d\n",
265 *(
DWORD *)pPfnMap, pageLocation);
274 ERROR(
"[ERROR] The page is not initialized!\n");
281 CRITICAL(
"[ERROR] Reference counter is higher than expected: 0x%08x\n", refCount);
292 ERROR(
"[ERROR] Ref counter underflow! rc = 0x%08x\n", refCount);
309 if (initialRefCount != refCount)
311 ERROR(
"[ERROR] The ref count was change since we started locking it " 312 "until now... Initial: 0x%04x, Now: 0x%04x\n", initialRefCount, *(
WORD *)pPfnMap);
317 ERROR(
"[ERROR] The page was released in the meantime! rc = 0x%08x\n", refCount);
325 (
INT16)initialFlags))
327 ERROR(
"[ERROR] Initial flags changed: Initial: 0x%04x, Now: 0x%04x\n", initialFlags, *(
WORD *)(pPfnMap + 2));
353 if (GpaPage == pLock->GpaPage)
379 if (GvaPage == pLock->Page)
416 if (0 != PfnLock->GpaPage)
421 ERROR(
"[ERROR] IntWinPfnModifyRefCount failed for GVA %llx GPA %llx: 0x%08x\n",
422 PfnLock->Page, PfnLock->GpaPage, status);
428 if (0 != PfnLock->GpaPage)
434 ERROR(
"[ERROR] IntWinPfnModifyRefCount failed for 0x%016llx 0x%016llx: 0x%08x\n",
435 PfnLock->Page, PfnLock->GpaPage, status);
437 PfnLock->GpaPage = 0;
473 WARNING(
"[WARNING] Cannot unlock user-mode pages for now: 0x%016llx!\n", Address);
505 LOG(
"[INFO] Page at 0x%016llx it's not locked by us...\n", Address);
518 ERROR(
"[ERROR] IntHookPtsRemoveHook failed for 0x%016llx: 0x%08x\n", Address, status);
568 LOG(
"[PFN] Page at 0x%016llx is already released, will leave now...\n", VirtualAddress);
588 TRACE(
"[PFN] Removing lock for 0x%016llx : 0x%016llx transitions from 0x%016llx to 0x%016llx (large: %d)\n",
598 ERROR(
"[ERROR] IntWinPfnModifyRefCount failed: 0x%08x\n", status);
612 ERROR(
"[ERROR] IntHookPtsRemoveHook failed for 0x%016llx: 0x%08x\n", pLock->
Page, status);
616 else if (newGpa != pLock->
GpaPage)
618 TRACE(
"[PFN] Moving lock for 0x%016llx from 0x%016llx -> 0x%016llx\n", pLock->
Page, pLock->
GpaPage, newGpa);
626 ERROR(
"[ERROR] IntWinPfnMoveLock failed: 0x%08x\n", status);
667 WARNING(
"[WARNING] Cannot lock user-mode pages for now: 0x%016llx!\n", Address);
681 ERROR(
"[ERROR] IntTranslateVirtualAddressEx failed for GVA 0x%016llx: 0x%08x\n", Address, status);
744 pLock->
Page = Address;
762 LOG(
"[INFO] Page at gva 0x%016llx and gpa 0x%016llx it's not initialized. Will hook the page!\n",
783 ERROR(
"[ERROR] IntHookPtsSetHook failed: 0x%08x\n", status);
868 if (!Force && (--PfnLock->RefCount) != 0)
878 ERROR(
"[ERROR] IntWinPfnModifyRefCount failed: 0x%08x\n", status);
882 if (NULL != PfnLock->SwapHook)
887 ERROR(
"[ERROR] IntHookPtsRemoveHook failed for gva 0x%016llx, gpa 0x%016llx: 0x%08x\n",
888 PfnLock->Page, PfnLock->GpaPage, status);
910 LOG(
"[DBGINTRO] Pfn locks:\n");
914 LOG(
" ## %04d @ %p -> VA: 0x%016llx, GPA: 0x%016llx, SwapHook: %p, RefCount: %x, Present: %d, LargePage: %d\n",
915 index++, pLock, pLock->Page, pLock->GpaPage, pLock->SwapHook, pLock->RefCount,
916 pLock->Present, pLock->LargePage);
936 ERROR(
"[ERROR] There should be no pfn locks remaining... Got one on %llx, %llx!\n",
937 pLock->GpaPage, pLock->Page);
942 ERROR(
"[ERROR] IntWinPfnRemoveLock failed: 0x%08x\n", status);
The page is active and valid, but not part of any list (ActiveAndValid).
#define INT_STATUS_PAGE_NOT_PRESENT
Indicates that a virtual address is not present.
QWORD PhysicalAddress
The physical address to which VirtualAddress translates to.
WORD RefCount
The reference count.
INTSTATUS IntVirtMemUnmap(void **HostPtr)
Unmaps a memory range previously mapped with IntVirtMemMap.
static int16_t _InterlockedCompareExchange16(int16_t volatile *Destination, int16_t Exchange, int16_t Comparand)
QWORD MmPfnDatabase
Guest virtual address of the PFN data base.
WINDOWS_GUEST * gWinGuest
Global variable holding the state of a Windows guest.
INTSTATUS IntWinPfnIsMmPfnDatabase(QWORD MmPfnDatabase)
Checks if a a guest virtual address points to MmPfnDatabase.
#define CLEAN_PHYS_ADDRESS64(x)
QWORD SystemCr3
The Cr3 used to map the kernel.
#define INT_STATUS_SUCCESS
static LIST_HEAD gWinPfns
The list of locked PFNs.
BOOLEAN ShutDown
True if the system process protection is in beta (log-only) mode.
BOOLEAN Present
True if Page is present.
#define INT_SUCCESS(Status)
INTSTATUS IntWinPfnLockGpa(QWORD Gpa, WIN_PFN_LOCK **PfnLock)
Locks a guest physical address.
#define INT_STATUS_NOT_NEEDED_HINT
#define HpAllocWithTag(Len, Tag)
int INTSTATUS
The status data type.
#define INT_STATUS_NOT_FOUND
#define TRFLG_NONE
No special options.
BOOLEAN LargePage
True if Page is a large page.
static PWIN_PFN_LOCK IntWinPfnFindByGva(QWORD GvaPage)
Finds a PFN lock by a guest virtual address.
static INTSTATUS IntWinPfnModifyRefCount(QWORD PhysicalAddress, BOOLEAN Increment)
Modifies the in-guest reference count of a physical page.
A page from the ModifiedNoWritePageList.
INTSTATUS IntHookPtsSetHook(QWORD Cr3, QWORD VirtualAddress, PFUNC_SwapCallback Callback, void *Context, void *Parent, DWORD Flags, PHOOK_PTS *Hook)
Start monitoring translation modifications for the given VirtualAddress.
void IntWinPfnUnInit(void)
Uninits the PFN locks.
DWORD MappingsCount
The number of entries inside the MappingsTrace and MappingsEntries arrays.
INTSTATUS IntWinPfnLockGva(QWORD Gva, WIN_PFN_LOCK **PfnLock)
Locks a guest virtual address.
void * SwapHook
The swap hook used for Page, is Page is a virtual address.
QWORD Flags
The entry that maps VirtualAddress to PhysicalAddress, together with all the control bits...
#define WIN_PFN_INC_VALUE
The value used to increment the reference counter of a PFN database entry.
#define INT_STATUS_NOT_INITIALIZED
INTSTATUS IntKernVirtMemFetchQword(QWORD GuestVirtualAddress, QWORD *Data)
Reads 8 bytes from the guest kernel memory.
BOOLEAN PaeEnabled
True if Physical Address Extension is enabled.
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
#define CLEAN_PHYS_ADDRESS32PAE(x)
#define IS_KERNEL_POINTER_WIN(is64, p)
Checks if a guest virtual address resides inside the Windows kernel address space.
#define HpFreeAndNullWithTag(Add, Tag)
INTSTATUS IntHookPtsRemoveHook(HOOK_PTS **Hook, DWORD Flags)
Remove a PTS hook.
#define INT_STATUS_INVALID_INTERNAL_STATE
QWORD KernelVa
The guest virtual address at which the kernel image.
static void InsertTailList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
static INTSTATUS IntWinPfnMoveLock(WIN_PFN_LOCK *PfnLock, QWORD NewGpa)
Moves a lock set for a guest virtual address when the page to which it translates to changes...
INTSTATUS IntTranslateVirtualAddressEx(QWORD Gva, QWORD Cr3, DWORD Flags, VA_TRANSLATION *Translation)
Translates a guest virtual address to a guest physical address.
LIST_ENTRY Link
Entry inside the gWinPfns list.
#define for_each_pfn_lock(_var_name)
Iterates the linked list in gWinPfns.
#define UNREFERENCED_PARAMETER(P)
INTSTATUS IntWinPfnRemoveLock(WIN_PFN_LOCK *PfnLock, BOOLEAN Force)
Removes a PFN lock.
A page from the StandbyPageList.
#define WIN_KM_FIELD(Structure, Field)
Macro used to access kernel mode fields inside the WIN_OPAQUE_FIELDS structure.
#define WIN_PFN_GET_STRUCT_VA(MmPfn, Gpa)
Get the address of a guest _MMPFN structure.
#define WIN_PFN_REF_MAX
The maximum value we allow a PFN reference counter to reach.
#define CLEAN_PHYS_ADDRESS32(x)
static INTSTATUS IntWinPfnHandleTranslationChange(WIN_PFN_LOCK *Context, QWORD VirtualAddress, QWORD OldEntry, QWORD NewEntry, QWORD OldPageSize, QWORD NewPageSize)
Handles translation changes for locked guest virtual pages.
void IntWinPfnDump(void)
Prints all the PFN locks.
#define INT_STATUS_INVALID_OBJECT_TYPE
__must_check INTSTATUS IntVirtMemMap(QWORD Gva, DWORD Length, QWORD Cr3, DWORD Flags, void **HostPtr)
Maps a guest virtual memory range inside Introcore virtual address space.
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
GUEST_STATE gGuest
The current guest state.
QWORD GpaPage
The guest physical page that is locked.
#define FIX_GUEST_POINTER(is64, x)
Masks the unused part of a Windows guest virtual address.
static PWIN_PFN_LOCK IntWinPfnFindByGpa(QWORD GpaPage)
Finds a PFN lock by a guest physical address.
QWORD PageSize
The page size used for this translation.
QWORD MappingsTrace[MAX_TRANSLATION_DEPTH]
Contains the physical address of each entry within the translation tables.
INTSTATUS IntKernVirtMemRead(QWORD KernelGva, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest kernel virtual memory range.
#define INT_STATUS_NO_MAPPING_STRUCTURES
Indicates that not all mapping structures of a virtual address are present.
#define LIST_HEAD_INIT(Name)
QWORD Page
The locked page.
A page from the ModifiedPageList.
Encapsulates information about a virtual to physical memory translation.
#define INT_STATUS_INVALID_PARAMETER_1
#define INT_STATUS_NOT_SUPPORTED
#define CRITICAL(fmt,...)
#define INT_STATUS_INVALID_PARAMETER_2
static INTSTATUS IntWinPfnLockAddress(QWORD Address, BOOLEAN IsPhysical, PWIN_PFN_LOCK *PfnLock)
Locks a guest page.
static INTSTATUS IntWinPfnUnlockAddress(QWORD Address, BOOLEAN IsPhysical)
Unlocks a guest page.
#define INT_STATUS_INSUFFICIENT_RESOURCES