記一次 .NET 某自動化采集軟件 崩潰分析

一:背景

1.講故事

前段時間有位朋友找到我,說他的程序在客戶的機器上跑著跑著會出現偶發卡死,然后就崩掉了,但在本地怎么也沒復現,dump也抓到了,讓我幫忙看下到底怎么回事,其實崩潰類的dump也有簡單的,也有非常復雜的,因為大多情況下都是非托管層面出現的各種故障,非常考驗對 C, C++, Win32 API 以及 匯編 的理解,所以能不能解決看運氣吧, 不管怎么說,先上 WinDbg。

二:WinDbg分析

1. 查找崩潰點

WinDbg 非常牛的地方在于它擁有一個自動化崩潰分析命令 !analyze -v,它的輸出信息非常有參考價值,所以嘗試一下看看。

0:136>?!analyze?-v
*******************************************************************************
*?????????????????????????????????????????????????????????????????????????????*
*????????????????????????Exception?Analysis???????????????????????????????????*
*?????????????????????????????????????????????????????????????????????????????*
*******************************************************************************
CONTEXT:??(.ecxr)
eax=00000000?ebx=00000000?ecx=00000000?edx=00000000?esi=00000003?edi=00000003
eip=777cf04c?esp=22dfd678?ebp=22dfd808?iopl=0?????????nv?up?ei?pl?nz?na?pe?nc
cs=0023??ss=002b??ds=002b??es=002b??fs=0053??gs=002b?????????????efl=00000206
ntdll!NtWaitForMultipleObjects+0xc:
777cf04c?c21400??????????ret?????14h
Resetting?default?scopeEXCEPTION_RECORD:??(.exr?-1)
ExceptionAddress:?0174ba6dExceptionCode:?00000000ExceptionFlags:?00000000
NumberParameters:?0PROCESS_NAME:??xxx.exeSTACK_TEXT:??
22dfd808?75b23b10?????00000003?22dfdc68?00000001?ntdll!NtWaitForMultipleObjects+0xc
22dfd808?75b23a08?????00000003?22dfdc68?00000000?KERNELBASE!WaitForMultipleObjectsEx+0xf0
22dfd824?672ff11a?????00000003?22dfdc68?00000000?KERNELBASE!WaitForMultipleObjects+0x18
22dfdca4?672ff3ac?????672dd150?672d0000?00000003?Faultrep!WerpReportFaultInternal+0x59e
22dfdcc4?672dd17d?????22dfdcec?708d0479?22dfdd60?Faultrep!WerpReportFault+0x9e
22dfdccc?708d0479?????22dfdd60?00000000?22dfdd60?Faultrep!ReportFault+0x2d
22dfdcec?708d07e9?????ec030e28?1c8f7728?00000003?clr!DoReportFault+0x43
22dfdd44?709f3c7e?????00000003?22dfe140?2e954594?clr!WatsonLastChance+0x19a
22dfe090?709f3d90?????ec0333f0?22dfe140?2e954594?clr!DoWatsonForUserBreak+0xc2
22dfe120?6fdc690f?????00000000?00000000?00000000?clr!DebugDebugger::Break+0xc9
22dfe148?0174ba6d?????00000000?00000000?00000000?mscorlib_ni!System.Diagnostics.Debugger.Break+0x57
WARNING:?Frame?IP?not?in?any?known?module.?Following?frames?may?be?wrong.
22dfe194?0174b58b?????00000000?00000000?00000000?0x174ba6d
22dfe1e8?0174b525?????00000000?00000000?00000000?mscorlib_ni!System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<<xxxAsync>d__10>+0x43
22dfe1e8?0174b525?????00000000?00000000?00000000?mscorlib_ni!System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<<xxxAsync>d__10>+0x43
22dfe22c?0174b3bd?????00000000?00000000?00000000?0x174b525
22dfe27c?0174b33b?????00000000?00000000?00000000?0x174b3bd
22dfe2d0?0174b2d5?????00000000?00000000?00000000?0x174b33b
...SYMBOL_NAME:??faultrep!WerpReportFaultInternal+59eMODULE_NAME:?FaultrepIMAGE_NAME:??Faultrep.dllSTACK_COMMAND:??~136s;?.ecxr?;?kb...

從卦中的調用棧看,有二個非常重要的信息。

  1. Debugger.Break()

這個是 C# 對 int 3 ?的封裝,即 斷點中斷異常,目的就是將程序的所有線程中斷。

  1. Faultrep!ReportFault()

