经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » ASP.net » 查看文章
记一次 .NET某工控WPF程序被人恶搞的 卡死分析
来源:cnblogs  作者:一线码农  时间:2024/5/29 9:12:11  对本文有异议

一:背景

1. 讲故事

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

二:WinDbg 分析

1. 程序是如何卡死的

既然是窗体程序自然就是看主线程,我们使用 k 命令即可。

  1. 0:000> k
  2. # Child-SP RetAddr Call Site
  3. 00 00000036`e1f7da18 00007ffe`70bf30ce ntdll!NtWaitForSingleObject+0x14
  4. 01 00000036`e1f7da20 00007ffd`eff74910 KERNELBASE!WaitForSingleObjectEx+0x8e
  5. ...
  6. 05 (Inline Function) --------`-------- coreclr!CLREventBase::Wait+0x12 [D:\a\_work\1\s\src\coreclr\vm\synch.cpp @ 412]
  7. 06 00000036`e1f7db20 00007ffd`f00c9afa coreclr!Thread::WaitSuspendEventsHelper+0xc8 [D:\a\_work\1\s\src\coreclr\vm\threadsuspend.cpp @ 4626]
  8. 07 (Inline Function) --------`-------- coreclr!Thread::WaitSuspendEvents+0x8 [D:\a\_work\1\s\src\coreclr\vm\threadsuspend.cpp @ 4663]
  9. 08 00000036`e1f7dbe0 00007ffd`f0009c80 coreclr!Thread::RareEnablePreemptiveGC+0x7d99a [D:\a\_work\1\s\src\coreclr\vm\threadsuspend.cpp @ 2414]
  10. 09 (Inline Function) --------`-------- coreclr!Thread::EnablePreemptiveGC+0x16 [D:\a\_work\1\s\src\coreclr\vm\threads.h @ 2044]
  11. 0a 00000036`e1f7dc20 00007ffd`f0075d10 coreclr!Thread::RareDisablePreemptiveGC+0xc8 [D:\a\_work\1\s\src\coreclr\vm\threadsuspend.cpp @ 2156]
  12. 0b 00000036`e1f7dca0 00007ffd`f0096a5f coreclr!JIT_ReversePInvokeEnterRare2+0x18 [D:\a\_work\1\s\src\coreclr\vm\jithelpers.cpp @ 5462]
  13. 0c 00000036`e1f7dcd0 00007ffd`907afe09 coreclr!JIT_ReversePInvokeEnterTrackTransitions+0xaf [D:\a\_work\1\s\src\coreclr\vm\jithelpers.cpp @ 5509]
  14. 0d 00000036`e1f7dd00 00007ffe`72e0e858 0x00007ffd`907afe09
  15. 0e 00000036`e1f7dd80 00007ffe`72e0e3dc user32!UserCallWinProcCheckWow+0x2f8
  16. 0f 00000036`e1f7df10 00007ffe`72e20c93 user32!DispatchClientMessage+0x9c
  17. 10 00000036`e1f7df70 00007ffe`730f0e64 user32!_fnDWORD+0x33
  18. 11 00000036`e1f7dfd0 00007ffe`70b31104 ntdll!KiUserCallbackDispatcherContinue
  19. 12 00000036`e1f7e058 00007ffe`72e21c0e win32u!NtUserGetMessage+0x14
  20. 13 00000036`e1f7e060 00007ffe`711e28f2 user32!GetMessageW+0x2e
  21. ...
  22. 1d 00000036`e1f7e460 00007ffd`f009ba53 xxx!xxx.App.Main+0x5e
  23. ...
  24. 2a 00000036`e1f7f140 00007ffe`4cd4e1e6 hostfxr!execute_app+0x2fa [D:\a\_work\1\s\src\native\corehost\fxr\fx_muxer.cpp @ 145]
  25. ...
  26. 34 00000036`e1f7f890 00000000`00000000 ntdll!RtlUserThreadStart+0x21

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

  1. BOOL Thread::WaitSuspendEventsHelper(void)
  2. {
  3. if (m_State & TS_DebugSuspendPending)
  4. {
  5. ThreadState oldState = m_State;
  6. while (oldState & TS_DebugSuspendPending)
  7. {
  8. ThreadState newState = (ThreadState)(oldState | TS_SyncSuspended);
  9. if (InterlockedCompareExchange((LONG*)&m_State, newState, oldState) == (LONG)oldState)
  10. {
  11. result = m_DebugSuspendEvent.Wait(INFINITE, FALSE);
  12. break;
  13. }
  14. oldState = m_State;
  15. }
  16. }
  17. return result != WAIT_OBJECT_0;
  18. }

