吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 10162|回复: 23
收起左侧

[分享] ESP定律详解

  [复制链接]
leel 发表于 2010-7-29 22:18
1.前言

在论坛上看到很多朋友,不知道什么是ESP定律,ESP的适用范围是什么,ESP定律的原理是什么,如何使用ESP定律?

调查结果发现,大家对ESP定律很感兴趣,当然因为实在是太好用了,现在我就来告诉大家什么是ESP定律,它的原理是什么!!

2.准备知识

在我们开始讨论ESP定律之前,我先给你讲解一下一些简单的汇编知识。
1.call
这个命令是访问子程序的一个汇编基本指令。也许你说,这个我早就知道了!别急请继续看完。
call真正的意义是什么呢?我们可以这样来理解:1.向堆栈中压入下一行程序的地址;2.JMP到call的子程序地址处。例如:

00401029  . E8 DA240A00  call 004A3508
0040102E  . 5A      pop edx
在执行了00401029以后,程序会将0040102E压入堆栈,然后JMP到004A3508地址处!

2.RET
与call对应的就是RET了。对于RET我们可以这样来理解:1.将当前的ESP中指向的地址出栈;2.JMP到这个地址。

这个就完成了一次调用子程序的过程。在这里关键的地方是:如果我们要返回父程序,则当我们在堆栈中进行堆栈的操作的时候,一定要保证在RET这条指令之前,ESP指向的是我们压入栈中的地址。这也就是著名的“堆栈平衡”原理!

3.狭义ESP定律

ESP定律的原理就是“堆栈平衡”原理。

让我们来到程序的入口处看看吧!

1.这个是加了UPX壳的入口时各个寄存器的值!
EAX 00000000
ECX 0012FFB0
EDX 7FFE0304
EBX 7FFDF000
ESP 0012FFC4
EBP 0012FFF0
ESI 77F51778 ntdll.77F51778
EDI 77F517E6 ntdll.77F517E6
EIP 0040EC90 note-upx.<ModuleEntryPoint>
C 0 ES 0023 32bit 0(FFFFFFFF)
P 1 CS 001B 32bit 0(FFFFFFFF)
A 0 SS 0023 32bit 0(FFFFFFFF)
Z 0 DS 0023 32bit 0(FFFFFFFF)
S 1 FS 0038 32bit 7FFDE000(FFF)
T 0 GS 0000 NULL
D 0
O 0 LastErr ERROR_MOD_NOT_FOUND (0000007E)

2.这个是UPX壳JMP到OEP后的寄存器的值!
EAX 00000000
ECX 0012FFB0
EDX 7FFE0304
EBX 7FFDF000
ESP 0012FFC4
EBP 0012FFF0
ESI 77F51778 ntdll.77F51778
EDI 77F517E6 ntdll.77F517E6
EIP 004010CC note-upx.004010CC
C 0 ES 0023 32bit 0(FFFFFFFF)
P 1 CS 001B 32bit 0(FFFFFFFF)
A 0 SS 0023 32bit 0(FFFFFFFF)
Z 1 DS 0023 32bit 0(FFFFFFFF)
S 0 FS 0038 32bit 7FFDE000(FFF)
T 0 GS 0000 NULL
D 0
O 0 LastErr ERROR_MOD_NOT_FOUND (0000007E)

呵呵~是不是除了EIP不同以外,其他都一模一样啊!

为什么会这样呢?
我们来看看UPX的壳的第一行:

0040EC90 n> 60       pushad   //****注意这里*****
0040EC91  BE 15B04000   mov esi,note-upx.0040B015

PUSHAD就是把所有寄存器压栈!我们在到壳的最后看看:

0040EE0F  61       popad   //****注意这里*****
0040EE10 - E9 B722FFFF   jmp note-upx.004010CC //JMP到OEP

POP就是将所有寄存器出栈!


而当我们PUSHAD的时候,ESP将寄存器压入了0012FFC0--0012FFA4的堆栈中!如下:

0012FFA4 77F517E6 返回到 ntdll.77F517E6 来自 ntdll.77F78C4E     //EDI
0012FFA8 77F51778 返回到 ntdll.77F51778 来自 ntdll.77F517B5     //ESI
0012FFAC 0012FFF0                          //EBP
0012FFB0 0012FFC4                         //ESP
0012FFB4 7FFDF000                         //EBX
0012FFB8 7FFE0304                        //EDX
0012FFBC 0012FFB0                        //ECX
0012FFC0 00000000                       //EAX

所以这个时候,在教程上面就告诉我们对ESP的0012FFA4下硬件访问断点。也就是说当程序要访问这些堆栈,从而恢复原来寄存器的值,准备跳向苦苦寻觅的OEP的时候,OD帮助我们中断下来。

于是我们停在0040EE10这一行!

总结:我们可以把壳假设为一个子程序,当壳把代码解压前和解压后,他必须要做的是遵循堆栈平衡的原理,让ESP执行到OEP的时候,使ESP=0012FFC4。

4.广义ESP定律

很多人看完了教程就会问:ESP定律是不是就是0012FFA4,ESP定律的适用范围是不是只能是压缩壳!

我的回答是:NO!

看完了上面你就知道你如果用0012FFA8也是可以的,ESP定律不仅用于压缩壳他也可以用于加密壳!!!

首先,告诉你一条经验也是事实---当PE文件运行开始的时候,也就是进入壳的第一行代码的时候。寄存器的值总是上面的那些值,不信你自己去试试!而当到达OEP后,绝大多的程序都第一句都是压栈!(除了BC编写的程序,BC一般是在下面几句压栈)

