Debugging Stop 0xC4 - DRIVER_VERIFIER_DETECTED_VIOLATION

x BlueRobot

Administrator
Staff member
Joined
May 7, 2013
Posts
10,391
Rich (BB code):
DRIVER_VERIFIER_DETECTED_VIOLATION (c4)
A device driver attempting to corrupt the system has been caught.  This is
because the driver was specified in the registry as being suspect (by the
administrator) and the kernel has enabled substantial checking of this driver.
If the driver attempts to corrupt the system, bugchecks 0xC4, 0xC1 and 0xA will
be among the most commonly seen crashes.
Arguments:
Arg1: 0000000000000062, A driver has forgotten to free its pool allocations prior to unloading.
Arg2: ffffc58bdf474f40, name of the driver having the issue.
Arg3: ffffc58be05fe550, verifier internal structure with driver information.
Arg4: 0000000000000001, total # of (paged+nonpaged) allocations that weren't freed.
    Type !verifier 3 drivername.sys for info on the allocations
    that were leaked that caused the bugcheck.

I wouldn't usually bother writing about a Stop 0xC4 since they're self-explanatory, however, this appears to a common bug with the Riot Vanguard driver and so I thought I would add some notes about how Driver Verifier detects this bug.

The second parameter contains a string which is the name of the driver which caused the system to bugcheck. The third parameter is actual a pointer to a structure which has no public symbol information, although, you can dump this using PyKd. It isn't particularly interesting though and really just contains the same information which you can obtain by using !verifier 3 <driver>.sys.

Rich (BB code):
15: kd> dc ffffc58bdf474f40 L4
ffffc58b`df474f40  00670076 002e006b 00790073 00000073  v.g.k...s.y.s...

Rich (BB code):
15: kd> !verifier 3 vgk.sys

[...]

Driver Verification List
------------------------

nt!_VF_TARGET_DRIVER 0xffffc58bdf5cc280: vgk.sys (Loaded)

    Pool Allocation Statistics: ( NonPagedPool / PagedPool )

      Current Pool Allocations: ( 0x00000000 / 0x00000001 )
      Current Pool Bytes:       ( 0x00000000 / 0x00000068 )
      Peak Pool Allocations:    ( 0x00000003 / 0x00000001 )
      Peak Pool Bytes:          ( 0x0000094a / 0x00000068 )
      Contiguous Memory Bytes:       0x00000000
      Peak Contiguous Memory Bytes:  0x00000000

    Pool Allocations:

      Address             Length      Tag   Caller Address
      ------------------  ----------  ----  ------------------
      0xffffb10cf7d4af90  0x00000068  VStr  0xfffff80ae1fcce8c  vgk+0x7cce8c

    Contiguous allocations are not displayed with public symbols.

The !verifier command simply lists the pool allocations which the problematic had made. These are usually always special allocations made through Driver Verifier itself hence the pooltag of VStr. The special pool type is specifically used for debugging purposes and is often used to detect buffer overflows. The Memory Manager will usually allocate a special region between the current pool allocation and the next in order to detect pool corruption without affecting the next "real" allocation.

Rich (BB code):
15: kd> !pooltag VStr
Pooltag VStr
Description: String buffer allocated by the Driver Verifier version of Rtl String APIs
Driver!Module: nt!Vf

Rich (BB code):
15: kd> !pool 0xffffb10cf7d4af90
Pool page ffffb10cf7d4af90 region is Special pool
*ffffb10cf7d4a000 size:   68 data: ffffb10cf7d4af90 (NonPaged) *VStr
        Pooltag VStr : String buffer allocated by the Driver Verifier version of Rtl String APIs, Binary : nt!Vf

If we dump the pool allocation, then we can see this special region which is called "slop bytes".

Rich (BB code):
15: kd> dq  ffffb10c`f7d4a010
ffffb10c`f7d4a010  ffffc58b`df7f4fe0 01010101`01010101
ffffb10c`f7d4a020  01010101`01010101 01010101`01010101
ffffb10c`f7d4a030  01010101`01010101 01010101`01010101
ffffb10c`f7d4a040  01010101`01010101 01010101`01010101
ffffb10c`f7d4a050  01010101`01010101 01010101`01010101
ffffb10c`f7d4a060  01010101`01010101 01010101`01010101
ffffb10c`f7d4a070  01010101`01010101 01010101`01010101
ffffb10c`f7d4a080  01010101`01010101 01010101`01010101

Notice the repeating pattern? The highlighted address is the pool tag which we saw earlier.

