一:背景
1. 講故事
為什么要提 宇宙射線
, 太陽耀斑
導(dǎo)致的程序崩潰呢?主要是昨天在知乎上看了這篇文章:莫非我遇到了傳說中的bug? ,由于 rip
中的0x41變成了0x61出現(xiàn)了bit位翻轉(zhuǎn)導(dǎo)致程序崩潰,截圖如下:
下面的評論大多是說由于 宇宙射線
,這個(gè)太玄乎了,說實(shí)話看到這個(gè) 傳說bug
的提法,我還是挺興奮的,畢竟在我的分析旅程中,我也是真的遇到過,這篇就拿出來給大家分享吧,當(dāng)時(shí)百思不得其解,真的是無語死了。
這位朋友找到我的時(shí)候,說程序會(huì)出現(xiàn)偶發(fā)性崩潰,自己在網(wǎng)上也發(fā)了很多帖子來尋找答案,最后都不了了之,問題確實(shí)太玄乎了,這一篇我們就開始這個(gè)奇妙之旅吧。
二:Windbg 分析
1. 為什么會(huì)崩潰
找崩潰點(diǎn)比較簡單,使用windbg 自帶的 !analyze -v
命令去挖那個(gè) EXCEPTION_POINTERS
結(jié)構(gòu)體即可。
0:083> !analyze -v
CONTEXT: (.ecxr)
rax=0000024f82c77341 rbx=000000f275dfe7f0 rcx=00007ffb05e55658
rdx=7ffb083d8c582d89 rsi=0000000000000000 rdi=000000f275dfe300
rip=00007ffb64be082f rsp=000000f275dfeaa0 rbp=000000007ffb05ee
r8=0000024ff9bc0810 r9=deb6f5c6f59b3377 r10=1441a86c71655650
r11=ebbed78e94800000 r12=00007ffb05e55640 r13=0000000000000020
r14=0000024b26a3d9e0 r15=0000024f82c77340
iopl=0 ov up ei ng nz na po cy
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010a85
clr!WKS::gc_heap::background_mark_simple1+0x516:
00007ffb`64be082f 4c8b02 mov r8,qword ptr [rdx] ds:7ffb083d`8c582d89=????????????????
Resetting default scope
EXCEPTION_RECORD: (.exr -1)
ExceptionAddress: 00007ffb64be082f (clr!WKS::gc_heap::background_mark_simple1+0x0000000000000516)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000001
NumberParameters: 2
Parameter[0]: 0000000000000000
Parameter[1]: ffffffffffffffff
Attempt to read from address ffffffffffffffff
STACK_TEXT:
000000f2`75dfeaa0 00007ffb`64be03a0 : clr!WKS::gc_heap::background_mark_simple1+0x516
000000f2`75dfeb00 00007ffb`64be074e : clr!WKS::gc_heap::background_mark_simple+0x6d
000000f2`75dfeb30 00007ffb`64a45fc7 : clr!WKS::gc_heap::background_promote+0x98
...
從卦中數(shù)據(jù)看,當(dāng)前觸發(fā)了后臺GC,并且處于標(biāo)記階段,在標(biāo)記托管堆上的對象時(shí)發(fā)現(xiàn)了有壞對象,無奈只能觸發(fā) CLR執(zhí)行引擎異常
,這也說明當(dāng)前的托管堆是處于損壞狀態(tài),可以用 !verifyheap
命令驗(yàn)證一下。
0:083> !verifyheap
object 0000024f82c76b18: bad member 0000024F82C77F40 at 0000024F82C76B70
Last good object: 0000024F82C76AA0.
object 0000024f82c76ca8: bad member 0000024F82C77340 at 0000024F82C76CB0
Last good object: 0000024F82C76C58.
object 0000024f82c76fa8: bad member 0000024F82C77050 at 0000024F82C76FD0
Last good object: 0000024F82C76F88.
Could not request method table data for object 0000024F82C77050 (MethodTable: 00007FFB3C032138).
Last good object: 0000024F82C76FA8.
果然卦中的數(shù)據(jù)也驗(yàn)證了這一點(diǎn),托管堆上有三個(gè)壞對象,接下來抽一個(gè)用 !do
命令來驗(yàn)證下。
0:083> !do 0000024f82c76b18
Name: System.Windows.Forms.TreeNode
MethodTable: 00007ffb3c431af8
EEClass: 00007ffb3c488500
Size: 168(0xa8) bytes
File: C:\xxxx\System.Windows.Forms.dll
Fields:
MT Field Offset Type VT Attr Value Name
...
00007ffb3c431ed8 400263f 58 ....Forms.TreeNode[] 0 instance 0000024f82c77f40 children
...
0:083> !do 0000024f82c77f40
<Note: this object has an invalid CLASS field>
Invalid object
從錯(cuò)誤信息以及剛才卦中的數(shù)據(jù)表明 TreeNode.children
內(nèi)存布局被破壞了,這種情況大多是因?yàn)?MethodTable 不對了導(dǎo)致CLR識別不出這塊內(nèi)存的對象,可以用 dp 驗(yàn)證下。
0:083> dp 0000024f82c77f40 L4
0000024f`82c77f40 00007ffb`3c411ed8 00000000`00400008
0000024f`82c77f50 0000024f`82c56fa8 0000024f`82c57378
0:083> !dumpmt 00007ffb`3c411ed8
00007ffb3c411ed8 is not a MethodTable
從卦中的 00007ffb3c411ed8 is not a MethodTable
可以看到這個(gè)地址是錯(cuò)誤的,那正確地址是什么呢?如果有心細(xì)的朋友會(huì)看到 !do
的時(shí)候已經(jīng)顯示了正確的方法表,即 00007ffb3c431ed8
。
接下來仔細(xì)觀察 00007ffb3c411ed8
和 00007ffb3c431ed8
這兩個(gè)地址,會(huì)發(fā)現(xiàn)一個(gè)是 3c41
一個(gè)是 3c43
,真的是無語了,截圖如下:
一般來說,這種單bit位的翻轉(zhuǎn)也不像是用 PInvoke 的方式讓 C++ 破壞了 C# 的托管堆,也不像是什么 hook 注入導(dǎo)致的,反正很神奇,為了拿更多證據(jù)可以在抽一個(gè) 壞對象 觀察下。
0:083> !do 0000024f82c76fa8
Name: System.Windows.Forms.TreeNode
MethodTable: 00007ffb3c431af8
EEClass: 00007ffb3c488500
Size: 168(0xa8) bytes
Fields:
MT Field Offset Type VT Attr Value Name
...
00007ffb3c432138 4002636 28 ...eNodeImageIndexer 0 instance 0000024f82c77050 imageIndexer
...
0:083> !do 00007ffb`3c032138
<Note: this object has an invalid CLASS field>
Invalid object
0:083> dp 0000024f82c77050 L1
0000024f`82c77050 00007ffb`3c032138
從卦中數(shù)據(jù)看:方法表 00007ffb3c032138
和 00007ffb3c432138
也是差了一個(gè)bit位,即 3c03
和 3c43
的差別。
2. 為什么會(huì)翻轉(zhuǎn)
有些朋友可能說,你這數(shù)據(jù)是不是網(wǎng)絡(luò)數(shù)據(jù),比如有什么 糾錯(cuò)碼
,海明碼
之類的,其實(shí) mt 的數(shù)據(jù)是嵌入到 image 中的,這塊數(shù)據(jù)一般在初始化的時(shí)候由 clr 構(gòu)建好,后期不會(huì)有人去改寫的,可以用 !address
看下。
0:083> !address 00007ffb3c432138
Usage: Image
Base Address: 00007ffb`3c431000
End Address: 00007ffb`3c434000
Region Size: 00000000`00003000 ( 12.000 kB)
State: 00001000 MEM_COMMIT
Protect: 00000004 PAGE_READWRITE
Type: 01000000 MEM_IMAGE
Allocation Base: 00007ffb`3c400000
Allocation Protect: 00000080 PAGE_EXECUTE_WRITECOPY
Image Path: C:\Windows\assembly\NativeImages_v4.0.30319_64\System.Windows.Forms\1534a59650e0fd08da0ed8931d9f6d5f\System.Windows.Forms.ni.dll
Module Name: System_Windows_Forms_ni
Loaded Image Name:
Mapped Image Name:
More info: lmv m System_Windows_Forms_ni
More info: !lmi System_Windows_Forms_ni
More info: ln 0x7ffb3c432138
More info: !dh 0x7ffb3c400000
Content source: 1 (target), length: 1ec8
后來計(jì)劃讓朋友開啟 MDA 托管調(diào)試助手去驗(yàn)證,結(jié)果朋友給我反饋說開啟后,程序運(yùn)行特別慢,這個(gè)很好理解,如果你的程序 PInvoke 過多,確實(shí)容易引發(fā)過高的 GC,所以能不能適應(yīng)到各位的程序,還需要實(shí)際測試。
遺憾的這條路朋友沒有走通,所以尋找答案就遙遙無期了,最后也就不了了之,因?yàn)槟菚r(shí)候我認(rèn)為所有的用戶態(tài)異常都是軟件造成的。。。
三:總結(jié)
直到昨天看了這篇 莫非我遇到了傳說中的bug?
我現(xiàn)在有想法了,在下面可能的七種選項(xiàng)中:文章來源:http://www.zghlxwxcb.cn/news/detail-760387.html
- 宇宙射線
- 太陽耀斑
- 地磁暴
- 電離輻射
- 硬件故障
- 殺毒軟件
- 內(nèi)存超頻
我覺得 內(nèi)存超頻
引發(fā)的程序不穩(wěn)定概率是最大的,不知道大家可有不同的看法?文章來源地址http://www.zghlxwxcb.cn/news/detail-760387.html

到了這里,關(guān)于記一次 .NET某工控 宇宙射線 導(dǎo)致程序崩潰分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!