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

记一次 .NET某防伪验证系统崩溃分析

来源: 责编: 时间:2024-03-28 17:49:15 259观看
导读一、背景1. 讲故事昨晚给训练营里面的一位朋友分析了一个程序崩溃的故障,因为看小伙子昨天在群里问了一天也没搞定,干脆自己亲自上阵吧,抓取的dump也是我极力推荐的用 procdump 注册 AEDebug 的方式,省去了很多沟通成本。

一、背景

1. 讲故事

昨晚给训练营里面的一位朋友分析了一个程序崩溃的故障,因为看小伙子昨天在群里问了一天也没搞定,干脆自己亲自上阵吧,抓取的dump也是我极力推荐的用 procdump 注册 AEDebug 的方式,省去了很多沟通成本。Xrg28资讯网——每日最新资讯28at.com

二、WinDbg分析

1. 为什么会崩溃

windbg有一个非常强大的点就是当你双击打开后,会自动帮你切换到崩溃的线程以及崩溃处的汇编代码,省去了 !analyze -v 命令的龟速输出,参考信息如下:Xrg28资讯网——每日最新资讯28at.com

...................................................................................................................This dump file has an exception of interest stored in it.The stored exception information can be accessed via .ecxr.(10f4.f58): Access violation - code c0000005 (first/second chance not available)For analysis of this file, run !analyze -veax=00000000 ebx=00000000 ecx=00000040 edx=00000000 esi=004c1b98 edi=07a8ed4ceip=7008508f esp=07a8ec74 ebp=07a8ec80 iopl=0         nv up ei pl zr na pe nccs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246clr!Thread::GetSafelyRedirectableThreadContext+0x7c:7008508f 8038eb          cmp     byte ptr [eax],0EBh        ds:002b:00000000=??...

从卦中可以看到,当前崩溃是因为 eax=0 导致的,那为什么 eax 等于 0 呢?要想寻找这个答案,需要观察崩溃前的线程栈上下文,可以使用命令 .ecxr;k 9 即可。Xrg28资讯网——每日最新资讯28at.com

0:009> .ecxr;k 9eax=00000000 ebx=00000000 ecx=00000040 edx=00000000 esi=004c1b98 edi=07a8ed4ceip=7008508f esp=07a8ec74 ebp=07a8ec80 iopl=0         nv up ei pl zr na pe nccs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246clr!Thread::GetSafelyRedirectableThreadContext+0x7c:7008508f 8038eb          cmp     byte ptr [eax],0EBh        ds:002b:00000000=?? # ChildEBP RetAddr      00 07a8ec80 6fe7f6cd     clr!Thread::GetSafelyRedirectableThreadContext+0x7c01 07a8f030 6fe7f2f3     clr!Thread::HandledJITCase+0x3102 07a8f0a4 6fee23da     clr!Thread::SuspendRuntime+0x26003 07a8f184 6fedf72d     clr!WKS::GCHeap::SuspendEE+0x1fe04 07a8f1b0 6fe309ca     clr!WKS::GCHeap::GarbageCollectGeneration+0x16805 07a8f1c0 6fe30a2e     clr!WKS::GCHeap::GarbageCollectTry+0x5606 07a8f1e4 6fe30a90     clr!WKS::GCHeap::GarbageCollect+0xa507 07a8f230 6f058b01     clr!GCInterface::Collect+0x5d08 07a8f26c 055fa4b1     mscorlib_ni+0x3b8b01

从卦中信息看,尼玛,真无语了 GCInterface::Collect 说明有人用 GC.Collect() 手工触发GC,不知道为什么要这么做来污染GC内部的统计信息,不管怎么说这个肯定不是崩溃的原因。Xrg28资讯网——每日最新资讯28at.com

2. GC正在干什么

我们继续观察线程栈,可以看到它的逻辑大概是这样的,通过 SuspendRuntime 把所有的托管线程进行逻辑上暂停,在暂停其中的一个线程时抛出了异常。Xrg28资讯网——每日最新资讯28at.com

稍微提醒一下,这个 HandledJITCase 方法是用 ip 劫持技术将代码引入到 coreclr 中进行 GC完成等待,这种神操作有些杀毒软件会认为是病毒!!!Xrg28资讯网——每日最新资讯28at.com

有些朋友肯定会说,有没有代码支撑。。。这里我就找一下 coreclr 的源码贴一下吧。Xrg28资讯网——每日最新资讯28at.com

void ThreadSuspend::SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason){ while ((thread = ThreadStore::GetThreadList(thread)) != NULL) {  ...  if (workingOnThreadContext.Acquired() && thread->HandledJITCase())  {   ...  }  ... }}

结合源码分析思路就非常清晰了,这里的 thread->HandledJITCase() 中的 thread 到底是哪一个线程?可以观察 kb 输出然后用 !t 去做比对。Xrg28资讯网——每日最新资讯28at.com

图片图片Xrg28资讯网——每日最新资讯28at.com

从卦中看,当前 GC 正在 Suspend 主线程,并且还看到了主线程有一个 System.AccessViolationException 异常,无语了。。。Xrg28资讯网——每日最新资讯28at.com

