记一次 .NET 某企业 ERP网站系统 崩溃分析

一次,net,企业,erp,网站,系统,崩溃,分析 · 浏览次数 : 1954

小编点评

1. satrda.dll 找不到文件路径导致程序崩溃。 2. C# 和 C++ 产生交互时经常会有各种奇怪的问题。 3. 在 C# 层面没收到这种C++异常,确实当 C# 和 C++ 产生交互时经常会有各种奇怪的问题。 4. 这项事故是由于 satrda 层面找不到文件路径导致的程序崩溃。

正文

一:背景

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++ 产生交互时经常会有各种奇怪的问题,我无意删除你的,你无意干扰我的,大家都好自为之吧😂😂😂

图片名称

与记一次 .NET 某企业 ERP网站系统 崩溃分析相似的内容:

记一次 .NET 某企业 ERP网站系统 崩溃分析

一:背景 1. 讲故事 前段时间收到了一个朋友的求助,说他的ERP网站系统会出现偶发性崩溃,找了好久也没找到是什么原因,让我帮忙看下,其实崩溃好说,用 procdump 自动抓一个就好,拿到 dump 之后,接下来就是一顿分析了。 二:WinDbg 分析 1. 是什么导致的崩溃 windbg 有一个

记一次 .NET某企业数字化平台 崩溃分析

一:背景 1. 讲故事 前些天群里有一个朋友说他们软件会偶发崩溃,想分析看看是怎么回事,所幸的是自己会抓dump文件,有了dump就比较好分析了,接下来我们开始吧。 二:WinDbg 分析 1. 程序为什么会崩溃 windbg 还是非常强大的,当你双击打开的时候会自动帮你定位过去展示崩溃时刻的寄存器

记一次 .NET 某企业OA后端服务 卡死分析

一:背景 1.讲故事 前段时间有位朋友微信找到我,说他生产机器上的 Console 服务看起来像是卡死了,也不生成日志,对方也收不到我的httpclient请求,不知道程序出现什么情况了,特来寻求帮助。 哈哈,一般来说卡死的情况在窗体程序(WinForm,WPF) 上特别多,在 Console,We

记一次 .NET 某企业内部系统 崩溃分析

## 一:背景 ### 1. 讲故事 前些天有位朋友找到我,说他的程序跑着跑着就崩溃了,让我看下怎么回事,其实没怎么回事,抓它的 crash dump 就好,具体怎么抓也是被问到的一个高频问题,这里再补一下链接: [.NET程序崩溃了怎么抓 Dump ? 我总结了三种方案] https://www.

记一次 .NET 某企业采购平台 崩溃分析

## 一:背景 ### 1. 讲故事 前段时间有个朋友找到我,说他们的程序有偶发崩溃的情况,让我帮忙看下怎么回事,针对这种 crash 的程序,用 AEDebug 的方式抓取一个便知,有了 dump 之后接下来就可以分析了。 ## 二:Windbg 分析 ### 1. 为什么会崩溃 既然是程序的崩溃

记一次 .NET某网络边缘计算系统 卡死分析

一:背景 1. 讲故事 早就听说过有什么 网络边缘计算,这次还真给遇到了,有点意思,问了下 chatgpt 这是干嘛的 ? 网络边缘计算是一种计算模型,它将计算能力和数据存储位置从传统的集中式数据中心向网络边缘的用户设备、传感器和其他物联网设备移动。这种模型的目的是在接近数据生成源头的地方提供更快速

记一次 .NET某机械臂上位系统 卡死分析

一:背景 1. 讲故事 前些天有位朋友找到我,说他们的程序会偶发性的卡死一段时间,然后又好了,让我帮忙看下怎么回事?窗体类的程序解决起来相对来说比较简单,让朋友用procdump自动抓一个卡死时的dump,拿到dump之后,上 windbg 说话。 二:WinDbg 分析 1. 主线程在做什么 要想

记一次 .NET某工厂报警监控设置 崩溃分析

一:背景 1. 讲故事 前些天有位朋友在微信上丢了一个崩溃的dump给我,让我帮忙看下为什么出现了崩溃,在 Windows 的事件查看器上显示的是经典的 访问违例 ,即 c0000005 错误码,不管怎么说有dump就可以上windbg开干了。 二:WinDbg 分析 1. 程序为谁崩溃了 在 Wi

记一次 .NET某游戏币自助机后端 内存暴涨分析

一:背景 1. 讲故事 前些天有位朋友找到我,说他们的程序内存会偶发性暴涨,自己分析了下是非托管内存问题,让我帮忙看下怎么回事?哈哈,看到这个dump我还是非常有兴趣的,居然还有这种游戏币自助机类型的程序,下次去大玩家看看他们出币的机器后端是不是C#写的?由于dump是linux上的程序,刚好win

记一次 .NET某工控视觉自动化系统 卡死分析

一:背景 1. 讲故事 今天分享的dump是训练营里一位学员的,从一个啥也不会到现在分析的有模有样,真的是看他成长起来的,调试技术学会了就是真真实实自己的,话不多说,上windbg说话。 二:WinDbg 分析 1. 为什么会卡死 这位学员是从事工控大类下的视觉自动化,也是目前.NET的主战场,这个