記一次 .NET 某企業 ERP網站系統 崩潰分析

来源:https://www.cnblogs.com/huangxincheng/archive/2023/03/27/17260332.html
-Advertisement-
Play Games

一:背景 1. 講故事 前段時間收到了一個朋友的求助,說他的ERP網站系統會出現偶發性崩潰,找了好久也沒找到是什麼原因,讓我幫忙看下,其實崩潰好說,用 procdump 自動抓一個就好,拿到 dump 之後,接下來就是一頓分析了。 二:WinDbg 分析 1. 是什麼導致的崩潰 windbg 有一個 ...


一:背景

1. 講故事

前段時間收到了一個朋友的求助,說他的ERP網站系統會出現偶發性崩潰,找了好久也沒找到是什麼原因,讓我幫忙看下,其實崩潰好說,用 procdump 自動抓一個就好,拿到 dump 之後,接下來就是一頓分析了。

二:WinDbg 分析

1. 是什麼導致的崩潰

windbg 有一個自動化的分析命令 !analyze -v 可以幫我們提前預診一下,就好像進醫院先在問詢台那裡過一下。


0:019> !analyze -v
CONTEXT:  (.ecxr)
eax=14c9cd00 ebx=00000000 ecx=00000000 edx=00000000 esi=00000000 edi=14c9d664
eip=682a024a esp=14c9cfd4 ebp=14c9d018 iopl=0         nv up ei pl nz ac po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000212
msvcr90!fprintf+0x34:
682a024a 83c414          add     esp,14h
Resetting default scope

EXCEPTION_RECORD:  (.exr -1)
ExceptionAddress: 682a024a (msvcr90!fprintf+0x00000034)
   ExceptionCode: c0000417
  ExceptionFlags: 00000001
NumberParameters: 0

PROCESS_NAME:  w3wp.exe

ERROR_CODE: (NTSTATUS) 0xc0000417 -    C

EXCEPTION_CODE_STR:  c0000417

STACK_TEXT:  
14c9d018 1766013b     00000000 176d9c60 17def1a8 msvcr90!fprintf+0x34
WARNING: Stack unwind information not available. Following frames may be wrong.
14c9d664 454c5153     75636578 203a6574 5332347b satrda!Writer_Write+0x4bb
000000c8 75636578     203a6574 5332347b 207d3230 0x454c5153
000000c8 17673623     17d538e8 17ded730 00000001 crypt32!profapi_NULL_THUNK_DATA_DLA <PERF> (crypt32+0x126578)
00000009 176604b6     14c9d74c 17ded730 17dae9c8 satrda!SATRDA_Proto_UnitTest+0x6c93
ffffffff 17654012     17dae9c8 17d538e8 17ded730 satrda!Writer_Write+0x836
17dae9c8 665fe072     14c9d74c 00000001 1765405b satrda!ConfigDSN+0xd0c2
...
160a0000 00000000     00000000 00000000 00000000 0x7071e31

FAULTING_SOURCE_LINE:  f:\dd\vctools\crt_bld\self_x86\crt\src\fprintf.c

FAULTING_SOURCE_FILE:  f:\dd\vctools\crt_bld\self_x86\crt\src\fprintf.c

FAULTING_SOURCE_LINE_NUMBER:  55

FAULTING_SOURCE_CODE:  
No source found for 'f:\dd\vctools\crt_bld\self_x86\crt\src\fprintf.c'


SYMBOL_NAME:  msvcr90!fprintf+34

MODULE_NAME: msvcr90

IMAGE_NAME:  msvcr90.dll

STACK_COMMAND:  ~19s; .ecxr ; kb

FAILURE_BUCKET_ID:  INVALID_CRUNTIME_PARAMETER_c0000417_msvcr90.dll!fprintf

從錯誤信息看,問題是出在 satrda.dll 這個第三方庫,趕緊網上搜一下是這是何方神聖。

看樣子是一個連接資料庫的商業組件,接下來看下 FAILURE_BUCKET_ID: INVALID_CRUNTIME_PARAMETER_c0000417_msvcr90.dll!fprintf 信息,可以發現因為在調用 fprintf 函數時出現了參數錯誤,到這裡我們將包圍圈極大的收縮了。

2. 為什麼會出現參數錯誤

熟悉 C 語言 fprintf 函數的朋友都知道,它是用來向 文件 寫入數據的,類似 C# 的 WriteFile,既然報了參數異常,那就說明肯定在參數上出了問題,接下來看下它的簽名。


int fprintf(
   FILE *stream,
   const char *format [,
   argument ]...
);

