最近做监控ATM的程序,由于不同厂商的ATM的各个部件的逻辑名称不同,而且同个类型的部件存在冗余的逻辑名
如Diebold的ATM,以读卡器为例
IDC对应下面一些逻辑设备:
DBD_MotoCardRdr
DBD_MotoCardRdrRear
DBD_MotoCardRdr_SAM2
DBD_MotoCardRdr_SAM3
DBD_MotoCardRdr_SAM4
DBD_MotoCardRdr_SAM5
DBD_DipCardRdr
DBD_DipCardRdr_SAM1
DBD_DipCardRdr_SAM2
DBD_DipCardRdr_SAM3
DBD_DipCardRdr_SAM4
DBD_DipCardRdr_SAM5
这些名称记录在注册表中
而实际上只有一个名字与实际的物理设备相对应。
为了找出那一个逻辑名称与物理设备对应,我采用的策略是遍历注册表,对每一个逻辑名,进行打开逻辑设备的办法,
根据打开的结果来判断。
这种方式有一定的自适应性,如果监控程序运行到NCR的ATM上不需要任何修改。
NCR上读卡器相关的逻辑设备名有:
IDCardUnit1
由于名称不同,所以如果不采用程序自己查找的办法,那只有人工查找出来后,配置到程序的配置文件中。
人工配置方法,显然有点笨拙。但是笨拙的方法不一定不是好方法。
Diebold 一些型号的ATM,出现的问题让我不得不采用这种笨方法。
问题表现是这样的:
我使用自己的测试程序,安照CDM、IDC、CIM、PIN、PTR的顺序。
对于每种设备类,遍历注册表查找可用的逻辑设备名,如同上面所述的。
结果除了看到CDM的信息能获取一次,其他所有设备类调用WFSOpen时均返回WFS_ERR_INTERNAL_ERROR。
鬼知道这个WFS_ERR_INTERNAL_ERROR是什么样的错误。
而且问题是出在给银行客户安装调试监控系统时,当时用的是实际使用的ATM,运行完测试程序后,ATM就不能正常工作了。
所以不能继续测试。
开始认为这种型号的ATM不支持CEN/XFS标准,其实我觉得现在做这些东西没有什么技术含量,没劲。
让崔总找Diebold的人问一下是否支持,他找了维护ATM的人一个Diebold安装包给我,我发现安装包是不完全的。
这个东西没劲,就放了一阵。
后来我去邮储测试发现一台机器好像跟客户那里的一样。如获至宝啊。
但是测试也没有什么重大发现,测试读卡器DBD_MotoCardRdr有时可以,有时又返回该死的internal_error。
烦的要命。
我又认为我采用编译方式有问题,Diebold的msxfs.dll与CEN发布的不一样,
是不是不应该用msxfs.lib来编译程序,而应直接显式加载msxfs.dll呢?
我修改完了,兴兴冲冲去了邮储,一测,还是WFS_ERR_INTERNAL_ERROR。它娘的,气死了。
回来仔细对着XFS文档,检查自己传入WFSOpen等函数的入参等是不是存在错误,没有发现,
但是看到了文档中有关于Debug日志的内容,在WFSOpen入参可以输入debug信息的输出等级。
我改了一下,在模拟环境上试验一下,果真能打印出日志,有点希望了。
我又跑到邮储,一测,没有日志!????
要了命了。
把问题设备上的msxfs.dll复制到U盘带回来,我冒出一个想法逆向它一下,找了IDA,
开始逆向,梳理逆向结果,发现WFSOpen凡是返回INTERNAL_ERROR的地方几乎都是查找注册表,找不到东西的情况。
但是那台设备上打印不出日志啊,不知道究竟是什么情况啊。
我决定hack一下这个msxfs.dll让它给打印出来。我够狠!!
仔细研究了它的日志记录函数,我写出来仿冒品函数,把代码注入到msxfs.dll中,
在原日志记录函数的开始地址,把它的指令改成jmp mylogfun。
这样hack工作完成。
再去邮储。
一试,靠,日志出来,貌似与注册表没有关系。
又郁闷了,安慰自己:至少现在问题可以确定处在SP层。
SP层,把dbdspi.dll考回来,再反汇编WFPOpen
发现有对应有名管道文件CreateFile失败,或者CreateNamePipe失败时,返回internal_error。
我对windows上编程不熟悉,一查MSDN,发现对应有名管道文件进行CreateFile,是使用有名管道文件的客户端干的事情。
snprintf(filename, 0x100u, "\%s\pipe\DbdSpi_Request_%s", *(_DWORD *)(v10 + 60), *(_DWORD *)(v10 + 44));
有可能是WFPOpen与某个进程进行进程间通讯出了问题,
或者我想了一个可能性低的
例如客户端查找“\.\pipe\A123"
而服务端创建“\.\piple\A122"
也就两边没有配合好。但是大厂商不会犯这种低级问题啊。
现在已经麻木了,没有在HUAWEI时分析问题那种按部就班,记录问题日志了,过程混乱。没有再细想。
不过我有个想法,就是要看看那个服务程序里有创建通讯用的“xxx\pipe\DbdSpi_Request_xxx”类似名称的有名管道
我又跟崔总要了一个Diebold安装程序(如果一开始开发监控时,就要过来就好!!!!)
现在找一下那个服务程序。
装好以后,再测试,发现了跟问题设备一样的现象,太兴奋了,还好我当时,开了procexp工具看系统中进程的情况,
无意见看见我测试时,SpiService.exe自己退出了!!!天!
后来证实当访问DBD_DipCardRdrxxx的逻辑设备时,SpiService.exe就回退出了。
它一退出了,再访问其它设备,均由于有名管道通讯不通,返回WFS_ERR_INTERNAL_ERROR。
回头想想这个问题,如果记忆清零,再分析一次,能否快速分析出来了呢?
现在看我是选择了最艰难的分析道路,强行逆向!
最简单逐条测试,这种实用的办法,应该可以给定位问题起个好头。
也就是对每一个设备进行单独测试,而不使用使用程序批量测试。
还有对于自己测试的结果中异常的部分,没有足够的重视。
原始自己的日志:
.....
###### CDM name is DBD_BulkCashRecycler_CDM ######
fwDevice : WFS_STAT_DEVOFFLINE
fwSafeDoor : WFS_CDM_DOORNOTSUPPORTED
-----------------------
lpPhysicalPositionName : BIN2
cUnitID :
ulInitialCount : 0
ulMaximum : 0
bHardwareSensor : 1
ulCount : 0
usPStatus : 7
begin Logical Cash Unit.....usNumber : 4
usType : WFS_CDM_TYPENA
CashUnitName : (null)
ulInitialCount : 0
ulRejectCount : 0
cUnitID :
cCurrencyID :
ulValues : 0
ulCount : 0
ulMinimum : 0
ulMaximum : 0
usStatus : 7
usNumPhysicalCUs : 1
-----------------------
lpPhysicalPositionName : BIN3
cUnitID :
ulInitialCount : 0
ulMaximum : 0
bHardwareSensor : 1
ulCount : 0
usPStatus : 7
....
IDC is DBD_DIPCardRdr ######
WFSOpen failed WFS_ERR_CONNECTION_LOST
###### IDC is DBD_DIPCardRdr_SAM1 ######
WFSOpen failed WFS_ERR_INTERNAL_ERROR
###### IDC is DBD_DIPCardRdr_SAM2 ######
WFSOpen failed WFS_ERR_INTERNAL_ERROR
###### IDC is DBD_DIPCardRdr_SAM3 ######
WFSOpen failed WFS_ERR_INTERNAL_ERROR
......
当时没有注意到WFS_ERR_CONNECTION_LOST与WFS_ERR_INTERNAL_ERROR
区别的重要意义。
后来邮储测试时我确实萌生对设备名一个一个测试想法,修改了测试idc的程序,手动输入设备名
测试IDC时
.......
WFSStartUp OK
WFSCreateAppHandle OK
WFSOpen DBD_DIPCardRdr Fail -15
WFSStartUp OK
WFSCreateAppHandle OK
WFSOpen DBD_DIPCardRdr Fail -15
WFSStartUp OK
WFSCreateAppHandle OK
WFSOpen DBD_DIPCardRdr_SAM3 Fail -15
WFSStartUp OK
WFSCreateAppHandle OK
WFSOpen DBD_DIPCardRdr_SAM3 Fail -15
WFSStartUp OK
WFSCreateAppHandle OK
WFSOpen DBD_MotoCardRdr OK
WFSStartUp OK
WFSCreateAppHandle OK
WFSOpen DBD_MotoCardRdr OK
WFSStartUp OK
WFSCreateAppHandle OK
WFSOpen DBD_MotoCardRdr OK
read track ok
.....
其中一段记录,中间可能我重启了设备。
都是问题中关键表现,我都没有发现!
教训:
定位问题日志记录,详细记录:输入数据、操作等、输出结果等。
对于程序日志需要分类,文件名改为当时日期。
