声明
本文章中发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不用于其他任何目的,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关.
YodasCrypter1.3
信息收集
PEID查看程序基本信息:
- 程序类型:32位 GUI
- 壳信息:YodasCrypter1.3
程序基本功能信息:运行程序会有一个弹窗出现
ReCrackMe
ESP定律定位OEP
程序导入OllyDbg,我们发现PUSHAD
语句,因此我们可以尝试使用ESP定律脱壳
懒人定位失败
对0x0019FF70
设置硬件访问断点
正常情况,程序会中断在POPAD
语句的下一句,但是这里发现,我们的断点未使得程序终端下来
我们尝试查看日志,未找到有用信息
正常定位
那么,我们猜测在自解压过程中,可能在0x0019FF70
前面的上面的栈数据出站时,出现新的问题。
因此这里我们对执行PUSHAD
命令后的栈顶设置硬件访问断点
F9运行,程序中断在0x00465976
处。
我们观察到这几句指令是在注册SEH-结构化异常处理,它是用来确保该程序可以从错误中恢复,
- 如果你没有设置SEH,那么当程序中有异常发生时,程序就会弹出一个错误信息框,告诉我们程序即将关闭。
- 如果我们设置了SEH的话,异常处理程序就能够捕获到程序中发生的异常,进行相应的处理后,就会把控制权重新交予程序继续执行
;SEH注册语句
push @_except_handler ;异常处理器
push dwod ptr fs:[0] ;取出 SEH链表头
mov dwod ptr fs:[0],esp ;添加链表
;程序指令
00465976 50 PUSH EAX
00465977 33C0 XOR EAX,EAX
00465979 64:FF30 PUSH DWORD PTR FS:[EAX]
0046597C 64:8920 MOV DWORD PTR FS:[EAX],ESP
当注册过SEH后,0x0046597F
语句会主动触发一个异常,然后交给SEH处理。
0046597F /EB 01 JMP SHORT UnPackMe.00465982
00465981 |CC INT3
00465982 \0000 ADD BYTE PTR DS:[EAX],AL
我们前面可以知道,最终程序是可以正常运行的,所以我们在这里可以程序的代码段设置断点。
然后F9运行程序,程序中断在OEP处
Dump程序
当定位OEP后,我们将程序Dump下来
我们将其保存为Dump.exe
IAT修复
我们定Dump程序后,我们来查找IAT的起始地址和结束地址,尝试修复IAT。
手动定位IAT
我们发现程序在0x004271D6
的指令CALL DWORD PTR DS:[460ADC]
,我们根据OllyDbg得知,该函数地址为0x00754D57
我们在反汇编窗口转到0x00754D57
,我们发现该处指令为JMP 759D1C10
,因此我们知道IAT被重定向了。
我们查看该程序的内存布局,我们知道程序在自解过程中新分配了内存空间0x00470000-0x02440000
我们来尝试确定IAT的范围,我们在数据窗口转到0x00460ADC
,将数据查看方式改编为 地址查看。
我们一直向上寻找,我们发现到0x00460810
处存储的值即不是重定向后的地址,也不是API地址,且我们尝试搜索存储的值,发现不存在,因此我们知道IAT的起始地址为0x00460818
我们现在向下寻找IAT的结束地址,我们发现到0x00460F28
处存储的值即不是重定向后的地址,也不是API地址,
我们尝试搜索存储的值,发现不存在,因此我们知道IAT的结束地址为0x00460F248
,
ImportREC修复IAT
目前我们已经知道以下信息,因此我们使用ImportREC尝试修复IAT。
- OEP地址:
0x004271B0
- IAT-Start:
0x00460818
- IAT-End:
0x00460F28
- IAT大小为
0x00460F248-0x00460818
=0x710
运行ImportREC工具,选定在内存中的程序,并将OEP、IAT-Start的RVA和IAT-Size填入,点击获取导入表
我们发现,IAT是无效的,那么我们需要修复IAT:点击显示无效的 -->然后右键 -->跟踪级别1(反汇编)
我们发现,IAT全被修复了
将修复的IAT给转存到我们Dump的程序,点击修正转储,选中Dump.exe
,然后会生成Dump_.exe
我们尝试运行脱壳后的程序,成功运行。
IAT重定向跟踪
我们这里跟踪一下该程序在自解过程中是如何重定向IAT的。
前面我们已经知道,IAT的范围是0x00460818-0x00460F28
,而且我们发现,这个程序的IAT重定向有一个明显的特征,
他不是将API调用放在自定义函数中,而且使用一个跳转来使得IAT重定向。且这个程序的IAT表被全部重定向。
这里我们重新导出一个定位到OEP的程序Dump-Hand.exe
我们先对其中一个项0x00460818
跟踪,来查看IAT重定向过程
这里有两种方法设置断点:
- 内存写入断点:程序中断在写入语句,即未完成写入
- 硬件写入断点:程序中断在写入语句后,即已完成写入
过程追踪
这里我设置内存写入断点,这样可以更好定位到写入过程
F9运行程序,我们发现程序中断在0x00465730
,且其后一句是一个跳转语句
这里先写入了API地址,那么后续就可能有一条写入语句会将API地址给覆盖掉,我们继续F9,查看什么时候将地址写进去。
我们发现程序中断在0x0046579D
-MOV DWORD PTR DS:[EDX],ESI
细心的人可能已经发现,这里的重定向地址与前面的不一样,这是正常的,如果不放心,我们F9运行程序,如果没有新的写入,那么处就是写入的重定向地址
我们目前已经知道该程序IAT重定向过程
- 先将API地址写入IAT
- 再将重定向地址写入IAT
关键跳转跟踪
我们这里来跟踪是哪个跳转控制写入重定向地址的,还是跟踪0x00460818
,我们设置内存断点,当写入API地址后,我们使用单步追踪法来追踪。
这四条语句检测地址是否为API地址
0046576F 81FB 00000070 CMP EBX,70000000
00465775 72 08 JB SHORT UnPackMe.0046577F
00465777 81FB FFFFFF77 CMP EBX,77FFFFFF
0046577D 76 0E JBE SHORT UnPackMe.0046578D
我们单步追踪发现以下信息:
- 重定向写入语句
0x0046579D
会被0x0046577F
给跳转过去 -
0x0046577F
语句,会被0x0046577D
给跳转过去
这里我们有两种方法解决:
- 将
0x0046577D
语句给NOP掉,一般采用这种 - 将
0x0046579D
重定向写入语句给NOP掉,这样有可能会破坏程序完整性
修复-1
我们重新运行程序,将0x00460818-0x00460F28
这个段设置内存写入断点。PS:我们不知道第一个被写入的是哪个地址
F9运行程序,到第一次写入
单步追踪到0x0046577D
,
将其NOP
,将内存写入断点给删除,对程序代码段设置断点,然后F9.
我们发现程序出现异常,这说明程序可能有检测,但是我们发现此时程序的IAT已经填充完毕
我们继续F9,将其终止
此时,我们再打开ImportREC,看看是否可以将程序的IAT导出来,我们输入相关信息,发现可以导出
导出后,我们运行程序,查看是否可以运行
修复-2
这里面我们还有一种修复方式,就是再开一个OD,加载该CrackMe的另一个实例,直接跟到OEP处,不修改任何东西,然后将当前我们这个实例的正确的IAT复制出来,覆盖掉新开的这个实例的IAT,
将复制的IAT二进制粘贴到OEP的实例
可以看到,粘贴后OllyD表格给区别出来,标红,成功粘贴
然后将其Dump出来,命名为Dump-Hand.exe
使用ImportREC,修复IAT,将其给转存到Dump-Hand.exe
运行程序,发现成功运行。
FSG_1.31
信息收集
PEID查看程序基本信息:
- 程序类型:32位 GUI
- 壳信息:FSG 1.31
程序基本功能信息:
ReCrackMe
程序导入OllyDbg,我们发现在EP附近没有PUSHAD
这类的指令,因此此加壳程序不适合ESP定律定位OEP。
单步追踪法定位OEP
单步追踪法要领:
-
对于循环/回跳操作,我们可以直接在该循环的下一指令
F4
-
对于
Call
指令,我们先F8
,若发现程序运行,则记录地址,F7
跟踪 -
当对这个程序的壳运行熟悉后,我们还可以时使用
F2
和F9
来更加快速定位。在追踪时,我们可能会因为一些意外是的OllyDbg中断,此时F9效率就很快
注意:有些程序可能会存在
CC
断点检测,我们需要注意。
我们单步跟踪,中间会有三个关键跳转,这里给列出来
00477FD2 /73 16 JNB SHORT unpackme.00477FEA ; 关键跳转-1
00478000 /74 48 JE SHORT unpackme.0047804A ; 关键跳转-2
00478052 /74 13 JE SHORT unpackme.00478067 ; 关键跳转-3
当我们执行到0x00478607
处,下面就是自解过程的关键之处
我们观察后续的指令,我们发现以下关键之处
-
0047808A - 0F84 7082FCFF JE unpackme.00440300
,这个就是跳往OEP的跳转指令 -
这两句是整个循环的关键的条件判断之处
00478098 > 85C0 TEST EAX,EAX 0047809A ^ 75 D9 JNZ SHORT unpackme.00478075 ; 循环
我们根据指令,我们可以得到,当达到IAT末尾时,0047809A
处的跳转语句不会执行,而是执行0047808A
处的跳转指令,跳转到OEP。
我们还要注意这几个指令
-
加载Dll
00478071 57 PUSH EDI ; Dll Name 00478072 FF13 CALL DWORD PTR DS:[EBX] ; lozclibraryA 00478074 95 XCHG EAX,EBP ; DLL Address
-
获取API地址
00478090 57 PUSH EDI ; API Name 00478091 55 PUSH EBP 00478092 FF53 04 CALL DWORD PTR DS:[EBX+4] ; GetProcAddress 00478095 8906 MOV DWORD PTR DS:[ESI],EAX ; API Address
因此我们可以使用条件记录断点,来达到OEP:
- 首先可以使用条件记录断点,来记录这个循环中获得的API的地址,
- 然后我们在设置条件断点
EAX == Last_-_API_Address
,使得程序在这里中断 - 单步追踪法跟踪到OEP。
设置条件记录断点,记录API地址
将log窗口清空,这样可以更加观察condition,F9运行程序,我们找到最后的API地址为0x73590C70
我们重新运行程序,在00478098
设置条件断点,EAX == 73590C70
单步追踪法,当执行到0047808A - 0F84 7082FCFF JE unpackme.00440300
,我们可以看到跳转实现
成功执行到OEP
Dump程序
IAT修复
前面我们知道,这两部分时获取API地址的关键指令
-
加载Dll
00478071 57 PUSH EDI ; Dll Name 00478072 FF13 CALL DWORD PTR DS:[EBX] ; lozclibraryA 00478074 95 XCHG EAX,EBP ; DLL Address
-
获取API地址
00478090 57 PUSH EDI ; API Name 00478091 55 PUSH EBP 00478092 FF53 04 CALL DWORD PTR DS:[EBX+4] ; GetProcAddress 00478095 8906 MOV DWORD PTR DS:[ESI],EAX ; API Address
因此我们观察起始和末位时的ESI地址,我们可以知道IAT的起始地址和末尾地址
起始地址0x004430F0
末尾地址:0x00443670 +4 =0x00443674
ImportREC修复IAT
我们查看程序是否可以成功执行
-
Packer-Shelling.zip 下载