Debugging Stop 0x3B - SYSTEM_SERVICE_EXCEPTION

x BlueRobot

Administrator
Staff member
Joined
May 7, 2013
Posts
10,400
Rich (BB code):
SYSTEM_SERVICE_EXCEPTION (3b)
An exception happened while executing a system service routine.
Arguments:
Arg1: 00000000c0000005, Exception code that caused the bugcheck
Arg2: fffff8073f54ea6c, Address of the instruction which caused the bugcheck
Arg3: ffff930136aee470, Address of the context record for the exception that caused the bugcheck
Arg4: 0000000000000000, zero.

The Stop 0x3B bugcheck is a very common bugcheck and you're guaranteed to come across one. Much like its cousins Stop 0x7E and Stop 0x1E, the bugcheck occurs because of a generic exception which isn't able to be handled by the operating system. The main difference being where the exception is thrown, and in the case of a Stop 0x3B, this is always during the execution of a system service. Although, you may be wondering, what is a system service routine?

I'm not going to go into the mechanisms between a system service routine too much, but will provide a brief explanation of what they are, so you can understand the context of the Stop 0x3B bugcheck. System service routines are essentially kernel-mode functions which are exposed to user-mode applications in a secure and controlled manner, they enable user-mode applications to open handles to files, terminate processes and gather information about the system.

All system service routines are stored in a pointer array known as the system service dispatch table (SSDT). Each system service routine is invoked by a special processor instruction called syscall or sysenter. The SSDT can be found by dumping the KeServiceDescriptorTable global variable. Please note that this will only work on kernel memory dumps.

Rich (BB code):
1: kd> dps nt!KeServiceDescriptorTable L4
fffff805`7ec018c0  fffff805`7dec8270 nt!KiServiceTable
fffff805`7ec018c8  00000000`00000000
fffff805`7ec018d0  00000000`000001d7
fffff805`7ec018d8  fffff805`7dec89d0 nt!KiArgumentTable

You can then dump the entire SSDT by using the following loop:

Rich (BB code):
1: kd> .foreach /ps 1 /pS 1 ( offset {dd /c 1 nt!KiServiceTable L poi(nt!KeServiceDescriptorTable+10)}){ r $t0 = ( offset >>> 4) + nt!KiServiceTable; .printf "%p - %y\n", $t0, $t0 }
fffff8057e0fcd00 - nt!NtAccessCheck (fffff805`7e0fcd00)
fffff8057e107730 - nt!NtWorkerFactoryWorkerReady (fffff805`7e107730)
fffff8057e4e3380 - nt!NtAcceptConnectPort (fffff805`7e4e3380)
fffff8057e6d2740 - nt!NtMapUserPhysicalPagesScatter (fffff805`7e6d2740)
fffff8057e42cb40 - nt!NtWaitForSingleObject (fffff805`7e42cb40)
fffff8057e1f9590 - nt!NtCallbackReturn (fffff805`7e1f9590)
fffff8057e3e5440 - nt!NtReadFile (fffff805`7e3e5440)
fffff8057e3fcb10 - nt!NtDeviceIoControlFile (fffff805`7e3fcb10)
fffff8057e3e3f00 - nt!NtWriteFile (fffff805`7e3e3f00)
fffff8057e4b7d80 - nt!NtRemoveIoCompletion (fffff805`7e4b7d80)

Each of the corresponding entries is one of the system functions which can be called by user-mode applications.

So, we now understand that an exception was thrown during the execution of a system service call, and if we examine the call stack we can see which system service call this was.

Rich (BB code):
17: kd> knL
 # Child-SP          RetAddr           Call Site
