首页
社区
课程
招聘
[翻译]haggar教程:PESpin v1.0 , 1.1 & 1.3 - manually unpacking
发表于: 2019-2-16 17:20 7683

[翻译]haggar教程:PESpin v1.0 , 1.1 & 1.3 - manually unpacking

2019-2-16 17:20
7683
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 PESpin v1.x - 手动脱壳
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

原文地址:http://www.reversing.be/article.php?story=20050811173217736


嗨,欢迎来到我的新脱壳教程。


本教程是关于手动脱壳PESpin 1.x版本,更准确地说是1.0、1.1和1.3版本。但是,本教程有一些限制:

- 不会叙述PESpin v0.7,因为不需要这样做。如果您知道如何脱壳版本1.3,那么您就知道如何脱壳所有以前的版本。

- 版本1.2是私有版本,不能公开,所以我无法对这个版本进行检测。

- PESpin v1.3有高级代码重定向选项,这在公共版本中不可用,因此本教程将不涵盖这种保护(如果您发现目标包含该选项,请在论坛上给我发送一个PM)。

- 本教程中所有已脱壳的目标只在解包所在的计算机上运行。关于这一点,请阅读第一个教程。


教程面向高级初学者。您必须具备有关PE文件结构和如何使用脱壳工具的基本知识。


内容:

1. 工具和使用材料
2. 教程 1 - PESpin v1.0
3. 教程 2 - PESpin v1.1
4. 教程 3 - PESpin v1.3
5. 最后的话和致谢


1. 工具和使用材料

- OllyDbg 1.10
- LordPE
- Hex Editor
- 目标和材料: http://www.reversing.be/binaries/articles/20050811172936661.rar(图片不清晰请点此下载原作者Word文档)

在这个档案中,你会发现两个文件夹:“PESpin脚本”和“PESpin签名”。第一个文件夹包含一些用于解包PESpin的有用脚本。这些脚本离完美还很远,但它们能帮你一点忙。稍后再了解更多信息,或者只需在记事本中打开它们并阅读信息即可。在第二个文件夹中,您将找到PEID的签名。如果用peid扫描一些加了壳PESpin 1.x版本的文件,它将无法正确识别。只需将这些签名复制粘贴到peid文件夹中的userdb.txt,对压缩文件使用外部扫描,peid就可以识别真正的PESpin版本。如果你注意到一些错误,请发邮件或者PM给我。

如果您想更好地理解本教程,您应该阅读一些优秀的论文:

- Descryption of PE format(解密 PE 格式) by Michael J.O'Leary ; 我认为这是可以在BIW旧网站发现的。

- PORTABLE EXECUTABLE FILE FORMAT(可移植可执行文件格式) by Goppit ; 在这里找到它 http://cracking.accessroot.com/ , 它是6兆大的文件,值得下载。

- 阅读我以前的教程,了解如何解包PESpin 0.3,因为新版本在以前的版本中得到了改进。


2. 教程 1 - PESpin v1.0

在这个版本中,PESpin有两个新技巧:API bp检查和代码重定向。抓取第一个目标packed1.0.exe并在olly中打开它(设置为忽略所有异常)。查找oep和阻止输入表重定向与我们在0.3版本中所做的类似。

保护壳会检查API断点,打开“可执行模块”窗口,选择kernel32.dll并单击“查看名称”。找到GetTickCount并双击它。您现在应该在Kernel32:
77E7A1EE > BA 0000FE7F      MOV EDX,7FFE0000
77E7A1F3   8B02             MOV EAX,DWORD PTR DS:[EDX]
77E7A1F5   F762 04          MUL DWORD PTR DS:[EDX+4]
77E7A1F8   0FACD0 18        SHRD EAX,EDX,18
77E7A1FC   C3               RETN
77E7A1EE > BA 0000FE7F      MOV EDX,7FFE0000
77E7A1F3   8B02             MOV EAX,DWORD PTR DS:[EDX]
77E7A1F5   F762 04          MUL DWORD PTR DS:[EDX+4]
77E7A1F8   0FACD0 18        SHRD EAX,EDX,18
77E7A1FC   C3               RETN
把bp放在retn操作码(因为有API bp检查,不能放头部)上并运行目标程序。您将中断在kernel中的断点bp。删除BP并返回目标代码:
00409D17   8BD8             MOV EBX,EAX
00409D19   F7D3             NOT EBX
00409D1B   33D8             XOR EBX,EAX
00409D1D   43               INC EBX
...
...
00409D17   8BD8             MOV EBX,EAX
00409D19   F7D3             NOT EBX
00409D1B   33D8             XOR EBX,EAX
00409D1D   43               INC EBX
...
...
现在向上滚动,找到这个地方:
00409109   F9               STC              ;也可能是 CLC (F8hex).(二进制查找:F9 72为无保护;F8 72为有保护,要NOP掉两J之间字节)
0040910A   72 0D            JB SHORT packed1_.00409119      ;这里下断!!!
0040910C   8D85 0660271E    LEA EAX,DWORD PTR SS:[EBP+1E276006]
00409112   2D 8417E71D      SUB EAX,1DE71784
00409117   FFD0             CALL EAX                   ;调用计时器函数。
00409119   EB 01            JMP SHORT packed1_.0040911C
这是跳到OEP之前的最后一个地方,就像0.3版一样,除了这里有点不同:如果目标用定时器选项打包,那么将有clc=F8hex而不是第一个stc操作码。在这种情况下,将不执行JB,程序流将继续在创建计时器线程的地方校准EAX。这个地方对于所有下一个PESpin版本都是一样的。你只要把bp放在jb操作码上(不要运行目标)。再次向上滚动并查看这部分代码:
00409109   F9               STC              ;也可能是 CLC (F8hex).(二进制查找:F9 72为无保护;F8 72为有保护,要NOP掉两J之间字节)
0040910A   72 0D            JB SHORT packed1_.00409119      ;这里下断!!!
0040910C   8D85 0660271E    LEA EAX,DWORD PTR SS:[EBP+1E276006]
00409112   2D 8417E71D      SUB EAX,1DE71784
00409117   FFD0             CALL EAX                   ;调用计时器函数。
00409119   EB 01            JMP SHORT packed1_.0040911C
这是跳到OEP之前的最后一个地方,就像0.3版一样,除了这里有点不同:如果目标用定时器选项打包,那么将有clc=F8hex而不是第一个stc操作码。在这种情况下,将不执行JB,程序流将继续在创建计时器线程的地方校准EAX。这个地方对于所有下一个PESpin版本都是一样的。你只要把bp放在jb操作码上(不要运行目标)。再次向上滚动并查看这部分代码:
0040905F  JMP DWORD PTR SS:[ESP-4]   ;重要跳转,这里下断。
00409063  CALL FAR EB00:000003E8
...
...
...
...
0040909B  ???
0040909C  CALL packed1_.004089F2
004090A1  CALL packed1_.004090A9
0040905F  JMP DWORD PTR SS:[ESP-4]   ;重要跳转,这里下断。
00409063  CALL FAR EB00:000003E8
...
...
...
...
0040909B  ???
0040909C  CALL packed1_.004089F2
004090A1  CALL packed1_.004090A9
在那个跳转下断并运行目标。当你中断它,你会看到跳转到409022地址。该跳转对IAT重定向负责。如果没有IAT重定向,该跳转将跳转到它调用的40909C地址,并跳过所有重定向过程。为了避免IAT重定向,您只需在该跳转和40909C的call之间patch掉所有字节(您也可以对它本身进行patch):
0040905F  NOP
00409060  NOP
...
...
...
0040909A  NOP
0040909B  NOP
0040909C  CALL packed1_.004089F2
004090A1  CALL packed1_.004090A9
004090A6  JMP SHORT packed1_.004090AC

