物理内存映射 获取PTE

IA-32的分页机制灰常给力的。弄几个函数玩

 

 注意里面的copyonwrite,很好玩的。

 

typedef struct _HARDWARE_PTE_X86 { ULONG Valid : 1; ULONG Write : 1; ULONG Owner : 1; ULONG WriteThrough : 1; ULONG CacheDisable : 1; ULONG Accessed : 1; ULONG Dirty : 1; ULONG LargePage : 1; ULONG Global : 1; ULONG CopyOnWrite : 1; // software field ULONG Prototype : 1; // software field ULONG reserved : 1; // software field ULONG PageFrameNumber : 20; } HARDWARE_PTE_X86, *PHARDWARE_PTE_X86; typedef struct _HARDWARE_PTE_X86PAE { union { struct { ULONGLONG Valid : 1; ULONGLONG Write : 1; ULONGLONG Owner : 1; ULONGLONG WriteThrough : 1; ULONGLONG CacheDisable : 1; ULONGLONG Accessed : 1; ULONGLONG Dirty : 1; ULONGLONG LargePage : 1; ULONGLONG Global : 1; ULONGLONG CopyOnWrite : 1; // software field ULONGLONG Prototype : 1; // software field ULONGLONG reserved0 : 1; // software field ULONGLONG PageFrameNumber : 26; ULONGLONG reserved1 : 26; // software field }; struct { ULONG LowPart; ULONG HighPart; }; }; } HARDWARE_PTE_X86PAE, *PHARDWARE_PTE_X86PAE;

 

 

_declspec(naked) DWORD __stdcall IsPAEEnabled() { __asm { _emit 0x0F; // mov eax,cr4 _emit 0x20; _emit 0xE0; and eax,0x20; //PAE flag 100000 ret; } }

该函数返回 是否开启PAE模式。

 

 

ULONG MiGetPteAddress(DWORD address) { if(IsPAEEnabled()) //PAE enabled... { address >>= 9; address &= 0x7FFFF8; } else { address >>= 0xA; address &= 0x3FFFFC; } address -= 0x40000000; return address; }

获取给定地址的PTE地址。逆向自HAL

 

 

 

ULONG MiGetPdeAddress(DWORD address) { if(IsPAEEnabled()) { address >>= 0x12; address &= 0x3FF8; address -= 0x3FA00000; } else { address >>= 0x14; address &= 0xFFC; address -= 0x3FD00000; } return address; }

获取给定地址的PDE地址

 

 

 

DWORD GetPFNNumeberFromKernelVA(DWORD Address) { DWORD MyPFN = 0; ULONG* MyPteAddress = GetPteAddressFromAddress(Address); __try { if(IsPAEEnabled() == 0) //PAE OFF { MyPFN = ((PHARDWARE_PTE_X86)MyPteAddress)->PageFrameNumber; } if(IsPAEEnabled()) //PAE On { PHARDWARE_PTE_X86PAE MyDataPDE = (PHARDWARE_PTE_X86PAE)MiGetPdeAddress(Address); if(MyDataPDE->LargePage) //LargePage on { MyPFN = MyDataPDE->PageFrameNumber; MyPFN += (Address >> 12) & 0x1FF; } else MyPFN = ((PHARDWARE_PTE_X86PAE)MyPteAddress)->PageFrameNumber; } } __except(1) { } return MyPFN; }

获取给定地址对应物理内存的PFN号

 

 

 

 

 

 

VOID FASTCALL MiLockPagedAddress ( IN PVOID VirtualAddress ) /*++ Routine Description: This routine checks to see if the virtual address is valid, and if not makes it valid. Arguments: VirtualAddress - Supplies the virtual address to make valid. Return Value: Returns TRUE if lock released and wait performed, FALSE otherwise. Environment: Kernel mode. --*/ { KIRQL OldIrql; PMMPFN Pfn1; PMMPTE PointerPte; PointerPte = MiGetPteAddress (VirtualAddress); // // The address must be within paged pool. // LOCK_PFN (OldIrql); if (PointerPte->u.Hard.Valid == 0) { MiMakeSystemAddressValidPfn (VirtualAddress, OldIrql); } Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); MI_ADD_LOCKED_PAGE_CHARGE (Pfn1); UNLOCK_PFN (OldIrql); return; }

 

你可能感兴趣的:(物理内存映射 获取PTE)