首页
社区
课程
招聘
[原创]脱壳后软件无法运行的原因分析及对策——写给初学者
发表于: 2007-4-19 22:54 48864

[原创]脱壳后软件无法运行的原因分析及对策——写给初学者

wulje 活跃值
14
2007-4-19 22:54
48864

我在《菜鸟啄硬壳(之四)》中给出的“通用脱壳机”对付UPX壳、ASpack壳还比较有效,只是自动搜索OEP功能稍弱。有网友来信说脱壳后不能运行,我想不一定是脱壳中的问题。本短文分析脱壳后不能运行的最简单的原因。
  
  一、脱壳是否成功的标志
  一般说来,对软件脱壳是不会改变原软件的运行机制的。它只是将加密的IAT地址还原成装载前的API函数名字串的地址,并以明码方式显示。脱壳是否成功的标志是软件运行前图标与脱壳前一致、运行时windows并未发出“……,初始化失败……”的警告,那么脱壳大体是成功的。若出现初始化失败警告,则百分之百是IID表或IAT表搞错了。
  
  二、用OD加载时出现“异常”或直接运行时,windows弹出“发送错误报告”消息。
  原因:
  (1)OEP入口地址错误;
  (2)在手动脱壳时“张冠李戴”,把某函数的地址写到了另一个函数的地址上去了。
  
  三、软件一运行就退出
  1.原因:
  (1)如果脱壳前软件能(直接)运行,脱壳后软件一闪而过,说明软件有“文件校验”。软件脱壳前后的最大变化是文件尺寸变化,那么软件的“校验和”一定要发生变化,当它发现“校验和”变了时,知道了你对软件“动了手脚”,它就毫不犹豫地退出了。若这时你想找到“文件校验”的位置,无异于大海捞针!
  (2)如果脱壳后能直接运行,但用OD加载时就退出或有无法跳过的异常,则是有“反跟踪”部件。(这和脱不脱壳没有关系)反跟踪不是本文今天讨论的内容,只是附带说一声。
  
  2.对策:
  在一个软件中去找出它的“文件检验”代码在什么地方,同样得用“思想”,和破案也差不多。别急,先看看它是什么语言编写的。若是用“VC++”或“Delphi”编写的,则脱壳后的软件对于使用者,则基本上没有秘密可言。唯一的是它们的“call”嵌套太深,要进行底层的跟踪,很容易跟丢。举个例子,说明跟踪方法。
  有个商业软件,脱壳前可以运行,脱壳后就不能运行了。它是用“VC++”编写的。
  
  3.破解思路:
  用“VC++”或“Delphi”来编写软件,有它快捷方便的一面。但是,因为它不能直接对内存进行操作,所以灵活性受到很大影响。例如,它就不能对运行中的内存文件进行“校验和”检验,若非要检验,除非在VC编程中嵌入ASM代码,但这样一来,地址的起点和终点难于确定,且给调试带来麻烦。一个变通的办法是:打开同一文件的一个“副本”,检验它“副本”的“校验和”也可以达到对自身检验的目的。这样一来,软件的秘密也就暴露无遗了,用OD来查看(已经脱壳的)软件怎样打开另一个文件,那实在是“再容易”不过的事情了!
  
  4.具体操作:
  (1)用OD打开要跟踪的软件,右键打开搜索“所有模块间的调用”,在所有“CreateFile”和“ReadFile”的调用地址上设断点。
  (2)运行OD,按“F9”,中断在一个CreateFile上:

  CreateFile中断:(该函数的返回值是被打开文件的句柄)
