记一次 .NET 某汽车控制焊接软件 卡死分析
一:背景
1. 讲故事
前些天有位朋友找到我,说他们开发的在客户工厂里的窗体程序出现了卡死情况,并且 Ctrl+C 也退不出来,自己分析了下也没找出是什么原因,后来在网络上就找到了我,让我帮忙看下怎么回事? 毕竟我在这一块是专业的。。。 哈哈,既然有dump,那就拿出来分析一下。
二:卡死分析
1. 为什么会卡死
既然是窗体,那就看主线程呗,使用 ~0s;k 即可,调用栈如下:
0:030> ~0s
ntdll!NtWaitForSingleObject+0x14:
00007ff8`d2f4d5e4 c3 ret
0:000> k
# Child-SP RetAddr Call Site
00 000000aa`f859e588 00007ff8`d058920e ntdll!NtWaitForSingleObject+0x14
01 000000aa`f859e590 00007ff8`d18d6765 KERNELBASE!WaitForSingleObjectEx+0x8e
02 000000aa`f859e630 00007ff8`d18d6049 sechost!ScSendResponseReceiveControls+0x149
03 000000aa`f859e770 00007ff8`d18d5b50 sechost!ScDispatcherLoop+0x159
04 000000aa`f859e8b0 00007ff8`bbe1d439 sechost!StartServiceCtrlDispatcherW+0x70
05 000000aa`f859e8e0 00007ff8`bbe204bc System_ServiceProcess_ni+0x2d439
06 000000aa`f859e990 00007ff8`621d08dd System_ServiceProcess_ni!System.ServiceProcess.ServiceBase.Run+0x1dc
07 000000aa`f859ea00 00007ff8`c19812c3 AgvTaskService!AgvTaskService.Program.Main+0x4d
08 000000aa`f859ea40 00007ff8`c184961b clr!CallDescrWorkerInternal+0x83
09 000000aa`f859ea80 00007ff8`c1898b5a clr!CallDescrWorkerWithHandler+0x47
0a 000000aa`f859eac0 00007ff8`c1808c95 clr!MethodDescCallSite::CallTargetWorker+0xfa
0b 000000aa`f859ebc0 00007ff8`c180899e clr!RunMain+0x269
0c 000000aa`f859eda0 00007ff8`c1808735 clr!Assembly::ExecuteMainMethod+0xae
0d 000000aa`f859f080 00007ff8`c180968f clr!SystemDomain::ExecuteMainMethod+0x619
0e 000000aa`f859f670 00007ff8`c180977d clr!ExecuteEXE+0x3f
0f 000000aa`f859f6e0 00007ff8`c1809b64 clr!_CorExeMainInternal+0xa9
10 000000aa`f859f770 00007ff8`c3b7d6ea clr!CorExeMain+0x14
11 000000aa`f859f7b0 00007ff8`c3fdac42 mscoreei!CorExeMain+0xfa
12 000000aa`f859f810 00007ff8`d1e27374 mscoree!CorExeMain_Exported+0x72
13 000000aa`f859f840 00007ff8`d2efcc91 kernel32!BaseThreadInitThunk+0x14
14 000000aa`f859f870 00000000`00000000 ntdll!RtlUserThreadStart+0x21
从卦中的 StartServiceCtrlDispatcherW 来看确实响应了 Ctrl+C 事件,并在非托管层等待 NtWaitForSingleObject 事件的完成,接下来的问题是为什么 Ctrl+C 完成不了?很显然有线程没有优雅的退出,所以目光就转移到其他的线程栈,使用 !t 观察下托管线程列表。
0:000> !t
ThreadCount: 37
UnstartedThread: 0
BackgroundThread: 25
PendingThread: 0
DeadThread: 11
Hosted Runtime: no
Lock
ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception
0 1 154c 000001d5ee9706a0 2a020 Preemptive 0000000000000000:0000000000000000 000001d5ee945930 0 MTA
2 2 57c0 000001d5ee999ba0 2b220 Preemptive 000001D5809EBE88:000001D5809EDDE0 000001d5ee945930 0 MTA (Finalizer)
...
30 42 6c78 000001d5f128e7d0 2b220 Preemptive 000001D5804C0B10:000001D5804C0B10 000001d5ee945930 1 MTA (GC)
从卦象看很不吉利,有一个 (GC) 字样,表示当前程序触发了 GC,接下来就是切过来观察下 GC 此时正在做什么?使用 ~30s;k 即可。
0:000> ~30s;k
ntdll!NtWaitForAlertByThreadId+0x14:
00007ff8`d2f50f94 c3 ret
# Child-SP RetAddr Call Site
00 000000aa`f9f3d2d8 00007ff8`d2f14d7d ntdll!NtWaitForAlertByThreadId+0x14
01 000000aa`f9f3d2e0 00007ff8`d2f14c32 ntdll!RtlpWaitOnAddressWithTimeout+0x81
02 000000aa`f9f3d310 00007ff8`d2f14a4d ntdll!RtlpWaitOnAddress+0xae
03 000000aa`f9f3d380 00007ff8`d2edfcb4 ntdll!RtlpWaitOnCriticalSection+0xfd
04 000000aa`f9f3d460 00007ff8`d2edfae2 ntdll!RtlpEnterCriticalSectionContended+0x1c4
05 000000aa`f9f3d4c0 00007ff8`d03c1999 ntdll!RtlEnterCriticalSection+0x42
06 000000aa`f9f3d4f0 00007ff8`d03c4e8e AisEsmUmh+0x1999
07 000000aa`f9f3d560 00007ff8`d05e5c50 AisEsmUmh+0x4e8e
08 000000aa`f9f3d9d0 00007ff8`c19377c6 KERNELBASE!SuspendThread+0x10
09 000000aa`f9f3da00 00007ff8`c1824381 clr!Thread::SuspendThread+0xee
0a 000000aa`f9f3df80 00007ff8`c1823696 clr!ThreadSuspend::SuspendRuntime+0x205
0b 000000aa`f9f3e060 00007ff8`c18220c0 clr!ThreadSuspend::SuspendEE+0xf6
0c 000000aa`f9f3e140 00007ff8`c198f0cb clr!WKS::GCHeap::GarbageCollectGeneration+0x270
0d 000000aa`f9f3e200 00007ff8`c18f58ae clr!WKS::gc_heap::try_allocate_more_space+0x4fb
0e 000000aa`f9f3e260 00007ff8`c18ac7a8 clr!WKS::GCHeap::Alloc+0x5e
0f 000000aa`f9f3e2b0 00007ff8`622081cb clr!JIT_New+0x1b8
10 000000aa`f9f3e540 00007ff8`62207670 System_Core_ni!System.Linq.Enumerable.TakeIterator<byte>+0x1b
11 000000aa`f9f3e580 00007ff8`bf530bf8 DAL!DAL.Request.OnReceivedServerData+0x50
12 000000aa`f9f3e5d0 00007ff8`bf530ae5 mscorlib_ni!System.Threading.ExecutionContext.RunInternal+0x108 [f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs @ 980]
13 000000aa`f9f3e6a0 00007ff8`bf530ab5 mscorlib_ni!System.Threading.ExecutionContext.Run+0x15 [f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs @ 928]
14 000000aa`f9f3e6d0 00007ff8`bfebd5a0 mscorlib_ni!System.Threading.ExecutionContext.Run+0x55 [f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs @ 917]
15 000000aa`f9f3e720 00007ff8`c19812c3 mscorlib_ni!System.Threading.ThreadHelper.ThreadStart+0x60 [f:\dd\ndp\clr\src\BCL\system\threading\thread.cs @ 93]
16 000000aa`f9f3e760 00007ff8`c184961b clr!CallDescrWorkerInternal+0x83
17 000000aa`f9f3e7a0 00007ff8`c1898b5a clr!CallDescrWorkerWithHandler+0x47
18 000000aa`f9f3e7e0 00007ff8`c1b91659 clr!MethodDescCallSite::CallTargetWorker+0xfa
19 000000aa`f9f3e8e0 00007ff8`c186230b clr!ThreadNative::KickOffThread_Worker+0x2186d9
1a 000000aa`f9f3eb30 00007ff8`c186222f clr!ManagedThreadBase_DispatchInner+0x33
1b 000000aa`f9f3eb70 00007ff8`c18620fb clr!ManagedThreadBase_DispatchMiddle+0x83
1c 000000aa`f9f3ec60 00007ff8`c186206f clr!ManagedThreadBase_DispatchOuter+0x87
1d 000000aa`f9f3ecf0 00007ff8`c1979e11 clr!ManagedThreadBase_FullTransitionWithAD+0x2f
1e 000000aa`f9f3ed50 00007ff8`c19658ea clr!ThreadNative::KickOffThread+0xe1
1f 000000aa`f9f3ee10 00007ff8`d1e27374 clr!Thread::intermediateThreadProc+0x8a
20 000000aa`f9f3f750 00007ff8`d2efcc91 kernel32!BaseThreadInitThunk+0x14
21 000000aa`f9f3f780 00000000`00000000 ntdll!RtlUserThreadStart+0x21
从卦象看,在 SuspendThread 的下游有一个 AisEsmUmh.dll,很显然这不是 coreclr 自带的,貌似被人家注入了,并且在 AisEsmUmh 的下游通过cs锁阻塞了当前的执行流,接下来的问题是 AisEsmUmh.dll 到底为何方神圣。
2. AisEsmUmh 到底是什么
要想知道是什么,可以使用 !lmi AisEsmUmh 命令即可,参考如下:
0:030> !lmi AisEsmUmh
Loaded Module Info: [aisesmumh]
Module: AisEsmUmh
Base Address: 00007ff8d03c0000
Image Name: AisEsmUmh.dll
Machine Type: 34404 (X64)
Time Stamp: 66bc19bf Wed Aug 14 10:43:11 2024
Size: 5a000
CheckSum: 67da6
Characteristics: 2022
Debug Data Dirs: Type Size VA Pointer
CODEVIEW 78, 43e90, 42a90 RSDS - GUID: {08FF691A-7607-413D-9F3C-7DD20738D992}
Age: 1, Pdb: e:\xxx\TRUSTONE_EDR\xxx\Win64\AisEsmUmh_X64.pdb
VC_FEATURE 10, 43f08, 42b08 [Data not mapped]
Image Type: MEMORY - Image read successfully from loaded memory.
Symbol Type: NONE - PDB not found from symbol server.
Load Report: no symbols loaded
从卦中可以看到,这个 AisEsmUmh_X64 目录中有一个 TRUSTONE_EDR 路径,看到这个 EDR(Endpoint Detection and Response) 我相信大家都知道是什么了,对。。。 就是安全软件,最后在 baidu 上搜一下 AisEsmUmh_X64 即可。