有了這些基礎之後切到 19 號線程觀察下它的調用棧。


0:019> ~19s; .ecxr ; kb 10
eax=14c9cd00 ebx=00000000 ecx=00000000 edx=00000000 esi=00000000 edi=14c9d664
eip=682a024a esp=14c9cfd4 ebp=14c9d018 iopl=0         nv up ei pl nz ac po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000212
msvcr90!fprintf+0x34:
682a024a 83c414          add     esp,14h
 # ChildEBP RetAddr      Args to Child              
00 14c9d018 1766013b     00000000 176d9c60 17def1a8 msvcr90!fprintf+0x34 [f:\dd\vctools\crt_bld\self_x86\crt\src\fprintf.c @ 55] 
WARNING: Stack unwind information not available. Following frames may be wrong.
01 14c9d664 454c5153     75636578 203a6574 5332347b satrda!Writer_Write+0x4bb
02 000000c8 75636578     203a6574 5332347b 207d3230 0x454c5153
03 000000c8 17673623     17d538e8 17ded730 00000001 crypt32!profapi_NULL_THUNK_DATA_DLA <PERF> (crypt32+0x126578)
04 00000009 176604b6     14c9d74c 17ded730 17dae9c8 satrda!SATRDA_Proto_UnitTest+0x6c93
05 ffffffff 17654012     17dae9c8 17d538e8 17ded730 satrda!Writer_Write+0x836
06 17dae9c8 665fe072     14c9d74c 00000001 1765405b satrda!ConfigDSN+0xd0c2
07 17ded730 63207463     2c44492e 6f532e63 632c7472 clr!CompressDebugInfo::CompressBoundariesAndVars+0x2d0
08 656c6573 2c44492e     6f532e63 632c7472 7261502e 0x63207463
09 656c6573 6f532e63     632c7472 7261502e 49746e65 0x2c44492e
0a 656c6573 69482e63     6e656464 4c2e632c 6c657665 Microsoft_Build_Tasks_v4_0_ni+0x2f2e63
0b 2c687461 6e656464     4c2e632c 6c657665 64646948 System_ServiceModel_Web_ni+0xf2e63
0c 69482e63 4c2e632c     6c657665 64646948 632c6e65 System_Runtime_Serialization_ni+0x226464
0d 6e656464 6c657665     64646948 632c6e65 6d6f432e 0x4c2e632c
0e 6e656464 64646948     632c6e65 6d6f432e 656e6f70 System_ServiceModel_ni+0x537665
0f 6c657665 632c6e65     6d6f432e 656e6f70 632c746e 0x64646948

從線程棧來看 msvcr90!fprintf 函數的第一個參數居然是 00000000 ,也就是說 *stream 這個參數為 NULL,難怪說參數異常!

3. 為什麼 stream 為空

熟悉 C 的朋友應該知道 *stream 參數是通過 fopen 函數得到的,可能有些朋友有點混,這裡就寫個簡單的模型吧。


int main()
{
	FILE* pFile;
	int n;
	char name[100];

	pFile = fopen("D:\\dumps\\myfile2.txt", "w");

	gets_s(name, 100);

	fprintf(pFile, "%s", name);

	fclose(pFile);

	return 0;
}

接下來我們到 dump 中尋找一下 fopen 函數,這個線上程棧上是沒有了,先提取出 msvcr90!fprintf+0x34 中的 RetAddr=1766013b 返回值地址到彙編視窗查找,截圖如下:

從圖中可以看到,esi 是 eax 給的,而 eax 是 call 返回值給的,不出意外 176D727Ch 中存的就是 fopen 函數,輸出如下:


0:019> u poi(176D727Ch)
msvcr90!fopen [f:\dd\vctools\crt_bld\self_x86\crt\src\fopen.c @ 123]:
682a01a2 8bff            mov     edi,edi
682a01a4 55              push    ebp
682a01a5 8bec            mov     ebp,esp
682a01a7 6a40            push    40h
682a01a9 ff750c          push    dword ptr [ebp+0Ch]
682a01ac ff7508          push    dword ptr [ebp+8]
682a01af e825ffffff      call    msvcr90!_fsopen (682a00d9)
682a01b4 83c40c          add     esp,0Ch

接下來我們需要提取 fopen 中的兩個參數,截圖如下:

第二個參數很好獲取就是 176D9C60h 的 ascii 表示,第一個參數獲取起來就麻煩了,我們需要詳細的如圖那樣推測當時的 esp 指向的位置。


