Internet Explorer 11: one-time crash on exit

This case shows us that there is some code that can run without error for years and then one day ends up with a failure.

First, let’s run !analyze command to display information about the current exception.

0:000> !analyze -v
74281f41 8b01            mov     eax,dword ptr [ecx]
EXCEPTION_RECORD:  ffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 74281f41 (iertutil!IsoReleaseDefaultScope+0x00000028)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 00000000
   Parameter[1]: 00000000
Attempt to read from address 00000000

Second, let's display the exception context record and the stack.

0:000> .ecxr
eax=ffffffff ebx=00000000 ecx=00000000 edx=77553300 esi=ffffffff edi=00000001
eip=74281f41 esp=007bf958 ebp=007bf960 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
74281f41 8b01            mov     eax,dword ptr [ecx]  ds:002b:00000000=????????
0:000> k
 # ChildEBP RetAddr  
00 007bf960 732637aa iertutil!IsoReleaseDefaultScope+0x28
01 007bfaac 00ec1170 ieframe!LCIEStartAsTabProcess+0x532
02 007bfd44 00ec1398 iexplore!wWinMain+0x344
03 007bfdd4 7742495d iexplore!_imp_load__WaitForInputIdle+0x25f
04 007bfde0 776698ee kernel32!BaseThreadInitThunk+0xe
05 007bfe24 776698c4 ntdll!__RtlUserThreadStart+0x20
06 007bfe34 00000000 ntdll!_RtlUserThreadStart+0x1b

Now we can disassemble the faulting function.

0:000> u iertutil!IsoReleaseDefaultScope iertutil!IsoReleaseDefaultScope+0x28
74281f19 8bff            mov     edi,edi
74281f1b 55              push    ebp
74281f1c 8bec            mov     ebp,esp
74281f1e 8b0dd4723874    mov     ecx,dword ptr [iertutil!g_pIsoScope (743872d4)]
74281f24 b8d8723874      mov     eax,offset iertutil!g_cIsoScopeRef (743872d8)
74281f29 56              push    esi
74281f2a 83ceff          or      esi,0FFFFFFFFh
74281f2d f00fc130        lock xadd dword ptr [eax],esi
74281f31 4e              dec     esi
74281f32 ff7508          push    dword ptr [ebp+8]
74281f35 8bc6            mov     eax,esi
74281f37 f7d8            neg     eax
74281f39 1bc0            sbb     eax,eax
74281f3b 2105d4723874    and     dword ptr [iertutil!g_pIsoScope (743872d4)],eax
74281f41 8b01            mov     eax,dword ptr [ecx]
0:000> dd iertutil!g_pIsoScope L1
743872d4  00000000
0:000> dd iertutil!g_cIsoScopeRef L1
743872d8  ffffffff

And finally let's see, from a live debugging session, what the g_pIsoScope variable should contain.

1:012:x86> dd iertutil!g_pIsoScope L1
744582cc  0139bc90
1:012:x86> dd 0139bc90 L1
0139bc90  74335bb4
1:012:x86> ln 74335bb4
(74335bb4)   iertutil!CIsoScope::`vftable'   |  (74335d00)   iertutil!CIsoSpace::`vftable'
1:012:x86> !address 0139bc90
Usage:                  Heap32
Base Address:           01370000
End Address:            013b9000
Region Size:            00049000
State:                  00001000	MEM_COMMIT
Protect:                00000004	PAGE_READWRITE
Type:                   00020000	MEM_PRIVATE
Allocation Base:        01370000
Allocation Protect:     00000004	PAGE_READWRITE
More info:              heap owning the address: !heap 0x1370000
More info:              heap segment
More info:              heap entry containing the address: !heap -x 0x139bc90
1:012:x86> !address 74335bb4
Usage:                  Image
Base Address:           74271000
End Address:            74458000
Region Size:            001e7000
State:                  00001000	MEM_COMMIT
Protect:                00000020	PAGE_EXECUTE_READ
Type:                   01000000	MEM_IMAGE
Allocation Base:        74270000
Allocation Protect:     00000080	PAGE_EXECUTE_WRITECOPY
Image Path:             C:\Windows\SysWOW64\iertutil.dll
Module Name:            iertutil
Loaded Image Name:      C:\Windows\SysWOW64\iertutil.dll
Mapped Image Name:      
More info:              lmv m iertutil
More info:              !lmi iertutil
More info:              ln 0x74335bb4
More info:              !dh 0x74270000

Now we can see that the function decrement the g_cIsoScopeRef variable, and if its value is zero, sets the g_pIsoScope to NULL. The problem is that the function doesn't check if g_cIsoScopeRef is equal to 0, decrements it and trying to get pointer to CIsoScope::`vftable'. In this case we can’t say for sure which module is a culprit because there is more than one module uses this function. We can determine that by searching the address of the function in the modules:

0:000> !for_each_module ".echo @#ModuleName; s-d @#Base @#End 74281f19"
72fdee14  74281f19 741a219f 742b5ada 742b34dc  ..(t.!.t.Z+t.4+t
736ca5ec  74281f19 74300c39 742fa48c 743019f7  ..(t9.0t../t..0t
74488768  74281f19 7435f403 742ad192 742b16ba  ..(t..5t..*t..+t

So, I've submitted the bug to the Hope that the Internet Explorer Team will fix it.