记一次 .NET 某企业 ERP网站系统 崩溃分析
一:背景
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 14c9d074
14c9d074 "0810"
0:019> da 176D9C64h
176d9c64 "at++"
还原成 C 代码大概就是:
FILE* pFile = fopen("0810", "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 到底表示啥意思,截图如下:

从图中看,原来是路径不存在的错误,应该就是没找到 0810 这个文件。
到这里就基本弄清楚了来龙去脉,应该是朋友的服务器有意或者无意清理了由 satrda 生成的 0810 文件,引发 satrda.dll 找不到文件路径导致的程序崩溃,将这些信息提供给朋友之后,让朋友去找 satrda 官网去了解下详情,毕竟官方才是最清楚的。
三:总结
这次事故是由于 satrda 层面找不到文件路径导致的程序崩溃,据朋友说在 C# 层面没收到这种C++异常,确实当 C# 和 C++ 产生交互时经常会有各种奇怪的问题,我无意删除你的,你无意干扰我的,大家都好自为之吧
记一次 .NET 某企业 ERP网站系统 崩溃分析的更多相关文章
- 记一次 .NET 某企业OA后端服务 卡死分析
一:背景 1.讲故事 前段时间有位朋友微信找到我,说他生产机器上的 Console 服务看起来像是卡死了,也不生成日志,对方也收不到我的httpclient请求,不知道程序出现什么情况了,特来寻求帮助 ...
- 记一次 .NET 某自动化集采软件 崩溃分析
一:背景 1.讲故事 前段时间有位朋友找到我,说他的程序在客户的机器上跑着跑着会出现偶发卡死,然后就崩掉了,但在本地怎么也没复现,dump也抓到了,让我帮忙看下到底怎么回事,其实崩溃类的dump也有简 ...
- 记一次 .NET 某工控MES程序 崩溃分析
一:背景 1.讲故事 前几天有位朋友找到我,说他的程序出现了偶发性崩溃,已经抓到了dump文件,Windows事件日志显示的崩溃点在 clr.dll 中,让我帮忙看下是怎么回事,那到底怎么回事呢? 上 ...
- OSCHina技术导向:开源企业ERP系统Opentaps
opentaps Open Source ERP + CRM 基于 Apache OFBiz (The Open For Business Project ) 构建, 是一款设计良好, 逐渐流行起来的 ...
- thinkphp5项目--企业单车网站(五)
thinkphp5项目--企业单车网站(五) 项目地址 fry404006308/BicycleEnterpriseWebsite: Bicycle Enterprise Websitehttps:/ ...
- thinkphp5项目--企业单车网站(四)
thinkphp5项目--企业单车网站(四) 项目地址 fry404006308/BicycleEnterpriseWebsite: Bicycle Enterprise Websitehttps:/ ...
- thinkphp5项目--企业单车网站(三)
thinkphp5项目--企业单车网站(三) 项目地址 fry404006308/BicycleEnterpriseWebsite: Bicycle Enterprise Websitehttps:/ ...
- thinkphp5项目--企业单车网站(二)
thinkphp5项目--企业单车网站(二) 项目地址 fry404006308/BicycleEnterpriseWebsite: Bicycle Enterprise Websitehttps:/ ...
- thinkphp5项目--企业单车网站(一)
thinkphp5项目--企业单车网站(一) 项目地址 fry404006308/BicycleEnterpriseWebsite: Bicycle Enterprise Websitehttps:/ ...
- thinkphp5项目--企业单车网站(七)
thinkphp5项目--企业单车网站(七) 项目地址 fry404006308/BicycleEnterpriseWebsite: Bicycle Enterprise Websitehttps:/ ...
随机推荐
- APP性能测试——热启动耗时测试
热启动耗时: 即当启动应用时,后台已有该应用的进程(我们模拟按下HOME键),打开软件,直到进入到首页activity页面,并计算耗时. 示例代码: import os import time def ...
- Java输入输出格式
一.输入字符串 Scanner in=new Scanner(System.in); String str1=in.next(); //输入一个字符串,以空格或回车结束 String str2=in. ...
- html 手机端适配不同手机高度 ,把内容居中显示
手机端适配不同手机高度 ,把内容居中显示,可以将div.img.section.span.p等等元素,设置 top:50%; margin-top:xxvw; 这样可以保证主题内容居中显示.
- Python循环任务,错误打包输出
有时候,多个任务循环在跑,但不想中间任何一个错误,停止主线程,但又想在主线程运行结束后,采集运行过程中所有的错误信息. 这种刁钻的想法,我自问自答,记录一下操作方法. err_list = [] ma ...
- el-table 固定列错位问题
1. 问题描述:el-table使用固定列时,使用keep-alive后页面切换导致该列错位. 2. 解决方法:使用el-table的doLayout方法对表格进行重新布局 activated() { ...
- Android自动化测试
一.环境搭建 必备软件: Windows或MacOS系统的电脑 python pycharm Android SDK(需要配置环境变量,网上有教程) Appium客户端(需要配置Android SDK ...
- SQL servr——基础篇之DML增删改查
DML:数据操作语言 用于添加.更新.删除和查询数据库中的语言 添加--insert语句 向数据表中插入新的行(记录)可多行可一行 语法:insert [into] 表名 [(column1,. ...
- Idea提交文件时,添加不需要提交的文件至.gitignore文件中
1.在Idea中,依次打开File ---->Setting ---> Editor --->File Types 2.在当前编辑栏下方找到Ignore files and fold ...
- 【APT】Hades APT组织针对乌克兰发起网络攻击事件分析
背景 Hades一个充满神秘色彩的APT组织,该组织因为2017年12月22日针对韩国平昌冬奥会的攻击活动被首次发现,后来卡巴斯基将该次事件的攻击组织命名为Hades.但是该攻击组织的归属问题却一直未 ...
- 2月21日python程序设计
Python变量 1.不需要事先声明变量名及其类型,直接赋值即可. 2.强类型编程语言,根据赋值或运算来推断变量类型. 3.动态类型语言,变量的类型也是可以随时变化的. >>> x ...