原来是 亚信安全 捣的鬼。。。到这里就彻底水落石出了。
3. 亚信安全 为什么要拦截
最后我们稍微解释下为什么会有拦截行为,大家都知道托管语言都有 GC 这么个东西,GC触发的时候会暂停所有的托管线程,俗称 STW(Stop The World),这里的暂停是一个抽象概念,CLR 会通过各种途径将 托管线程 引流到一个 event 事件上,其中就不乏 HiJack 方式,这个在coreclr源码中都是有痕迹的,截图如下:

这种 线程劫持 行为是被大多数杀毒软件所不容的,有些智能点的杀毒软件会放行,有些则不放,最后就导致这种灾难性的后果。
解决办法也比较简单:
- 关闭 亚信安全。
- 添加 白名单,或者你懂的的方式
三:总结
这次卡死事故原因是安全软件介入了 GC 过程,让 STW 迟迟得不到结束,哎,窗体类程序的生存环境举步维艰啊。。。

记一次 .NET 某汽车控制焊接软件 卡死分析的更多相关文章
- 记一次 .NET 某企业OA后端服务 卡死分析
一:背景 1.讲故事 前段时间有位朋友微信找到我,说他生产机器上的 Console 服务看起来像是卡死了,也不生成日志,对方也收不到我的httpclient请求,不知道程序出现什么情况了,特来寻求帮助 ...
- 记一次 .NET 某物管后台服务 卡死分析
一:背景 1. 讲故事 这几个月经常被朋友问,为什么不更新这个系列了,哈哈,确实停了好久,主要还是打基础去了,分析 dump 的能力不在于会灵活使用 windbg,而是对底层知识有一个深厚的理解,比如 ...
- 记一次 .NET 某工控自动化控制系统 卡死分析
一:背景 1. 讲故事 前段时间遇到了好几起关于窗体程序的 进程加载锁 引发的 程序卡死 和 线程暴涨 问题,这种 dump 分析难度较大,主要涉及到 Windows操作系统 和 C++ 的基础知识, ...
- 记一次 .NET 某自动化集采软件 崩溃分析
一:背景 1.讲故事 前段时间有位朋友找到我,说他的程序在客户的机器上跑着跑着会出现偶发卡死,然后就崩掉了,但在本地怎么也没复现,dump也抓到了,让我帮忙看下到底怎么回事,其实崩溃类的dump也有简 ...
- 记一次 .NET某医疗器械清洗系统 卡死分析
一:背景 1. 讲故事 前段时间协助训练营里的一位朋友分析了一个程序卡死的问题,回过头来看这个案例比较经典,这篇稍微整理一下供后来者少踩坑吧. 二:WinDbg 分析 1. 为什么会卡死 因为是窗体程 ...
- 机械大楼电梯控制项目软件 -- github团队组建
目前在Github网站上建立了机械大楼电梯控制项目软件的软件仓库(Repository),提供了软件功能需求说明文档和Automation Studio程序模板.地址为 https://github. ...
- ESP8266_04管脚控制与软件定时器
ESP8266_04管脚控制与软件定时器 from :https://mp.weixin.qq.com/s/APawDx4io4gKJyOeuErTLA 原创: MCU启航 单片机爱好者 今天 这一节 ...
- [DFNews] 入侵汽车控制刹车和油门?——速度与激情6 的节奏?
原文跳转: http://arstechnica.com/security/2013/07/disabling-a-cars-brakes-and-speed-by-hacking-its-compu ...
- Mpale 在汽车底盘悬架系统公差分析应用
汽车底盘的作用是接受发动机的动力,使车轮转动,并保证汽车按驾驶员的操纵正常行驶.底盘包括传动系统.行驶系统.转向系统和制动系统这四大部分,通常,这四大系统也简称为传动系.行驶系.转向系和制动系.悬架是 ...
- 记一次常规的Mysql数据库访问的时间分析
背景:记一次常规的数据访问的时间分析(插入操作) 1. TCP三次握手 SYN ---> <--- SYN,ACK ACK ---> 花费时间: 386.718-385.784=0. ...
随机推荐
- C#实现SSE通信方式的MCP Server
前面的课程,我们使用MCP Server,用的是网络上魔搭提供的. 下面我们一起来实现,用C#实现自己的MCP Server. MCP Server通信方式支持SSE.Stdio. 下面我们先实现SS ...
- 【拥抱鸿蒙】基于 Cocos Creator 的 HarmonyOS 自动构建
概述 随着 Cocos Creator 新版本的发布,开发者们迎来了一个令人振奋的消息:Cocos Creator 现已支持发布到 HarmonyOS 平台.这为游戏开发者和应用开发者开辟了新的天地, ...
- Odoo14前端框架常用操作
单页Web应用(single page web application,SPA): SPA 是一种特殊的 Web 应用,是加载单个 HTML 页面并在用户与应用程序交互时动态更新该页面的. 它将所有的 ...
- 洛谷P4643 [国家集训队]阿狸和桃子的游戏 & 初赛心情
洛谷P4643 [国家集训队]阿狸和桃子的游戏 引入 其实是道小水题,没有那么多的数据结构和卡常.但是我就是喜欢这种题!giao! (希望这道题不要变色啊--这可是我a的第一道黑题啊啊啊-- 蒟蒻的心 ...
- Spring扩展接口-初始化(@PostConstruct,afterPropertiesset, init-method)
.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...
- 自签名证书工具cfssl详解
概述 GitHub地址:https://github.com/cloudflare/cfssl 官方地址:https://pkg.cfssl.org CFSSL(CloudFlare's PKI an ...
- 关于Node.js 构建中遇到node-gyp报错问题的解决方案记录
项目今天进行版本更新,在走阿里云流水线的时候,出现了Node.js 构建过程报错问题,抱歉详情截图如下: 经过反复排查,最终发现是因为阿里云的npm仓库的问题,于是果断更换npm仓库,执行命令如下: ...
- Error: Activity class MainActivity does not exist.
这是一个熟悉而又陌生的错误,当年做的第一个React-Native项目就有这个错误,一直没有解决,今天又出现了,原因是我改了项目文件夹的名称,用Android Studio重新打开之后,就又出现了这个 ...
- hot100之链表上
相交链表(160) 先看代码 public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode ...
- Java集合--HashMap底层原理可视化,秒懂扩容、链化、树化
文章内容较长,带着疑问慢慢读. 文章对应的视频连接:https://www.bilibili.com/video/BV1wM3KzaE3d/ 哈希冲突问题如何高效解决? 1. 什么是冲突? 准确的说是 ...