這個是 WER 2.0 ,全稱為 Windows Error Reporting Service,用來抓崩潰dump的,前身是 Waston 醫生,在 Windows 服務列表中可以看到。

786d910bc1989bacfca437508a615d1b.png

還有一點, Faultrep.dll 是 WER 的一個組件,會在抓取過程中自動加載,我們用 lm 觀察進程中的 dll 列表。

0:136>?lm
start????end????????module?name
00fe0000?01034000???xxx?C?(service?symbols:?CLR?Symbols?without?PDB)????????
0c100000?0c123000???WINMMBASE???(deferred)?????????????
662d0000?662ef000???clrcompression???(deferred)???????????????????
672d0000?67327000???Faultrep???(pdb?symbols)??????????c:\mysymbols\FaultRep.pdb\E16126C7FB9849A8B9AC57D8D62CABB01\FaultRep.pdb
...

匯總以上信息,大概就能推測出代碼中用了 Debugger.Break() 函數,因為無catch處理,Windows 啟動了 WER 2.0,程序代碼在 ntdll!NtWaitForMultipleObjects 處等待第三方組件處理完畢,因為各種原因出現了問題導致無法返回最后崩潰。

通過卦中的信息我們大概知道了前因后果,但代碼中為什么會出現 Debugger.Break() 呢?這就需要我們繼續深挖。

2. 為什么會有 Debugger.Break()

剛才的輸出中有這么一段話: STACK_COMMAND: ~136s; .ecxr ; kb ,它可以讓我們找到異常前的調用棧,為了能看到托管棧,這里將 kb 改成 !clrstack

0:136>??~136s;?.ecxr?;?!clrstackOS?Thread?Id:?0x13ec?(136)
Child?SP???????IP?Call?Site
22dfe0ac?777cf04c?[HelperMethodFrame:?22dfe0ac]?System.Diagnostics.Debugger.BreakInternal()
22dfe128?6fdc690f?System.Diagnostics.Debugger.Break()?[f:\dd\ndp\clr\src\BCL\system\diagnostics\debugger.cs?@?65]
22dfe150?0174ba6d?xxx.xxx+d__10.MoveNext()
22dfe19c?0174b58b?System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[[xxx.xxx+d__10,?xxx.Abstractions]](d__10?ByRef)?[f:\dd\ndp\clr\src\BCL\system\runtime\compilerservices\AsyncMethodBuilder.cs?@?316]
22dfe1f0?0174b525?xxx.xxxAsync(System.String,?System.String)
22dfe238?0174b3bd?xxx.xxxProducer+d__7.MoveNext()
22dfe284?0174b33b?System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[[xxx.xxx+d__7,?xxx.Abstractions]](d__7?ByRef)
22dfe2d8?0174b2d5?xxx.xxx.xxx(System.String,?System.String)

從卦中看,貌似是在一個異步方法中手工調用了 Deubgger.Break() 方法,接下來我們觀察下源碼,由于比較隱私,這里就簡化一下。

internal?async?Task?xxxAsync(string?x1,?string?x2)
{if?(string.IsNullOrEmpty(x1)){Debugger.Break();return;}if?(string.IsNullOrEmpty(x2)){Debugger.Break();return;}...
}

這代碼果然有意思,在防御性編程中居然用 Debugger.Break() 來處理,比較少見。

找到了問題源頭,解決方法就簡單了,大概有兩種做法。

  1. 去掉 Debugger.Break() 語句

  2. 關閉 WER 2.0 服務

32398e66b4dcf1283b171eb99bf75100.png

3. 對 Debugger.Break() 的題外話

在 clr 源碼中有對 Debugger.Break() 非常詳細的注釋。

//?This?does?a?user?break,?triggered?by?System.Diagnostics.Debugger.Break,?or?the?IL?opcode?for?break.
//
//?Notes:
//????If?a?managed?debugger?is?attached,?this?should?send?the?managed?UserBreak?event.
//????Else?if?a?native?debugger?is?attached,?this?should?send?a?native?break?event?(kernel32!DebugBreak)
//????Else,?this?should?invoke?Watson.
//
//?Historical?trivia:
//?-?In?whidbey,?this?would?still?invoke?Watson?if?a?native-only?debugger?is?attached.
//?-?In?arrowhead,?the?managed?debugging?pipeline?switched?to?be?built?on?the?native?pipeline.
FCIMPL0(void,?DebugDebugger::Break)
{...
}
FCIMPLEND

