你好,欢迎进入江苏优软数字科技有限公司官网!

诚信、勤奋、创新、卓越

友好定价、专业客服支持、正版软件一站式服务提供

13262879759

工作日:9:00-22:00

codejock 162 Codejock 162版本下空引用异常try catch无效的深度分析与修复方案

发布时间:2025-12-07

浏览次数:0

一:背景 1. 讲故事

前几天,有一位朋友,在微信上,给我丢了一个,处于崩溃状态下形成的dump文件,要我帮忙,查看一下,导致出现崩溃情况的缘由,该情况,在特定的事件查看器上,所显示的,是典型的一种访问违例问题,确切来讲是错误码方面的情况,不管怎样,既然拿到了dump文件,那就可以着手处理这件事了。

二: 分析 1. 程序为谁崩溃了

于平台之上相对简易,能够借由! -v 指令加以查看,其输出结果呈现如下:


0:120> !analyze -v
...
CONTEXT: (.ecxr)
rax等于零零零零零零零零零零零零零零零零,rbx等于零零零零零零d5140fcf00,rcx等于零零零零零零零零零零零零零零零零。
rsi等于000001d7d3635a10,rdi等于000000d5140fc890,rdx等于000001d7f61cf1d8 。
rip等于00007ff80e17d233,rsp等于000000d5140fc760,rbp等于000000d5140fc8a0 。
r8等于000001d7d3308144,r9等于0000000000000000,r10等于0000000000000000。
R11等于000001d96736b620,R12等于000000d5140fca08,R13等于00007ff80d326528 。
r14等于000000d5140fcf00,r15等于0000000000000000。
iopl等于0,nv状态为向上,ei状态为有效,pl状态情况存着,nz为空,na为无,po为。
.cs的值是0033,.ss的值是002b,.ds的值是002b,.es的值是002b,.fs的值是0053,.gs的值是002b,.efl的值是00。
00007ff8`0e17d233,3909,比较双字指针指向的内存单元内容与ecx寄存器的值,数据段中该内存单元地址为00000000`00000000,其值未知,为???????? 。
Resetting default scope

EXCEPTION_RECORD: (.exr -1)
异常地址为 ,是 00007ff80e17d233 。
异常代码:c0000005,(未遵守对内存的访问限制)。
ExceptionFlags: 00000000
NumberParameters: 2
参数[0]:零,零,零,零,零,零,零,零,零,零,零,零,零。
参数[1]为,0000000000000000 。


错误代码:,(NT 状态),0xc0000005,减,0x%p,0x%p,%s,。

EXCEPTION_CODE_STR: c0000005

STACK_TEXT:
零零零零零零d5`140fc760,零零零零7ff8`6bcc6d93,冒号,零零零零零一d7`d3635a10,零零零零零零d5`140fcb80,零零零零7ff8`6bcfda57,零零零零7ff8`695acc92,冒号,零x零零零零7ff8`0e17d233。
表示为,000000d5`140fc8b0 ,00007ff8`6bcc6c48 ,这里是,00000000`00000004 ,00007ff8`6be5ba73 ,00000000`00000000 ,00000000`00000000 ,而这对应着,clr!CallDescrWorkerInternal+0x83 ,句号。
在000000d5`140fc8f0处,00007ff8`6be5bf66 ,对应着000001d7`d3635a10 ,有00000000`00000000 ,还有000000d5`140fcad8,再有00000000`00000000 ,这表示clr!CallDescrWorkerWithHandler+0x4e 。
000000d5`140fc930,000000d5`140fca30,000000d5`140fcb60,00007ff8`6be5c41f,clr!CallDescrWorkerReflectionWrapper+0x1a,这些分别是不同的内容,其中000000d5`140fc930对应着这样的情况,这里是以一种特定的形式呈现,000000d5`140fca30又有着与之不同的情况,000000d5`14。
000000d5`140fc980,00007ff8`69993ee4,冒号之后是00000000`00000000,00000000`00000000,000001d7`d3635a10,00007ff8`699f9700,clr!RuntimeMethodHandle::InvokeMethod加上0x45f 。
数字串000000d5`140fcf90 、00007ff8`6997eeae ,冒号之后 ,分别为000001d7`d3376af0 、00000000`00000000 、00000000`0000011e 、00007ff8`699f82f3 ,这表示 mscorlib_ni!System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal+0x104 。
000000d5`140fd000,00007ff8`699c3a06,其值为:00000000`00000000,00000000`00000000,00000000`00000000,00000000`00000000,此对应mscorlib_ni!System.Reflection.RuntimeMethodInfo.Invoke+0x8e 。
由000000d5`140fd080、00007ff8`0dfb7bb3组成的这一串数据,对应着代表某个状况的值,该值是000001d7`d3635998 、000001d7`d45e28e0 、00000000`0000011c和000001d7`d3376af0,这串数据所关联的情况,与mscorlib_ni!System.RuntimeType.InvokeMember+0x306有所关联 。
...
STACK_COMMAND,其时长约为120秒,涉及.ecxr,还有kb 。
...

由卦中传来的信息而去瞧那已然崩溃了的,汇编语句是dword ptr, ecx,常常去看C#汇编代码啊,我笃定对于这条语句颇具敏感性的朋友们,没错呀,它正是被JIT在自动状态下插入的一条this!=的防御类型的判断语句,看来程序当中存在this=这样的状况呢,接下来着手的切入点便是RIP所处的地方,用!U去观察一番上下文 。


0:120> !U 00007ff80e17d233
Normal JIT generated code
MyScript.Process
起始为00007ff80e17d1c0,大小是3d5 ,。
00007ff8`0e17d1c0 55 push rbp
00007ff8`0e17d1c1 57 push rdi
00007ff8`0e17d1c2 56 push rsi
对于地址为00007ff8 ` 0e17d1c3处,执行了4881ec30010000这一指令操作,随后进行的。
这里有一串字符,分别是,00007ff8,然后是,0e17d1ca,接着是,c5f87。
...
零,零,零,零,七,f,f,八,冒号,零,e,一,七,d,二,二,零,空格,e,八,一,三,c,一,e,d,f,e,空格,调用,零,零,零,零,七,f,f,八,冒号,零,d,零,五,九,三,三,八,左括号,双引号,x,x,x,点,获取区域,左括号,系统,。
把`00007ff8`这个,`0e17d225`这个,`48898570ffffff`这个,进行`mov`操作,将`qword ptr`指向的,`[rbp - 90h。
00007ff8`0e17d22c,488b8d70ffffff,将rcx设立为指向rbp减去90h地址处的四字指针所对应的十六进制值 。
先看这个地址 00007ff8`0e17d233 处,进行了这样一个操作 3909,它是 将双字指针指向的内存内容 与 ecx 的。
00007ff8`0e17d235,e8de87edfe,调用 00007ff8`0d055a18(xxx.get_Region,mdToken: 0000000006000073),。

依据卦里的汇编代码去看,其逻辑是极为清晰的,也就是xxx.方法所返回的内容codejock 162,随后在获取其中的属性之际直接就崩溃了,简单来讲这是一个单纯的空引用异常,完整的代码截图如下:

怪异之处便在于此,代码当中分明是以try catch将其给包裹起来的,为何程序径直就崩溃掉了呢。

2. 为什么try catch 无效

嗨呀,这可是我在这持续多年进行dump分析期间,头一回碰到这般状况,真的是让人毫无办法了没辙了,随之而后我们去查验核实一下这个异常究竟有没有抵达托管层面呢?

是否有

对dump分析熟悉的朋友理应清楚,万一线程抛出了异常,那么在回溯进程当中是会被记录下来的,。

存在于.ndle字段里头,与此同时,!t命令能够在列当中查看得到此信息。


0:120> !t
ThreadCount: 48
UnstartedThread: 0
BackgroundThread: 47
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
Lock
身份标识操作系统标识线程对象状态垃圾回收模式垃圾回收分配上下文域计数适配异常,是这样吗? ,是类似这种表述吗? ,那这样符合要求吗? 。
0,1,29dc,000001d7d162d5d0,26020,Preemptive,000001D7D8228A00,000001D7D8228D28,000001d7d1602380,STA ,句号。
...
159,18,22dc,000001d967906ff0,1029220,Preemptive,000001D7D834E558:000001D7D834E558,000001d7d1602380,1 MTA(GC)(线程池工作线程), 。
...

然而,仅从卦中的数据去观察,所有的列并不存在异常信息这件事,这便意味着程序未曾抵达CLR的异常处理链条之上,起码是不完整的状态。

是否有 tion

参与过C#内功修炼训练营的友人应当都清楚,诸如此类的异常在C#层面最终会被映射为两种异常中的某一个,也就是 和tion,挑选其一蕴含的逻辑乃是判定RIP是处于托管层还是非托管层,其模型图如下:

然而,令人惋惜的是,于!t的列表当中,同样不存在任何呈现tion字样的情况,这进一步证实了它未对异常处理链里的函数进行调用。。。

情况出现不符合常规的状况必然存在可疑之处,于,!t的输出成果当中能够见到这个时候159号线程促使了GC,紧接着切换过去瞧一瞧。


0:120> ~159s
在ntdll模块里的NtQueryInformationThread函数处,偏移量为0x14的位置 ,。
00007ff8`8317ea34 c3 ret
0:159> k
# Child-SP RetAddr Call Site
零零点零零零零零零d五撇零零点c三e七d八,零零点零零零七ff八撇七f二一六e二e,ntdll冒号NtQueryInformationThread加零x十四 。
把这串字符拆分成三个部分 01, 000000d5, 00c3e7e0`00007ff8`6bcea731 KERNELBASE!(GetThreadPriority+0.18),。
把02 000000d5`00c3e850 00007ff8`6be69cc5,clr!Thread::GetThreadPriority+0x56 改写为:02 000000d5`00c3e850。
编号为03的,地址为000000d5`00c3e8a0的,以及地址为00007ff8`6be69bc4的,clr!ThreadSuspend::SuspendRuntime加上偏移量0xa5 。
零四,零零零零零零d五,零0c三e九九零,零零零零七ff八,六bd八一四e三,clr!线程挂起::挂起执行环境加零x一二八 。
05,000000d5,00c3ea90,00007ff8`6bd85f51,clr!WKS::GCHeap::做内存垃圾回收于特定代且偏移量为0xb7 ,标点符号为中文全角的句号。
06,000000d5,00c3eaf0,00007ff8,6be7ee6b,clr!WKS::gc_heap::trigger_gc_for_alloc加上0x2d,。
零七,零零零零零零d五撇零,零零c三eb三零,零零零零七ff八撇四七零e五三ec,clr叹号JIT下划线New加零x四d十六分号。
08,000000d5`00c3eee0,00007ff8`470e537c,Microsoft_VisualBasic_ni这个东西里头的Microsoft.VisualBasic.Strings.ReplaceInternal加上等于0x3c,它所在的位置是f:\dd\vb\runtime\msvbalib\Strings.vb,具体是在第761的位置~。
在09这个时刻,面对着000000d5`00c3ef80,又有00007ff8`0d04f81f与之相关联,这属于Microsoft_VisualBasic_ni部分!其中涉及到Microsoft.VisualBasic.Strings.Replace这个内容,具体是加上了0x15c ,其所在位置为[f:\dd\vb\runtime\msvbalib\Strings.vb @ 737] 。
...

当从卦里的线程栈着手去看时,此刻正处于某阶段,并且此阶段还是处于早期的那种阶段,同时正对给某事物安排一个良好的优先级这种行为做准备动作,主要是害怕因为优先级太低了,进而致使线程饥饿这种状况出现,使得得不到调度,毕竟垃圾回收的这个过程必然得是在快的基础上还要更快,接下来我们去查看一下程序的某版本。


0:159> !eeversion
4.7.3190.0 free
Workstation mode
紧急求救版本:4.7.3190.0 零售版构建 ,紧急求救版本:4.7.3190.0 零售。

能看到它是相对较老的。4.7.3,把如此多的信息结合起来,我个人认为这大概是CLR的一个漏洞,在阶段的前期(尚无)恰好碰到了一个硬件异常事件codejock 162,这个硬件异常CLR在业务逻辑方面没能妥善处理,致使SEH异常未被引入到托管层面,或者中途的某一个环节中断了,我放置一张C#内功修炼训练营里的硬件异常详尽流程图。

最后给到朋友的建议比较简单:

三:总结

这次程序出现崩溃状况,其缘由相当简单,乃是空引用异常所致,然而诡异之处在于,明明在外部存在相关内容,结果却硬是没能承接得住,这种情况大概率是CLR出现了bug,这使得身为分析多年dump的老手的我,都不禁大为惊叹,增长了见识,满心无奈 。

如有侵权请联系删除!

13262879759

微信二维码