现在,根据上面的ESP原理,我们知道多数壳在运行到OEP的时候ESP=0012FFC4。这就是说程序的第一句是对0012FFC0进行写入操作!

最后我们得到了广义的ESP定律,对只要在0012FFC0下,硬件写入断点,我们就能停在OEP的第二句处!!

下面我们来举个例子,就脱壳进阶第一篇吧!

载入OD后,来到这里:

0040D042 N> B8 00D04000   mov eax,Notepad.0040D000 //停在这里
0040D047  68 4C584000   push Notepad.0040584C
0040D04C  64:FF35 00000000 push dword ptr fs:[0]  //第一次硬件中断,F9
0040D053  64:8925 00000000 mov dword ptr fs:[0],esp
0040D05A  66:9C      pushfw
0040D05C  60       pushad
0040D05D  50       push eax

直接对0012FFC0下硬件写入断点,F9运行。(注意硬件中断)

在0040D04C第一次硬件中断,F9继续!

0040D135  A4       movs byte ptr es:[edi],byte ptr ds:[esi] //访问异常,不管他 shift+F9继续
0040D136  33C9      xor ecx,ecx
0040D138  83FB 00     cmp ebx,0
0040D13B ^ 7E A4      jle short Notepad.0040D0E1

第二次硬件中断。

004058B5   64      db 64                //断在这里
004058B6   89      db 89
004058B7   1D      db 1D
004058B8   00      db 00
004058B9   00      db 00

这里也不是,F9继续!

004010CC /. 55      push ebp
004010CD |. 8BEC     mov ebp,esp //断在这里,哈哈,到了!(如果发现有花指令,用ctrl+A分析一下就能显示出来)
004010CF |. 83EC 44    sub esp,44
004010D2 |. 56      push esi

快吧!还不过瘾,在来一个例子。

脱壳进阶第二篇

如果按上面的方法断不下来,程序直接运行了!没什么,我们在用另一种方法!

载入后停在这里,用插件把OD隐藏!

0040DBD6 N>^\E9 25E4FFFF   jmp Note_tEl.0040C000         //停在这里
0040DBDB  0000      add byte ptr ds:[eax],al
0040DBDD  0038      add byte ptr ds:[eax],bh
0040DBDF  A4       movs byte ptr es:[edi],byte ptr ds:[esi]
0040DBE0  54       push esp

F9运行,然后用SHIFT+F9跳过异常来到这里:

0040D817 ^\73 DC      jnb short Note_tEl.0040D7F5   //到这里
0040D819  CD20 64678F06  vxdcall 68F6764
0040D81F  0000      add byte ptr ds:[eax],al
0040D821  58       pop eax

在这里对0012FFC0下硬件写入断点!(命令行里键入HW 12FFC0)SHIFT+F9跳过异常,就来到OEP的第二行处:(用CTRL+A分析一下)

004010CC /. 55      push ebp
004010CD |. 8BEC     mov ebp,esp           //断在这里
004010CF |. 83EC 44    sub esp,44
004010D2 |. 56      push esi
004010D3 |. FF15 E4634000 call dword ptr ds:[4063E4]
004010D9 |. 8BF0     mov esi,eax
004010DB |. 8A00     mov al,byte ptr ds:[eax]
004010DD |. 3C 22     cmp al,22

就这样我们轻松搞定了两个加密壳的找OEP问题!

5.总结

现在我们可以轻松的回答一些问题了。

1.ESP定律的原理是什么?

堆栈平衡原理。

2.ESP定律的适用范围是什么?

几乎全部的压缩壳,部分加密壳。只要是在JMP到OEP后,ESP=0012FFC4的壳,理论上我们都可以使用。但是在何时下断点避开校验,何时下断OD才能断下来,这还需要多多总结和多多积累。欢迎你将你的经验和我们分享。

3.是不是只能下断12FFA4的访问断点?

当然不是,那只是ESP定律的一个体现,我们运用的是ESP定律的原理,而不应该是他的具体数值,不能说12FFA4,或者12FFC0就是ESP定律,他们只是ESP定律的一个应用罢了!

4.对于STOLEN CODE我们怎么办?

哈哈,这正是寻找STOLEN CODE最好的办法!当我们断下时,正好断在了壳处理STOLEN CODE的地方,在F8一会就到OEP了!

6.后话

看了上面的文字希望能对你在寻找OEP的时候有帮助,但是别忘了一句话:菜鸟认为找OEP很难,高手认为修复才是最难!

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

boteli 发表于 2010-7-29 22:32
本帖最后由 boteli 于 2010-7-29 22:35 编辑

我晕。。。楼主从某某教程里面拿过来的。。无语了。。。。


我知道了。。你这个是  《黑鹰破解教程50课》里面的第11课。。怪不得这么面熟。。。。
tysan 发表于 2010-7-29 22:37
作者:Lenus



FROM: poptown.gamewan.com/bbs



E-MAIL:meila2003@163.com


我帮你把作者补上吧~~
小Z 发表于 2010-7-29 23:08
wxt51 发表于 2010-7-29 23:27
恩,不错,很好,很强大,我确定在本论坛已经看过这篇文章了,又被你翻出来重发,以后我也试试看能不能加精
紫锋 发表于 2010-7-29 23:33
好东西,收藏了,谢谢
monnyabc 发表于 2010-7-30 00:33
温顾而知新,谢谢
jllsl2280 发表于 2010-7-30 08:13
又看了一遍
谢谢了
头像被屏蔽
qq526033781 发表于 2010-7-30 15:34
提示: 作者被禁止或删除 内容自动屏蔽
hrbwz 发表于 2010-7-30 15:46
收藏了,谢谢
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 13:53

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表