注釋文本:Else, this should invoke Watson 中的 Watson 其實就是本篇聊到的 WER,觀察反匯編其實就是對 int 3 的封裝。

0:136>?uf?kernelBase!DebugBreak
KERNELBASE!DebugBreak:
75ba5e40?8bff????????????mov?????edi,edi
75ba5e42?cc??????????????int?????3
75ba5e43?c3??????????????ret

在很多反調試機制中,經常會用 int 3 來檢測當前程序是否被附加了調試器,參考如下 C++ 代碼。

#include?<iostream>int?isAttach?=?0;int?main()
{__try{__asm?{int?3}isAttach?=?1;}__except(1){isAttach?=?0;}if?(isAttach)?{printf("不好,發現有調試器?...");}else?{printf("哈哈,一切正常!");}getchar();
}

如果你用 WinDbg 附加上去, 就會被程序檢測到,截圖如下:

e9b3f471a1afb433e57286d07330a2fc.png

如果是正常運行,會是如下界面

07e072e8fab69afbcb52e78ce11c1986.png

可以在 C# 中通過 Pinvoke 引入,這種動態方式,反反調試會有不小的難度。

三:總結

這次事故是朋友在開發過程中為了方便調試,使用了 Debugger.Break() 方法,但在生產環境下并沒有刪除,導致在某些客戶機器上因為 WER 的開啟,被 Waston 捕獲導致的事故。

本次教訓是:發給客戶的版本,內含的調試信息該關閉的一定要關閉,以免生出此亂。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281125.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281125.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281125.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

onlyoffice修改字號

原文同步自作者博客&#xff1a;https://www.daxueyiwu.com/post/758 :/var/www/onlyoffice/documentserver/web-apps/apps/documenteditor/main/app.js 里找到{value:22,displayValue:"22"} 把displayValue對應的值換成漢字字體 小二等 其實中文數字&#xff08;字…

大數據

大數據技術的快速發展&#xff0c;對現如今人們的思維方式產生了巨大的改變。 首先&#xff0c;大數據的發展&#xff0c;改善了人們思維的局限性。在過去&#xff0c;數據流通速度慢&#xff0c;人們獲取的數據資源有限&#xff0c;所以在看待事物方面&#xff0c;基于過去固有…

如何在 .NET MAUI 中加載 json 文件?

引言:按.NET core傳統方式添加 AddJsonFile("appsettings.json") 在windows平臺和ssr工作正常,但是在 ios 和 android 無法用這種方式,因為資源生成方式不一樣. 使用內置資源方式不夠靈活而且 ios 平臺會提示不能復制 json 文件到目錄,于是進行了幾天的研究,終于能正…

onlyOfice取消上傳文件大小的限制

原文同步自作者博客&#xff1a;https://www.daxueyiwu.com/post/757 使用onlyOfice的時候&#xff0c;在打開的文件中&#xff0c;對文件的大小有限制的&#xff0c;可以在服務中修改被限制的大小&#xff0c;在服務上有/etc/onlyoffice/documentserver/default.json的文件&a…

SSH整合注解版(Spring+Struts2+Hibernate)

整體架構&#xff1a; pom.xml 引入maven節點&#xff1a; <dependencies><!--單測--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.3</version><scope>test</scope><…

定時插座動一下就斷_使用插座定時器在某些時候自動將您的Amazon Echo靜音

定時插座動一下就斷The Amazon Echo is an always-listening voice-controlled virtual assistant, but if there are times you’d rather not listen (or be listened to) by the Echo, here’s how to automatically mute it at certain times of the day. Amazon Echo是一個…

周末讀書:《紅樓夢》

【周末讀書】| 作者/Edison大家好&#xff0c;我是Edison。古人曾說“開談不說紅樓夢&#xff0c;讀盡詩書也枉然”&#xff0c;剛好最近我爸開始在閱讀《紅樓夢》&#xff0c;我想起當年看了兩遍《紅樓夢》原著和一遍87版《紅樓夢》電視劇的場景。本文是我首發于2018年的一篇讀…

onlyoffice啟用HTTPS

原文同步自作者博客&#xff1a;https://www.daxueyiwu.com/post/765 HTTPS需要使用SSL證書&#xff0c;可以自己簽發也可以用ca機構簽發的&#xff0c;加密效果相同。 生成證書&#xff1a; 創建私鑰 openssl genrsa -out onlyoffice.key 2048 創建CSR openssl req -new -k…

Oracle-邏輯體系結構