现在按下F9,中断在前面设置的断点:

00409109  STC                                    ;F9(Hex)
0040910A  JB SHORT packed1_.00409119             ;你在这里!!!
0040910C  LEA EAX,DWORD PTR SS:[EBP+1E276006]
00409112  SUB EAX,1DE71784
00409117  CALL EAX
00409119  JMP SHORT packed1_.0040911C
现在,如果第一个操作码是clc(替代STC),请在0040910c、00409112和00409117处(两J之间)修补所有指令,以防止调用计时器函数。其实,你总是可以修补那个指令,在这种情况下它不会改变任何东西。然后向下滚动搜索popad操作码。您将看不到它,所以在一些指令中搜索61hex字节。我应该在这里:
0040905F  NOP
00409060  NOP
...
...
...
0040909A  NOP
0040909B  NOP
0040909C  CALL packed1_.004089F2
004090A1  CALL packed1_.004090A9
004090A6  JMP SHORT packed1_.004090AC

现在按下F9,中断在前面设置的断点:

00409109  STC                                    ;F9(Hex)
0040910A  JB SHORT packed1_.00409119             ;你在这里!!!
0040910C  LEA EAX,DWORD PTR SS:[EBP+1E276006]
00409112  SUB EAX,1DE71784
00409117  CALL EAX
00409119  JMP SHORT packed1_.0040911C
现在,如果第一个操作码是clc(替代STC),请在0040910c、00409112和00409117处(两J之间)修补所有指令,以防止调用计时器函数。其实,你总是可以修补那个指令,在这种情况下它不会改变任何东西。然后向下滚动搜索popad操作码。您将看不到它,所以在一些指令中搜索61hex字节。我应该在这里:
00409278    E8 616A00EB      CALL EB40FCDE

修补第一个字节,将bp放在popad上并运行:

00409278   90               NOP                           ;Patch这个字节.
00409279   61               POPAD                         ;这里下断
0040927A   C1E2 F3          SHL EDX,0F3
0040927D   23D0             AND EDX,EAX
0040927F   0FC1D1           XADD ECX,EDX
00409282   BA 69533D94      MOV EDX,943D5369
00409287   69C8 262C4AF2    IMUL ECX,EAX,F24A2C26
0040928D   11C2             ADC EDX,EAX
0040928F   0FBDD0           BSR EDX,EAX
00409292   C7C2 BDCC6DB9    MOV EDX,B96DCCBD
00409298   42               INC EDX
00409299   FFC2             INC EDX
0040929B   C1D2 83          RCL EDX,83 
0040929E   0FBCC8           BSF ECX,EAX
004092A1   23D0             AND EDX,EAX
004092A3   39C2             CMP EDX,EAX
004092A5   81E9 B576A23F    SUB ECX,3FA276B5
004092AB   EB 01            JMP SHORT packed1_.004092AE
004092AD   E7 0F            OUT 0F,EAX 
004092AF   AF               SCAS DWORD PTR ES:[EDI]
004092B0   C8 0FB7D0        ENTER 0B70F,0D0
004092B4   C7C1 0EE985D6    MOV ECX,D685E90E
004092BA   F3:              PREFIX REP: 
004092BB   F7C1 1E8ABDAB    TEST ECX,ABBD8A1E
004092C1  -E9 3A7DFFFF      JMP packed1_.00401000
00409278    E8 616A00EB      CALL EB40FCDE

修补第一个字节,将bp放在popad上并运行:

00409278   90               NOP                           ;Patch这个字节.
00409279   61               POPAD                         ;这里下断
0040927A   C1E2 F3          SHL EDX,0F3
0040927D   23D0             AND EDX,EAX
0040927F   0FC1D1           XADD ECX,EDX
00409282   BA 69533D94      MOV EDX,943D5369
00409287   69C8 262C4AF2    IMUL ECX,EAX,F24A2C26
0040928D   11C2             ADC EDX,EAX
0040928F   0FBDD0           BSR EDX,EAX
00409292   C7C2 BDCC6DB9    MOV EDX,B96DCCBD
00409298   42               INC EDX
00409299   FFC2             INC EDX
0040929B   C1D2 83          RCL EDX,83 
0040929E   0FBCC8           BSF ECX,EAX
004092A1   23D0             AND EDX,EAX
004092A3   39C2             CMP EDX,EAX
004092A5   81E9 B576A23F    SUB ECX,3FA276B5
004092AB   EB 01            JMP SHORT packed1_.004092AE
004092AD   E7 0F            OUT 0F,EAX 
004092AF   AF               SCAS DWORD PTR ES:[EDI]
004092B0   C8 0FB7D0        ENTER 0B70F,0D0
004092B4   C7C1 0EE985D6    MOV ECX,D685E90E
004092BA   F3:              PREFIX REP: 
004092BB   F7C1 1E8ABDAB    TEST ECX,ABBD8A1E
004092C1  -E9 3A7DFFFF      JMP packed1_.00401000
你现在是在壳保护代码的最后一部分。在这里,您可以找到与垃圾代码混合的被盗OEP字节。我打包文件时并没有选择删除OEP,所以这里只有一些垃圾可以让你迷惑。无论你有没有偷过oep,当你到达popad之后的第一个操作码时,你总是可以转储文件,它将正常工作。无所谓oep在壳代码中、目标执行从壳开始。但是如果你想要的话,你可以找到被盗的字节,把它恢复到原来的位置,然后从那里转储。现在,只需跟踪,直到到达某个跳转,该跳转指向代码部分:
004092C1  -E9 3A7DFFFF      JMP packed1_.00401000

在这种情况下,跳转直接进入OEP:

00401000   . 6A 00          PUSH 0
00401002   . E8 F1F1FFFF    CALL packed1_.004001F8
00401007   . A3 CA204000    MOV DWORD PTR DS:[4020CA],EAX
0040100C   . 6A 00          PUSH 0
0040100E   .-E9 EBF1FFFF    JMP packed1_.004001FE
00401013   . E8 F1F1FFFF    CALL packed1_.00400209
00401018   . 0BC0           OR EAX,EAX
0040101A   . 74 01          JE SHORT packed1_.0040101D
0040101C   . C3             RETN
0040101D   > C705 64204000 >MOV DWORD PTR DS:[402064],4003
00401027   . C705 68204000 >MOV DWORD PTR DS:[402068],packed1_.00401>
如果您转储文件,它将无法正常工作。 原因是代码重定向。 注意一些CALL和JMP引导的地方:
004092C1  -E9 3A7DFFFF      JMP packed1_.00401000

在这种情况下,跳转直接进入OEP:

00401000   . 6A 00          PUSH 0
00401002   . E8 F1F1FFFF    CALL packed1_.004001F8
00401007   . A3 CA204000    MOV DWORD PTR DS:[4020CA],EAX
0040100C   . 6A 00          PUSH 0
0040100E   .-E9 EBF1FFFF    JMP packed1_.004001FE
00401013   . E8 F1F1FFFF    CALL packed1_.00400209
00401018   . 0BC0           OR EAX,EAX
0040101A   . 74 01          JE SHORT packed1_.0040101D
0040101C   . C3             RETN
0040101D   > C705 64204000 >MOV DWORD PTR DS:[402064],4003
00401027   . C705 68204000 >MOV DWORD PTR DS:[402068],packed1_.00401>
如果您转储文件,它将无法正常工作。 原因是代码重定向。 注意一些CALL和JMP引导的地方:
00401002  CALL packed1_.004001F8
...
0040100E  JMP packed1_.004001FE
它们指向的地址低于401000,这意味着PE头。 这不正常。 我会快速解释一下:
00401002  CALL packed1_.004001F8
...
0040100E  JMP packed1_.004001FE
它们指向的地址低于401000,这意味着PE头。 这不正常。 我会快速解释一下:

PESpin将加载所有段到内存中,解密并完成解包所需的所有操作。之后,PE头对任何事情都不再重要,所以它可以随心所欲地改变 - 它不会影响程序在内存中。 PESpin将采用这个事实的优点,它将用FFFFF填充PE头的一部分...(顺便说一句,它会破坏掉保存有段信息的PE头的一部分)。 然后它将在代码段搜索PUSH xxxxxxxx或CALL xxxxxxxx(也许是JMP)指令,因为它们长5个字节。 然后它将该操作码替换为一些JMP或CALL到PE头,它将放置原始指令并返回代码段(如果需要)。 指令必须长5个字节的原因是因为它们很容易用JMP操作码替换(它的长度为5个字节)。 我们来看两个例子:

a) CALL example(call-jmp):特征码#E8??????FF#---->处理:直接用后者替换前者
00401002   . E8 F1F1FFFF    CALL packed1_.004001F8
此CALL指向PE头。 右键单击它并跟随它。 在那里你会发现原始的“被盗代码”:
00401002   . E8 F1F1FFFF    CALL packed1_.004001F8
此CALL指向PE头。 右键单击它并跟随它。 在那里你会发现原始的“被盗代码”:
004001F8  -E9 09130000      JMP packed1_.00401506
所以你只需要用JMP 401506替换CALL 4001F8。如你所见,它非常简单。
004001F8  -E9 09130000      JMP packed1_.00401506
所以你只需要用JMP 401506替换CALL 4001F8。如你所见,它非常简单。