3. 主线程到底怎么了

主线程进入到视野之后,那就重点关注一下它,可以用 k 看一下输出。Xrg28资讯网——每日最新资讯28at.com

0:009> ~0seax=00000000 ebx=0029ea50 ecx=0029ea90 edx=00000000 esi=7efdb800 edi=000d0000eip=00000000 esp=0029ea4c ebp=75146381 iopl=0         nv up ei pl nz na po nccs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=0021020200000000 ??              ???0:000> k00 75146381 7efdb800     0x001 75146381 7517fa04     0x7efdb80002 0029ea80 7736013a     user32!__fnHkINLPKBDLLHOOKSTRUCT+0x2803 0029eae4 7514908d     ntdll!KiUserCallbackDispatcher+0x2e04 0029eae4 076e3912     user32!CallNextHookEx+0x8405 0029eb28 076e3064     0x76e391206 0029eb5c 0011d48f     xxx!xxx.ScanerHook.KeyboardHookProc+0xe407 0029eb8c 75146381     0x11d48f08 0029eba8 7517fa04     user32!DispatchHookW+0x3809 0029ebd8 7736013a     user32!__fnHkINLPKBDLLHOOKSTRUCT+0x280a 0029ec3c 751406eb     ntdll!KiUserCallbackDispatcher+0x2e0b 0029ec3c 75140751     user32!_PeekMessage+0x880c 0029ec68 6d8af3bf     user32!PeekMessageW+0x108...

从卦象看,这卦非常奇怪,有如下两点信息:Xrg28资讯网——每日最新资讯28at.com

  • eip=00000000,这个很无语,线程已经疯了
  • KeyboardHookProc ,居然有键盘钩子

熟悉 eip 的朋友应该知道,它相当于一辆车的方向盘,一辆高速行驶的车突然没了方向盘,真的太可怕了,最后必然车毁人亡。Xrg28资讯网——每日最新资讯28at.com

4. 是 eip=0 导致的崩溃吗

在汇编中是因为eax=0导致,而这里eip恰好也等于0,仿佛冥冥之中自有牵连,带着强烈的好奇心我们来反汇编下 GetSafelyRedirectableThreadContext 方法逻辑,简化后如下:Xrg28资讯网——每日最新资讯28at.com

0:000> uf 7008508fclr!Thread::GetSafelyRedirectableThreadContext:6fe7f60e 55              push    ebp6fe7f60f 8bec            mov     ebp,esp6fe7f611 53              push    ebx6fe7f612 56              push    esi6fe7f613 57              push    edi6fe7f614 8bf1            mov     esi,ecx...7008506d ffe9            jmp     rcx7008506f fd              std70085070 c1daff          rcr     edx,0FFh70085073 f6450801        test    byte ptr [ebp+8],170085077 0f84efa5dfff    je      clr!Thread::GetSafelyRedirectableThreadContext+0xcc (6fe7f66c)7008507d 8b8604010000    mov     eax,dword ptr [esi+104h]70085083 3987b8000000    cmp     dword ptr [edi+0B8h],eax70085089 0f85dda5dfff    jne     clr!Thread::GetSafelyRedirectableThreadContext+0xcc (6fe7f66c)7008508f 8038eb          cmp     byte ptr [eax],0EBh

从上面的汇编代码看eax的取值链条是: eax <- esi+104h <- ecx ,很显然这里的 ecx 是 thiscall 协议中的 Thread=004c1b98 参数,可以用 dp 验证下。Xrg28资讯网——每日最新资讯28at.com

0:000> dp 004c1b98+0x104 L1004c1c9c  00000000

从卦中看果然是 0,有些朋友好奇这个 104 偏移到底是个什么东西,参考 coreclr 源码其实就是 m_LastRedirectIP 字段,参考如下:Xrg28资讯网——每日最新资讯28at.com

BOOL Thread::GetSafelyRedirectableThreadContext(DWORD dwOptions, CONTEXT* pCtx, REGDISPLAY* pRD){    if (!EEGetThreadContext(this, pCtx))    {        return FALSE;    }    ...  if (GetIP(pCtx) == m_LastRedirectIP) {  const BYTE short_jmp = 0xeb;  const BYTE self = 0xfe;  BYTE* ip = (BYTE*)m_LastRedirectIP;  if (ip[0] == short_jmp && ip[1] == self)   m_LastRedirectIP = 0;  return FALSE; }}

结合汇编代码其实我们崩溃在 ip[0] == short_jmp 这一句上,仔细分析上面的C++代码会发现一个很奇怪的信息,那就是为什么 GetIP(pCtx)= 0,接下来用 dt 观察下寄存器上下文。Xrg28资讯网——每日最新资讯28at.com