這里指數據文件的邏輯體系結構&#xff0c;包括1.表空間(TABLESPACE) 2.段(SEGMENT) 3.區(EXTENT) 4.塊(BLOCK) 數據庫(Database)由若干表空間(TABLESPACE)組成&#xff0c;表空間由若干段(SEGMENT)組成&#xff0c;段由若干區(EXTENT)組成&#xff0c;區由若干塊(BLOCK)組成…

win10下用docker安裝onlyoffice服務

原文同步自作者博客&#xff1a;https://www.daxueyiwu.com/post/699 1. 使用DockerToolbox安裝docker 1.1 DockerToolbox下載地址 DockerToolbox-19.03.1 GitHub上下載實在是太慢了。 我找了好久終于下載下來了&#xff0c;在這里分享一下&#xff01; 網盤下載&#xff1…

chromebook刷機_如何從Chromebook上的APK側面加載Android應用

chromebook刷機Chromebooks can now download and install Android apps from Google Play, and it works pretty well. But not every Android app is available in Google Play. Some apps are available from outside Google Play as APK files, and you can install them o…

速度和性能狂卷,.NET 7來了

.NET 作為一個免費的跨平臺開放源代碼開發人員平臺&#xff0c;這些年在不斷的升級完善。就在最近&#xff0c;史上最快最強的.net平臺.NET 7于2022年11月8日正式發布, .NET 朝著更好的???邁進了?步&#xff01;那么&#xff0c;.NET 7 有什么新東西&#xff1f;.NET 7 建立…

前端JavaScript規范

摘要&#xff1a; JavaScript規范 目錄 類型 對象 數組 字符串 函數 屬性 變量 條件表達式和等號 塊 注釋 空白 逗號 分號 類型轉換 命名約定 存取器 構造器 事件 模塊 jQuery ES5 兼容性 HTML、CSS、JavaScript分離 使用jsHint 前端工具 類型 原始值: 相當于傳值(JavaScript對…

修改onlyoffice存儲為手動存儲關閉瀏覽器時不進行保存

原文同步自作者博客&#xff1a;https://www.daxueyiwu.com/post/704 相關官方API地址&#xff1a; 文件保存 回調處理程序 配置-編輯-定制-自動保存 配置-編輯-定制-forcesave 需要將: config.editorConfig.customization.forcesave改為true, 并且config.editorConfig.…

如何使用NVIDIA ShadowPlay錄制PC游戲

NVIDIA’s ShadowPlay, now known as NVIDIA Share, offers easy gameplay recording, live streaming, and even an FPS counter overlay. It can automatically record gameplay in the background–just on the PlayStation 4 and Xbox One–or only record gameplay when y…

.Net 7 的 R2R,Crossgen2是什么?

楔子來下這些概念R22,Crossgen2這兩個東西&#xff0c;跟前面講的AOT和CLR有異曲同工之妙&#xff0c;到底什么呢&#xff1f;本篇來看下。R2RR2R(ReadyToRun),是一種結合了AOT和CLR編譯模式&#xff0c;取其優點&#xff0c;拋其缺點的一種編譯方式。具體的呢&#xff0c;R2R包…

Java流

流分類 字節流字符流輸入流InputStreamReader輸出流OutputStream WriterInputStream:BufferedInputStream、DataInputStream、ObjectInputStreamOutputStream:BufferedOutputStream、DataOutputStream、ObjectOutputStream、PrintStream 標準流: System.in 、Syst…

Win7安裝OnlyOffice(不使用Docker)

原文同步自作者博客&#xff1a;https://www.daxueyiwu.com/post/741 1、安裝準備 &#xff08;1&#xff09;安裝Elang&#xff1a; 【注意事項】 a)Elang是為了給RabbitMQ使用的&#xff0c;因此在安裝Elang之前應確定RabbitMQ的版本及其所需的Elang版本。RabbitMQ的地址…

geek_享受How-To Geek用戶樣式腳本的好處

geekMost people may not be aware of it but there are two user style scripts that have been created just for use with the How-To Geek website. If you are curious then join us as we look at these two scripts at work. 大多數人可能不知道它&#xff0c;但是已經創…

.NET Core統一參數校驗、異常處理、結果返回

我們開發接口時&#xff0c;一般都會涉及到參數校驗、異常處理、封裝結果返回等處理。如果每個后端開發在參數校驗、異常處理等都是各寫各的&#xff0c;沒有統一處理的話&#xff0c;代碼就不優雅&#xff0c;也不容易維護。所以&#xff0c;我們需要統一校驗參數&#xff0c;…