b) JMP example(JMP-PUSH):特征码#E9??????FF#---->处理:直接用后者替换前者
0040100E   .-E9 EBF1FFFF    JMP packed1_.004001FE
再次,跟随此跳转到PE头,您将看到被盗的原始代码:
0040100E   .-E9 EBF1FFFF    JMP packed1_.004001FE
再次,跟随此跳转到PE头,您将看到被盗的原始代码:
004001FE   68 F4204000      PUSH packed1_.004020F4
您将在像第一个示例中一样修复此问题,您放置PUSH 4020F4指令替换那个跳转。
004001FE   68 F4204000      PUSH packed1_.004020F4
您将在像第一个示例中一样修复此问题,您放置PUSH 4020F4指令替换那个跳转。


好的,你处理它并不难。 首个想法是“为什么要恢复那些代码,为什么不把它留在那里而一起dump它?”。 原因是PE头被破坏(部分信息被删除),我们不再拥有有效的PE文件。 如果我们从磁盘粘贴原始头,程序将跳转到它,它将找不到重定向的代码,因此结果是崩溃。 第二个想法是“但是有很多重定向的代码,如何解决所有这些问题?手动?我不会疯狂地在电脑前浪费一整夜!”。 其实,由于PE头的大小决定了重定向的代码数量可能有限,但这个数字也很大。 因此,要修复大量代码,我们将使用/编写Olly Script来自动执行作业。 这根本不难。 它应该是这样的:

- 首先,我们需要找到这样的JMP/CALL操作码。 我们的srcipt必须搜索以F结尾的JMP/CALL,因为这意味着它会跳转到后面。 因此搜索带有E9???????F或E8???????F字节的指令。

- 然后我们必须检查它是否跳转到PE头。 以我们的a) CALL example为例。 取CALL的地址=401002并取CALL值(E8后的四个字节,按相反顺序)FFFFF1F1。 现在相加这两个值401002 + FFFFF1F1 = 4001F3,如果结果在400000 <= RESULT <401000之间,那么你知道你在正确的位置。

- 然后,使用基本数学,您必须恢复原始操作码。 它不能被复制粘贴,必须进行计算。 这里需要基本的十六进制数学,很少的计算和一些时间。 之后,您将拥有完美的脚本。 如果你不(或不知道如何)自己做,你可以使用我的“PESpin  -  Code Fixer.txt”(包含在档案中)。


现在,如果你已完成所有操作,就像我写的那样,然后使用脚本来修复重定向代码,转储文件。 如果你运行它,你可能会得到错误消息,告诉你这个应用程序是如何无效的Win32应用程序。 别担心。 打开LordPE,转到选项并在重建PE下仅选中“验证PE”选项。 关闭选项,打开重建PE并打开我们的转储文件。 验证转储后,运行它,它将工作得很完美;)干得好! 你刚刚解压缩了PEspin v1.0。

这种方法适用于ASM和BC ++程序,但不适用于Delphi和MSVC ++。 原因是不同的IAT重定向,OllyDump插件无法处理。 这可以通过构建新的导入段来解决。 我们将在下一个教程中看到。

但是有一个原因就是为什么转储文件可能只能在解压缩文件的机器上运行。 如果你看看入口跳转,你会发现大多数跳转都是绝对跳转,跳转到内存中的指定位置。 因此,在另一台具有不同版本dll的计算机上,转储文件可能会崩溃。 这可以修复,但对于更大的文件,手动操作是不可能的。 这是所有PESpin版本的问题。


3. 教程 2 - PESpin v1.1


在这个版本中,一切都与1.0相同,除了这个带来了新选项 -  CRYPT和CLEAR 守护。 那是什么? 简单,阅读PESpin的帮助文件:

CRYPT守护:
加密标记CRYPT_START和CRYPT_END之间的代码在文件保护过程中被加密,并且当执行受保护文件时,代码在使用之前被严密地解密,并在使用后立即再次加密(运行时防止转储)。

CLEAR守护:
CLEAR_START和CLEAR_END标记提供了在执行后删除代码块的功能。这些宏应该只放在应用程序中执行一次的代码区域。在受保护的应用程序中,任何尝试在这些宏中重新执行代码块都会导致异常。


这对我们来说不是什么大问题。 对于我们的第二个目标,我们将选择keygen.exe,它包含所有CLEAR和CRYPT选项(感谢detten;)。 查找OEP的过程与1.0版本中的完全相同,因此没有必要再将其全部写出。 简而言之; 不忽略所有异常,将bp放在GetTickCount API的末尾并运行目标,删除bp并返回目标代码。 但是......我们将遇到一个问题,我们将在所有PESpin 1.x版本中使用Delphi和MSVC ++目标。 问题是OllyDump无法重建IAT。 我们必须手动完成所有操作。 由于这个问题,我们必须知道我们的打包目标正在使用哪个dll。 让我们开始吧!


首先,我们将找到keygen.exe需要什么dll。 命令行中将bp放在LoadLibraryA(API中的最后一个RETN)上并运行目标。 你会在奇怪的地方中断(也许你的值不同):
77ED6FC4 >-E9 1860FB42      JMP BAE8CFE1
77ED6FC9   90               NOP
77ED6FCA   90               NOP
77ED6FCB   90               NOP
77ED6FCC   90               NOP
77ED6FCD   90               NOP
77ED6FCE   90               NOP
77ED6FCF   90               NOP
77ED6FD0   90               NOP
77ED6FD1   90               NOP
77ED6FD2   90               NOP
77ED6FD3 >-E9 7D61FB42      JMP BAE8D155
77ED6FD8   90               NOP
77ED6FD9   90               NOP
77ED6FDA   90               NOP
77ED6FDB   90               NOP
77ED6FDC   90               NOP
77ED6FDD   90               NOP
77ED6FDE   90               NOP
77ED6FDF   90               NOP
删除bp,打开内存窗口并在最后一节放置“访问内存bp”。 这是一个SFX。 现在按Shift + F9,你将返回到壳代码(然后删除mem bp):
77ED6FC4 >-E9 1860FB42      JMP BAE8CFE1
77ED6FC9   90               NOP
77ED6FCA   90               NOP
77ED6FCB   90               NOP
77ED6FCC   90               NOP
77ED6FCD   90               NOP
77ED6FCE   90               NOP
77ED6FCF   90               NOP
77ED6FD0   90               NOP
77ED6FD1   90               NOP
77ED6FD2   90               NOP
77ED6FD3 >-E9 7D61FB42      JMP BAE8D155
77ED6FD8   90               NOP
77ED6FD9   90               NOP
77ED6FDA   90               NOP
77ED6FDB   90               NOP
77ED6FDC   90               NOP
77ED6FDD   90               NOP
77ED6FDE   90               NOP
77ED6FDF   90               NOP
删除bp,打开内存窗口并在最后一节放置“访问内存bp”。 这是一个SFX。 现在按Shift + F9,你将返回到壳代码(然后删除mem bp):
0040D491   85C0             TEST EAX,EAX
0040D493   0F84 3F090000    JE keygen.0040DDD8
0040D499   E8 01000000      CALL keygen.0040D49F
0040D49E   FF59 50          CALL FAR FWORD PTR DS:[ECX+50]
0040D4A1   51               PUSH ECX
0040D4A2   55               PUSH EBP
0040D4A3   810424 12374000  ADD DWORD PTR SS:[ESP],keygen.00403712
0040D4AA   814424 04 220000>ADD DWORD PTR SS:[ESP+4],22
我们在这里搜索什么? 如果您记得上一章,PESpin解密DLL名称,将其加载到内存中,然后删除它的名称。 我们现在在壳加载DLL的地方,我们将找到他删除DLL名称的地方。 我们将修补该擦除过程,以便稍后我们可以看到使用了什么DLL。 使用F7追踪,直到你到达(这是很多追踪):
0040D491   85C0             TEST EAX,EAX
0040D493   0F84 3F090000    JE keygen.0040DDD8
0040D499   E8 01000000      CALL keygen.0040D49F
0040D49E   FF59 50          CALL FAR FWORD PTR DS:[ECX+50]
0040D4A1   51               PUSH ECX
0040D4A2   55               PUSH EBP
0040D4A3   810424 12374000  ADD DWORD PTR SS:[ESP],keygen.00403712
0040D4AA   814424 04 220000>ADD DWORD PTR SS:[ESP+4],22
我们在这里搜索什么? 如果您记得上一章,PESpin解密DLL名称,将其加载到内存中,然后删除它的名称。 我们现在在壳加载DLL的地方,我们将找到他删除DLL名称的地方。 我们将修补该擦除过程,以便稍后我们可以看到使用了什么DLL。 使用F7追踪,直到你到达(这是很多追踪):
0040D4F0   800B 00          OR BYTE PTR DS:[EBX],0
0040D4F3   74 0D            JE SHORT keygen.0040D502
0040D4F5   8813             MOV BYTE PTR DS:[EBX],DL
0040D4F7   C1C2 04          ROL EDX,4
0040D4FA   75 01            JNZ SHORT keygen.0040D4FD
0040D4FC   E8 43FF6424      CALL 24A5D444
0040D501   FC               CLD
0040D502   93               XCHG EAX,EBX
0040D503   8B56 10          MOV EDX,DWORD PTR DS:[ESI+10]
0040D4F0   800B 00          OR BYTE PTR DS:[EBX],0
0040D4F3   74 0D            JE SHORT keygen.0040D502
0040D4F5   8813             MOV BYTE PTR DS:[EBX],DL
0040D4F7   C1C2 04          ROL EDX,4
0040D4FA   75 01            JNZ SHORT keygen.0040D4FD
0040D4FC   E8 43FF6424      CALL 24A5D444
0040D501   FC               CLD
0040D502   93               XCHG EAX,EBX
0040D503   8B56 10          MOV EDX,DWORD PTR DS:[ESI+10]
这是删除DLL名称的地方。 走到这一行
0040D4F5   8813             MOV BYTE PTR DS:[EBX],DL
并在转储窗口中跟随它。 在那里你会看到KERNEL32.DLL的名字。 修补此操作码MOV BYTE PTR DS:[EBX],DL然后就运行目标。 我们的目标将开始,但这就是我们想要的。 进入转储窗口,在那里你会发现目标使用的所有dll:
0040D4F5   8813             MOV BYTE PTR DS:[EBX],DL
并在转储窗口中跟随它。 在那里你会看到KERNEL32.DLL的名字。 修补此操作码MOV BYTE PTR DS:[EBX],DL然后就运行目标。 我们的目标将开始,但这就是我们想要的。 进入转储窗口,在那里你会发现目标使用的所有dll:
00402102  4B 45 52 4E 45 4C 33 32 2E 44 4C 4C 00 00 F7 00  KERNEL32.DLL..÷.
00402112  00 00 00 00 00 00 00 00 00 00 C4 00 00 00 00 00  ..........?.....
00402122  00 00 00 00 00 00 00 00 00 00 00 00 C5 00 00 00  ............?...
00402132  00 00 00 00 00 00 00 00 CC 00 00 00 00 00 00 00  ........?.......
00402142  00 00 00 00 00 00 CC 00 00 00 00 00 00 00 00 00  ......?.........
00402152  00 00 D2 00 00 00 00 00 00 00 00 00 00 00 00 00  ..?.............
00402162  00 00 00 00 D3 00 00 00 00 00 00 00 00 00 00 00  ....?...........
00402172  00 00 00 00 00 00 00 00 00 00 D3 00 00 00 00 00  ..........?.....
00402182  00 00 00 00 00 00 00 00 00 00 D3 00 00 00 00 00  ..........?.....
00402192  00 00 00 00 00 00 00 00 00 00 00 00 55 53 45 52  ............USER
004021A2  33 32 2E 44 4C 4C 00 00 C3 00 00 00 00 00 00 00  32.DLL..?.......
004021B2  00 00 00 00 00 00 00 00 00 00 00 00 D3 00 00 00  ............?...
004021C2  00 00 00 00 00 00 00 00 00 00 D3 00 00 00 00 00  ..........?.....
004021D2  00 00 00 00 00 00 D3 00 00 00 00 00 00 00 00 00  ......?.........
004021E2  00 00 00 00 00 00 47 44 49 33 32 2E 44 4C 4C 00  ......GDI32.DLL.
004021F2  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
我们的目标很小,它只使用kernel32.dll,user32.dll和gdi32.dll。 好! 现在我们将在Olly中重新启动目标并找到OEP。 将bp放在GetTickCount API中的最后一个RETN上,运行目标,删除bp并返回代码:
00402102  4B 45 52 4E 45 4C 33 32 2E 44 4C 4C 00 00 F7 00  KERNEL32.DLL..÷.
00402112  00 00 00 00 00 00 00 00 00 00 C4 00 00 00 00 00  ..........?.....
00402122  00 00 00 00 00 00 00 00 00 00 00 00 C5 00 00 00  ............?...
00402132  00 00 00 00 00 00 00 00 CC 00 00 00 00 00 00 00  ........?.......
00402142  00 00 00 00 00 00 CC 00 00 00 00 00 00 00 00 00  ......?.........
00402152  00 00 D2 00 00 00 00 00 00 00 00 00 00 00 00 00  ..?.............
00402162  00 00 00 00 D3 00 00 00 00 00 00 00 00 00 00 00  ....?...........
00402172  00 00 00 00 00 00 00 00 00 00 D3 00 00 00 00 00  ..........?.....
00402182  00 00 00 00 00 00 00 00 00 00 D3 00 00 00 00 00  ..........?.....
00402192  00 00 00 00 00 00 00 00 00 00 00 00 55 53 45 52  ............USER
004021A2  33 32 2E 44 4C 4C 00 00 C3 00 00 00 00 00 00 00  32.DLL..?.......
004021B2  00 00 00 00 00 00 00 00 00 00 00 00 D3 00 00 00  ............?...
004021C2  00 00 00 00 00 00 00 00 00 00 D3 00 00 00 00 00  ..........?.....
004021D2  00 00 00 00 00 00 D3 00 00 00 00 00 00 00 00 00  ......?.........
004021E2  00 00 00 00 00 00 47 44 49 33 32 2E 44 4C 4C 00  ......GDI32.DLL.
004021F2  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
我们的目标很小,它只使用kernel32.dll,user32.dll和gdi32.dll。 好! 现在我们将在Olly中重新启动目标并找到OEP。 将bp放在GetTickCount API中的最后一个RETN上,运行目标,删除bp并返回代码:
0040E4D8   8BD8             MOV EBX,EAX
0040E4DA   F7D3             NOT EBX
0040E4DC   33D8             XOR EBX,EAX
0040E4DE   43               INC EBX
0040E4DF   68 87000000      PUSH 87
0040E4E4   59               POP ECX
0040E4E5   66:35 4C50       XOR AX,504C
0040E4E9   66:05 8911       ADD AX,1189
0040E4ED   AA               STOS BYTE PTR ES:[EDI]
0040E4EE   EB 01            JMP SHORT keygen.0040E4F1
0040E4F0   68 499CC12C      PUSH 2CC19C49
0040E4F5   24 06            AND AL,6
0040E4D8   8BD8             MOV EBX,EAX
0040E4DA   F7D3             NOT EBX
0040E4DC   33D8             XOR EBX,EAX
0040E4DE   43               INC EBX
0040E4DF   68 87000000      PUSH 87
0040E4E4   59               POP ECX
0040E4E5   66:35 4C50       XOR AX,504C
0040E4E9   66:05 8911       ADD AX,1189
0040E4ED   AA               STOS BYTE PTR ES:[EDI]
0040E4EE   EB 01            JMP SHORT keygen.0040E4F1
0040E4F0   68 499CC12C      PUSH 2CC19C49
0040E4F5   24 06            AND AL,6
查找导致重定向过程的跳转并修补介于它与良好调用之间的所有字节:
0040D5DF   FF6424 FC        JMP DWORD PTR SS:[ESP-4]  <--- Jump!!!
...
...                                                   <--- Patch所有这些操作码!!!
...
0040D643   E8 C4F6FFFF      CALL keygen.0040CD0C      <--- Good call!!!
0040D648   E8 03000000      CALL keygen.0040D650

然后向下滚动到我们众所周知的地方:

0040D6D7   B0 F9            MOV AL,0F9
0040D6D9   72 3F            JB SHORT keygen.0040D71A
0040D6DB   8D85 F469271E    LEA EAX,DWORD PTR SS:[EBP+1E2769F4]
0040D6E1   2D 8417E71D      SUB EAX,1DE71784
0040D6E6   FFD0             CALL EAX
0040D6E8   EB 02            JMP SHORT keygen.0040D6EC
0040D5DF   FF6424 FC        JMP DWORD PTR SS:[ESP-4]  <--- Jump!!!
...
...                                                   <--- Patch所有这些操作码!!!
...
0040D643   E8 C4F6FFFF      CALL keygen.0040CD0C      <--- Good call!!!
0040D648   E8 03000000      CALL keygen.0040D650

然后向下滚动到我们众所周知的地方:

0040D6D7   B0 F9            MOV AL,0F9
0040D6D9   72 3F            JB SHORT keygen.0040D71A
0040D6DB   8D85 F469271E    LEA EAX,DWORD PTR SS:[EBP+1E2769F4]
0040D6E1   2D 8417E71D      SUB EAX,1DE71784
0040D6E6   FFD0             CALL EAX
0040D6E8   EB 02            JMP SHORT keygen.0040D6EC
这是可能调用计时器的地方。 我们的目标在加壳时没有启用该选项,我们不需要修补40D6DB到40D6E6的操作码。 好的,向下滚动并找到POPAD操作码。 你会发现它稍稍被混淆。
0040D8FA   E8 610FC90F      CALL 1009E860

所以修补第一个字节以获得清晰的画面。

0040D8FA   90               NOP
0040D8FB   61               POPAD

POPAD之后,开始窃取OEP代码并混之以垃圾代码。 看起来没有被盗的OEP字节,因为指向代码段的跳转现在跳到段开头401000:

0040D8FC   0FC9             BSWAP ECX
0040D8FE   0FACC2 13        SHRD EDX,EAX,13
...
...
...
0040D947  -E9 B436FFFF      JMP keygen.00401000 <---跳到OEP!!!
0040D8FA   E8 610FC90F      CALL 1009E860

所以修补第一个字节以获得清晰的画面。

0040D8FA   90               NOP
0040D8FB   61               POPAD

POPAD之后,开始窃取OEP代码并混之以垃圾代码。 看起来没有被盗的OEP字节,因为指向代码段的跳转现在跳到段开头401000:

0040D8FC   0FC9             BSWAP ECX
0040D8FE   0FACC2 13        SHRD EDX,EAX,13
...
...
...
0040D947  -E9 B436FFFF      JMP keygen.00401000 <---跳到OEP!!!
执行跳转,你将落在OEP上。 即使按Ctrl + A分析代码,代码仍然看起来很糟糕,所以右键单击它,选择分析并从模块中删除分析。 然后你会有更好的画面:
00401000   9C               PUSHFD
00401001   60               PUSHAD
00401002   B9 B5381023      MOV ECX,231038B5
00401007   BF 7896AA00      MOV EDI,0AA9678
0040100C   81E9 91381023    SUB ECX,23103891
00401012   B8 5F1360C2      MOV EAX,C260135F
...
...
首先,我们将检查PE头部分是否有被盗/重定向的代码。 只需运行“PESpin  -  Code Fixer.txt”脚本即可。 检查日志窗口,您将看到该脚本修复了4A操作码:
00401000   9C               PUSHFD
00401001   60               PUSHAD
00401002   B9 B5381023      MOV ECX,231038B5
00401007   BF 7896AA00      MOV EDI,0AA9678
0040100C   81E9 91381023    SUB ECX,23103891
00401012   B8 5F1360C2      MOV EAX,C260135F
...
...
首先,我们将检查PE头部分是否有被盗/重定向的代码。 只需运行“PESpin  -  Code Fixer.txt”脚本即可。 检查日志窗口,您将看到该脚本修复了4A操作码:
[ Simple Code Fixing - number of stolen opcodes ]
stolen = 0000004A
[ Simple Code Fixing - number of stolen opcodes ]
stolen = 0000004A
好的,这就是我们从PESpin的早期版本中所知道的,但现在我们将遇到新的技巧 - 代码解密和擦除。 这部分代码一开始就是第一个解密过程的开始:
00401000   9C               PUSHFD
00401001   60               PUSHAD
00401002   B9 B5381023      MOV ECX,231038B5
00401007   BF 7896AA00      MOV EDI,0AA9678
0040100C   81E9 91381023    SUB ECX,23103891
00401012   B8 5F1360C2      MOV EAX,C260135F
00401017   05 DCE1E03D      ADD EAX,3DE0E1DC
0040101C   FF0D 22104000    DEC DWORD PTR DS:[401022]
00401022   0011             ADD BYTE PTR DS:[ECX],DL<--- 跟踪这一行!!!
00401024   61               POPAD
00401025   9D               POPFD
使用F8跟踪我在上面显示的行,你会看到它变为:
00401000   9C               PUSHFD
00401001   60               PUSHAD
00401002   B9 B5381023      MOV ECX,231038B5
00401007   BF 7896AA00      MOV EDI,0AA9678
0040100C   81E9 91381023    SUB ECX,23103891
00401012   B8 5F1360C2      MOV EAX,C260135F
00401017   05 DCE1E03D      ADD EAX,3DE0E1DC
0040101C   FF0D 22104000    DEC DWORD PTR DS:[401022]
00401022   0011             ADD BYTE PTR DS:[ECX],DL<--- 跟踪这一行!!!
00401024   61               POPAD
00401025   9D               POPFD
使用F8跟踪我在上面显示的行,你会看到它变为:
00401022   FF10             CALL DWORD PTR DS:[EAX]
该调用将引导您进入一个程序,该程序将解密目标中的某些代码并擦除某些内容。 如果你想看看那里发生了什么,你可以去F7。 它只会解密POPFD操作码以下的几个操作码并擦除以上所有操作码。 按F8而不是F7,你会看到变化:
00401022   FF10             CALL DWORD PTR DS:[EAX]
该调用将引导您进入一个程序,该程序将解密目标中的某些代码并擦除某些内容。 如果你想看看那里发生了什么,你可以去F7。 它只会解密POPFD操作码以下的几个操作码并擦除以上所有操作码。 按F8而不是F7,你会看到变化:
00401000   0000             ADD BYTE PTR DS:[EAX],AL
00401002   0000             ADD BYTE PTR DS:[EAX],AL
00401004   0000             ADD BYTE PTR DS:[EAX],AL
00401006   0000             ADD BYTE PTR DS:[EAX],AL
00401008   0000             ADD BYTE PTR DS:[EAX],AL
0040100A   0000             ADD BYTE PTR DS:[EAX],AL
0040100C   0000             ADD BYTE PTR DS:[EAX],AL
0040100E   0000             ADD BYTE PTR DS:[EAX],AL
00401010   0000             ADD BYTE PTR DS:[EAX],AL
00401012   0000             ADD BYTE PTR DS:[EAX],AL
00401014   0000             ADD BYTE PTR DS:[EAX],AL
00401016   0000             ADD BYTE PTR DS:[EAX],AL
00401018   0000             ADD BYTE PTR DS:[EAX],AL
0040101A   0000             ADD BYTE PTR DS:[EAX],AL
0040101C   0000             ADD BYTE PTR DS:[EAX],AL
0040101E   0000             ADD BYTE PTR DS:[EAX],AL
00401020   0000             ADD BYTE PTR DS:[EAX],AL
00401022   0000             ADD BYTE PTR DS:[EAX],AL
00401024   61               POPAD
00401025   9D               POPFD
00401026   6A 00            PUSH 0
00401028   E8 83F1FFFF      CALL keygen.004001B0
0040102D   A3 E4304000      MOV DWORD PTR DS:[4030E4],EAX
00401032   6A 00            PUSH 0
00401034  -E9 7DF1FFFF      JMP keygen.004001B6  <--- 到PE头!
00401039   6A 00            PUSH 0
0040103B   6A 01            PUSH 1
0040103D   50               PUSH EAX
0040103E   E8 7EF1FFFF      CALL keygen.004001C1 <--- 到PE头!
00401043   6A 00            PUSH 0
00401045   E8 7DF1FFFF      CALL keygen.004001C7 <--- 到PE头!
请注意,一些新的解密跳转和调用会指向PE头,因此我们必须再次运行脚本来修复重定向,然后使用NOP填充401000到401025的所有代码:
00401000   0000             ADD BYTE PTR DS:[EAX],AL
00401002   0000             ADD BYTE PTR DS:[EAX],AL
00401004   0000             ADD BYTE PTR DS:[EAX],AL
00401006   0000             ADD BYTE PTR DS:[EAX],AL
00401008   0000             ADD BYTE PTR DS:[EAX],AL
0040100A   0000             ADD BYTE PTR DS:[EAX],AL
0040100C   0000             ADD BYTE PTR DS:[EAX],AL
0040100E   0000             ADD BYTE PTR DS:[EAX],AL
00401010   0000             ADD BYTE PTR DS:[EAX],AL
00401012   0000             ADD BYTE PTR DS:[EAX],AL
00401014   0000             ADD BYTE PTR DS:[EAX],AL
00401016   0000             ADD BYTE PTR DS:[EAX],AL
00401018   0000             ADD BYTE PTR DS:[EAX],AL
0040101A   0000             ADD BYTE PTR DS:[EAX],AL
0040101C   0000             ADD BYTE PTR DS:[EAX],AL
0040101E   0000             ADD BYTE PTR DS:[EAX],AL
00401020   0000             ADD BYTE PTR DS:[EAX],AL
00401022   0000             ADD BYTE PTR DS:[EAX],AL
00401024   61               POPAD
00401025   9D               POPFD
00401026   6A 00            PUSH 0
00401028   E8 83F1FFFF      CALL keygen.004001B0
0040102D   A3 E4304000      MOV DWORD PTR DS:[4030E4],EAX
00401032   6A 00            PUSH 0
00401034  -E9 7DF1FFFF      JMP keygen.004001B6  <--- 到PE头!
00401039   6A 00            PUSH 0
0040103B   6A 01            PUSH 1
0040103D   50               PUSH EAX
0040103E   E8 7EF1FFFF      CALL keygen.004001C1 <--- 到PE头!
00401043   6A 00            PUSH 0
00401045   E8 7DF1FFFF      CALL keygen.004001C7 <--- 到PE头!
请注意,一些新的解密跳转和调用会指向PE头,因此我们必须再次运行脚本来修复重定向,然后使用NOP填充401000到401025的所有代码:
00401000   . 90             NOP
...
...
...
00401024   . 90             NOP
00401025   . 90             NOP
00401026   . 6A 00          PUSH 0
00401028   . E8 1B040000    CALL keygen.00401448
0040102D   . A3 E4304000    MOV DWORD PTR DS:[4030E4],EAX 
00401032   . 6A 00          PUSH 0
00401034   . 68 7F104000    PUSH keygen.0040107F
00401039   . 6A 00          PUSH 0
0040103B   . 6A 01          PUSH 1
0040103D   . 50             PUSH EAX
0040103E   . E8 11040000    CALL keygen.00401454
00401043   . 6A 00          PUSH 0
00401045   . E8 F8030000    CALL keygen.00401442
0040104A   . EB 0B          JMP SHORT keygen.00401057
0040104C     EB             DB EB
我们已经修复了第一种解密类型CLEAR。 现在我们要找到并修复CRYPT。 由于目标很小,你可以向下滚动,找到两个有趣的call:
00401000   . 90             NOP
...
...
...
00401024   . 90             NOP
00401025   . 90             NOP
00401026   . 6A 00          PUSH 0
00401028   . E8 1B040000    CALL keygen.00401448
0040102D   . A3 E4304000    MOV DWORD PTR DS:[4030E4],EAX 
00401032   . 6A 00          PUSH 0
00401034   . 68 7F104000    PUSH keygen.0040107F
00401039   . 6A 00          PUSH 0
0040103B   . 6A 01          PUSH 1
0040103D   . 50             PUSH EAX
0040103E   . E8 11040000    CALL keygen.00401454
00401043   . 6A 00          PUSH 0
00401045   . E8 F8030000    CALL keygen.00401442
0040104A   . EB 0B          JMP SHORT keygen.00401057
0040104C     EB             DB EB

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2020-1-28 22:33 被kanxue编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//