0:009> kb 2 # ChildEBP RetAddr      Args to Child              00 07a8ec80 6fe7f6cd     00000003 07a8ed4c 07a8ecf0 clr!Thread::GetSafelyRedirectableThreadContext+0x7c01 07a8f030 6fe7f2f3     004c1b98 0b367326 76a016a1 clr!Thread::HandledJITCase+0x310:009> dt _CONTEXT 07a8ed4cntdll!_CONTEXT   +0x000 ContextFlags     : 0x10007   ...   +0x01c FloatSave        : _FLOATING_SAVE_AREA   +0x08c SegGs            : 0x2b   +0x090 SegFs            : 0x53   +0x094 SegEs            : 0x2b   +0x098 SegDs            : 0x2b   +0x09c Edi              : 0xd0000   +0x0a0 Esi              : 0x7efdb800   +0x0a4 Ebx              : 0x29ea50   +0x0a8 Edx              : 0   +0x0ac Ecx              : 0x29ea90   +0x0b0 Eax              : 0   +0x0b4 Ebp              : 0x75146381   +0x0b8 Eip              : 0   +0x0bc SegCs            : 0x23   +0x0c0 EFlags           : 0x210202   +0x0c4 Esp              : 0x29ea4c   ...

从卦中看果然 eip=0,这是一个非常错误的信息,还有一点就是 m_LastRedirectIP 字段一般用来处理一些比较诡异的兼容性问题,所以这里两个字段都是 0 导致崩溃的产生。Xrg28资讯网——每日最新资讯28at.com

有了上面的信息,我们就知道了前因后果,原来是主线程车毁人亡(eip=0),导致GC无法暂停它,在内部抛出了代码异常,你可以说是 CLR 的bug,也可以说是主线程的Bug,所以给到的解决方案就是:Xrg28资讯网——每日最新资讯28at.com

  1. 屏蔽掉 键盘钩子 的业务逻辑,肯定是它造成的。
  2. 不去掉的话,要重点观察 键盘盘子 ,是否是代码改动引发的。

三、总结

说实话要想解释这个程序为什么会崩溃,需要分析者对GC的SuspendRuntime运作逻辑有一定的了解,否则真抓瞎了,所以.NET调试训练营中的GC理论知识一定是分析这些 dump 的基石。Xrg28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-80192-0.html记一次 .NET某防伪验证系统崩溃分析

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

上一篇: 负载均衡原理最全详解

下一篇: vivo 消息中间件测试环境项目多版本实践

标签:
  • 热门焦点
  • 影音体验是真的强 简单聊聊iQOO Pad

    大公司的好处就是产品线丰富,非常细分化的东西也能给你做出来,例如早先我们看到了新的vivo Pad2,之后我们又在iQOO Neo8 Pro的发布会上看到了iQOO的首款平板产品iQOO Pad。虽
  • 5月iOS设备好评榜:iPhone 14仅排第43?

    来到新的一月,安兔兔的各个榜单又重新汇总了数据,像安卓阵营的榜单都有着比较大的变动,不过iOS由于设备的更新换代并没有那么快,所以相对来说变化并不大,特别是iOS好评榜,老款设
  • 从 Pulsar Client 的原理到它的监控面板

    背景前段时间业务团队偶尔会碰到一些 Pulsar 使用的问题,比如消息阻塞不消费了、生产者消息发送缓慢等各种问题。虽然我们有个监控页面可以根据 topic 维度查看他的发送状态,
  • Java NIO内存映射文件:提高文件读写效率的优秀实践!

    Java的NIO库提供了内存映射文件的支持,它可以将文件映射到内存中,从而可以更快地读取和写入文件数据。本文将对Java内存映射文件进行详细的介绍和演示。内存映射文件概述内存
  • 学习JavaScript的10个理由...

    作者 | Simplilearn编译 | 王瑞平当你决心学习一门语言的时候,很难选择到底应该学习哪一门,常用的语言有Python、Java、JavaScript、C/CPP、PHP、Swift、C#、Ruby、Objective-
  • 重估百度丨“晚熟”的百度云,能等到春天吗?

    &copy;自象限原创作者|程心排版|王喻可2016年7月13日,百度云计算战略发布会在北京举行,宣告着百度智能云的正式启程。彼时的会场座无虚席,甚至排队排到了门外,在场的所有人几乎都
  • 最“俊美”淘宝卖家,靠直播和短视频圈粉,上架秒光,年销3000万

    来源 | 电商在线文|易琬玉编辑|斯问受访店铺:Ringdoll戒之人形图源:微博@御座的黄山、&ldquo;Ringdoll戒之人形&rdquo;淘宝店铺有关外貌的评价,黄山已经听累了。生于1985年的他,哪
  • 腾讯盖楼,字节拆墙

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之&ldquo;想重温暴刷深渊、30+技能搭配暴搓到爽的游戏体验吗?一起上晶核,即刻暴打!&rdquo;曾凭借直播腾讯旗下代理格斗游戏《DNF》一
  • 国行版三星Galaxy Z Fold5/Z Flip5发布 售价7499元起

    2023年8月3日,三星电子举行Galaxy新品中国发布会,正式在国内推出了新一代折叠屏智能手机三星Galaxy Z Fold5与Galaxy Z Flip5,以及三星Galaxy Tab S9
Top