从上面的代码可以明显的看到当前Thread 处于 TS_DebugSuspendPending 状态,从名字上看貌似和调试有关,接下来查下这个枚举的注解。

  1. enum ThreadState
  2. {
  3. TS_DebugSuspendPending = 0x00000008, // Is the debugger suspending threads?
  4. }

从注解看是因为调试器阻塞了这个线程,我去,哪里来的调试器呢?这引起了我的巨大兴趣。。。

2. 哪里来的调试器

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

  1. 0:000> !peb
  2. PEB at 00000036e1c11000
  3. ...
  4. BeingDebugged: Yes
  5. ...
  6. Base TimeStamp Module
  7. 7ff7f5230000 65310000 Oct 19 18:08:00 2023 G:\xxx\C#\Projects\NugetApplications\Applications\xxx\bin\Debug\net6.0-windows\xxx.exe
  8. ...

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

3. 真的是 VS 跑起来的吗

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

  1. FCIMPL0(FC_BOOL_RET, DebugDebugger::IsDebuggerAttached)
  2. {
  3. CORDebuggerAttached();
  4. }
  5. inline bool CORDebuggerAttached()
  6. {
  7. return (g_CORDebuggerControlFlags & DBCF_ATTACHED);
  8. }
  9. enum DebuggerControlFlag
  10. {
  11. DBCF_ATTACHED = 0x0200,
  12. };

有了这些基础知识之后,接下来就可以用 x 命令去验证下。

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

从卦中看,你说正常发布的程序怎么可能会有 9 个 Microsoft.VisualStudio.DesignTools 字符串呢?

4. 这个dump是如何生成的

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

  1. internal class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. Console.WriteLine($"托管调试器:{Debugger.IsAttached}");
  6. Console.WriteLine($"非托管调试器:{IsDebuggerPresent()}");
  7. Console.ReadLine();
  8. }
  9. [DllImport("kernel32.dll")]
  10. static extern bool IsDebuggerPresent();
  11. }

调试起来后,截图如下:

最后打开生成好的 Dump 文件,使用 kc 观察主线程的输出:

  1. 0:000> kc
  2. # Call Site
  3. 00 ntdll!NtWaitForSingleObject
  4. 01 KERNELBASE!WaitForSingleObjectEx
  5. 02 coreclr!CLREventWaitHelper2
  6. 03 coreclr!CLREventWaitHelper
  7. 04 coreclr!CLREventBase::WaitEx
  8. 05 coreclr!CLREventBase::Wait
  9. 06 coreclr!Thread::WaitSuspendEventsHelper
  10. 07 coreclr!Thread::WaitSuspendEvents
  11. 08 coreclr!Thread::RareEnablePreemptiveGC
  12. 09 coreclr!Thread::EnablePreemptiveGC
  13. 0a coreclr!Thread::RareDisablePreemptiveGC
  14. 0b coreclr!Thread::DisablePreemptiveGC
  15. ...
  16. 19 ConsoleApp4!ConsoleApp4.Program.Main
  17. ...
  18. 30 ntdll!RtlUserThreadStart

从卦中看,正是停留在 WaitSuspendEventsHelper 函数里,一摸一样,彻底被360°无死角的证实。。。。

三:总结

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

原文链接:https://www.cnblogs.com/huangxincheng/p/18217252

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号