Monday, May 12, 2014

0x19 Debugging

I've been busy lately so it has been hard to have a sit down and write a proper debugging blog post! I'm here now relaxing before bed, so I figured no better time to go ahead and write a nice post! In today's post we're going to discuss debugging the 0x19 bug check, however debugging this type of bug check also has similarities to 0xC5/0xC2 bug checks as well.

---------------------------

Right, so as always, here's the basic bug check information:

BAD_POOL_HEADER (19)

This indicates that a pool header is corrupt.

Great, so now that we know that, what is pool, and what is bad/went wrong here? This bug check has a lot to do with Windows' memory management, which is pretty complicated. There's a lot of different parts to it, but only a few we really need to discuss for this bug check.

First off, let's discuss pool. What is pool? Well, pool is kernel-mode memory that is used as storage space for drivers. Memory is organized into pages, and a page of memory is usually/typically ~4KB. Windows' memory manager breaks this 4KB of memory up into various smaller 'blocks', some being as small as ~8 bytes. When it comes to 0x19 debugging, we end up looking exactly at these blocks mentioned above. The pool header is used to provide information about the allocation, such as the size/owner of the pool allocation.

Let's take a look at the parameters of the bug check:

BugCheck 19, {d, ffffe000109e288f, 8e83b75113111670, 168e83b751131109}
The 1st parameter of the bug check in our case here is 0xD which indicates the pool header of a freed block has been modified after it was freed. This is not typically the fault of the prior owner of the freed block; instead it is usually (but not always) due to the block preceding the freed block being overrun. The other three parameters are reserved, and to my knowledge, for pool entries/addresses.

Let's go ahead and run !pool on the 2nd parameter of the bug check:

1: kd> !pool ffffe000109e288f
Pool page ffffe000109e288f region is GetUlongFromAddress: unable to read from fffff802f49cb208
Nonpaged pool
 ffffe000109e2000 size:  250 previous size:    0  (Allocated)  klxm
 ffffe000109e2250 size:   80 previous size:  250  (Free)       Free
 ffffe000109e22d0 size:   c0 previous size:   80  (Allocated)  KLWc
 ffffe000109e2390 size:   e0 previous size:   c0  (Allocated)  klpt
 ffffe000109e2470 size:   50 previous size:   e0  (Allocated)  KLWp
 ffffe000109e24c0 size:   90 previous size:   50  (Allocated)  KLWe
 ffffe000109e2550 size:   e0 previous size:   90  (Allocated)  klpt
 ffffe000109e2630 size:   30 previous size:   e0  (Free)       Free
 ffffe000109e2660 size:   c0 previous size:   30  (Allocated)  KLWc
 ffffe000109e2720 size:   90 previous size:   c0  (Allocated)  KLPS
 ffffe000109e27b0 size:   90 previous size:   90  (Free )  KLWe
*ffffe000109e2840 size:   50 previous size:   90  (Free)      *KLWp
        Owning component : Unknown (update pooltag.txt)
 ffffe000109e2890 size:   50 previous size:   50  (Free )  KLWp
 ffffe000109e28e0 size:   30 previous size:   50  (Free)       Free
 ffffe000109e2910 size:   50 previous size:   30  (Allocated)  KLWp
 ffffe000109e2960 size:   c0 previous size:   50  (Allocated)  KLWc
 ffffe000109e2a20 size:   80 previous size:   c0  (Allocated)  KLip
 ffffe000109e2aa0 size:   90 previous size:   80  (Allocated)  KLWe
 ffffe000109e2b30 size:   80 previous size:   90  (Allocated)  KLip
 ffffe000109e2bb0 size:   10 previous size:   80  (Free)       Free
 ffffe000109e2bc0 size:   a0 previous size:   10  (Allocated)  dlib
 ffffe000109e2c60 size:   50 previous size:   a0  (Allocated)  KLWp
 ffffe000109e2cb0 size:   30 previous size:   50  (Free)       Free
 ffffe000109e2ce0 size:   50 previous size:   30  (Allocated)  KLWp
 ffffe000109e2d30 size:   80 previous size:   50  (Allocated)  KLip
 ffffe000109e2db0 size:   90 previous size:   80  (Allocated)  KLWe
 ffffe000109e2e40 size:  100 previous size:   90  (Allocated)  KLWc
 ffffe000109e2f40 size:   c0 previous size:  100  (Allocated)  KLWc