00 ffff9301`36aedb68 fffff807`3c809169 nt!KeBugCheckEx
01 ffff9301`36aedb70 fffff807`3c8085bc nt!KiBugCheckDispatch+0x69
02 ffff9301`36aedcb0 fffff807`3c80006f nt!KiSystemServiceHandler+0x7c
03 ffff9301`36aedcf0 fffff807`3c6e6dd7 nt!RtlpExecuteHandlerForException+0xf
04 ffff9301`36aedd20 fffff807`3c6e59d6 nt!RtlDispatchException+0x297
05 ffff9301`36aee440 fffff807`3c8092ac nt!KiDispatchException+0x186
06 ffff9301`36aeeb00 fffff807`3c804fe0 nt!KiExceptionDispatch+0x12c
07 ffff9301`36aeece0 fffff807`3f54ea6c nt!KiGeneralProtectionFault+0x320
08 ffff9301`36aeee70 fffff807`3f54540d Ntfs!NtfsCommonCleanup+0x65c
09 ffff9301`36aef320 fffff807`3c68f6f5 Ntfs!NtfsFsdCleanup+0x1bd
0a ffff9301`36aef670 fffff807`392d6c5f nt!IofCallDriver+0x55
0b ffff9301`36aef6b0 fffff807`392d4673 FLTMGR!FltpLegacyProcessingAfterPreCallbacksCompleted+0x28f
0c ffff9301`36aef720 fffff807`3c68f6f5 FLTMGR!FltpDispatch+0xa3
0d ffff9301`36aef780 fffff807`3ca75d4a nt!IofCallDriver+0x55
0e ffff9301`36aef7c0 fffff807`3c9f39cf nt!IopCloseFile+0x17a
0f ffff9301`36aef850 fffff807`3c9f79ac nt!ObCloseHandleTableEntry+0x51f
10 ffff9301`36aef990 fffff807`3c808bb5 nt!NtClose+0xec
11 ffff9301`36aefa00 00000000`771d1cfc nt!KiSystemServiceCopyEnd+0x25
12 00000000`005aec68 00000000`00000000 0x771d1cfc

The KiSystemServiceCopyEnd function indicates the end of our transition from user-mode to kernel-mode and it appears that the service function being executed was NtClose which closes a handle to an object. Eventually, we can see that a general protection fault is thrown which then leads to the system bugchecking with a Stop 0x3B. The first parameter supports this observation with the exception code being an access violation.

Rich (BB code):
17: kd> !error c0000005
Error code: (NTSTATUS) 0xc0000005 (3221225477) - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s.

And if we dump the context record shown in the third parameter, we'll be able to see exactly where the exception was thrown.

Rich (BB code):
17: kd> .cxr 0xffff930136aee470
rax=ffff930136aef401 rbx=bfffe309a8d639f8 rcx=ffffe309b5921de0
rdx=ffff930136aef450 rsi=0000000000000000 rdi=ffff930136aef3c0
rip=fffff8073f54ea6c rsp=ffff930136aeee70 rbp=0000000000000000
 r8=0000000000000000  r9=0000000000000008 r10=0000000000000000
r11=ffff930136aeedc0 r12=ffff82072bf45d10 r13=0000000000000200
r14=bfffe309a8d639f8 r15=ffffe309a8d635a0
iopl=0         nv up ei ng nz na pe nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00050282
Ntfs!NtfsCommonCleanup+0x65c:
fffff807`3f54ea6c 418b4604        mov     eax,dword ptr [r14+4] ds:002b:bfffe309`a8d639fc=????????

As we can see, the instruction address matches the address shown in the second parameter, and if we examine the address being referenced by the instruction, we can clearly see that it does not appear to be correct. Notice the single bit flip? This causes the address to become non-canonical and will always result in a general protection fault error being thrown. It should be noted that single bit flips are commonly caused by some hardware malfunction such as RAM or the processor, and therefore in this situation, it would be wise to run some hardware diagnostics.

If you would like more information on non-canonical addresses and bit-flips, then please read the following tutorials:
References:

https://www.ired.team/miscellaneous...rnals/glimpse-into-ssdt-in-windows-x64-kernel
Just enough kernel to get by (part 2) : Syscall & SSDT – TrapFrame – Developer & Security guy
 

Has Sysnative Forums helped you? Please consider donating to help us support the site!

Back
Top