Rich (BB code):
15: kd> dc ffffb10cf7d4af90
ffffb10c`f7d4af90  0052005c 00470045 00530049 00520054  \.R.E.G.I.S.T.R.
ffffb10c`f7d4afa0  005c0059 0041004d 00480043 004e0049  Y.\.M.A.C.H.I.N.
ffffb10c`f7d4afb0  005c0045 00590053 00540053 004d0045  E.\.S.Y.S.T.E.M.
ffffb10c`f7d4afc0  0043005c 006e006f 00720074 006c006f  \.C.o.n.t.r.o.l.
ffffb10c`f7d4afd0  00650053 00300074 00310030 0053005c  S.e.t.0.0.1.\.S.
ffffb10c`f7d4afe0  00720065 00690076 00650063 005c0073  e.r.v.i.c.e.s.\.
ffffb10c`f7d4aff0  00670076 0000006b 01010101 01010101  v.g.k...........
ffffb10c`f7d4b000  ???????? ???????? ???????? ????????  ????????????????

The data itself is simply the registry key of the service associated to the driver. This is stored at the end of the allocation. If we now examine the call stack, we'll see the following:

Rich (BB code):
15: kd> knL
 # Child-SP          RetAddr               Call Site
00 ffffef89`a52074d8 fffff806`52de2e34     nt!KeBugCheckEx
01 ffffef89`a52074e0 fffff806`52df2169     nt!VerifierBugCheckIfAppropriate+0xe0
02 ffffef89`a5207520 fffff806`5289a64e     nt!VfPoolCheckForLeaks+0x49
03 ffffef89`a5207560 fffff806`52dd44f2     nt!VfTargetDriversRemove+0x118f62
04 ffffef89`a52075e0 fffff806`52adadeb     nt!VfDriverUnloadImage+0x3e
05 ffffef89`a5207610 fffff806`52b7d331     nt!MiUnloadSystemImage+0x2eb
06 ffffef89`a52077b0 fffff806`52b7d25e     nt!MmUnloadSystemImage+0x41
07 ffffef89`a52077e0 fffff806`52a208c0     nt!IopDeleteDriver+0x4e
08 ffffef89`a5207830 fffff806`526302f7     nt!ObpRemoveObjectRoutine+0x80
09 ffffef89`a5207890 fffff806`5263021e     nt!ObfDereferenceObjectWithTag+0xc7
0a ffffef89`a52078d0 fffff806`52b476aa     nt!HalPutDmaAdapter+0xe
0b ffffef89`a5207900 fffff806`52e6bd2f     nt!IopLoadDriver+0x76a
0c ffffef89`a5207ad0 fffff806`52e579ca     nt!IopInitializeSystemDrivers+0x157
0d ffffef89`a5207b70 fffff806`52ba323b     nt!IoInitSystem+0x2e
0e ffffef89`a5207ba0 fffff806`52735915     nt!Phase1Initialization+0x3b
0f ffffef89`a5207bd0 fffff806`52813cf8     nt!PspSystemThreadStartup+0x55
10 ffffef89`a5207c20 00000000`00000000     nt!KiStartSystemThread+0x28

The IoDeleteDriver function takes a single parameter which is a pointer to the driver object. This invokes the driver unload routine specified by the driver itself, eventually Driver Verifier checks that the driver has freed its pool allocations and then bugchecks the system if it hasn't.
 
When you dumped the pool allocation (ffffb10cf7d4a000) you dumped an address 0x10 bytes on from the allocation start (ffffb10c`f7d4a010). Is this because the first 0x10 bytes is a header? How did you know that this header was 0x10 bytes long?

The repeating pattern is obvious, but you highlight the first address (ffffc58b`df7f4fe0) as 'the pool tag which we saw earlier' and I don't see that address anywhere...?
 
Is this because the first 0x10 bytes is a header? How did you know that this header was 0x10 bytes long?
Yes, and you can find the size of any type using the following:

Rich (BB code):
15: kd> ?? sizeof(_POOL_HEADER)
unsigned int64 0x10

I don't see that address anywhere...?
It's not really the address which I was pointing out but rather that the address just refers to the same pool tag.

Rich (BB code):
15: kd> dc ffffc58b`df7f4fe0
ffffc58b`df7f4fe0  f7d4af90 ffffb10c e1fcce8c fffff80a  ................
ffffc58b`df7f4ff0  00000068 00000000 72745356 00000000  h.......VStr....
ffffc58b`df7f5000  44524352 00090028 e9011d56 00000008  RCRD(...V.......
ffffc58b`df7f5010  00000001 00010001 00000b08 00000000  ................
ffffc58b`df7f5020  e9011d56 00000008 00081517 00003b4d  V...........M;..
ffffc58b`df7f5030  00000000 00000000 00000000 0008e000  ................
ffffc58b`df7f5040  e9011c08 00000008 e9011bf5 00000008  ................
ffffc58b`df7f5050  00000000 00000000 00000028 00000000  ........(.......

Rich (BB code):
15: kd> .formats 72745356
Evaluate expression:
  Hex:     00000000`72745356
  Decimal: 1920226134
  Octal:   0000000000016235051526
  Binary:  00000000 00000000 00000000 00000000 01110010 01110100 01010011 01010110
  Chars:   ....rtSV << VStr
  Time:    Wed Nov  6 20:08:54 2030
  Float:   low 4.83937e+030 high 0
  Double:  9.48718e-315
 
Back
Top