Data Execution Protection in Action

Hello, my name is Graham, and I’m an escalation engineer on the Platforms Global Escalation Team.  I recently worked a case where a group of Windows XP machines were hitting a bugcheck on boot, error 0xC000021A.   This error occurs when a critical usermode process such as winlogon or csrss crashes.  I had access to a failing machine, so I attached the kernel debugger to find out why winlogon was crashing.  I found the cause, and a little bit more about Data Execution Prevention (DEP) in the process.


The initial debugger spew gave me this information:


*** An Access Violation occurred in winlogon.exe:


The instruction at 10030F90 tried to write to an invalid address, 10030F90


 *** enter .exr 0006F4AC for the exception record

 *** enter .cxr 0006F4C8 for the context

 *** then kb to get the faulting stack



So I followed its cue and got the exception record and context record:


1: kd> .exr 0006F4AC

ExceptionAddress: 10030f90

   ExceptionCode: c0000005 (Access violation)

  ExceptionFlags: 00000000

NumberParameters: 2

   Parameter[0]: 00000008

   Parameter[1]: 10030f90

Attempt to execute non-executable address 10030f90


Ahh, OK, so we know this is a DEP crash now.


1: kd> .cxr 0006F4C8

eax=00000400 ebx=00000000 ecx=00000000 edx=00010000 esi=00000000 edi=00084370

eip=10030f90 esp=0006f794 ebp=0006f81c iopl=0         nv up ei pl nz na pe nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206

001b:10030f90 33c0            xor     eax,eax



Let's check out the crashing stack to see what's going on:


1: kd> kb

  *** Stack trace for last set context - .thread/.cxr resets it

ChildEBP RetAddr  Args to Child             

0006f81c 010297c1 00084370 01010ab4 00000000 3rdparty!nosymbols

0006fcfc 010312a6 00072364 7c80b6a1 00000000 winlogon!ExecSystemProcesses+0x14d

0006ff50 0103d4d0 01000000 00000000 00072364 winlogon!WinMain+0x2b6

0006fff4 00000000 7ffd7000 000000c8 000001ec winlogon!WinMainCRTStartup+0x174



The first thing I decided to look for was how we got to this address.  To begin, I unassembled the code right before the return address to winlogon!ExecSystemProcesses.


kd> ub 010297c1


010297a2 6a02            push    2

010297a4 ffb594fbffff    push    dword ptr [ebp-46Ch]

010297aa 6880000000      push    80h

010297af 56              push    esi

010297b0 56              push    esi

010297b1 68b40a0101      push    offset winlogon!`string' (01010ab4)

010297b6 ffb5a0fbffff    push    dword ptr [ebp-460h]

010297bc e891fcffff      call    winlogon!StartSystemProcess (01029452)



According to the stack, winlogon!ExecSystemProcesses didn't call the function currently running.  So, I suspected some hooking was going on.  Using !chkimg, I verified this was the case.  Note that chkimg requires a valid copy of the binary in the symbol path.


1: kd> !chkimg -db kernel32

10 errors : kernel32 (7c802332-7c80236b)

7c802330  90  90 *e9 *59 *ec *82 *93  6a  00  ff  75  2c  ff  75  28  ff ...Y...j..u,.u(.


7c802360  28  00  90  90  90  90  90 *e9 *d4 *eb *82 *93  6a  00  ff  75 (...........j..u

1: kd> u 7c802330 


7c802330 90              nop

7c802331 90              nop


7c802332 e959ec8293      jmp     3rdparty!nosymbols (10030f90)



Aha! Something has hooked CreateProcessW to jump to our current instruction.  Now that we know how we got there, let's understand why we crashed.  Since DEP fired, that means this address is non-executable.  I verified this by dumping out the PTE for the address.


1: kd> !pte 10030F90

               VA 10030f90

PDE at 00000000C0600400    PTE at 00000000C0080180

contains 000000004E102867  contains 800000004E021867

pfn 4e102 ---DA--UWEV    pfn 4e021 ---DA--UW-V


Notice that in the protection flags for the PTE, the 'E' bit isn't set, saying this page isn't executable.   So, where is this address we were trying to execute?  Many times with DEP crashes this will be in stack or heap memory.  But not this time.  In this case, the address is actually in a module's memory mapped address space, as shown by the 'lm' command


1: kd> lm m 3rdparty

10000000 1003c000   3rdparty C (export symbols)       3rdparty.dll


Hmm...  So the address falls in this module. Why isn't it executable?   Usually when I think of image files, I think of running code.  But, remembering back to how the PE images are laid out, a module is broken into subsections, with different types of data in each one, and different protection levels.  There's a place in the image for code, and for data, such as global variables and static data.  So, let's dump the image header and find which section offset 0x30F90 is in.


1: kd>!dh 3rdparty




   .data name

   1EE3C virtual size

   1A000 virtual address   //  (1A000+1EE3C=0x38e3c so mem range for section is 1A000 to 0x38e3c)

    3000 size of raw data

   1A000 file pointer to raw data

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

C0000040 flags

         Initialized Data

         (no align specified)

         Read Write  // no Execute !



This is our section, since the virtual address starts at 0x1A000 and is 0x1EE3C in size, putting the end of the section at 0x38e3c.  Our address of 0x30F90 falls between them.

Sure enough, this section is labeled as "Initialized Data", and the protection flags show Read and Write, but no Execute!  So, this address is not in a code section of the module, and DEP will not allow it to run. 


Knowing this, I was able to find an update on the 3rd party manufacturer's site that modified their DLL to prevent this from occurring.  Mystery solved!

Comments (5)

  1. ak says:

    I hate it when blogs protect the 3rdpart like this. There are better ways to hook process creation, tell me the name of the 3rd party so I can avoid their stuff

    [We don’t call out 3rd party software by name, since often the bug in question has already been fixed, and we don’t want to needlessly give that vendor a bad reputation. All software has bugs, and the point of our blog isn’t to call out which vendors had what bugs.]
  2. John Hall says:

    So what was the 3rd party DLL possibly doing that caused it to try and execute code from its Initialized Data section?

    [The DLL was probably generating small amounts of code during runtime, and storing those in global variables. This was a problem with older versions of ATL/MFC, which wrote small Thunking stubs at runtime. (see But, the only way to do this safely with DEP in the picture is to use VirtualAlloc and then Virtual Protect to grant PAGE_EXECUTE access.]
  3. You Had Me At EHLO… : Where does the time go? -519 Jet_errLogSequenceEnd Microsoft Advanced Windows

  4. Myth says:

    I like this type of article. Showing us the real world problem and the process to solve it. Thank you for the Aritcle

Skip to main content