Memory Management – Windows part2

Agenda

  1. Interface to windows memory manager
    1. Allocation
    2. Reserved, committed, freed memory
    3. Memory guards
  2. User mode Memory management
    1. AWE (Address Windowing Extension)
    2. Heaps
  3. Kernel mode Memory management
    1. Memory Pools
    2. Address spaces in kernel mode

From where we last landed we shall take off. In case you’re experienced with windows you’ll find most of the current details almost trivial however It’s always safe to lay a strong basis.

1

1- Interface to windows memory manager

In Windows, memory manager term implies many components since It’s considered a set of services that serves multiple goals such as: de/allocation or fault handling. anyway I guess we’ve given big attention to memory management in previous part. Moreover, A process by definition has it’s -almost- isolated address space which means that same addresses in two different functions map to different physical addresses. This is because every process has its own page directory which entries differ from other page directories and therefore a linear address translates to different physical address.

From a ring 3 environment perspective in windows pages are either free or reserved or committed or sharable. A free page is any page that isn’t present or doesn’t have an entry in process address space. So to allocate a page you simply add an entry of the allocated thunk virtual address into process address space to allow it to translate to a valid physical address. Nonetheless, Reserved pages doesn’t translate to a physical memory address. they are simply a way of booking a range of virtual address until usage.. Just like a train seat. Unlike reserved pages, committed pages do resolve to a physical address which makes you read/write committed memory but not reserved memory. It’s always better to code, This code allocates a reserved memory thunk and tries to access it. This of course will raise a page fault exception.

#include

int
main(void){
	LPBYTE lpMem;
	lpMem = VirtualAlloc(NULL, 0x1000, MEM_RESERVE, 0x40);
	lpMem[1] = 0x31;
	return 0;
}

If you slap the compiled binary into a debugger you’ll see this.
2However once you add the MEM_COMMIT to the memory allocation function you’ll have a valid virtual address thunk.
Due to the fact that each process has its own process space, the only way to make two processes share a page is to make virtual addresses in two processes -or more- resolve to the same physical address or memory mapped files (page file backed sections). and that’s how a memory is shared between processes. a very obvious example for that is dlls they are accessible from every process running. This figure explains how it work [Windows internals].
3When a binary is loaded into memory, few sections are allocated to store program components. for instance several pages are allocated for the .text section which are only readable and executable. and other for .data section which are only readable and 1 MB for stack which is readable and writable. If you give attention to olly Memory map you’ll find some memory thunks Access marked as Guarded which means that there’s a guard page exists after a guarded thunk of data which state is reserved to avoid access to further addresses than allocated or guarded memory. If you try to modify them in olly you won’t be able to, since It is reserved not committed page.
4For more access overflowing prevention or execution prevention techniques, There’s the famous DEP (Data Execution Prevention) supported by Windows or stack cookies which I shall not discuss in this post, you can read about it in many places on the internet and overriding techniques are the same.

2- User Mode Memory Management

We’ve been taking a brief introduction on how memory is treated in user space but Windows provides multiple extra features that are both user space related and independent of machine specified memory unit (a page in our case).

AWE
Address Windowing extension is an impressive feature in windows which allows you to walk through huge physical memory using a limited virtual address range. If you’ve ever tried to push the limits of allocation on windows you’ll find that normally a 32-bit process is limited to 2GB usable memory which means that a user process can have a 2GB virtual address range. But of course this limits 32-bit processes under 64bit architecture where 64bit processes are allowed to possess bigger space. That’s when AWE comes in hand. Actually you’re performing an AWE right now, since your screen can’t be wide enough for the whole article you need to scroll for the rest of the post to be visible to you. and that’s what AWE does EXACTLY!
5In case you didn’t understand what the previous paragraph ment. Code always makes you understand how it works. To allocate an AWE all you need is to use AllocateUserPhysicalPages and aquire the right to use a range of physical memory through your address window and then scroll through the aquired physical memory through VirtuaAlloc. This example is provided by msdn for AWE usage implementation.

Heaps

From the start till this point we’ve been discussing allocating big sizes (more than a page). But mostly we don’t need to allocate a page to store small data such as small arrays or what so ever. This would result to a huge internal fragmentation and therefore windows provides us with the heaps through the Heap Manager. If you’re familiar with linux or K&R C you’d definitely know the famous malloc function. This function  is provided by windows but of course as you all know.. Microsoft has to place its touch..
There’s a standard way in windows to allocate heaps via the Heap manager which is done using either HeapCreate/Destroy and HeapAlloc/Free/ReAlloc. A process by default has one heap once it’s loaded into memory of size 1MB which can be aquired through GetProcessHeap. a heap manager consists of functions provided by API (previously mentioned) and Front-End heap such as Low-Fragmentation-Heap and core heap. A heap manager exists in both kernel space and user space unlike a memory manager of course. The next figure shows how Heap manager looks like.

5Anyway, I’d rather be brief on heaps since most of you is surely familiar with it.

3- Kernel Mode Heaps

In kernel life is much different than user space. there’s no VirtualAlloc or AWEs or regular Heaps there’s only Pools. Pools are the term used to describe the kernel mode heaps. Pools are two types (Non Paged Pool/ Paged Pools). the term paged here implys that a heap cannot be stored in a memory mapped file, so it’s always present in RAM which is of course what happens in paged pools. Pools can be allocated using the WDK ExAllocatePool and freed by ExFreePool. A non-paged pool size can start with 40MB or 10% of total RAM size up to 75% of RAM size or 2GB and a paged pool size ends at 2GB at all cases that is of course if you’re x86. WDK comes with a poolmon tool which enables you watch used pools by present system modules. Still of course if you’re in a debugging session all you need is to issue !vm command.
6

Address Spaces in Kernel Mode

You might find the title pretty vague or ambigious. but If you’re familiar with Linux LKM development you definitely know that once you insert a module into the kernel It has its own address space allocated for it which alter every time you reload the driver. This protects several kernel components from code at ring 0 and isolates modules from the main system image. In windows however this is not the case.. a driver once loaded in kernel space it uses the same DirBase used by the system image which makes the whole kernel naked to any code at ring 0. I don’t claim that i know better than windows developers but removing exported symbols and undocumented functions isn’t always that secure. You can always check that yourself in both windows and Linux by the following code.
Windows Driver

#include "ntddk.h"

VOID Unload(IN PDRIVER_OBJECT DriverObject)
{
	return;
}

NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING regPath)
{

	UINT32 i;
	__asm{
		mov eax,cr3
		mov i, eax
	}
	DbgPrint("Address Space %p\n", i);
	(*DriverObject).DriverUnload = Unload;
	return STATUS_SUCCESS;
}

Which gives this output
7
In Linux

#include <linux/module.h>
#include <linux/kernel.h>

static int __init init_mod(void)
{

	unsigned int i;

	asm volatile(" mov  %%cr3, %%eax	\n"
				 " mov %%eax, %0" : "=m" (i));
	printk("Address space %x\n", i);
	return 0;

}
static void __exit exit_mod(void)
{
	printk("Unloading..\n");
	return;
}
module_init(init_mod);
module_exit(exit_mod);
MODULE_LICENSE("GPL");

Which outputs the following
saad

By here we’ve finished discussing Memory management. You’ve must have been wondering all along why a blog which targets security as a topic would be discussing memory management. The case is on future topics we will be discussing many topics that depends heavily on how far you understand memory management and we’ll be using this post as a reference all along.. Feel free to discuss any points.

This was Saad Talaat,
You might have navigated here by a seach. But, my job is to research.

Advertisements
This entry was posted in Windows and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s