……………………………………………………………………
0013E708    0013E90C   |FileName = "E:\xxxx\New_xxxxxxx.exe"
0013E70C    80000000   |Access = GENERIC_READ
0013E710    00000003   |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
0013E714    00000000   |pSecurity = NULL
0013E718    00000003   |Mode = OPEN_EXISTING
0013E71C    00000080   |Attributes = NORMAL
0013E720    00000000   \hTemplateFile = NULL
……………………………………………………………………
  以上是堆栈中的显示,其中,FileName = "E:\xxxx\New_xxxxxxx.exe"是将要打开的文件。若不是正在运行中的同名文件,则继续按“F9”。其余的参数是打开方式,不重要。
  监视CreateFile中断的另一个收获是知道了该软件在硬盘上写入了哪些文件,比如注册表中、系统文件夹中等(我最讨厌那些在硬盘中乱写文件的软件)。更重要的是,若软件有“反跟踪”代码,那么“CreateFile”或“FindWindow”等API函数调用时,它明码显示的文件名或窗口名是某个“调试软件”,就表明它在“反跟踪”,若发现了它们,相应的“反—反跟踪”措施也应该不是太困难的事。当然,高明的作者用VC也会让你伤透脑筋。
  当FileName=“正在运行的文件名时”, 再按“F9”来到ReadFile的中断上:

  ReadFile中断:
…………………………………………………………
0013E708    000001C0   |hFile = 000001C0    
0013E70C    0013EA10   |Buffer = 0013EA10
0013E710    00001000   |BytesToRead = 1000 (4096.)
0013E714    0013E71C   |pBytesRead = 0013E71C
0013E718    00000000   \pOverlapped = NULL
0013E71C    00000000
0013E720    00001000
0013E724    004C5CD7   
0013E728    0000016F  ;调用次数记录
…………………………………………………………
  其中,hFile = 000001C0是打开的文件句柄,Buffer = 0013EA10是保存读入数据的地址,BytesToRead = 1000 (4096.)是读入的字节数,其余的不重要。  
  由于一个软件,不可能只有1000h字节,一次不能读完,所以ReadFile要调用多次,调用的次数总可以在某个寄存器中或堆栈中找到,这里(0013E728 :0000016F)就是递减的调用次数。每调用一次,后面的程序就将这1000h字节累加一次,稍加跟踪就到了“校验和”代码处:

  (3)文件“校验和”代码:  
……………………………………
004E0164    .  8D85 E0EFFFFF   lea eax,dword ptr ss:[ebp-1020]  ;eax=读入字节存放地址
004E016A    >  33C9            xor ecx,ecx
004E016C    .  8A08            mov cl,byte ptr ds:[eax]
004E016E    .  014D EC         add dword ptr ss:[ebp-14],ecx  ;[ebp-14]=累加值
004E0171    .  40              inc eax
004E0172    .  4A              dec edx        ;1000h字节的计数
004E0173    .^ 75 F5           jnz short 004E016A                
004E0175    >  4B              dec ebx        ;调用次数计数
004E0176    .^ 75 C6           jnz short 004E013E                
004E0178    >  836D EC 7B      sub dword ptr ss:[ebp-14],7B  ;累加完成后的修正
004E017C    .  8D85 48EDFFFF   lea eax,dword ptr ss:[ebp-12B8]
004E0182    .  E8 B564F2FF     call 0040663C                     
………………………………………
  累加结果存放在[ebp-14]=0013FA1C中。
  不停地按“F9”,并观查(0013E728 :0000016F)中的值,当它变为1时,就单步跟踪,“比较转跳”代码就近在咫尺了。

  (4)“比较转跳”代码:  
………………………………………
004E0182    .  E8 B564F2FF     call 0040663C        ;这就是前面的最后一行                       
004E0187    .  E8 E826F2FF     call 00402874         ;释放一些内存等善后(VC特有)                  
004E018C    .  837D F4 00      cmp dword ptr ss:[ebp-C],0  
004E0190    .  75 22           jnz short 004E01B4                
004E0192    .  8B45 E4         mov eax,dword ptr ss:[ebp-1C]  ;取0013FA14的检验值
004E0195    .  3B45 EC         cmp eax,dword ptr ss:[ebp-14]  ;和累加值比较
004E0198       75 13           jnz short 004E01AD     ;最关键的(非0)转跳               
004E019A    .  BB 01000000     mov ebx,1
004E019F    .  8B45 FC         mov eax,dword ptr ss:[ebp-4]
004E01A2    .  FE80 10450100   inc byte ptr ds:[eax+14510]
004E01A8    .  E9 96000000     jmp 004E0243                      
004E01AD    >  33DB            xor ebx,ebx
004E01AF    .  E9 8F000000     jmp 004E0243  

  5.修改代码:
  到了现在,文件检验和转跳都清楚了,修改就变得十分简单,只需将:(用16进制编辑器)