0:019> da poi(14c9d02c+0x5c)
17def0e0  "log/20220810.txt"
0:019> da 176D9C64h
176d9c64  "at++"

還原成 C 代碼大概就是:


FILE*  pFile = fopen("log/20220810.txt", "at++");

代碼大概是恢復出來了,那為什麼會拋異常呢? windbg 有一個 !gle 命令可以查看當時發生了什麼錯誤。


0:019> !gle
LastErrorValue: (NTSTATUS) 0 (0) - STATUS_SUCCESS
LastStatusValue: (NTSTATUS) 0xc000003a - {            }       %hs

接下來到微軟的官方文檔:https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55 找一下這個 3a 到底表示啥意思,截圖如下:

從圖中看,原來是路徑不存在的錯誤,應該就是沒找到 20220810.txt 這個文件。

到這裡就基本弄清楚了來龍去脈,應該是朋友的伺服器有意或者無意清理了由 satrda 生成的20220810.txt文件,引發 satrda.dll 找不到文件路徑導致的程式崩潰,將這些信息提供給朋友之後,讓朋友去找 satrda 官網去瞭解下詳情,畢竟官方纔是最清楚的。

三:總結

這次事故是由於 satrda 層面找不到文件路徑導致的程式崩潰,據朋友說在 C# 層面沒收到這種C++異常,確實當 C# 和 C++ 產生交互時經常會有各種奇怪的問題,我無意刪除你的,你無意干擾我的,大家都好自為之吧

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 基於.NET Core + Jquery實現文件斷點分片上傳 前言 該項目是基於.NET Core 和 Jquery實現的文件分片上傳,沒有經過測試,因為博主沒有那麼大的文件去測試,目前上傳2G左右的文件是沒有問題的。 使用到的技術 Redis緩存技術 Jquery ajax請求技術 為什麼要用到R ...
  • 1. 重寫和覆蓋的定義 1.1 重寫(override)的定義 在C#中,用override關鍵字來重寫一個父類中的虛方法或抽象方法。override關鍵字用於指示編譯器,我要用派生類中的一個方法,重寫基類中的同名方法。通過重寫基類中的方法,可以實現多態性。有關重寫與虛方法和抽象方法的詳細示例,可移 ...
  • 1. 多態性定義 C#中的多態性是OOP(面向對象編程)的一個基本概念,它允許一個對象在不同情況下表現出不同的行為,以增強代碼的可重用性和靈活性。 根據網上的教程,我們得知C#多態性分為兩類,靜態和動態。但實際上,C#沒有嚴格的靜態和動態多態性的分法。之所以這麼分,還是為了我們便於理解,我們沿用這個 ...
  • 1. 抽象方法與虛方法的區別 先說兩者最大的區別:抽象方法是需要子類去實現的。虛方法是已經實現了的,可以被子類覆蓋,也可以不覆蓋,取決於需求。因為抽象類無法實例化,所以抽象方法沒有辦法被調用,也就是說抽象方法永遠不可能被實現。 如果需要瞭解虛方法及抽象方法具體的定義和語句,請移步:C#多態性學習,虛 ...
  • 前段時間小編同事面試遇到了這個問題,由於同事比較菜並未很完美的完成這個問題,本文就替小編來解答一下。在C#中有多種方式類遍歷指定文件夾中的文件,本文將介紹三種方式。 一、使用Directory類的GetFiles方法: 示例代碼如下: string[] files = Directory.GetFi ...
  • PDF/A是一種ISO標準的PDF文件格式版本,是為長期保存文件而設計的。它提供了一種工具,使電子文件在長時間之後依然以一種保留其外觀的方式重現,而不管該文件是用什麼工具和系統創建、儲存或製作的。這種保留方式使PDF文件可自我持續。PDF/A通過嵌入在文檔自身內部顯示該文檔的信息(內容、顏色、字體、 ...
  • 本文屬於OData系列 目錄 武裝你的WEBAPI-OData入門 武裝你的WEBAPI-OData便捷查詢 武裝你的WEBAPI-OData分頁查詢 武裝你的WEBAPI-OData資源更新Delta 武裝你的WEBAPI-OData之EDM 武裝你的WEBAPI-OData常見問題 武裝你的WE ...
  • 一、前言 在最近的項目開發中,涉及到瞭解析DICOM文件。根據百度百科可知,DICOM(Digital Imaging and Communications in Medicine)即醫學數字成像和通信,是醫學圖像和相關信息的國際標準(ISO 12052)。它定義了質量能滿足臨床需要的可用於數據交換 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...