【运行环境】windows xp sp2/sp3
【运行程序】再看某草视频教程的时候,发现有个程序在我的xp虚拟机(有配置逆向环境,记为机器A)里面打不开,但是在另外一个xp虚拟机(很多年前配置的虚拟机,记为机器B)里面可以打开。
【问题现象】
再练习的时候,发现一个该软件再部分xp虚拟机里面,打开就报错。


【尝试方法】
方案一:重新安装虚拟机。
1、网上下载了xp sp3的ghost版本,重新安装,不能运行。
发现现在网上的ghost版本,里面夹带的私活太多了,里面有太多的垃圾文件。
2、重新使用机器B的镜像安装虚拟机,里面很清爽,这个镜像是2011年的,不过安装后还是不能运行。
3、重新下载微软sp3原版安装镜像,安装后,不能运行。
4、找到雨林木风的一个08年的xp sp2的ghost版本,安装后,不能运行。
方案一,至此尝试失败。
方案二:和机器B对比环境和安装包。
1、使用机器B的镜像安装虚拟机(记为机器C ),和机器B对比安装的程序,保证安装程序一样,测试NG,还是不能运行。
2、检查机器C和机器B的服务,保证一致,测试NG,还是不能运行。
3、机器C,禁止加载无关的启动项,测试NG,还是不能运行。
4、机器C,安全模式启动,测试NG,还是不能运行
方案三:安装.net 环境
1、某Q群里,有人提供思路安装.net环境,下载了.net3.5的环境,安装.net环境后重启,程序可以运行。
2、机器重新后,发现软件又运行不起来了,排除了和.net的关系。
方案四:机器A,使用OD测试运行过程
1、机器A,OD载入后,马上F9运行,程序运行NG。
2、机器A,OD载入后,等个5~10秒钟,F9运行,程序可以运行。
============================
方案五:机器A,OD初步分析运行过程
1、机器A,OD载入后,再几个call后面设置断点,如图

