Windows Kernel Programming Tutorial 9 – Memory – Part 2

Hello,youtube.I’m Langester. In this video, we will talk about some errors you may encounter when you use pool memory. The first thing I like to mention is what it looks like when you allocate pool memory using ExAllocatePoolXXX. Here,memory block represents the memory you get and you could use. Poolheader is actually a structure in front of your memory block. Start address is the address you receive using ExAllocatePoolXXX In most cases, you don’t even know the existence of poolheader.Because start addr is not at poolheader,you dont need to bother to think about that. However,if your driver causing some error like BAD_POOL_HEADER/BAD_POOL_CALL,you need to know this in order to troubleshoot your driver issues. Poolheader is a very important stucture which contains info about your pool memory. We will cover this using windbg later in this video. By the way,generally there are many of these structures together, so it’s likely to overwrite the poolheader. Imagine some module(in the left) accidentally wipes out poolheader structure, what will happen when you free it is bugcheck by windows(BSOD) it’s not easy to debug your driver without this kind of knowledge.

So I recommend you follow this tutorial and do it yourself. If you don’t know how to set up windbg,please check out my 2nd and 4th tutorials. Let’s get started. What I’m going to do is overwrite the header of my new allocated memory block. In windows x64 version, pool header is 16 bytes, In x86 version it might be 8 bytes(I’m not sure). We could get this info using windbg. We simply copy some characters in the poolheader using strcpy. Here we must convert this type(PWCHAR) to PUCHAR in order to get right addr subtract Poolheader length 16 bytes(0x10) in x64. Now we get our poolheader addr. Build and load it in our virtual machine. We first look at the structure to get an overview. click debug-> break The command we are using this time is dt for print structure info.

The real name of poolheader is _pool_header type dt _pool_header and hit enter The member we will use is previoussize,blocksize pooltype and pooltag What we are going to do next is set up a breakpoint in our driver to ensure we get the right addr. How? Let’s find out. bp command is the command you can use to set up a breakpoint in a function. For example, we want our driver stop when it loaded.So we bp string!DriverEntry, string is our driver name,DriverEntry is function. Press enter and press F5 to continue our virtual machine,Now we load our driver.Hope it will work. After we click start,we cannot do anything in virtual machine if our breakpoint works. When pdb is downloaded,we will enter source debugging mode. Using step over command(F10) to step one statement and also step over will not enter function.

Highlighted line is the current line we are about to run,we step to if statement to get our memory block addr. Why if statement? Simply because we can easily get address value.In fact You could more easily get deststring.buffer by clicking view->Locals The right column is the assembly language version of left column. cmp(compare) value,0 is really the if statement in our case. How to print value in specific address? The answer is db(byte) dw(word) dd(dword) dq(qword).

In x64 version,we will use dq to print address value. Now we get our start addr of memory block. We print our header stucture using dt again. This time we provide start addr of the pool header. And don’t forget to subtract 16(windbg using hexdecimal,so we type 10) Like I said in the previous tutorial,the third parameter in Exallocatepoolwithtag is used for debugging. It’s time to find out. Pooltag is what we want. The value is 0x61626364,nothing special.Let’s look at this way,0x61,0x62,0x63,0x64 and it’s all ASCII value. If you look it up against ascii table,you will know this is our tag. Once we ensure everything is going as planned,we can corrupt our header now.

Press F10 to run our driver step by step. Now our header is overwritten,Let’s see if our memory is still usable We can see DbgPrint print our string successfully. So Despite our corrupt header,our memory block still works well. Let’s see what will happen when will free it. press F10 and our system crashes immediately. We click !analyze-v to get detailed info. Now this arrow stops after our free function. We get BAD_POOL_CALLER error, and the debug details say XXXX does not look like a valid allocation. We can also find some info in call stack. The function below bugcheck is where our problem happens. Our system crashes in Exfreepool function. The next thing we will do is take a closer look at pool header and use some member to debug our driver.

Let’s do it. One thing you need to know is that preivoussize and blocksize is not as it appears. What you need to do is times 16(0x10) in x64 version Previous size is the total size of memory block(including poolheader) before it and block size is our block(including poolheader) We could use db to print our pool header in byte format. L with number means how many bytes(db) you like to display. And finally you could see what happened to our block memory.

You can double check the address is the address of our allocated memory. Next we will list memory blocks within a page(4k) using previousize and blocksize. Reboot your virtual machine first and then we will find out. We do the same thing as we did just now. We see this structure several times.Now let’s list some other memory blocks using these two members.

We can go to the start of memory block before us by minus preivoussize*0x10(dont’ forget times 16) By the same logic,we can go to the start of memory block after us by plus blocksize*0x10. The common value of pool type is 0x2(allocated)0x4(freed) There is a command called !pool which can easily list memory blocks within a page. type !pool with poolheader addr . This table could make much more sense than what I just said. If we damage the relations between previousize and blocksize,windows will bugcheck when it detects We can consolidate our knowledge by dt memory block one by one and look it up in this table. You can do it with what I do in this video.

That’s it. As always I hope this video will help you..

As found on Youtube