……………………………………………………………………
004E0198   75 13    jnz short 004E01AD    ;改为:90 90   nop  ,nop
…………………………………………………………………………
  存盘,大功告成了。怎么样?一个大海捞针的工作变得谨然有序。运行一切正常。
(注:该软件是国产商业软件,需要注册才能有全部功能,为了保护知识产权,注册破解法不是讨论内容)


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 7
支持
分享
最新回复 (56)
雪    币: 224
活跃值: (147)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
2
支持~是CreateFileA,其他的没仔细看
2007-4-20 00:47
0
雪    币: 29249
活跃值: (7769)
能力值: ( LV15,RANK:3306 )
在线值:
发帖
回帖
粉丝
3
支持~~crc校验~
2007-4-20 02:41
0
雪    币: 465
活跃值: (667)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
4
谢谢分享。。。。。。。
2007-4-20 08:39
0
雪    币: 405
活跃值: (10)
能力值: ( LV9,RANK:1130 )
在线值:
发帖
回帖
粉丝
5
我个人感觉delphi的自校验比较麻烦。
2007-4-20 10:27
0
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
6
现在流行虚拟机
2007-4-20 19:56
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
ding一下....
2007-4-20 21:09
0
雪    币: 217
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
好文章,学习了,收获不小。
2007-4-21 12:21
0
雪    币: 237
活跃值: (10)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
9
2007-4-21 16:13
0
雪    币: 347
活跃值: (30)
能力值: ( LV9,RANK:420 )
在线值:
发帖
回帖
粉丝
10
难道用bp CreateFileA的断点不行么?
2007-4-22 00:05
0
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
如果我用校验和与程序文件名对程序的关键数据加密,然后用GetModuleFileName得到该程序文件名和校验和对进行数据解密后运行,您如何解决?
2007-4-22 07:23
0
雪    币: 305
活跃值: (10)
能力值: ( LV9,RANK:570 )
在线值:
发帖
回帖
粉丝
12
        我猜想,你的意思是“将校验和、文件名运算加密后生成一个文件”,然后用GetModuleFileName打开这个文件,将解密后的数据写回“正在运行的程序”。是这样的吧?
        首先,GetModuleFileName只是返回“运行中的模块”的路径和文件名,不能用于打开文件。打开文件还得用CreateFileA,或CreateProcess(创建进程)。
        其次,当你用前面的API打开了一个“奇怪的文件”,读了几个字节,程序就莫名其妙地地出了,(这无异于打开“注册文件——key File”)。跟踪这奇怪文件或nop就是破解入口。
        文件保护方式没有“固定模式”,给写小说构思没有太大差异,任何保护方式都会留下蛛丝马迹,破解就是善于发现和追踪它们。
2007-4-22 13:13
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
学习下  有点不明白 呵呵
2007-6-26 00:16
0
雪    币: 144
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
好文:):)——
2007-6-26 12:11
0
雪    币: 190
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
不错!!!!
2007-7-7 12:44
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
学习中,刚学破解,破的软件用到的是网络验证,这方面 的文章好像比较少哦
2007-7-9 10:28
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
好文章,学习了。
2007-12-1 11:43
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
好复杂啊
看来更要努力啦
2007-12-1 15:49
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
嘻嘻!

路过滴!嘻嘻!

我到底对电脑感不感兴趣呢?  我自己也说不清楚,不过我只有这一条出路了,不学也不行了,还是继续啊!

初学者,还请多多照顾!
2007-12-14 15:06
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
学习一下。。。。
2007-12-15 23:17
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
ding一下....
2008-1-8 21:10
0
雪    币: 88
活跃值: (115)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
正好学习用……谢谢,希望有多点这样的教程
2008-1-9 11:51
0
雪    币: 186
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
楼主好像消失了一样,很久没见到
2008-4-9 14:55
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
Stone's PE Encryptor 1.13请问用什么脱壳
2008-4-9 14:58
0
雪    币: 129
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
CreateFileA henhao
2008-4-9 20:30
0
游客
登录 | 注册 方可回帖
返回
//