日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

记一次 .NET某股票交易软件 灵异崩溃分析

發(fā)布時(shí)間:2023/12/29 asp.net 48 coder
生活随笔 收集整理的這篇文章主要介紹了 记一次 .NET某股票交易软件 灵异崩溃分析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一:背景

1. 講故事

在dump分析的旅程中也會(huì)碰到一些讓我無法解釋的靈異現(xiàn)象,追過這個(gè)系列的朋友應(yīng)該知道,上一篇我聊過 宇宙射線 導(dǎo)致的程序崩潰,后來我又發(fā)現(xiàn)了一例,而這一例恰恰是高鐵的 列控連鎖一體化 程序,所以更加讓我確定這是由于 電離輻射 干擾了計(jì)算機(jī)的 數(shù)字信號(hào) 導(dǎo)致程序的bit翻轉(zhuǎn),而這一篇也是一個(gè)我認(rèn)為的 靈異現(xiàn)象,拿出來給朋友們分享一下。

前段時(shí)間有位朋友找到我,說他的程序會(huì)偶發(fā)性崩潰,一直找不到原因很糾結(jié),看我在這一塊非常有經(jīng)驗(yàn)讓我?guī)兔匆幌略趺椿厥拢热皇怯袀涠鴣碜匀籨ump也準(zhǔn)備好了,接下來開始分析之旅吧。

二:WinDbg 分析

1. 為什么會(huì)崩潰

要想分析崩潰的原因還得windbg自帶的自動(dòng)化分析命令 !analyze -v ,輸出如下:


0:117> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

CONTEXT:  (.ecxr)
rax=0000000000000001 rbx=0000000000000000 rcx=0000000000000002
rdx=000000000005001b rsi=000000000000000e rdi=00000161b1b8c718
rip=00007ffdd0961abd rsp=000000341547b370 rbp=000000341547b250
 r8=0000000000000005  r9=000000000000003d r10=0000000000000000
r11=7007f0b8d350316a r12=0000000000000000 r13=0000000000000003
r14=000000341547b5c0 r15=0000000000000001
iopl=0         nv up ei pl nz na pe nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
clr!_report_gsfailure+0x1d:
00007ffd`d0961abd cd29            int     29h
Resetting default scope

EXCEPTION_RECORD:  (.exr -1)
ExceptionAddress: 00007ffdd0961abd (clr!_report_gsfailure+0x000000000000001d)
   ExceptionCode: c0000409 (Security check failure or stack buffer overrun)
  ExceptionFlags: 00000001
NumberParameters: 1
   Parameter[0]: 0000000000000002
Subcode: 0x2 FAST_FAIL_STACK_COOKIE_CHECK_FAILURE 

SYMBOL_NAME:  clr!_report_gsfailure+1d

...

卦中有一句話叫 Security check failure or stack buffer overrun,淺層意思就是: 安全檢查失敗或緩沖區(qū)溢出,行話就是:棧上的cookie遭到了破壞。

可能有些朋友對(duì) cookie 不是很了解,這個(gè)cookie非web的cookie,而是在方法棧上藏的一個(gè)隨時(shí)值,在方法的退出前會(huì)檢查這個(gè)值有沒有被破壞,目的就是防止有人無意或者惡意攻擊線程棧,如果遭到破壞,會(huì)觸發(fā) int 29nt!KiRaiseSecurityCheckFailure 函數(shù)讓程序快速硬性崩潰。

如果有些朋友不明白,畫個(gè)圖如下:

既然說 cookie 被破壞了,說明有棧溢出的情況,那到底溢出了什么東西呢?這需要分析崩潰處附近的匯編代碼才能知道,接下來使用 .ecxr ; k 3 切到崩潰前的上下文。


0:117> .ecxr ; k 3
rax=0000000000000001 rbx=0000000000000000 rcx=0000000000000002
rdx=000000000005001b rsi=000000000000000e rdi=00000161b1b8c718
rip=00007ffdd0961abd rsp=000000341547b370 rbp=000000341547b250
 r8=0000000000000005  r9=000000000000003d r10=0000000000000000
r11=7007f0b8d350316a r12=0000000000000000 r13=0000000000000003
r14=000000341547b5c0 r15=0000000000000001
iopl=0         nv up ei pl nz na pe nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
clr!_report_gsfailure+0x1d:
00007ffd`d0961abd cd29            int     29h
 # Child-SP          RetAddr               Call Site
00 00000034`1547b370 00007ffd`d0977900     clr!_report_gsfailure+0x1d
01 00000034`1547b3b0 00007ffd`d097816d     clr!RtlAllocateLUnicodeString+0xe0
02 00000034`1547b420 00007ffd`d09e1d06     clr!RtlDuplicateLUnicodeString+0x8d
...

卦中的信息很豐富,說 clr 在 RtlAllocateLUnicodeString 函數(shù)退出階段時(shí)檢查 cookie 被破壞了,繼而程序快速崩潰,接下來需要反編譯 RtlAllocateLUnicodeString 函數(shù),簡(jiǎn)化后如下:


0:117> uf clr!RtlAllocateLUnicodeString
clr!RtlAllocateLUnicodeString:
00007ffd`d0977820 48895c2418      mov     qword ptr [rsp+18h],rbx
00007ffd`d0977825 55              push    rbp
00007ffd`d0977826 56              push    rsi
00007ffd`d0977827 57              push    rdi
00007ffd`d0977828 488bec          mov     rbp,rsp
00007ffd`d097782b 4883ec50        sub     rsp,50h
00007ffd`d097782f 488b05d2777600  mov     rax,qword ptr [clr!_security_cookie (00007ffd`d10df008)]
00007ffd`d0977836 4833c4          xor     rax,rsp
00007ffd`d0977839 488945f8        mov     qword ptr [rbp-8],rax
00007ffd`d097783d 488bfa          mov     rdi,rdx
00007ffd`d0977840 488bf1          mov     rsi,rcx
00007ffd`d0977843 c745f0e50000c0  mov     dword ptr [rbp-10h],0C00000E5h
00007ffd`d097784a 33db            xor     ebx,ebx
00007ffd`d097784c 4885d2          test    rdx,rdx
00007ffd`d097784f 745f            je      clr!RtlAllocateLUnicodeString+0x90 (00007ffd`d09778b0)  Branch
...
00007ffd`d09778f2 8bc3            mov     eax,ebx
00007ffd`d09778f4 488b4df8        mov     rcx,qword ptr [rbp-8]
00007ffd`d09778f8 4833cc          xor     rcx,rsp
00007ffd`d09778fb e820a1feff      call    clr!_security_check_cookie (00007ffd`d0961a20)
00007ffd`d0977900 488b9c2480000000 mov     rbx,qword ptr [rsp+80h]
00007ffd`d0977908 4883c450        add     rsp,50h
00007ffd`d097790c 5f              pop     rdi
00007ffd`d097790d 5e              pop     rsi
00007ffd`d097790e 5d              pop     rbp
00007ffd`d097790f c3              ret

卦中的信息量還是非常大的,我們通讀下匯編代碼理解下 安全檢查 中的一些基本元素以及邏輯是什么? 步驟大概如下:

  1. _security_cookie

這個(gè)是 cookie 種子,可以用 dp 給撈出來,即下面的 0000d9998c879750


0:117> dp clr!_security_cookie L1
00007ffd`d10df008  0000d999`8c879750

  1. xor rax,rsp

將 cookie 種子和當(dāng)前方法的棧頂指針rsp異或一下,目的就是做一個(gè)和棧幀相關(guān)的隨機(jī)值,當(dāng)前的rsp即k上的000000341547b3b0 ,用 windbg 計(jì)算之后為:


0:117> ? 00000034`1547b3b0 ^ 0000d999`8c879750
Evaluate expression: 239339632076000 = 0000d9ad`99c024e0

  1. qword ptr [rbp-8],rax

將異或后的 安全值 塞到 rbp-8 的棧位置,這里的 rbp 由上面的匯編語句 mov rbp,rsp 賦值的,因?yàn)樯厦嬗腥齻€(gè)push加一個(gè)call,所以rbp應(yīng)該退掉4個(gè)0x8,最后計(jì)算的結(jié)果為棧位置000000341547b3f8 存的就是安全值,下面的輸出也可以確認(rèn)。


0:117> ? 00000034`1547b420-0x8-0x8-0x8-0x8
Evaluate expression: 223695320064 = 00000034`1547b400

0:117> dp 00000034`1547b400-8 L1
00000034`1547b3f8  0000d9ad`99c024e0

  1. clr!_security_check_cookie

在方法退出時(shí)需要通過 _security_check_cookie 方法來檢查cookie是否損壞,核心代碼為:


clr!RtlAllocateLUnicodeString+0xd2:
00007ffd`d09778f4 488b4df8        mov     rcx,qword ptr [rbp-8]
00007ffd`d09778f8 4833cc          xor     rcx,rsp
00007ffd`d09778fb e820a1feff      call    clr!_security_check_cookie (00007ffd`d0961a20)

經(jīng)過 windbg 計(jì)算 rcx=0000d9998c879750 ,即 _security_cookie 值。


0:117> dp 00000034`1547b400-8 L1
00000034`1547b3f8  0000d9ad`99c024e0

0:117> ? 0000d9ad`99c024e0 ^ 00000034`1547b3b0
Evaluate expression: 239253510920016 = 0000d999`8c879750

接下來拿著 rcx= 0000d9998c879750 去反匯編下 _security_check_cookie 函數(shù),簡(jiǎn)化后如下:


0:117> uf clr!_security_check_cookie
00007ffd`d0961a20 483b0de1d57700  cmp     rcx,qword ptr [clr!_security_cookie (00007ffd`d10df008)]
00007ffd`d0961a27 7510            jne     clr!_security_check_cookie+0x19 (00007ffd`d0961a39) 
00007ffd`d0961a29 48c1c110        rol     rcx,10h
00007ffd`d0961a2d 66f7c1ffff      test    cx,0FFFFh
00007ffd`d0961a32 7501            jne     clr!_security_check_cookie+0x15 (00007ffd`d0961a35) 
00007ffd`d0961a34 c3              ret
00007ffd`d0961a35 48c1c910        ror     rcx,10h
00007ffd`d0961a39 e962000000      jmp     clr!_report_gsfailure (00007ffd`d0961aa0) 
00007ffd`d0961aa0 48894c2408      mov     qword ptr [rsp+8],rcx
00007ffd`d0961aa5 4883ec38        sub     rsp,38h
00007ffd`d0961aa9 b917000000      mov     ecx,17h
00007ffd`d0961aae ff15e4fa5a00    call    qword ptr [clr!_imp_IsProcessorFeaturePresent (00007ffd`d0f11598)]
00007ffd`d0961ab4 85c0            test    eax,eax
00007ffd`d0961ab6 7407            je      clr!_report_gsfailure+0x1f (00007ffd`d0961abf) 
00007ffd`d0961ab8 b902000000      mov     ecx,2
00007ffd`d0961abd cd29            int     29h

代碼邏輯非常簡(jiǎn)單,還原成 C 大概如下:


void __fastcall _security_check_cookie(uintptr_t stackcookie)
{
	if ((stackcookie == __security_cookie) && (stackcookie高四位 == "0000")) {
		return;
	}
	else {
		_report_gsfailure()
	}
}

從C的邏輯看我們的 stackcookie=0000d9998c879750 完全滿足 if 條件,但不知道為什么會(huì)走到這個(gè) else 里面去,無法想象。。。所以定性為 靈異事件!!!

4. 故事后續(xù)

把所有的值都推算完了之后,在不可能走到 else 的情況下還是走到了 else,這個(gè)真的很讓人無語+費(fèi)解,過了幾天找朋友確認(rèn)的時(shí)候,朋友又反饋了一個(gè)信息,說電腦上的其他程序也會(huì)遇到這種情況,讓客戶重裝操作系統(tǒng),目前還沒遇到問題。

所以我覺得這個(gè)問題可能是 操作系統(tǒng)層面 的問題,或者是 硬件層面 的問題,而且程序的異常是在 clr 層面,用戶代碼是無法干涉的,程序中也沒有做 Pinvoke。

三:總結(jié)

一個(gè)是輻射導(dǎo)致的bit位翻轉(zhuǎn),一個(gè)是不可能走到else的地方走了else,各個(gè)奇奇怪怪的事情,讓我的高級(jí)調(diào)試之旅豐富多彩,大家覺得這個(gè)崩潰還有其他的可能性嗎?期待大家的留言。

總結(jié)

以上是生活随笔為你收集整理的记一次 .NET某股票交易软件 灵异崩溃分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。