2、F9运行,发现程序马上报错,没有停下来,初步定位到问题是发生在 call 00406848 这里。
0051489D E8 A61FEFFF call unpacked.00406848
进入该call内部
00406848 53 push ebx
00406849 8BD8 mov ebx,eax
0040684B 33C0 xor eax,eax
0040684D A3 A0505100 mov dword ptr ds:[0x5150A0],eax
00406852 6A 00 push 0x0
00406854 E8 2BFFFFFF call <jmp.&KERNEL32.GetModuleHandleA>
00406859 A3 68A65100 mov dword ptr ds:[0x51A668],eax //设置断点
0040685E A1 68A65100 mov eax,dword ptr ds:[0x51A668]
00406863 A3 AC505100 mov dword ptr ds:[0x5150AC],eax
00406868 33C0 xor eax,eax
0040686A A3 B0505100 mov dword ptr ds:[0x5150B0],eax
0040686F 33C0 xor eax,eax
00406871 A3 B4505100 mov dword ptr ds:[0x5150B4],eax
00406876 E8 C1FFFFFF call unpacked.0040683C
0040687B BA A8505100 mov edx,unpacked.005150A8 //设置断点
00406880 8BC3 mov eax,ebx
00406882 E8 C9D7FFFF call unpacked.00404050
00406887 5B pop ebx ; ntdll.7C9375D6 //设置断点
00406888 C3 retn
可以定位到 call unpacked.00404050 这个内部,我们进入
00404050 C705 14A05100 1>mov dword ptr ds:[0x51A014],<jmp.&KERNEL>
0040405A C705 18A05100 1>mov dword ptr ds:[0x51A018],<jmp.&KERNEL>
00404064 A3 40A65100 mov dword ptr ds:[0x51A640],eax
00404069 33C0 xor eax,eax
0040406B A3 44A65100 mov dword ptr ds:[0x51A644],eax
00404070 8915 48A65100 mov dword ptr ds:[0x51A648],edx
00404076 8B42 04 mov eax,dword ptr ds:[edx+0x4]
00404079 A3 30A05100 mov dword ptr ds:[0x51A030],eax
0040407E E8 C5FEFFFF call unpacked.00403F48
00404083 C605 38A05100 0>mov byte ptr ds:[0x51A038],0x0 //设置断点
0040408A E8 61FFFFFF call unpacked.00403FF0
0040408F C3 retn //设置断点
定位到 call unpacked.00403FF0 ,进入该call内部
00403FF0 55 push ebp
00403FF1 8BEC mov ebp,esp
00403FF3 53 push ebx
00403FF4 56 push esi
00403FF5 57 push edi
00403FF6 A1 40A65100 mov eax,dword ptr ds:[0x51A640]
00403FFB 85C0 test eax,eax
00403FFD 74 4B je short unpacked.0040404A
00403FFF 8B30 mov esi,dword ptr ds:[eax]
00404001 33DB xor ebx,ebx
00404003 8B78 04 mov edi,dword ptr ds:[eax+0x4]
00404006 33D2 xor edx,edx
00404008 55 push ebp
00404009 68 36404000 push unpacked.00404036
0040400E 64:FF32 push dword ptr fs:[edx]
00404011 64:8922 mov dword ptr fs:[edx],esp
00404014 3BF3 cmp esi,ebx
00404016 7E 14 jle short unpacked.0040402C
00404018 8B04DF mov eax,dword ptr ds:[edi+ebx*8]
0040401B 43 inc ebx
0040401C 891D 44A65100 mov dword ptr ds:[0x51A644],ebx
00404022 85C0 test eax,eax
00404024 74 02 je short unpacked.00404028
00404026 FFD0 call eax
00404028 3BF3 cmp esi,ebx
0040402A ^ 7F EC jg short unpacked.00404018
0040402C 33C0 xor eax,eax
0040402E 5A pop edx ; ntdll.7C9375D6
0040402F 59 pop ecx ; ntdll.7C9375D6
00404030 59 pop ecx ; ntdll.7C9375D6
00404031 64:8910 mov dword ptr fs:[eax],edx
00404034 EB 14 jmp short unpacked.0040404A
00404036 ^ E9 59F9FFFF jmp unpacked.00403994
0040403B E8 50FFFFFF call unpacked.00403F90
00404040 E8 27FDFFFF call unpacked.00403D6C
00404045 E8 76FDFFFF call unpacked.00403DC0
0040404A 5F pop edi ; ntdll.7C9375D6
0040404B 5E pop esi ; ntdll.7C9375D6
0040404C 5B pop ebx ; ntdll.7C9375D6
0040404D 5D pop ebp ; ntdll.7C9375D6
0040404E C3 retn
定位到 00404026 FFD0 call eax
但是这个是个循环,我们把这部分代码单独取出来分析
00404018 8B04DF mov eax,dword ptr ds:[edi+ebx*8] //这里像是取以edi(00514360)为基址的一个矩阵数组指针,放入eax
0040401B 43 inc ebx //ebx,自加1
0040401C 891D 44A65100 mov dword ptr ds:[0x51A644],ebx //ebx的地址放入,0x51A644指向的内存
00404022 85C0 test eax,eax //判断eax是否为空
00404024 74 02 je short unpacked.00404028 //如果eax为空,这里则执行跳转
00404026 FFD0 call eax //调用 eax位置的call
00404028 3BF3 cmp esi,ebx //判断 ebx是大于esi ,这里esi为A6 ,这里下断点
0040402A ^ 7F EC jg short unpacked.00404018 //如果小于esi,则跳转
0040402C 33C0 xor eax,eax
查看edi对应的数据
$ ==> (00514360) > 004068BC 0040688C 004066B0 0040665C
$+10 > 00406960 00406930 00407870 00407840
$+20 > 004078A8 00407878 0041A9BC 0041A98C
$+30 > 00407C30 00407C00 0040EFE8 0040EE68
$+40 > 0040F884 0040F854 00418C3C 00418BC4
$+50 > 00418E38 00418E08 0041A674 0041A624
$+60 > 00425054 00424FA4 0042ECBC 0042EC8C
$+70 > 0042EF74 0042EF44 00430BA4 00430B64
$+80 > 0042FB6C 0042FB3C 0042F3EC 0042F3BC
$+90 > 004253D0 004253A0 0042EB80 0042EAAC
$+A0 > 004643B0 00464380 0042FBAC 0042FB7C
$+B0 > 0046AA14 0046A9A4 004310E4 004310B4
$+C0 > 00431A8C 00431A38 004326A4 00432674
$+D0 > 0043266C 0043263C 00432634 00432604
$+E0 > 004325FC 004325CC 004326DC 004326AC
$+F0 > 00439758 00439728 0044FA94 0044FA64
$+100 > 00430BDC 00430BAC 00430C20 00430BE4
$+110 > 00432714 004326E4 0043274C 0043271C
$+120 > 00433A24 004339C8 00436C6C 00436C24
$+130 > 004325AC 0043257C 00431AD8 00431AA8
$+140 > 00438EE8 00438EA0 0043965C 00439614
$+150 > 00436E88 00436E50 00436EE0 00436EB0
$+160 > 00436DB0 00436D80 00436D28 00436CEC
$+170 > 0044FBFC 0044FBCC 004396C8 00439678
$+180 > 00439720 004396D0 00436CE4 00436CB4
$+190 > 00449BA0 00449B28 0044A730 0044A6EC
$+1A0 > 004617E8 00461780 00462AE0 00462AB0
$+1B0 > 004508C8 00450850 00430F38 00430F08
$+1C0 > 004770D0 00477074 004C1BB8 004C1B88
$+1D0 > 004C68A0 004C6864 004C7250 004C7220
$+1E0 > 004D5E78 004D5E48 004D7AF0 004D7AC0
$+1F0 > 004DC968 004DC938 004DB714 004DB6E4
$+200 > 00477AEC 00477ABC 004DA300 004DA2D0
$+210 > 004DA2C8 004DA298 004DC9A0 004DC970
$+220 > 004DE07C 004DE04C 004DEDCC 004DED9C
$+230 > 004F2DD4 004F2DA4 004E3170 004E3140
$+240 > 004DA290 004DA260 004A92D8 004A92A8
$+250 > 004BC7DC 004BC79C 004F31E0 004F31B0
$+260 > 004F47B8 004F4770 004F31A8 004F3178
$+270 > 004F5B74 004F5B18 004F6094 004F6064
$+280 > 004FE32C 004FE2FC 004FE378 004FE334
$+290 > 004FE4F8 004FE47C 004FE57C 004FE54C
$+2A0 > 004FE5B4 004FE584 004FF748 004FF6EC
$+2B0 > 004FFD10 004FFCE0 005011EC 005011BC
$+2C0 > 004FAAA4 004FAA74 004F60F4 004F60C4
$+2D0 > 004F62A4 004F6274 004F9D78 004F9D48
$+2E0 > 0050169C 0050166C 00502910 005028E0
$+2F0 > 00503320 005032D8 005041F0 005041C0
$+300 > 004FC3D8 004FC3A8 004A4528 004A44F8
$+310 > 0047D7CC 0047D79C 0047E934 0047E8B4
$+320 > 004A5CA0 004A5C40 004A5D1C 004A5CEC
$+330 > 004A923C 004A9200 004BD15C 004BD12C
$+340 > 004BE1B0 004BE180 00477CFC 00477CCC
$+350 > 0047D758 0047D71C 00477B5C 00477B2C
$+360 > 00478C5C 00478C20 00492D60 00492D04
$+370 > 004930F8 004930C8 00492EA8 00492E78
$+380 > 00493CD4 00493CA4 00493C24 00493BF4
$+390 > 00493AC4 00493A94 004A44A4 004A4454
$+3A0 > 005111B0 00511180 00505634 00505604
$+3B0 > 0050FA04 0050F9B4 005059DC 005059AC
$+3C0 > 005057D4 005057A4 005084B4 00508484
$+3D0 > 00506AFC 00506AC4 00506B3C 00506B0C
$+3E0 > 00508458 00508414 005089C4 00508908
$+3F0 > 00507368 00507338 00508BD8 00508BA8
$+400 > 0050A250 0050A220 0050A67C 0050A634
$+410 > 0050A744 0050A714 0050A6D4 0050A6A4
$+420 > 0050A7B4 0050A784 0050A7EC 0050A7BC
$+430 > 0050A824 0050A7F4 0050A77C 0050A74C
$+440 > 0050A70C 0050A6DC 0050AFC4 0050AF94
$+450 > 0050B2B8 0050B288 0050AEE8 0050AEB8
$+460 > 0050D910 0050D8E0 005096D8 005096A8
$+470 > 00508CF4 00508CA4 00509F64 00509F34
$+480 > 0050EE24 0050EDF4 0050EDB4 0050ED84
$+490 > 0050B974 0050B930 0050BB0C 0050BADC
$+4A0 > 0050C8E0 0050C8B0 0050C194 0050C164
$+4B0 > 0050C438 0050C3FC 0050D88C 0050D85C
$+4C0 > 0050F914 0050F8CC 0050DFB4 0050DF78
$+4D0 > 0050E274 0050E238 0050EB04 0050EAD4
$+4E0 > 0050ED50 0050ED20 0050EDEC 0050EDBC
$+4F0 > 0050F974 0050F944 0050F9AC 0050F97C
$+500 > 00510700 005106D0 00504228 005041F8
$+510 > 005140EC 005140BC 00514124 005140F4
$+520 > 00514328 005142F8 00000000 00514330
$+530 > 83EC8B55 5653F0C4 514358B8 1FA6E800
在 call eax 后面下断点,
00404026 FFD0 call eax //调用 eax位置的call
00404028 3BF3 cmp esi,ebx //判断 ebx是大于esi ,这里esi为A6 ,这里下断点
不停F9运行,发现出现异常的时候,ebx为60,说明出问题的时候即eax为 [edi + 60*8] = [edi + 300] =004FC3D8 ,查看该处的代码。
004FC3D8 832D 6CBE5100 0>sub dword ptr ds:[0x51BE6C],0x1
004FC3DF 73 0A jnb short unpacked.004FC3EB //这里下断点
004FC3E1 E8 D67DFFFF call unpacked.004F41BC
004FC3E6 A3 70BE5100 mov dword ptr ds:[0x51BE70],eax
004FC3EB C3 retn
很明显,问题应该出在 call unpacked.004F41BC ,进入该函数,发现该函数好像是一个算法,里面数据比较多,这里就不再列出。
取消所有断点,004FC3DF下断,重新运行程序,会断在004FC3DF这个地方。
打开-->调试-->跟踪步入(Ctrl + F 11),等到弹出异常,点击查看-->Run跟踪。

