寻找真正的入口(OEP)--广义ESP定律
1.前言
在论坛上看到很多朋友,不知道什么是ESP定律,ESP的适用范围是什么,ESP定律的原理是什么,如何使用ESP定律?看到了我在“”调查结果发现,大家对ESP定律很感兴趣,当然因为实在是太好用了,现在我就来告诉大家什么是ESP定律,它的原理是什么!
BTW:在看完了手动脱壳入门十八篇了以后,再看这篇文章也许会对你更有帮助!
在下面地址下载:
http://www.jetdown.com/down/down.asp?id=37350&no=1
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.后话
以上的方法原理都是我自己总结,自己的经验,如果有什么不对的地方,有什么没解释清楚的地方。还请海涵!但是如果觉得我很厉害,那就大可不必,因为ESP定律也是别人教我的,不是我第一个提出来的!我只是个比你们早飞一点的菜鸟罢了^-^
看了上面的文字希望能对你在寻找OEP的时候有帮助,但是别忘了一句话:菜鸟认为找OEP很难,高手认为修复才是最难! 好了,下一篇应该写IAT的修复原理了!让我们共同努力吧!
寻找真正的入口(OEP)--广义ESP定律的更多相关文章
- 菜鸟脱壳之脱壳的基础知识(四)——利用ESP定律来寻找OEP
.上节说的是单步跟踪法,这节讲的是利用堆栈平衡(ESP定律)来进行脱壳!想必大家都听说过ESP定律这个大名吧!ESP定律运用的就是堆栈平衡原理!一般的加壳软件在执行时,首先要初始化,保存环境(保存各个 ...
- EBP的妙用[无法使用ESP定律时]
1.了解EBP寄存器 在寄存器里面有很多寄存器虽然他们的功能和使用没有任何的区别,但是在长期的编程和使用 中,在程序员习惯中已经默认的给每个寄存器赋上了特殊的含义,比如:EAX一般用来做返回值,ECX ...
- ESP定律脱壳
ESP定律是比较常用的脱壳方式,作为新手用的也比较多简单写一下我的看法. esp定律的使用过程大致为: 1.开始就点F8,注意观察OD右上角的寄存器中ESP有没突现(变成红色),并且只有sp和ip为 ...
- “破解大牛是怎么炼成的”之壳与ESP定律
文章难易度:★★★ 文章阅读点/知识点:逆向破解 文章作者:Sp4ce 文章来源:i春秋 关键字:网络 信息安全技术 本文参与i春秋社区原创文章奖励计划,未经许可禁止转载! 一.前言 通过前面几篇 ...
- 脱壳第一讲,手工脱壳ASPack2.12的壳.ESP定律
脱壳第一讲,手工脱壳ASPack2.12的壳.ESP定律 一丶什么是ESP定律 首先我们要明白什么是壳.壳的作用就是加密PE的. 而ESP定律就是壳在加密之前,肯定会保存所有寄存器环境,而出来的时候, ...
- ESP定律学习
ESP = 堆栈平衡 ESP定理脱壳: (1)开始就点F8,注意观察OD右上角的寄存器中ESP有没突现(变成红色)(这只是一 般情况下,更确切的说我们选择的ESP值是关键句之后的第一个ESP值) ( ...
- ESP定律脱壳——NsPack3.x脱壳
首先进行查壳,NsPack 将程序拖入x64dbg 程序入口处标志性的push F8单步,发现仅有esp寄存器有变化 在esp上右键,在内存窗口查看,下硬件断点 F9运行程序,程序断在pop之后. 使 ...
- [物理学与PDEs]第5章习题4 广义 Hookean 定律的张量的对称性
设材料是超弹性的, 并设参考构形为自然状态, 证明由线性化得到的张量 ${\bf A}=(a_{ijkl})=\sex{2\cfrac{\p \bar p_{ij}}{c_{kl}}}$ 具有以下的对 ...
- 手脱UPX v0.89.6 - v1.02
声明: 只为纪录自己的脱壳历程,高手勿喷 这个壳的脱法很多一般都一步直达的,步过我喜欢ESP定律 1.载入OD,在入口下一行ESP定律运行一次 > pushad ; //入口 BE mov es ...
随机推荐
- Java 计算两个日期相差月数、天数
package com.myjava; import java.text.ParseException; import java.text.SimpleDateFormat; import java. ...
- C# - LINQ 语言集成查询
LINQ(Language Integrated Query) LINQ语言集成查询是一组用于C#语言的扩展.它允许编写C#代码对数据集进行查询,比如查询内存中的对象或查询远程数据库的表.利用linq ...
- springboot项目中如何在pom文件覆盖starter中默认指定的jar版本号
分两种情况: 1.项目继承自spring-boot-starter-parent 通过定义properties的方式改变starter中的默认版本 <!-- Inherit defaults ...
- 【原创】大叔问题定位分享(6)Dubbo monitor服务iowait高,负载高
一 问题 Dubbo monitor所在服务器状态异常,iowait一直很高,load也一直很高,监控如下: iowait如图: load如图: 二 分析 通过iotop命令可以查看当前系统中磁盘io ...
- 用WKWebView 截取整个Html页面
以前使用UIWebview时,想截取整个页面,可以调整内部scrollView的frame,之后调用 scrollView的layer的 render 方法,很方便. 但是在WKWebView上,行不 ...
- Vue实战笔记
1.组件的属性 例子: <template> <div class="hello"> <test-props name="demo" ...
- Zabbix告警发送邮件时附带性能图
脚本处理逻辑分析: 通过zabbix传递给脚本的message参数,筛选出报警信息的itemid; 通过itemid获取到图片并保存; 将报警信息和图片组装成html; 发送邮件. 后续脚本里面的处理 ...
- Niagara workbench (Basic )
1.the basic information about workbench Last saved station open in the workbench or opened another ...
- Flask上下文管理源码--亲自解析一下
前戏 偏函数 def index(a,b): return a+b # 原来的调用方法 # ret=index(1,2) # print(ret) # 偏函数--帮助开发者自动传递参数 import ...
- AI数据分析(三)
见笔记本 通用函数