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

一:背景

1. 讲故事

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

二:WinDbg 分析

1. 程序是如何卡死的

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


0:000> k 
 # Child-SP          RetAddr               Call Site
00 00000036`e1f7da18 00007ffe`70bf30ce     ntdll!NtWaitForSingleObject+0x14
01 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`907afe09
0e 00000036`e1f7dd80 00007ffe`72e0e3dc     user32!UserCallWinProcCheckWow+0x2f8
0f 00000036`e1f7df10 00007ffe`72e20c93     user32!DispatchClientMessage+0x9c
10 00000036`e1f7df70 00007ffe`730f0e64     user32!_fnDWORD+0x33
11 00000036`e1f7dfd0 00007ffe`70b31104     ntdll!KiUserCallbackDispatcherContinue
12 00000036`e1f7e058 00007ffe`72e21c0e     win32u!NtUserGetMessage+0x14
13 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事件,接下来看下这个方法的源码到底是怎么写的?简化后如下:


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 状态,从名字上看貌似和调试有关,接下来查下这个枚举的注解。


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

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

2. 哪里来的调试器

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


0:000> !peb
PEB 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 直接跑起来的呀。。。。

3. 真的是 VS 跑起来的吗

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


FCIMPL0(FC_BOOL_RET, DebugDebugger::IsDebuggerAttached)
{
    CORDebuggerAttached();
}

inline bool CORDebuggerAttached()
{
    return (g_CORDebuggerControlFlags & DBCF_ATTACHED);
}

enum DebuggerControlFlag
{
    DBCF_ATTACHED                   = 0x0200,
};

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

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

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

4. 这个dump是如何生成的

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


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

            Console.ReadLine();
        }

        [DllImport("kernel32.dll")]
        static extern bool IsDebuggerPresent();
    }

调试起来后,截图如下:

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


0:000> kc
 # Call Site
00 ntdll!NtWaitForSingleObject
01 KERNELBASE!WaitForSingleObjectEx
02 coreclr!CLREventWaitHelper2
03 coreclr!CLREventWaitHelper
04 coreclr!CLREventBase::WaitEx
05 coreclr!CLREventBase::Wait
06 coreclr!Thread::WaitSuspendEventsHelper
07 coreclr!Thread::WaitSuspendEvents
08 coreclr!Thread::RareEnablePreemptiveGC
09 coreclr!Thread::EnablePreemptiveGC
0a coreclr!Thread::RareDisablePreemptiveGC
0b coreclr!Thread::DisablePreemptiveGC
...
19 ConsoleApp4!ConsoleApp4.Program.Main
...
30 ntdll!RtlUserThreadStart

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

三:总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/652485.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

光学测量反射率定标版

在光学测量和成像领域,准确性和一致性是至关重要的。为了确保设备能够提供可靠的数据,必须对其进行精确的校准。这就是反射率定标版发挥作用的地方。本文将深入探讨反射率定标版的概念、重要性、使用方式以及它们如何帮助科学家和工程师实现光学测量的精…

李飞飞亲自撰文:大模型不存在主观感觉能力,多少亿参数都不行

近日,李飞飞连同斯坦福大学以人为本人工智能研究所 HAI 联合主任 John Etchemendy 教授联合撰写了一篇文章,文章对 AI 到底有没有感觉能力(sentient)进行了深入探讨。 「空间智能是人工智能拼图中的关键一环。」知名「AI 教母」李…

JAVA 17

文章目录 概述一 语法层面变化1_JEP 409:密封类2_JEP 406:switch模式匹配(预览) 二 API层面变化1_JEP 414:Vector API(第二个孵化器)2_JEP 415:特定于上下文的反序列化过滤器 三 其他…

Mysql 8.0 主从复制及读写分离搭建记录

前言 搭建参考:搭建Mysql主从复制 为什么要做主从复制? 做数据的热备,作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。架构的扩展。业务量越来越大,I/O访问频…

运营商系统快速上云的实践分享

运营商系统上云的背景 系统上云是数字经济发展的潮流,在数字化转型的浪潮中,上云已经成为推动各行各业创新和效率提升的关键力量。运营商作为服务行业和企业上云的服务商,积极响应国家号召的同时为行业上云打造案例标杆,自身的系统…

PS中常用的快捷速查表以及常用的工具速查表

PS中常用的快捷速查表:大家有需要可以收藏一下 文件菜单 新建 ... CtrlN 打开 ... CtrlO 在 Bridge 中浏览 ... AltCtrlO 打开为 ... AltShiftCtrlO 关闭 CtrlW 关闭全部 AltCtrlW 关闭并转到 Bridge... ShiftCtrlW 存储 CtrlS 存储为 ... Shi…

康医养产教服务平台发布会

五月的上海,繁花似锦。22号下午在上海市长宁区虹桥路1999号黎黎酒家隆重举办“康医养产教服务平台发布会!” 【韩邑 康医养产教服务平台发起人】 【盛汇中国创造学会理事】 【宋舒易博士上海会会联盟发起人】 为促进健康产业链可持续发展,结…

计算机网络——在地址栏输入网址(URL)之后都发生了什么

网址,也叫域名,域名就像一个 IP 地址的可读版本,比如,百度的域名 www.baidu.com,他的 ip 是 110.242.68.3,输入 IP 一样可以跳转到百度搜索的页面,我想没有一个人没去记百度的 IP 吧。其实我们真…

钡铼技术BL205模块在智能制造产线的灵活配置与优化

钡铼技术的OPC UA耦合器BL205模块在智能制造产线中的灵活配置与优化是当今工业领域中的一个关键议题。随着工业4.0和数字化转型的不断推进,生产线的灵活性和智能化程度成为了企业追求的目标。在这一背景下,BL205模块以其分布式、可插拔、结构紧凑、可编程…

I.MX6ULL Linux 点灯实验理论及汇编点灯

系列文章目录 I.MX6ULL Linux C语言开发 I.MX6ULL Linux 点灯实验理论 系列文章目录一、I.MX6ULL GPIO二、I.MX6ULL IO 命名三、I.MX6ULL IO 复用四、I.MX6ULL IO 配置五、I.MX6ULL GPIO 配置六、I.MX6ULL GPIO 时钟使能七、硬件原理分析八、实验程序编写 一、I.MX6ULL GPIO 一…

嵌入式进阶——外部中断(EXTI)

🎬 秋野酱:《个人主页》 🔥 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 STC8H中断外部中断外部中断编写配置外部中断调用中断触发函数 外部中断测试测试外部中断0测试外部中断2、3或者4 PCB中断设计 STC8…

Unity 生成模版代码

1、创建模版代码文本 using System.Collections; using System.Collections.Generic; using UnityEngine;public class ClassNameScritpItem : MonoBehaviour {public GameObject go;// Start is called before the first frame updatevoid Start(){go new GameObject();}// …

驱动开发学习之新旧字符设备接口,自动创建设备的点灯

1.前言 本章将介绍新旧字符设备接口,以及自动创建设备节点的点灯实验。 2.实验原理介绍 2.1.寄存器知识 学习过单片机的兄弟都知道,点灯有以下步骤: (1)开启相应的GPIO时钟 (2)如果需要配置复用&…

聊聊如何感知项目引入哪些功能特性

前言 使用过springcloud全家桶朋友,应该知道springcloud涉及的组件很多,为了让开发者快速了解项目引入了springcloud哪些组件,springcloud引入了HasFeatures,配合Actuator,可以让开发者感知到项目引入的组件功能类型、…

C++ std::reference_wrapper:让引用更强大

std::reference_wrapper 的通俗易懂解释 一、简介二、std::reference_wrapper 的初衷三、常用示例3.1、与 make_pair 和 make_tuple 一起使用3.2、引用容器3.3、通过 std::thread 按引用传递参数给启动函数3.4、引用作为类成员3.5、按引用传递函数对象3.6、与绑定表达式一起使用…

苹果手机备忘录共享到微信,为何显示不支持的类型

作为一名苹果手机用户,我深知其系统的流畅与便捷。然而,在日常使用中,我发现了一个令人不解的问题:为何苹果手机的原生备忘录无法直接分享到微信?每次当我尝试将备忘录里的内容共享给微信好友时,总会遇到“…

代码随想录算法训练营第四十二天|62.不同路径、63. 不同路径 II

62.不同路径 文档讲解:代码随想录 题目链接:. - 力扣(LeetCode) 记录每个格子的状态 二维矩阵-->二维dp数组 dp数组 题目是要求到达最后一个格子有多少种路径 所以dp[i,j]: 到达第(i,j)个格子有多少种路径 递推公式 到达一…

WPS文件没有保存怎么恢复?5个解决方案轻松恢复!

“我在WPS上编辑了一个文件,但是还没来得及将它保存,我不小心就退出软件了,现在不知道有什么方法可以恢复WPS文件呢?大家可以帮帮我吗” WPS作为一款功能强大且用户友好的软件,给我们的工作带来了很多的便利。但我们在…

记录一次内存取证

1.情景复现 我姐姐的电脑坏了。我们非常幸运地恢复了这个内存转储。你的工作是从系统中获取她所有的重要文件。根据我们的记忆,我们突然看到一个黑色的窗口弹出,上面有一些正在执行的东西。崩溃发生时,她正试图画一些东西。这就是我们从崩溃…

# WIN10/WIN11 找不到【应用商店 Microsoft.WindowsStore】怎么办?

WIN10/WIN11 找不到【应用商店 Microsoft.WindowsStore】怎么办? 解决方法: 1、右键【开始】菜单,点击【Windows PowerShell (管理员)】,输入: Get-AppxPackage -allusers | Select Name, PackageFullName 2、查询…