Windows逆向之脱壳-脱壳实战
Aking9 发表于 河南 历史精选 2624浏览 · 2024-07-31 15:33

声明

本文章中发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不用于其他任何目的,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关.

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跟踪

  • 当对这个程序的壳运行熟悉后,我们还可以时使用F2F9来更加快速定位。

    在追踪时,我们可能会因为一些意外是的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

我们查看程序是否可以成功执行

附件:
0 条评论
某人
表情
可输入 255