news 2025/12/25 17:09:11

记一次 .NET 某医联体管理系统 崩溃分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
记一次 .NET 某医联体管理系统 崩溃分析

一:背景

1. 讲故事

这段时间都在跑外卖,感觉好久都没写文章了,今天继续给大家带来一篇崩溃类的生产事故,这是微信上有位老朋友找到我的,让我帮忙看下为啥崩溃了,dump也在手,接下来就可以一顿分析。

二:崩溃分析

1. 为什么会崩溃

双击打开dump文件,会看到崩溃信息通览,参考如下:

Executable search path is:

Windows 10 Version 17763 MP (48 procs) Free x64

Product: Server, suite: TerminalServer DataCenter SingleUserTS

Edition build lab: 17763.1.amd64fre.rs5_release.180914-1434

Debug session time: Fri Oct 31 17:38:42.000 2025 (UTC + 8:00)

System Uptime: 14 days 2:42:29.643

Process Uptime: 0 days 0:00:58.000

................................................................

.......................................

Loading unloaded module list

.

This dump file has an exception of interest stored in it.

The stored exception information can be accessed via .ecxr.

(5a74.6250): Unknown exception - code c0000374 (first/second chance not available)

For analysis of this file, run !analyze -v

ntdll!NtWaitForMultipleObjects+0x14:

00007ffe`57baf0e4 c3 ret

从卦中看崩溃码是 c0000374,即 ntheap 损坏,哈哈,到这里一下子就把范围给缩小了。

2. 为什么ntheap 损坏

那为什么ntheap会损坏呢?可以使用 .ecxr 切到崩溃时的调用栈,观察崩溃行为。

0:032> .ecxr

0:032> k

*** Stack trace for last set context - .thread/.cxr resets it

# Child-SP RetAddr Call Site

00 000000b4`8503ede0 00007ffe`57c0b313 ntdll!RtlReportFatalFailure+0x9

01 000000b4`8503ee30 00007ffe`57c13b9e ntdll!RtlReportCriticalFailure+0x97

02 000000b4`8503ef20 00007ffe`57c13eaa ntdll!RtlpHeapHandleError+0x12

03 000000b4`8503ef50 00007ffe`57bae109 ntdll!RtlpHpHeapHandleError+0x7a

04 000000b4`8503ef80 00007ffe`57bbbb0e ntdll!RtlpLogHeapFailure+0x45

05 000000b4`8503efb0 00007ffe`17d17b3f ntdll!RtlFreeHeap+0x9d3ce

06 000000b4`8503f050 00007ffe`541392af AcLayers!NS_FaultTolerantHeap::APIHook_RtlFreeHeap+0x41f

07 000000b4`8503f0b0 00007ffe`3773b17e KERNELBASE!LocalFree+0x2f

08 000000b4`8503f0f0 00007ffe`37661d12 mscorlib_ni+0x58b17e

09 000000b4`8503f1a0 00007ffd`e49fe127 mscorlib_ni!System.Runtime.InteropServices.Marshal.FreeHGlobal+0x22 [f:\dd\ndp\clr\src\BCL\system\runtime\interopservices\marshal.cs @ 1212]

...

0:032> !clrstack

OS Thread Id: 0x6250 (32)

Child SP IP Call Site

000000b48503f118 00007ffe57baf0e4 [InlinedCallFrame: 000000b48503f118] Microsoft.Win32.Win32Native.LocalFree(IntPtr)

000000b48503f118 00007ffe3773b17e [InlinedCallFrame: 000000b48503f118] Microsoft.Win32.Win32Native.LocalFree(IntPtr)

000000b48503f0f0 00007ffe3773b17e DomainNeutralILStubClass.IL_STUB_PInvoke(IntPtr)

000000b48503f1a0 00007ffe37661d12 System.Runtime.InteropServices.Marshal.FreeHGlobal(IntPtr) [f:\dd\ndp\clr\src\BCL\system\runtime\interopservices\marshal.cs @ 1212]

000000b48503f1e0 00007ffde49fe127 b.B+A.MoveNext()

000000b48503f240 00007ffe376b3423 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) [f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs @ 954]

000000b48503f310 00007ffe376b32b4 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) [f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs @ 902]

...

000000b48503f5c0 00007ffde49fb04e DomainBoundILStubClass.IL_STUB_ReversePInvoke(Int32, Int32, Int64)

从卦中可以清晰的看到是 b.B+A.MoveNext 方法中调用了 FreeHGlobal 导致的NTHeap崩溃,如果你经验比较足的话,看到这个 FreeHGlobal 就应该想到 double free 问题,这是一个经典的问题。

3. 何为 double free

双释放即对一个 block 块进行二次释放,windows 的 RtlFreeHeap 方法会在业务逻辑中对这种情况直接判为异常,接下来你或许想知道这个 block 的地址是什么?这个可以用 !heap -s 观察,参考代码如下:

0:032> !heap -s

************************************************************************************************************************

NT HEAP STATS BELOW

************************************************************************************************************************

Details:

Heap address: 0000028c75bb0000

Error address: 0000028c786018a0

Error type: HEAP_FAILURE_BLOCK_NOT_BUSY

Details: The caller performed an operation (such as a free

or a size check) that is illegal on a free block.

Follow-up: Check the error's stack trace to find the culprit.

Stack trace:

Stack trace at 0x00007ffe57c72848

00007ffe57bae109: ntdll!RtlpLogHeapFailure+0x45

00007ffe57bbbb0e: ntdll!RtlFreeHeap+0x9d3ce

00007ffe17d17b3f: AcLayers!NS_FaultTolerantHeap::APIHook_RtlFreeHeap+0x41f

00007ffe541392af: KERNELBASE!LocalFree+0x2f

00007ffe3773b17e: mscorlib_ni+0x58b17e

00007ffe37661d12: mscorlib_ni!System.Runtime.InteropServices.Marshal.FreeHGlobal+0x22

00007ffde49fe127: +0xe49fe127

LFH Key : 0x765363a7204cf973

Termination on corruption : ENABLED

Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast

(k) (k) (k) (k) length blocks cont. heap

-------------------------------------------------------------------------------------

0000028c75bb0000 00000002 17920 9256 16364 2120 214 5 1 a LFH

External fragmentation 23 % (214 free blocks)

0000028c75b40000 00008000 64 4 64 2 1 1 0 0

0000028c75de0000 00001002 2636 132 1080 20 5 2 0 0 LFH

0000028c76190000 00001002 4680 2268 3124 1420 40 3 0 0 LFH

External fragmentation 62 % (40 free blocks)

0000028c76130000 00001002 2636 472 1080 5 27 2 0 0 LFH

0000028c767f0000 00041002 60 8 60 5 1 1 0 0

0000028c77020000 00041002 60 16 60 2 2 1 0 0

-------------------------------------------------------------------------------------

从卦中可以看到 Heap address: 0000028c75bb0000 即为 block 地址,接下来使用 !heap -x 0000028c786018a0 观察这个 block 块的状态,可以看到此时确实是 free 的。

0:032> !heap -x 0000028c786018a0

Entry User Heap Segment Size PrevSize Unused Flags

-------------------------------------------------------------------------------------------------------------

0000028c786018a0 0000028c786018b0 0000028c75bb0000 0000028c785c80d0 e0 - 0 LFH;free

到这里问题的成因我们是完全搞清楚了,接下来就是反推问题代码的时候了。

4. 问题代码在哪里

应该有朋友知道问题是在 b.B+A.MoveNext() 方法中,从名字上看这个项目应该是混淆的,有点搞哈。。。得要费点眼力,截图如下:

从卦中的 IntPtr intPtr = Interlocked.Exchange(ref b.A, IntPtr.Zero); 来看,这个 intPtr 是一个类级别变量,看样子是多个方法在操控类级别变量时没有合理的控制好,为了一探究竟,再次分析源代码,果然是的,截图如下:

到这里就真相大白了,让朋友修改源码自己控制好这个变量。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/14 11:15:32

5大革新维度:WanVideo多模态生成引擎如何重塑视频创作生态

5大革新维度:WanVideo多模态生成引擎如何重塑视频创作生态 【免费下载链接】WanVideo_comfy 项目地址: https://ai.gitcode.com/hf_mirrors/Kijai/WanVideo_comfy 在人工智能视频生成领域,一场技术革命正悄然改变着内容创作的游戏规则。WanVideo…

作者头像 李华
网站建设 2025/12/22 16:16:23

OpenChat成本控制终极指南:5大策略实现AI对话系统费用优化

OpenChat成本控制终极指南:5大策略实现AI对话系统费用优化 【免费下载链接】OpenChat OpenChat - 一个用户聊天机器人控制台,简化了大型语言模型的利用,支持创建和管理定制聊天机器人。 项目地址: https://gitcode.com/gh_mirrors/op/OpenC…

作者头像 李华
网站建设 2025/12/14 11:12:45

CubeFS贡献者成长路线:从入门到专家的实战指南

CubeFS贡献者成长路线:从入门到专家的实战指南 【免费下载链接】cubefs CubiFS 是一个开源的分布式文件系统,用于数据存储和管理,支持多种数据存储模型和云原生环境。 * 分布式文件系统、数据存储和管理 * 有什么特点:支持多种数据…

作者头像 李华
网站建设 2025/12/14 11:12:03

FBCTF竞赛平台深度解析:从部署到实战的完整管理方案

FBCTF作为Facebook开源的专业CTF竞赛平台,为安全竞赛组织者提供了从基础设施搭建到竞赛运营的全方位解决方案。本文将从实战角度出发,为您揭示高效管理CTF竞赛的核心技巧与最佳实践。 【免费下载链接】fbctf Platform to host Capture the Flag competit…

作者头像 李华
网站建设 2025/12/14 11:08:38

基于GA遗传优化的电动汽车光储充电站容量配置

1.程序功能描述基于GA遗传优化的电动汽车光储充电站容量配置算法matlab仿真。通过运行基于 GA 的光储充电站容量配置算法,得到了最优的容量配置方案。与传统的容量配置方法相比,该方案在降低投资成本和运行成本方面具有明显的优势。同时,通过…

作者头像 李华