拉到下面,发现有异常,导致系统调用了ntdll的异常处理

根据上面得知,我们进入的call为4F41BC,因此可以初步判断,异常时产生在00402BDB
00402BD8 83EC 08 sub esp,0x8
00402BDB DF3C24 fistp qword ptr ss:[esp]
00402BDE 9B wait
00402BDF 58 pop eax
00402BE0 5A pop edx ; ntdll.7C99B178
00402BE1 C3 retn
是在004F42F3这个位置调用的call里面
004F42F1 DEF9 fdivp st(1),st
004F42F3 E8 E0E8F0FF call unpacked.00402BD8 //这里下断
004F42F8 8BD8 mov ebx,eax
方案六:机器A,通过OD的异常分析。
1、StrongOD,跳过所有异常。
2、调试设置里面,取消勾选所有

3、OD载入,F9运行

发现为“浮点除以0” ,Shift+F9

读取内存访问违规。
Ctrl+F11打开跟踪,Shift+F9,弹出应用程序错误的对话框。
打开异常视图。

根据提示,发现最终应该时 004034FA的地方,访问了内存无法读取导致的异常。
重新Ctrl+F2,两次shift+F9,来到004034FA断点处

Alt +M , 发现 0x00B80b30 ,这一部分的内存地址根本不存在。

