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

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

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

一、背景

1. 讲故事

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

二、WinDbg 分析

1. 程序是如何卡死的

既然是窗体程序自然就是看主线程,我们使用 k 命令即可。anZ28资讯网——每日最新资讯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事件,接下来看下这个方法的源码到底是怎么写的?简化后如下:anZ28资讯网——每日最新资讯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 状态,从名字上看貌似和调试有关,接下来查下这个枚举的注解。anZ28资讯网——每日最新资讯28at.com

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

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

2. 哪里来的调试器

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

3. 真的是 VS 跑起来的吗

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

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

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

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

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

4. 这个dump是如何生成的

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

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

最后打开生成好的 Dump 文件,使用 kc 观察主线程的输出:anZ28资讯网——每日最新资讯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°无死角的证实......anZ28资讯网——每日最新资讯28at.com

三、总结

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

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

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

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

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

标签:
  • 热门焦点
  • 小米官宣:2023年上半年出货量中国第一!

    今日早间,小米电视官方微博带来消息,称2023年小米电视上半年出货量达到了中国第一,同时还表示小米电视的巨屏风暴即将开始。“公布一个好消息2023年#小米电视上半年出货量中国
  • 影音体验是真的强 简单聊聊iQOO Pad

    大公司的好处就是产品线丰富,非常细分化的东西也能给你做出来,例如早先我们看到了新的vivo Pad2,之后我们又在iQOO Neo8 Pro的发布会上看到了iQOO的首款平板产品iQOO Pad。虽
  • 7月安卓手机性价比榜:努比亚+红魔两款新机入榜

    7月登场的新机有努比亚Z50S Pro和红魔8S Pro,除了三星之外目前唯二的两款搭载超频版骁龙8Gen2处理器的产品,而且努比亚和红魔也一贯有着不错的性价比,所以在本次的性价比榜单
  • 太卷!Redmi MAX 100英寸电视便宜了:12999元买Redmi史上最大屏

    8月5日消息,从小米商城了解到,Redmi MAX 100英寸巨屏电视日前迎来官方优惠,到手价12999元,比发布价便宜了7000元,在大屏电视市场开卷。据了解,Redmi MAX 100
  • JavaScript 混淆及反混淆代码工具

    介绍在我们开始学习反混淆之前,我们首先要了解一下代码混淆。如果不了解代码是如何混淆的,我们可能无法成功对代码进行反混淆,尤其是使用自定义混淆器对其进行混淆时。什么是混
  • 三言两语说透设计模式的艺术-单例模式

    写在前面单例模式是一种常用的软件设计模式,它所创建的对象只有一个实例,且该实例易于被外界访问。单例对象由于只有一个实例,所以它可以方便地被系统中的其他对象共享,从而减少
  • JVM优化:实战OutOfMemoryError异常

    一、Java堆溢出堆内存中主要存放对象、数组等,只要不断地创建这些对象,并且保证 GC Roots 到对象之间有可达路径来避免垃 圾收集回收机制清除这些对象,当这些对象所占空间超过
  • 华为HarmonyOS 4升级计划公布:首批34款机型今日开启公测

    8月4日消息,今天下午华为正式发布了HarmonyOS 4系统,在更流畅的前提下,还带来了不少新功能,UI设计也有变化,会让手机焕然一新。华为宣布,首批机型将会在
  • 世界人工智能大会国际日开幕式活动在世博展览馆开启

    30日上午,世界人工智能大会国际日开幕式活动在世博展览馆开启,聚集国际城市代表、重量级院士专家、国际创新企业代表,共同打造人工智能交流平台。上海市副市
Top