蓝屏分析
04蓝屏分析
直接上蓝屏代码
#include <ntifs.h>
VOID Unload(PDRIVER_OBJECT pDriver)
{
DbgPrint("Driver Unload\r\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
pDriver->DriverUnload = Unload;
//DbgBreakPoint();
DbgPrint("Driver Load\r\n");
int* x = 0;//指针x指向的是地址0x00000000
*x = 100;//向0x00000000地址处写入100数据,会引发异常
return STATUS_SUCCESS;
}
这里可以看到指针x
指向的是0x00000000
单步一下,崩掉了
kd> p
*** Fatal System Error: 0x0000007e
(0xC0000005,0xAE916026,0x91776904,0x91776370)
A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.
A fatal system error has occurred.
nt!RtlpBreakWithStatusInstruction:
8406bd8c cc int 3
双机调试
这里我是用的原版Windbg不知道为什么总是出不来!analysize -v
所以我又用Windbg Preview
调了一下,下面是Windbg Preview
的!analyze -v
输出信息
kd> !analyze -v
Connected to Windows 7 7601 x86 compatible target at (Sat Jan 7 21:09:04.397 2023 (UTC + 8:00)), ptr64 FALSE
Loading Kernel Symbols
.............
Press ctrl-c (cdb, kd, ntsd) or ctrl-break (windbg) to abort symbol loads that take too long.
Run !sym noisy before .reload to track down problems loading symbols.
..................................................
................................................................
.................................
Loading User Symbols
Loading unloaded module list
............
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (7e)
This is a very common BugCheck. Usually the exception address pinpoints
the driver/function that caused the problem. Always note this address
as well as the link date of the driver/image that contains this address.
Arguments:
Arg1: c0000005, The exception code that was not handled
Arg2: b42bf025, The address that the exception occurred at
Arg3: 9344890c, Exception Record Address
Arg4: 93448370, Context Record Address
Debugging Details:
------------------
KEY_VALUES_STRING: 1
Key : AV.Dereference
Value: NullPtr
Key : AV.Fault
Value: Write
Key : Analysis.CPU.mSec
Value: 1077
Key : Analysis.DebugAnalysisManager
Value: Create
Key : Analysis.Elapsed.mSec
Value: 174659
Key : Analysis.IO.Other.Mb
Value: 4
Key : Analysis.IO.Read.Mb
Value: 1
Key : Analysis.IO.Write.Mb
Value: 7
Key : Analysis.Init.CPU.mSec
Value: 1874
Key : Analysis.Init.Elapsed.mSec
Value: 137328
Key : Analysis.Memory.CommitPeak.Mb
Value: 78
Key : Bugcheck.Code.DumpHeader
Value: 0x7e
Key : Bugcheck.Code.KiBugCheckData
Value: 0x7e
Key : WER.OS.Branch
Value: win7sp1_ldr_escrow
Key : WER.OS.Timestamp
Value: 2018-03-30T16:00:00Z
Key : WER.OS.Version
Value: 7.1.7601.24094
BUGCHECK_CODE: 7e
BUGCHECK_P1: ffffffffc0000005
BUGCHECK_P2: ffffffffb42bf025
BUGCHECK_P3: ffffffff9344890c
BUGCHECK_P4: ffffffff93448370
EXCEPTION_RECORD: 9344890c -- (.exr 0xffffffff9344890c)
ExceptionAddress: b42bf025 (MyDriver10!DriverEntry+0x00000025)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000001
Parameter[1]: 00000000
Attempt to write to address 00000000
CONTEXT: 93448370 -- (.cxr 0xffffffff93448370)
eax=00000000 ebx=00000000 ecx=00000000 edx=0000000d esi=88980a98 edi=87162000
eip=b42bf025 esp=934489d4 ebp=934489d8 iopl=0 nv up ei ng nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010286
MyDriver10!DriverEntry+0x25:
b42bf025 c70164000000 mov dword ptr [ecx],64h ds:0023:00000000=????????
Resetting default scope
PROCESS_NAME: System
WRITE_ADDRESS: 00000000
ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%p 0x%p %s
EXCEPTION_CODE_STR: c0000005
EXCEPTION_PARAMETER1: 00000001
EXCEPTION_PARAMETER2: 00000000
EXCEPTION_STR: 0xc0000005
STACK_TEXT:
934489d8 84212986 88980a98 87162000 00000000 MyDriver10!DriverEntry+0x25 [C:\Users\MuRKuo\source\repos\MyDriver10\main.c @ 14]
93448bbc 841faaa0 00000001 00000000 93448be4 nt!IopLoadDriver+0x7ed
93448c00 840b43e3 83b59bd0 00000000 8894f9c0 nt!IopLoadUnloadDriver+0x70
93448c50 84241906 80000001 a9cb5ac9 00000000 nt!ExpWorkerThread+0x10d
93448c90 840e2e0d 840b42d6 80000001 00000000 nt!PspSystemThreadStartup+0x9e
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x19
FAULTING_SOURCE_LINE: C:\Users\MuRKuo\source\repos\MyDriver10\main.c
FAULTING_SOURCE_FILE: C:\Users\MuRKuo\source\repos\MyDriver10\main.c
FAULTING_SOURCE_LINE_NUMBER: 14
FAULTING_SOURCE_CODE:
10: pDriver->DriverUnload = Unload;
11: //DbgBreakPoint();
12: DbgPrint("Driver Load\r\n");
13: int* x = 0;//????x???¨°???????¡¤0x00000000
> 14: *x = 100;//?¨°0x00000000???¡¤??????100???????¨¢??¡¤??¨¬??
15: return STATUS_SUCCESS;
16: }
SYMBOL_NAME: MyDriver10!DriverEntry+25
MODULE_NAME: MyDriver10
IMAGE_NAME: MyDriver10.sys
STACK_COMMAND: .cxr 0xffffffff93448370 ; kb
FAILURE_BUCKET_ID: 0x7E_MyDriver10!DriverEntry+25
OS_VERSION: 7.1.7601.24094
BUILDLAB_STR: win7sp1_ldr_escrow
OSPLATFORM_TYPE: x86
OSNAME: Windows 7
FAILURE_ID_HASH: {f7940179-d75c-5c40-e993-537b8464fd03}
Followup: MachineOwner
---------
可以清楚的看到导致系统崩掉的驱动详细信息
BugCode 7e (有源代码)
转储文件分析
我们g
一下让他继续运行
可以看到现在正在dump内存
等他dump
完会输出complete
的
之后我们让虚拟机重启
去虚拟机的控制面板->系统和安全->系统
按照如上步骤可以找到存储的崩溃转储文件
我这个核心内存转储的dmp文件在Windbg中打开后基本和直接调试是没啥区别的,除了标题换成了本地,其他的基本没变化
这里我们假装这个转储不正确,手动调试一下看看
kd> r //查看寄存器
eax=841878e4 ebx=00000000 ecx=00000003 edx=00000000 esi=80b96120 edi=00000000
eip=8412b3b8 esp=93448218 ebp=93448230 iopl=0 nv up ei pl nz na po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000202
nt!KeBugCheckEx+0x1e:
8412b3b8 cc int 3
kd> dds 93448218 //树形打印从esp开始的栈
VirtualToOffset: 93448218 not properly sign extended
93448218 0000007e
9344821c c0000005
93448220 b42bf025 MyDriver10!DriverEntry+0x25 [C:\Users\MuRKuo\source\repos\MyDriver10\main.c @ 14]
93448224 9344890c
93448228 93448370
9344822c 00000000
93448230 93448c90
93448234 84241946 nt!PspSystemThreadStartup+0xde
93448238 0000007e
9344823c c0000005
93448240 b42bf025 MyDriver10!DriverEntry+0x25 [C:\Users\MuRKuo\source\repos\MyDriver10\main.c @ 14]
93448244 9344890c
93448248 93448370
9344824c 840b10e4 nt!_EH4_CallFilterFunc+0x12
93448250 00000000
93448254 93448c90
93448258 840a70d0 nt! ?? ::FNODOBFM::`string'+0x3270
9344825c 93448284
93448260 8410ee85 nt!_except_handler4+0x8e
93448264 00000000
93448268 00000000
9344826c 00000000
93448270 9344890c
93448274 93448370
93448278 840a70e0 nt! ?? ::FNODOBFM::`string'+0x3280
9344827c 00000001
93448280 00056000
93448284 934482a8
93448288 840aede2 nt!ExecuteHandler2+0x26
9344828c fffffffe
93448290 93448c80
93448294 93448370
这里我们先获取了崩溃前的ESP
的值,然后通过dds
指令(树形排列堆栈)的方式获取崩溃前的栈中的情况
从中栈的底部可以很明显的看到崩溃前执行的驱动信息等,例如下面这段
93448220 b42bf025 MyDriver10!DriverEntry+0x25 [C:\Users\MuRKuo\source\repos\MyDriver10\main.c @ 14]
从中就可以看到最后执行到了我们驱动的第14
行,而驱动源文件的第14
行也确实是崩溃的地方
*x = 100;//向0x00000000地址处写入100数据,会引发异常
使用!analyze -v
可以看到一堆的信息输出
其中有一行BugCheck_Code
这时候可以去微软官方查找一下这是什么错误
https://learn.microsoft.com/zh-cn/windows-hardware/drivers/debugger/bug-check-code-reference2
从中就可以得到关于这个崩溃的一些详细信息
根据如下的参数,可以去Windbg看每个参数对应了什么
SYSTEM_THREAD_EXCEPTION_NOT_HANDLED参数
参数 | 说明 |
---|---|
1 | 未处理的异常代码。 |
2 | 发生异常的地址。 |
3 | 异常记录的地址。 |
4 | 上下文记录的地址。 |
BUGCHECK_CODE: 7e
BUGCHECK_P1: ffffffffc0000005
BUGCHECK_P2: ffffffffb42bf025
BUGCHECK_P3: ffffffff9344890c
BUGCHECK_P4: ffffffff93448370
其中P1-P4和上图的参数对应
可以看到对应的代码出错的地方
这个有源代码比较简单就不看了
BugCode 8e
看一下转储文件的BugCode
FILE_IN_CAB: 032821-18891-01.dmp
BUGCHECK_CODE: 8e
BUGCHECK_P1: ffffffffc0000005
BUGCHECK_P2: ffffffff83ee33f5
BUGCHECK_P3: ffffffff8376765c
BUGCHECK_P4: 0
先去官网看一下对应的参数
KERNEL_MODE_EXCEPTION_NOT_HANDLED 参数
参数 | 说明 |
---|---|
1 | 未处理的异常代码 |
2 | 发生异常的地址 |
3 | 捕获帧 |
4 | 保留 |
看一下发生异常的地址
根据官方的如下说明
KERNEL_MODE_EXCEPTION_NOT_HANDLED bug 检查是一个非常常见的 bug 检查。 若要对其进行解释,必须确定生成的具体异常。
常见的异常代码包括:
- 0x80000002: STATUS_DATATYPE_MISALIGNMENT 指示遇到了未对齐的数据引用。
- 0x80000003: STATUS_BREAKPOINT 指示在没有内核调试器附加到系统时遇到断点或断言。
- 0xC0000005: STATUS_ACCESS_VIOLATION 指示发生了内存访问冲突。
这里可以对应上我们的BugCode的P1的BUGCHECK_P1: ffffffffc0000005
也就是C005
说明是发生了内存访问冲突
总之这个转储文件反映出的问题就是在ffffffff83ee33f5
地址处出现了内存访问冲突
83ee33f5 8b0a mov ecx,dword ptr [edx] ds:0023:00000124=????????
Windbg也写得很清楚,[EAX]
中的值没有读取到,原因是出现了内存访问冲突
同时这里也可以去ntkrnlpa
里面看一下
BugCode 7e
对应一下参数
BUGCHECK_CODE: 7e
BUGCHECK_P1: ffffffffc0000005
BUGCHECK_P2: ffffffff84043f7c
BUGCHECK_P3: ffffffff8d7036f8
BUGCHECK_P4: ffffffff8d703160
参数 | 说明 |
---|---|
1(ffffffffc0000005) | 未处理的异常代码。 |
2(ffffffff84043f7c) | 发生异常的地址。 |
3(ffffffff8d7036f8) | 异常记录的地址。 |
4(ffffffff8d703160) | 上下文记录的地址。 |
异常代码
常见的未经处理的异常代码
- 0x80000002:STATUS_DATATYPE_MISALIGNMENT表示遇到未对齐的数据引用。
- 0x80000003:STATUS_BREAKPOINT指示未将内核调试器附加到系统时遇到断点或 ASSERT。
- 0xC0000005:STATUS_ACCESS_VIOLATION指示发生了内存访问冲突。
这次还是内存访问冲突
发生异常的地方
nt!SeCreateAccessStateEx+0x9b:
84043f7c a5 movs dword ptr es:[edi],dword ptr [esi] es:0023:8d7038bc=00000000 ds:0023:00000034=????????
可以发现是取[esi]
的值取不到
接下来看一下栈
kd> kv
# ChildEBP RetAddr Args to Child
00 8d7037d0 84043ed8 85ee5798 85ec9920 8d703840 nt!SeCreateAccessStateEx+0x9b
01 8d7037f0 84092d30 8d703840 8d7038b8 00000000 nt!SeCreateAccessState+0x28
02 8d703980 971d5115 8d7039a8 00000040 00000000 nt!ObReferenceObjectByName+0x8f
WARNING: Stack unwind information not available. Following frames may be wrong.
03 8d7039b8 971d5064 971d5284 00220020 971d525c 122+0x1115
04 8d7039d8 83fe02e6 8728fe10 876ec000 00000000 122+0x1064
05 8d703bbc 83fe3d98 00000001 00000000 8d703be4 nt!IopLoadDriver+0x7ed
06 8d703c00 83e99aab 97b37bd0 00000000 85ee5798 nt!IopLoadUnloadDriver+0x70
07 8d703c50 84025f5e 00000001 2734038b 00000000 nt!ExpWorkerThread+0x10d
08 8d703c90 83ecd219 83e9999e 00000001 00000000 nt!PspSystemThreadStartup+0x9e
09 00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x19
发现其中有两行这个
03 8d7039b8 971d5064 971d5284 00220020 971d525c 122+0x1115
04 8d7039d8 83fe02e6 8728fe10 876ec000 00000000 122+0x1064
这个112
就代表当时加载的驱动的基地址
后面+0x1115
是驱动出错的代码的偏移
例如PE
程序的起始地址是0x00400000
那么这个驱动(驱动是PE结构的)崩溃的代码位置就是0x00400000 + 0x1115 = 0x00401237
然后这个驱动调用了ObReferenceObjectByName
进而nt!SeCreateAccessState+0x28
最后地址不对,然后系统挂掉
诡异的蓝屏-1
#include <ntifs.h>
VOID Unload(PDRIVER_OBJECT pDriver)
{
DbgPrint("Driver Unload\r\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
char buf[0x100000000] = { 0 };//内核栈爆了
int x = 0;
pDriver->DriverUnload = Unload;
//DbgBreakPoint();
return STATUS_SUCCESS;
}
这段代码我编译的时候显示数组过大,但是可以编译通过
编译完后虚拟机里一运行就蓝
原因是内核栈爆了,内核栈一共是12K
,也就是4096 * 12
这种错误会导致蓝屏的BugCheckCode
经常变动,第一次可能是7e
,第二次可能就是50
了,而且不一定是一加载就崩溃,我写的这个程序由于是在入口这直接开辟超大空间,直接把栈顶爆了,所以才一加载就出问题,有的时候栈是一点点顶爆的,可能需要挺长的时候才会蓝屏
栈炸了停留的位置一般是不一样的
诡异的蓝屏-2
#include <ntifs.h>
VOID Unload(PDRIVER_OBJECT pDriver)
{
DbgPrint("unload\r\n");
}
VOID
vStart(
_In_ PVOID StartContext
)
{
*(int*)PsCreateSystemThread = 100;
//这里可以写创建新线程后,新线程要做的事
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
pDriver->DriverUnload = Unload;
//DbgBreakPoint();
HANDLE hThread = NULL;
NTSTATUS status = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, vStart, NULL);//创建线程
if (NT_SUCCESS(status))
{
ZwClose(hThread);//释放线程句柄
}
return STATUS_SUCCESS;
}
这里由于想写PsCreateSystemThread
的函数地址所以炸了
不过令我无语的是这个BugCheckCode
依然是7e
别人的BugCheckCode
都是BE
,就我的依旧是7e