在设置里面忽略所有异常,004034FA这里设置断点,重新运行程序,断下来后查看Alt+M,再F9,以此多查看一下Alt+M。
发现多了一个00B80000的区段

到这里,差生了疑问:
1、这个区段00B80000为什么会消失呢
2、同样的方法再机器B上面调试,没有发现00B80000的区段,但是00B40000的区段的size会变化。
3、分析到这里,没有头绪了。不知道为什么机器A会有这个问题,而机器B则时可以正常运行。
【解决方法】
方法一:找到004FC3D8
004FC3D8 832D 6CBE5100 0>sub dword ptr ds:[0x51BE6C],0x1
004FC3DF 73 0A jnb short unpacked.004FC3EB
004FC3E1 E8 D67DFFFF call unpacked.004F41BC
004FC3E6 A3 70BE5100 mov dword ptr ds:[0x51BE70],eax
004FC3EB C3 retn
修改为
004FC3D8 C3 retn
004FC3D9 90 nop
004FC3DA 90 nop
004FC3DB 90 nop
004FC3DC 90 nop
004FC3DD 90 nop
004FC3DE 90 nop
004FC3DF 73 0A jnb short unpacked.004FC3EB
004FC3E1 E8 D67DFFFF call unpacked.004F41BC
004FC3E6 A3 70BE5100 mov dword ptr ds:[0x51BE70],eax
004FC3EB C3 retn
发现可以运行
方法二:找到数据端 51 4660 处,把 004FC3D8修改为0

可以运行。
===============
这个可能时凑巧让程序可以运行起来,可能不是最根本原因。
附件备注:
1、附件密码 kanxue
2、附件为2005年左右的一款软件,该软件可能是流氓软件,可能会被报毒,请务必再虚拟机环境。
3、附件使用UPX加壳,直接用PEID的插件脱壳后即可使用。
[培训]科锐逆向工程师培训第53期2025年7月8日开班!
最后于 2020-10-18 22:13
被黑色帝国编辑
,原因: 添加分析使用的软件,修改附件备注