当前位置:首页 > 科技  > 软件

记一次 .NET某工控WPF程序被人恶搞的卡死分析

来源: 责编: 时间:2024-05-29 08:57:02 79观看
导读一、背景1. 讲故事这一期程序故障除了做原理分析,还顺带吐槽一下,熟悉我的朋友都知道我分析dump是免费的,但免费不代表可以滥用我的宝贵时间,我不知道有些人故意恶搞卡死是想干嘛,不得而知,希望后面类似的事情越来越少吧!废

一、背景

1. 讲故事

这一期程序故障除了做原理分析,还顺带吐槽一下,熟悉我的朋友都知道我分析dump是免费的,但免费不代表可以滥用我的宝贵时间,我不知道有些人故意恶搞卡死是想干嘛,不得而知,希望后面类似的事情越来越少吧!废话不多说,我们来看看是如何被恶搞的。tHN28资讯网——每日最新资讯28at.com

二、WinDbg 分析

1. 程序是如何卡死的

既然是窗体程序自然就是看主线程,我们使用 k 命令即可。tHN28资讯网——每日最新资讯28at.com

0:000> k  # Child-SP          RetAddr               Call Site00 00000036`e1f7da18 00007ffe`70bf30ce     ntdll!NtWaitForSingleObject+0x1401 00000036`e1f7da20 00007ffd`eff74910     KERNELBASE!WaitForSingleObjectEx+0x8e...05 (Inline Function) --------`--------     coreclr!CLREventBase::Wait+0x12 [D:/a/_work/1/s/src/coreclr/vm/synch.cpp @ 412] 06 00000036`e1f7db20 00007ffd`f00c9afa     coreclr!Thread::WaitSuspendEventsHelper+0xc8 [D:/a/_work/1/s/src/coreclr/vm/threadsuspend.cpp @ 4626] 07 (Inline Function) --------`--------     coreclr!Thread::WaitSuspendEvents+0x8 [D:/a/_work/1/s/src/coreclr/vm/threadsuspend.cpp @ 4663] 08 00000036`e1f7dbe0 00007ffd`f0009c80     coreclr!Thread::RareEnablePreemptiveGC+0x7d99a [D:/a/_work/1/s/src/coreclr/vm/threadsuspend.cpp @ 2414] 09 (Inline Function) --------`--------     coreclr!Thread::EnablePreemptiveGC+0x16 [D:/a/_work/1/s/src/coreclr/vm/threads.h @ 2044] 0a 00000036`e1f7dc20 00007ffd`f0075d10     coreclr!Thread::RareDisablePreemptiveGC+0xc8 [D:/a/_work/1/s/src/coreclr/vm/threadsuspend.cpp @ 2156] 0b 00000036`e1f7dca0 00007ffd`f0096a5f     coreclr!JIT_ReversePInvokeEnterRare2+0x18 [D:/a/_work/1/s/src/coreclr/vm/jithelpers.cpp @ 5462] 0c 00000036`e1f7dcd0 00007ffd`907afe09     coreclr!JIT_ReversePInvokeEnterTrackTransitions+0xaf [D:/a/_work/1/s/src/coreclr/vm/jithelpers.cpp @ 5509] 0d 00000036`e1f7dd00 00007ffe`72e0e858     0x00007ffd`907afe090e 00000036`e1f7dd80 00007ffe`72e0e3dc     user32!UserCallWinProcCheckWow+0x2f80f 00000036`e1f7df10 00007ffe`72e20c93     user32!DispatchClientMessage+0x9c10 00000036`e1f7df70 00007ffe`730f0e64     user32!_fnDWORD+0x3311 00000036`e1f7dfd0 00007ffe`70b31104     ntdll!KiUserCallbackDispatcherContinue12 00000036`e1f7e058 00007ffe`72e21c0e     win32u!NtUserGetMessage+0x1413 00000036`e1f7e060 00007ffe`711e28f2     user32!GetMessageW+0x2e...1d 00000036`e1f7e460 00007ffd`f009ba53     xxx!xxx.App.Main+0x5e...2a 00000036`e1f7f140 00007ffe`4cd4e1e6     hostfxr!execute_app+0x2fa [D:/a/_work/1/s/src/native/corehost/fxr/fx_muxer.cpp @ 145] ...34 00000036`e1f7f890 00000000`00000000     ntdll!RtlUserThreadStart+0x21

从卦中的调用栈可以看到,主线程通过 GetMessageW 从消息队列中拿到了数据,在处理时被 coreclr 押解到 WaitSuspendEventsHelper 处等待一个event事件,接下来看下这个方法的源码到底是怎么写的?简化后如下:tHN28资讯网——每日最新资讯28at.com

BOOL Thread::WaitSuspendEventsHelper(void){    if (m_State & TS_DebugSuspendPending)    {        ThreadState oldState = m_State;        while (oldState & TS_DebugSuspendPending)        {            ThreadState newState = (ThreadState)(oldState | TS_SyncSuspended);            if (InterlockedCompareExchange((LONG*)&m_State, newState, oldState) == (LONG)oldState)            {                result = m_DebugSuspendEvent.Wait(INFINITE, FALSE);                break;            }            oldState = m_State;        }    }    return result != WAIT_OBJECT_0;}

从上面的代码可以明显的看到当前Thread 处于 TS_DebugSuspendPending 状态,从名字上看貌似和调试有关,接下来查下这个枚举的注解。tHN28资讯网——每日最新资讯28at.com

enum ThreadState{    TS_DebugSuspendPending = 0x00000008,    // Is the debugger suspending threads?}

从注解看是因为调试器阻塞了这个线程,我去,哪里来的调试器呢?这引起了我的巨大兴趣。。。tHN28资讯网——每日最新资讯28at.com

2. 哪里来的调试器

我刚开始是抱有巨大的善意,我以为他的程序被人恶意注入导致卡死,但分析下来我还是太单纯了,继续往下看吧,既然有调试器,一般来说PEB.BeingDebugged=Yes状态,命令的输出结果也得到了证实。tHN28资讯网——每日最新资讯28at.com

0:000> !pebPEB at 00000036e1c11000    ...    BeingDebugged:            Yes    ...                    Base TimeStamp                     Module            7ff7f5230000 65310000 Oct 19 18:08:00 2023 G:/xxx/C#/Projects/NugetApplications/Applications/xxx/bin/Debug/net6.0-windows/xxx.exe            ...

我以为到这里就可以告诉朋友答案,你的程序可能被人恶意注入了,但眼尖的我发现了一点异常,他的 xxx.exe 启动目录怎么会有 /bin/Debug/net6.0-windows/ 呢?很明显这是用 VS 直接跑起来的呀。。。。tHN28资讯网——每日最新资讯28at.com

3. 真的是 VS 跑起来的吗

首先大家要知道 Visual Studio 是托管调试器,托管调试器在调试程序的时候会在 coreclr 层面设置一个全局变量 g_CORDebuggerControlFlags=0x0200,这也是 Debugger.IsAttached 的底层判断依据,不相信的朋友可以看下这个方法的底层实现:tHN28资讯网——每日最新资讯28at.com

FCIMPL0(FC_BOOL_RET, DebugDebugger::IsDebuggerAttached){    CORDebuggerAttached();}inline bool CORDebuggerAttached(){    return (g_CORDebuggerControlFlags & DBCF_ATTACHED);}enum DebuggerControlFlag{    DBCF_ATTACHED                   = 0x0200,};

有了这些基础知识之后,接下来就可以用 x 命令去验证下。tHN28资讯网——每日最新资讯28at.com

看到上面的答案基本就可以实锤了,有些朋友可能还是不大相信,我们可以这样看,VisualStudio 是 WPF 写的,如果用 VS 来调试,那么线程栈里面应该会有很多类似的 VisualStudio 字符串。tHN28资讯网——每日最新资讯28at.com

从卦中看,你说正常发布的程序怎么可能会有 9 个 Microsoft.VisualStudio.DesignTools 字符串呢?tHN28资讯网——每日最新资讯28at.com

4. 这个dump是如何生成的

这个问题我相信可能有一些朋友会比较疑惑,其实没什么疑惑的,Visual Studio 有生成Dump的功能,操作步骤为:Debug -> Save Dump As... , 接下来通过一个小例子观察一下。tHN28资讯网——每日最新资讯28at.com

internal class Program    {        static void Main(string[] args)        {            Console.WriteLine($"托管调试器:{Debugger.IsAttached}");            Console.WriteLine($"非托管调试器:{IsDebuggerPresent()}");            Console.ReadLine();        }        [DllImport("kernel32.dll")]        static extern bool IsDebuggerPresent();    }

调试起来后,截图如下:tHN28资讯网——每日最新资讯28at.com

最后打开生成好的 Dump 文件,使用 kc 观察主线程的输出:tHN28资讯网——每日最新资讯28at.com

0:000> kc # Call Site00 ntdll!NtWaitForSingleObject01 KERNELBASE!WaitForSingleObjectEx02 coreclr!CLREventWaitHelper203 coreclr!CLREventWaitHelper04 coreclr!CLREventBase::WaitEx05 coreclr!CLREventBase::Wait06 coreclr!Thread::WaitSuspendEventsHelper07 coreclr!Thread::WaitSuspendEvents08 coreclr!Thread::RareEnablePreemptiveGC09 coreclr!Thread::EnablePreemptiveGC0a coreclr!Thread::RareDisablePreemptiveGC0b coreclr!Thread::DisablePreemptiveGC...19 ConsoleApp4!ConsoleApp4.Program.Main...30 ntdll!RtlUserThreadStart

从卦中看,正是停留在 WaitSuspendEventsHelper 函数里,一摸一样,彻底被360°无死角的证实......tHN28资讯网——每日最新资讯28at.com

三、总结

这是一次人为的故意恶搞,大概率就是想看下我到底是骡子是马。我分析的结果对他和他所在的公司来说没有任何价值,只能白白的浪费我的时间,真是分析多了,什么样的人都能遇到,谨以此文告知后来者,免费但请不要滥用!tHN28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-91362-0.html记一次 .NET某工控WPF程序被人恶搞的卡死分析

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 每个前端开发人员都应该了解的软件工程原理

下一篇: 面试官:你能实现一个 JavaScript 模板引擎吗?

标签:
  • 热门焦点
  • Mate60手机壳曝光 致敬自己的经典设计

    Mate60手机壳曝光 致敬自己的经典设计

    8月3日消息,今天下午博主数码闲聊站带来了华为Mate60的第三方手机壳图,可以让我们在真机发布之前看看这款华为全新旗舰的大致轮廓。从曝光的图片看,Mate 60背后摄像头面积依然
  • 天猫精灵Sound Pro体验:智能音箱没有音质?来听听我的

    天猫精灵Sound Pro体验:智能音箱没有音质?来听听我的

    这几年除了手机作为智能生活终端最主要的核心之外,第二个可以成为中心点的产品是什么?——是智能音箱。 手机在执行命令的时候有两种操作方式,手和智能语音助手,而智能音箱只
  • Automa-通过连接块来自动化你的浏览器

    Automa-通过连接块来自动化你的浏览器

    1、前言通过浏览器插件可实现自动化脚本的录制与编写,具有代表性的工具就是:Selenium IDE、Katalon Recorder,对于简单的业务来说可快速实现自动化的上手工作。Selenium IDEKat
  • 企业采用CRM系统的11个好处

    企业采用CRM系统的11个好处

    客户关系管理(CRM)软件可以为企业提供很多的好处,从客户保留到提高生产力。  CRM软件用于企业收集客户互动,以改善客户体验和满意度。  CRM软件市场规模如今超过580
  • 三言两语说透柯里化和反柯里化

    三言两语说透柯里化和反柯里化

    JavaScript中的柯里化(Currying)和反柯里化(Uncurrying)是两种很有用的技术,可以帮助我们写出更加优雅、泛用的函数。本文将首先介绍柯里化和反柯里化的概念、实现原理和应用
  • 拼多多APP上线本地生活入口,群雄逐鹿万亿市场

    拼多多APP上线本地生活入口,群雄逐鹿万亿市场

    Tech星球(微信ID:tech618)文 | 陈桥辉 Tech星球独家获悉,拼多多在其APP内上线了“本地生活”入口,位置较深,位于首页的“充值中心”内,目前主要售卖美食相关的
  • 阿里瓴羊One推出背后,零售企业迎数字化新解

    阿里瓴羊One推出背后,零售企业迎数字化新解

    作者:刘旷近年来随着数字经济的高速发展,各式各样的SaaS应用服务更是层出不穷,但本质上SaaS大多局限于单一业务流层面,对用户核心关切的增长问题等则没有提供更好的解法。在Saa
  • 小米MIX Fold 3下月亮相:今年唯一无短板的全能折叠屏

    小米MIX Fold 3下月亮相:今年唯一无短板的全能折叠屏

    这段时间以来,包括三星、一加、荣耀等等有不少品牌旗下的最新折叠屏旗舰都有新的进展,其中荣耀、三星都已陆续发布了最新的折叠屏旗舰,尤其号荣耀Magi
  • 7月4日见!iQOO 11S官宣:“鸡血版”骁龙8 Gen2+200W快充加持

    7月4日见!iQOO 11S官宣:“鸡血版”骁龙8 Gen2+200W快充加持

    上半年已接近尾声,截至目前各大品牌旗下的顶级旗舰都已悉数亮相,而下半年即将推出的顶级旗舰已经成为了数码圈爆料的主流,其中就包括全新的iQOO 11S系
Top