Above we can see the blocks we discussed above earlier. Now, what are all those letters at the end? Good question! Those are pool tags. What exactly is a pool tag? Well, a pool tag is a four-byte character that is associated with a dynamically allocated chunk of pool memory. Notice how we have klxm (4), Free (4), KLWc (4), etc. All are 4. No more, no less. The tag is specified by a driver when it allocates the memory.

Notice that in our case for the owning component it says:

*ffffe000109e2840 size:   50 previous size:   90  (Free)      *KLWp
        Owning component : Unknown (update pooltag.txt)
The reason for this is due to the fact that pooltag.txt only contains kernel-mode components and drivers supplied with Windows. If the driver is 3rd party, it may have a tag thanks to the developer and/or manufacturer, however, it will not be in pooltag.txt. This is a pretty big clue that a 3rd party driver is causing corruption in your case if this is what you see.

In our case, this is exactly the case. klxm, KLWc, KLPS, KLWE, etc, are all pool tags relating to the klif.sys driver. We can also confirm this by dumping the call stack:

1: kd> k
Child-SP          RetAddr           Call Site
ffffd000`21512a38 fffff802`f4910167 nt!KeBugCheckEx
ffffd000`21512a40 fffff802`f490fa03 nt!ExFreePoolWithTag+0xe97
ffffd000`21512ac0 fffff800`014380f3 nt!ExFreePoolWithTag+0x733
ffffd000`21512b90 fffff802`f467e000 klif+0x380f3
ffffd000`21512b98 ffffe000`1090bde0 nt!_guard_check_icall_fptr <PERF> (nt+0x0)
ffffd000`21512ba0 ffffe000`004514e0 0xffffe000`1090bde0
ffffd000`21512ba8 00000000`6d734c4b 0xffffe000`004514e0
ffffd000`21512bb0 fffff800`0237bd60 0x6d734c4b
ffffd000`21512bb8 00000000`00000004 klflt+0xed60
ffffd000`21512bc0 00000000`00000080 0x4
ffffd000`21512bc8 fffff800`02393f51 0x80
ffffd000`21512bd0 ffffe000`00453390 klflt+0x26f51
ffffd000`21512bd8 ffffe000`004514e0 0xffffe000`00453390
ffffd000`21512be0 ffffe000`0048e870 0xffffe000`004514e0
ffffd000`21512be8 ffffe000`00453390 0xffffe000`0048e870
ffffd000`21512bf0 00000000`00000000 0xffffe000`00453390
We can see klif.sys calls into the nt!ExFreePoolWithTag routine which deallocates a block of pool memory allocated with the specified tag. We can see directly afterwards the bug check was called because the pool header of the freed block has been modified after it was freed, thus the reason I believe it was called twice in this instance.

With this said, what's the klif.sys driver? It's a Kaspersky driver, although I cannot find any documentation on what specifically this driver is in charge of.

-- You can find out what driver(s) belong to what pool tag(s) if they are 3rd party by doing the following:

1. Run CMD, preferably as admin (Elevated).

2. Change your directory to the drivers folder -- Example: cd %systemroot%\system32\drivers

3. findstr /m /l <tag> *.sys

Obviously replace <tag> with your tag -- So for example, findstr /m /l KLWp *.sys.

---------------------------

Right, so now that we've established that Kaspersky is the problem here, I advised the user to be confirm that removing Kaspersky stopped this problem (it did). Given that the problem didn't exist with Kaspersky removed, the user contacted Kaspersky, and I imagine they either attempted provided a workaround of some sort, or the user simply removed Kaspersky.

Hope you enjoyed reading!

References/extra reading:

http://blogs.technet.com/b/yongrhee/archive/2009/06/24/pool-tag-list.aspx
http://blogs.technet.com/b/askperf/archive/2008/04/11/an-introduction-to-pool-tags.aspx
http://msdn.microsoft.com/en-us/library/windows/hardware/ff557389%28v=vs.85%29.aspx
http://blogs.msdn.com/b/ntdebugging/archive/2013/06/14/understanding-pool-corruption-part-1-buffer-overflows.aspx



2 comments: