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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

记一次 .NET 某发证机系统 崩溃分析

發布時間:2025/6/17 编程问答 11 如意码农
生活随笔 收集整理的這篇文章主要介紹了 记一次 .NET 某发证机系统 崩溃分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一:背景

1. 講故事

前些天有位朋友在微信上找到我,說他的系統有偶發崩潰,自己也沒找到原因,讓我幫忙看下怎么回事,我分析dump一直都是免費的,畢竟對這些東西挺感興趣,有問題可以直接call我,好了,接下來我們就來分析dump吧。

二:程序為什么會崩

1. 觀察崩潰上下文

windbg有一個厲害之處在于雙擊dump之后會自動定位到崩潰的線程,然后通過 .ecxr; k10 命令就可以看到崩潰點了,輸出如下:


0:083> .ecxr; k10
rax=000000004bdefa50 rbx=00000c45ea960c80 rcx=000000ffffffffff
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=00000000773da365 rsp=0000000046d0fb50 rbp=000000004bde28d0
r8=000000004bde28c0 r9=0000000000000001 r10=0000000000000000
r11=0000000000000206 r12=00000000006b0000 r13=000000004bde2950
r14=0000000000000000 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=00010202
ntdll!RtlFreeHeap+0x1a5:
00000000`773da365 488b7b08 mov rdi,qword ptr [rbx+8] ds:00000c45`ea960c88=????????????????
# Child-SP RetAddr Call Site
00 00000000`46d0fb50 000007fe`feda10c8 ntdll!RtlFreeHeap+0x1a5
01 00000000`46d0fbd0 000007fe`ee66f126 msvcrt!free+0x1c
02 00000000`46d0fc00 000007fe`ee6556ae ksproxy!CStandardInterfaceHandler::KsCompleteIo+0x4e6
03 00000000`46d0fce0 000007fe`ee66bf5c ksproxy!CKsOutputPin::OutputPinBufferHandler+0x1e
04 00000000`46d0fd10 00000000`771a556d ksproxy!CAsyncItemHandler::AsyncItemProc+0x20c
05 00000000`46d0fd70 00000000`7740372d kernel32!BaseThreadInitThunk+0xd
06 00000000`46d0fda0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d

從卦中可以看到,程序崩潰在 RtlFreeHeap 函數中,熟悉這玩意的朋友應該知道它是用來釋放 堆塊 的,簽名如下:


NTSYSAPI LOGICAL RtlFreeHeap(
[in] PVOID HeapHandle,
[in, optional] ULONG Flags,
_Frees_ptr_opt_ PVOID BaseAddress
);

接下來就是尋找該堆塊的首地址 BaseAddress,即 r8 寄存器值,使用 uf ntdll!RtlFreeHeap 即可,輸出如下:


0:083> uf ntdll!RtlFreeHeap
ntdll!RtlFreeHeap:
00000000`773da1c0 4053 push rbx
00000000`773da1c2 55 push rbp
00000000`773da1c3 56 push rsi
00000000`773da1c4 57 push rdi
00000000`773da1c5 4154 push r12
00000000`773da1c7 4883ec50 sub rsp,50h
00000000`773da1cb 33f6 xor esi,esi
00000000`773da1cd 498be8 mov rbp,r8
00000000`773da1d0 8bfa mov edi,edx
00000000`773da1d2 4c8be1 mov r12,rcx
00000000`773da1d5 488bde mov rbx,rsi
00000000`773da1d8 4d85c0 test r8,r8
...
ntdll!RtlFreeHeap+0x179:
00000000`773da339 498b4008 mov rax,qword ptr [r8+8]
00000000`773da33d 498bd8 mov rbx,r8
00000000`773da340 48b9ffffffffff000000 mov rcx,0FFFFFFFFFFh
00000000`773da34a 4933dc xor rbx,r12
00000000`773da34d 4823c1 and rax,rcx
00000000`773da350 48c1eb04 shr rbx,4
00000000`773da354 4833d8 xor rbx,rax
00000000`773da357 48331d3a321000 xor rbx,qword ptr [ntdll!RtlpLFHKey (00000000`774dd598)]
00000000`773da35e 48c1e304 shl rbx,4
00000000`773da362 0f0d0b prefetchw [rbx]
00000000`773da365 488b7b08 mov rdi,qword ptr [rbx+8]

根據卦中的匯編代碼 mov rbp,r8 ,看樣子是 rbp 保存了 BaseAddress 地址,接下來使用 !heap -x 000000004bde28d0 看看到底啥情況,輸出如下:


0:083> !heap -x 000000004bde28d0
SEGMENT HEAP ERROR: failed to initialize the extention
List corrupted: (Blink->Flink = 0000000000000000) != (Block = 000000004bde28c0)
HEAP 00000000006b0000 (Seg 000000004bde0000) At 000000004bde28b0 Error: block list entry corrupted List corrupted: (Flink->Blink = 900000004bdefa50) != (Block = 000000004bdefa50)
HEAP 00000000006b0000 (Seg 000000004bde0000) At 000000004bdefa40 Error: block list entry corrupted Entry User Heap Segment Size PrevSize Unused Flags
-------------------------------------------------------------------------------------------------------------
000000004bde28b0 000000004bde28c0 00000000006b0000 000000004bde0000 3740 800 0 free

從卦中可以看到,當前的 000000004bde28c0 是一個 free 堆塊,同時也拋了一個 堆塊列表 的損壞錯誤,這就有點意思了。。。

2. doublefree 導致的嗎

熟悉 win32 的朋友應該知道,在已經 free 的塊上再次調用 RtlFreeHeap 釋放會是一個經典的 doublefree,貌似這個問題已經定位了。。。但如果你修車經驗豐富的話,你應該知道 堆管理器 檢測到 doublefree 的時候會是這樣的調用棧記一次 .NET 某醫療住院系統 崩潰分析, 參考如下:


0:090> !heap -s
Details: Heap address: 000001c14fd20000
Error address: 000001ce25531c50
Error type: HEAP_FAILURE_BLOCK_NOT_BUSY
Details: The caller performed an operation (such as a free
or a size check) that is illegal on a free block.
Follow-up: Check the error's stack trace to find the culprit. Stack trace:
Stack trace at 0x00007ffed7b82848
00007ffed7abe109: ntdll!RtlpLogHeapFailure+0x45
00007ffed7acbb0e: ntdll!RtlFreeHeap+0x9d3ce
00007ffeb093276f: OraOps12!ssmem_free+0xf
00007ffeb0943077: OraOps12!OpsMetFreeValCtx+0xd7
00007ffeb093cdd8: OraOps12!OpsDacDispose+0x2b8
00007ffe655e4374: +0x655e4374
...

而我們這個dump是訪問違例,雖然這個dump必崩無疑,但這段邏輯此時還沒執行到,也就是在這塊邏輯之前就崩掉了,那為什么會崩掉呢?到底經歷了何樣的驚魂時刻。。。

3. 突破口在哪里

要想尋找突破口,就得理解下面的這兩句了,再次輸出一下吧。


List corrupted: (Blink->Flink = 0000000000000000) != (Block = 000000004bde28c0)
HEAP 00000000006b0000 (Seg 000000004bde0000) At 000000004bde28b0 Error: block list entry corrupted List corrupted: (Flink->Blink = 900000004bdefa50) != (Block = 000000004bdefa50)
HEAP 00000000006b0000 (Seg 000000004bde0000) At 000000004bdefa40 Error: block list entry corrupted

要理解這個,需要你對 _HEAP 結構有一個深度的理解,這個在我的 .NET高級調試訓練營 里有一個系統的解讀。

大家要知道 堆管理器 對 Free 的管理采用的是 雙向鏈表 的方式,其中 Flink 表示下一個(Forward)節點,BLink 表示前一個(Backward)結點,有朋友搞不清的話,我畫個簡圖。

有了簡圖之后,接下來逐個解讀下:

  • (Blink->Flink = 0000000000000000) != (Block = 000000004bde28c0)

這是經典的 一去一回 ,結果發現不再是自己了。。。即 0000000000000000 != 000000004bde28c0,我們用 ntdll!_LIST_ENTRY 來具象化一下,截圖如下:

從卦中可以看到 Blink = 0x900000004bdefa50 時就報錯了,由于報錯windbg 就將結果顯示為 0000000000000000,所以這一來一回居然不等于自己,所以堆管理器就覺得很奇葩。。。

  • (Flink->Blink = 900000004bdefa50) != (Block = 000000004bdefa50)

這是經典的 一回一去,結果發現 Blink 不對。。。本來應該是 0x000000004bdefa50 結果是 0x900000004bdefa50 截圖如下:

到這里我相信很多人會有一個疑問,我也沒看到 0x000000004bdefa50 地址呀,憑什么說0x900000004bdefa50 的前身是 0x000000004bdefa50

要想找到這個答案,又是考你的 堆管理器 知識,所有的 free 都掛在 FreeLists 字段里,同樣也是采用 雙向鏈表 的方式,輸出如下:


0:083> dt nt!_HEAP 00000000006b0000 -y FreeLists
ntdll!_HEAP
+0x158 FreeLists : _LIST_ENTRY [ 0x00000000`1f1d7f90 - 0x00000000`1f23dbf0 ]

接下來寫一段簡單的腳本把這個list給遍歷下,看看 0x000000004bde28c0 的BLink結點是不是 0x000000004bdefa50 即可,腳本如下:


$$ $$>a< D:\debugging\18.20250506\src\Example\scripts\while2.txt
r @$t0 = 0x00000000006b0000 ; r @$t1 = poi(@$t0+0x158) ; $$ Flink
r @$t2 = poi(@$t0+0x158+8); $$ Blink .if (@$t1 == @$t2)
{
.echo "@$t0+0x158 list is empty"
}
.else
{
.echo "Walking @$t0+0x128 list..." r @$t3 = @$t0+0x158
r @$t4 = @$t1 .while (@$t4 != @$t3)
{
.printf "Entry at %p\n", @$t4
r @$t4 = poi(@$t4)
} .echo "End of list reached"
}

哈哈,睜大眼睛看下卦哦,真的是 000000004bdefa50,而不是 0x900000004bdefa50,到這里基本就搞清楚了,由于地址的變化 000000004bdefa50 -> 0x900000004bdefa50 導致 雙向鏈表 斷裂,當 RtlFreeHeap 在解碼這個錯誤的內存地址時,導致程序的崩潰,同樣你了解底層的話,你會發現用戶態怎么可能會有 0x900000004bdefa50 這樣的內存地址呢???

4. 為什么地址變化了

這個問題真的問到我了,因為我也不知道為什么地址 突變了, 原因是我在 000000004bde28c0 周圍也沒發現有越界寫入的情況,為啥高3128位就硬生生的由0變1了,輸出如下:


0:083> dp 000000004bde28b0
00000000`4bde28b0 00000000`00000000 0001a08c`44153f2e
00000000`4bde28c0 00000000`4bdf79e0 90000000`4bdefa50
00000000`4bde28d0 00000000`00000080 00000000`00000000 0:083> .formats 90000000`4bdefa50
Binary: 10010000 00000000 00000000 00000000 01001011 11011110 11111010 01010000

最后就是這種問題該如何解決呢?只能開啟 頁堆,可以用 Application Verifier 工具,截圖如下:

能不能找到就看個人造化了,如何真的找不到,就當是神奇的 bit位翻轉 吧,建議換機器嘗試,或上 ECC 糾錯的內存條。。。

三:總結

這次生產事故非常考察你對 Windows 堆管理器 的深度理解,這塊在我的訓練營里有系統而深入的講解,dump分析就是這樣的有趣,各種迷惑和幻境,全靠扎實的底層功力和豐富的經驗來沖出迷霧!

總結

以上是生活随笔為你收集整理的记一次 .NET 某发证机系统 崩溃分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩第一视频 | 在线无| 50度灰在线| 日韩三级在线播放 | 日韩欧美的一区二区 | 国产天堂av | 成年人在线免费 | 国产农村妇女毛片精品久久麻豆 | 一区二区91 | 久久久一二三区 | 国产免费福利视频 | 成人欧美一区二区三区白人 | 青青草在线免费视频 | 自拍偷拍在线视频 | 熟妇高潮喷沈阳45熟妇高潮喷 | 国产日本欧美在线观看 | 成人午夜福利视频 | 国产又粗又大又长 | 黄色片视频网站 | 国产欧美一区二区三区在线老狼 | 亚洲伦理精品 | 欧美日韩3p | 精品人妻无码专区在线 | 国产精品国产三级国产三级人妇 | 日韩无遮挡 | 浪荡奴双性跪着伺候 | 国产一级二级三级在线观看 | 免费成人小视频 | 成av人在线观看 | 日日插日日操 | 男女羞羞的视频 | 狠狠干在线 | 香蕉在线观看视频 | 婷婷爱五月天 | 国产成人精品免费视频 | 天天看片天天爽 | www.999av| www.4虎| 国产亚洲av综合人人澡精品 | 少妇一级淫片免费观看 | 交专区videossex农村 | 91久久国产视频 | 极品蜜桃臀肥臀-x88av | 日韩在线观看视频一区二区 | 欧美三级影院 | 亚洲在线观看av | 锦绣未央在线观看 | 国产黄a三级三级三级看三级男男 | 午夜欧美成人 | 日韩99| 精品无码一区二区三区蜜臀 | 人禽高h交| 午夜福利理论片在线观看 | 涩涩涩综合| 国产女同91疯狂高潮互磨 | 影音先锋美女 | 免费的一级黄色片 | 婷久久| 欧美日韩国产91 | 亚洲com | 天堂无乱码 | 久久中文字幕无码 | 欧美一级片一区 | 西西4444www大胆无码 | 亚州激情视频 | 国产ts网站 | 成人在线网 | 成人免费看类便视频 | 国产区在线 | 欧美精品一线 | 日本在线观看一区二区 | 无码人妻精品一区二区50 | a级免费网站 | 伊人av综合 | 成人视频在线观看 | 91av中文字幕 | 丰满少妇一区 | 亚洲精品国产精品乱码不卡√香蕉 | 天天干人人干 | 一本久久综合亚洲鲁鲁五月天 | 这里只有精品免费视频 | 久艹在线播放 | 天天综合天天添夜夜添狠狠添 | 久草网在线观看 | 成人人伦一区二区三区 | 肉色超薄丝袜脚交一区二区图片 | av免费观看网址 | a级片在线 | 什么网站可以看毛片 | 99久久一区二区 | 艳母免费在线观看 | 青草青青视频 | 五月情网| 人操人人 | 久久美| 黄色片子一级 | 国产伦精品视频一区二区三区 | 成熟妇人a片免费看网站 | 短裙公车被强好爽h吃奶视频 |