---
tags: thesis
---
# Thesis reading note:
Mainly from Windows Internal 7th edition
## Memory management:
### Paged pool vs non-paged pool:
- https://docs.microsoft.com/en-us/windows/win32/memory/memory-pools
- The nonpaged pool consists of virtual memory addresses that are guaranteed to reside in physical memory as long as the corresponding kernel objects are allocated.
- The paged pool consists of virtual memory that can be paged in and out of the system
- A page can be locked, meaning that it will be guaranteed to stay in the memory. Some functions to do that: `VirtualLock` (for application), `MmProbeAndLockPage`, `MmLockPagableCodeSection`, `MmLockPagableDataSection` (for device drivers)
### Reserving and commiting pages:
- Reserving: processes set aside a range of virtual address for future use --> cant access yet cause it's not mapped to physical address
- Commiting: actually map the page to physical address
### Shared memory:
- Multiple virtual pages in different processes that get mapped to the same physical page.
#### Copy-on-write protection:
- A protection method used for shared pages
- Assume process A and B are sharing a physical page in memory:
- If process A writes to the shared page --> The modified content will be saved in a new physical page
- Process B's data remains unchanged.
- ==> 2 processes are now no longer sharing anything.
- Detail explaination: https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection
## Virtual address space layout
Three main types of data mapped into the virtual address space:
- Per-process private code and data.
- Sessionwide code and data (a session = a logon session of a user).
- Systemwide code and data: contains global operating system code and data structures visible to each process
Each process has their user-mode address space, and their own mapping of kernel memory (which on windows 64bit is 0x80000000000 to 0xFFFFFFFFFFF). The a
**Note about kernel processes:** Each user-mode process has its own private virtual address space, but all code that runs in kernel mode shares a single virtual address space called system space.

As seen from the image, system space of all process consists of the same virtual addresses, which is mapped to the same page in physical memory.
## Address translation:
OS supplies structures and virtual address to Address Translation unit in CPU. It will then translate the virtual address to a physical address.
About Page Fault:
`If the address cannot be translated successfully (for example, the page may not be in physical memory but resides in a page file), the CPU throws an exception known as a page fault that indicates to the OS that the page cannot be located. Because the CPU has no idea where to find the page (page file, mapped file, or something else), it relies on the OS to get the page from wherever it’s located (if possible), fix the page tables to point to it, and request that the CPU tries translation again.`

### Page directory:
- Page directory contains the location of all page tables
- The physical address of the process page directory is stored in the kernel process (KPROCESS) block
- CPU know the address of this page thanks to a special register (`CR3` on x86)
- `CR3` is updated with the value inside KPROCESS every time a context switch happends (It is stored inside: `_KPROCESS.DirectoryTableBase`)
### Page table and Page table entry (PTE):
- Page table: store the mapping between virtual addresses and physical addresses
- Structure of a page table entry:

==> We gonna use those protection bit fields to detect pages with injected code later on.
### x86 address translation:
`Virtual address = (Page Directory Pointer Table index)CONCAT (Page directory index) CONCAT (Page table index) CONCAT (offset)`
Basic steps to translate virtual address -> physical address:
- Using the Page Directory Pointer Table index --> Locate the page directory
- Using page directory index --> Locate the **Page Directory Entry** (PDE). PDE contains **Page Frame Number** of the page table --> Locate the Page Table
- Use Page table index --> Locate the **Page Table Entry**. If the page is valid, PTE contains the Page Frame Number of the page in physical memory
- Use offset to locate the exact address inside the physical page
### x64 address translation:
- Use 4-level page table scheme
- PML4e = Page map level 4 entry
- Virtual address is 48-bit long.

- **Write more about paging mode: 4KB Paging, 2MB Paging, 1GB Paging**
## Virtual address descriptor
- VAD: a structure to keep track of which virtual addresses have been **reserved** (doesn't need to be commited) in the process’s address space
- Each process has its own VAD
- Info on VAD node: address range, reserved or commit, protection, shared or private,...
- When a process reserves address space or maps a view of a section, memory manager create VAD.
- When a thread first access an address, the memory manager find a VAD whose range contains the address --> create a PTE for the page containing the address with the info from the VAD.
- How to get VAD tree: \_EPROCESS-->VadRoot
## Section object:
- Section object: represents a block of memory that two or more processes can share.
## Page frame number database:
- PFN database describes the state of each page in physical memory --> Windows uses this to manage physical memory.
- PFN database is an array of \_MMPFN structs with the PFN as an index
- Each \_MMPFN struct represents each physical page of memory on the system.
- `Every PFN DB entry describes one physical page and contains a field called PrototypePte (accessible via its u4 member), which is a bit flag that is set when the physical page belongs to shared memory`
- There is paging structure for each processes, but PFN is basically a central data structure so that Windows can keep track of every pages in every processes --> basically a struct that has all the PTE(??)
## PTE states:
### Prototype PTE:
## About Kernel Virtual Address Shadow:
https://wumb0.in/windows-10-kvas-and-software-smep.html
https://www.fortinet.com/blog/threat-research/a-deep-dive-analysis-of-microsoft-s-kernel-virtual-address-shadow-feature
- KAVS was implemented to prevent user mode code from reading data in kernel space (in order to prevent `Meltdown` attack)
- Basically, there are 2 set of paging structures for a usermode process: a user-mode page tables and a kernel-mode page tables.
- User-mode page tables only contains mapping of user-mode addresses. The physical address of this table is stored in `_KPROCESS.UserDirectoryTableBase`
- Kernel-mode page tables contains mapping of both kernel-mode and user-mode addresses. The physical address of this table is stored in `_KPROCESS.DirectoryTableBase` and `_KPROCESS.KernelDirectoryTableBase`
- **Processes that execute in an elevated context do not use KVAS at all**
- According to `Fortinet`, having 2 sets of page tables like that would cause overhead during context switch (for example: TLB flusing). I don't fully understand why.
- Windows mitigates the overhead by *only flushing TLB for user-mode page tables*
```cpp=
// This code is from `SwapContext` in ntoskrnl.exe
// KiKvaShadow is used to check if KVAS is enabled
// NewCR3 & 2 is the supervisor of CR3, used to check if the new page table belongs to usermode or kernelmode
if ( (KiKvaShadow & 1) != 0 && (NewCR3 & 2) == 0 )
{
// Perform TLB flush
v19 = __readcr4();
v19 ^= 0x80ui64;
__writecr4(v19);
__writecr4(v19 ^ 0x80);
}
```