前段时间收到了一个朋友的求助,说他的ERP网站系统会出现偶发性崩溃,找了好久也没找到是什么原因,让我帮忙看下,其实崩溃好说,用procdump自动抓一个就好,拿到dump之后,接下来就是一顿分析了。
二:WinDbg分析1.是什么导致的崩溃windbg有一个自动化的分析命令!analyze-v可以帮我们提前预诊一下,就好像进医院先在问询台那里过一下。
0:019!analyze-vCONTEXT:(.ecxr)eax=14c9cd00ebx=00000000ecx=00000000edx=00000000esi=00000000edi=14c9d664eip=682a024aesp=14c9cfd4ebp=14c9d018iopl=0nvupeiplnzacponccs=0023ss=002bds=002bes=002bfs=0053gs=002befl=00000212msvcr90!fprintf+0x34:682a024a83c414addesp,14hResettingdefaultscopeEXCEPTION_RECORD:(.exr-1)ExceptionAddress:682a024a(msvcr90!fprintf+0x00000034)ExceptionCode:c0000417ExceptionFlags:00000001NumberParameters:0PROCESS_NAME:_CODE:(NTSTATUS)0xc0000417-CEXCEPTION_CODE_STR:c0000417STACK_TEXT:14c9d0181766013b00000000176d9c6017def1a8msvcr90!fprintf+0x34WARNING:!Writer_Write+0x4bb000000c875636578203a65745332347b207d32300x454c5153000000c81767362317d538e817ded73000000001crypt32!profapi_NULL_THUNK_DATA_DLAPERF(crypt32+0x126578)00000009176604b614c9d74c17ded73017dae9c8satrda!SATRDA_Proto_UnitTest+0x6c93ffffffff1765401217dae9c817d538e817ded730satrda!Writer_Write+0x83617dae9c8665fe07214c9d74c000000011765405bsatrda!ConfigDSN+0xd0c2160a0000000000000000000000000000000000000x7071e31FAULTING_SOURCE_LINE:f:\dd\vctools\crt_bld\self_x86\crt\src\_SOURCE_FILE:f:\dd\vctools\crt_bld\self_x86\crt\src\_SOURCE_LINE_NUMBER:55FAULTING_SOURCE_CODE:Nosourcefoundfor'f:\dd\vctools\crt_bld\self_x86\crt\src\'SYMBOL_NAME:msvcr90!fprintf+34MODULE_NAME:msvcr90IMAGE_NAME:_COMMAND:~19s;.ecxr;kbFAILURE_BUCKET_ID:INVALID_CRUNTIME_PARAMETER_c0000417_!fprintf
从错误信息看,问题是出在这个第三方库,赶紧网上搜一下是这是何方神圣。
看样子是一个连接数据库的商业组件,接下来看下FAILURE_BUCKET_ID:INVALID_CRUNTIME_PARAMETER_c0000417_!fprintf信息,可以发现因为在调用fprintf函数时出现了参数错误,到这里我们将包围圈极大的收缩了。
2.为什么会出现参数错误熟悉C语言fprintf函数的朋友都知道,它是用来向文件写入数据的,类似CChildEBPRetAddrArgstoChild0014c9d0181766013b00000000176d9c6017def1a8msvcr90!fprintf+0x34[f:\dd\vctools\crt_bld\self_x86\crt\src\@55]WARNING:!Writer_Write+0x4bb02000000c875636578203a65745332347b207d32300x454c5c81767362317d538e817ded73000000001crypt32!profapi_NULL_THUNK_DATA_DLAPERF(crypt32+0x126578)076604b614c9d74c17ded73017dae9c8satrda!SATRDA_Proto_UnitTest+0x6c9305ffffffff1765401217dae9c817d538e817ded730satrda!Writer_Write+0x8360617dae9c8665fe07214c9d74c000000011765405bsatrda!ConfigDSN+0xd0c20717ded730632074632c44492e6f532e63632c7472clr!CompressDebugInfo::CompressBoundariesAndVars+0x2d008656c65732c44492e6f532e63632c74727261502e0x6320746309656c65736f532e63632c74727261502e49746e650x2c44492e0a656c657369482e636e6564644c2e632c6c657665Microsoft_Build_Tasks_v4_0_ni+0x2f2e630b2c6874616e6564644c2e632c6c65766564646948System_ServiceModel_Web_ni+0xf2e630c69482e634c2e632c6c65766564646948632c6e65System_Runtime_Serialization_ni+0x2264640d6e6564646c65766564646948632c6e656d6f432e0x4c2e632c0e6e65646464646948632c6e656d6f432e656e6f70System_ServiceModel_ni+0x5376650f6c657665632c6e656d6f432e656e6f70632c746e0x64646948
从线程栈来看msvcr90!fprintf函数的第一个参数居然是00000000,也就是说*stream这个参数为NULL,难怪说参数异常!
3.为什么stream为空熟悉C的朋友应该知道*stream参数是通过fopen函数得到的,可能有些朋友有点混,这里就写个简单的模型吧。
intmain(){FILE*pFile;intn;charname[100];pFile=fopen("D:\\dumps\\","w");gets_s(name,100);fprintf(pFile,"%s",name);fclose(pFile);return0;}接下来我们到dump中寻找一下fopen函数,这个在线程栈上是没有了,先提取出msvcr90!fprintf+0x34中的RetAddr=1766013b返回值地址到汇编窗口查找,截图如下:
从图中可以看到,esi是eax给的,而eax是call返回值给的,不出意外176D727Ch中存的就是fopen函数,输出如下:
0:019upoi(176D727Ch)msvcr90!fopen[f:\dd\vctools\crt_bld\self_x86\crt\src\@123]:682a01a28bffmovedi,edi682a01a455pushebp682a01a58becmovebp,esp682a01a76a40push40h682a01a9ff750cpushdwordptr[ebp+0Ch]682a01acff7508pushdwordptr[ebp+8]682a01afe825ffffffcallmsvcr90!_fsopen(682a00d9)682a01b483c40caddesp,0Ch
接下来我们需要提取fopen中的两个参数,截图如下:
第二个参数很好获取就是176D9C60h的ascii表示,第一个参数获取起来就麻烦了,我们需要详细的如图那样推测当时的esp指向的位置。
0:019dapoi(14c9d02c+0x5c)17def0e0"log/20220810.txt"0:019da176D9C64h176d9c64"at++"
还原成C代码大概就是:
FILE*pFile=fopen("log/20220810.txt","at++");代码大概是恢复出来了,那为什么会抛异常呢?windbg有一个!gle命令可以查看当时发生了什么错误。
0:019!gleLastErrorValue:(NTSTATUS)0(0)-STATUS_SUCCESSLastStatusValue:(NTSTATUS)0xc000003a-{}%hs接下来到微软的官方文档:,截图如下:
从图中看,原来是路径不存在的错误,应该就是没找到20220810.txt这个文件。
到这里就基本弄清楚了来龙去脉,应该是朋友的服务器有意或者无意清理了由satrda生成的20220810.txt文件,引发找不到文件路径导致的程序崩溃,将这些信息提供给朋友之后,让朋友去找satrda官网去了解下详情,毕竟官方才是最清楚的。
三:总结这次事故是由于satrda层面找不到文件路径导致的程序崩溃,据朋友说在C和C++产生交互时经常会有各种奇怪的问题,我无意删除你的,你无意干扰我的,大家都好自为之吧




