1.了解EBP寄存器

在寄存器里面有很多寄存器虽然他们的功能和使用没有任何的区别,但是在长期的编程和使用 中,在程序员习惯中已经默认的给每个寄存器赋上了特殊的含义,比如:EAX一般用来做返回值,ECX用于记数等等。在win32的环境下EBP寄存器用与 存放在进入call以后的ESP的值,便于退出的时候回复ESP的值,达到堆栈平衡的目的。

应用以前说过的一段话:

原程序的OEP,通常是一开始以 Push EBP 和MOV Ebp,Esp这两句开始的,不用我多说大家也知道这两句的意思是以EBP代替ESP,作为访问堆栈的指针。

为什么要这样呢?为什么几乎每个程序都是的开头能?因为如果我们写过C等函数的时候就应该清楚,程序的开始是以一个主函数main()为开始的,而函数在访问的过程中最重要的事情就是要确保堆栈的平衡,而在win32的环境下保持平衡的办法是这样的:

1.让EBP保存ESP的值;

2.在结束的时候调用

mov esp,ebp
pop ebp
retn

或者是

leave
retn

两个形式是一个意思。

这样做的好处是不用考虑ESP等于多少,PUSH了多少次,要POP多少次了,因为我们知道EBP里面放的是开始时候的ESP值。

2.推广的ESP定律

在寻找OEP的时候,往往下断HW ESP-4不成功,除了壳代码将硬件断点删除了以外,很可能的情况就是因为壳代码在运行到OEP的时候他的ESP已经不再是在EP时候的ESP(12FFC4)了,这样我们下断当然是不成功的。

那么如何找到在壳到达OEP的时候的堆栈的值将是关键。

在这里我们应用的关键是

Push EBP
MOV Ebp,Esp----》关键是这句

我来解释一下,当程序到达OEP的时候Push EBP这句对于ESP的值来说就是ESP-4,然后是ESP-4赋给了EBP,而做为保存ESP值作用的EBP寄存器在这个“最上层的程序”中的值将始终 不会改变。虽然他可能在进入子call里面以后会暂时的改变(用于子程序的堆栈平衡)但是在退出了以后依*pop ebp这一句将还原原来的EBP的值。

以这句做为突破口,就是说只要我们能断在“最上层的程序”中,就能通过观察EBP的值得到壳在JMP到OEP的时候的ESP的值了。

3.实战

来看看pespin1.1的壳,在pespin1.0的壳中,我们使用HW 12FFC0能很容易的找到stolen code的地方,但是到pespin1.1的时候,我们就不行了。用HW 12FFC0根本断不下来。

现在我们就使用这个推广的ESP定律,载入程序后来到最后的一个异常

0040ED85     2BDB             sub ebx,ebx                           //停在这里
0040ED87 64:8F03 pop dword ptr fs:[ebx]
0040ED8A 58 pop eax
0040ED8B 5D pop ebp
0040ED8C 2BFF sub edi,edi
0040ED8E EB 01 jmp short pespin1_.0040ED91
0040ED90 C466 81 les esp,fword ptr ds:[esi-7F]

我用使用内存断点办法来到FOEP处

004010D3     0000             add byte ptr ds:[eax],al
004010D5 0000 add byte ptr ds:[eax],al
004010D7 0000 add byte ptr ds:[eax],al
004010D9 0000 add byte ptr ds:[eax],al
004010DB 0000 add byte ptr ds:[eax],al
004010DD 0000 add byte ptr ds:[eax],al
004010DF 75 1B jnz short pespin1_.004010FC //这里是FOEP
004010E1 56 push esi
004010E2 FF15 99F44000 call dword ptr ds:[40F499]
004010E8 8BF0 mov esi,eax
004010EA 8A00 mov al,byte ptr ds:[eax]

好了,这里就是“最上层的程序”的地方了,看看寄存器

EAX 00141E22
ECX 0040C708 pespin1_.0040C708
EDX 0040C708 pespin1_.0040C708
EBX 0040C708 pespin1_.0040C708
ESP 0012F978
EBP 0012F9C0 //注意这里
ESI 00141EE0
EDI 0040E5CD pespin1_.0040E5CD
EIP 004010DF pespin1_.004010DF

看到了吧,EBP=0012F9C0,我们来想象一下这个值是怎么得到的。

首先肯定是通过MOV ESP,EBP这一句,也就是说ESP这时是0012F9C0的,然而上面还有一句PUSH EBP也就是说ESP在到达OEP的时候应该是0012F9C4的。好了得到这个结论我们就能很快的找到stolen code的所在了。

重来停在最后的异常

0040ED85     2BDB             sub ebx,ebx                           //停在这里
0040ED87 64:8F03 pop dword ptr fs:[ebx]
0040ED8A 58 pop eax
0040ED8B 5D pop ebp
0040ED8C 2BFF sub edi,edi
0040ED8E EB 01 jmp short pespin1_.0040ED91
0040ED90 C466 81 les esp,fword ptr ds:[esi-7F]

然后下断HW 0012F9C0 ,F9运行,来到这里

0040D8FB     61               popad
0040D8FC 55 push ebp
0040D8FD EB 01 jmp short pespin1_.0040D900 //停在这里
0040D8FF 318B ECEB01AC xor dword ptr ds:[ebx+AC01EBEC],ecx
0040D905 83EC 44 sub esp,44
0040D908 EB 01 jmp short pespin1_.0040D90B
0040D90A 72 56 jb short pespin1_.0040D962
0040D90C EB 01 jmp short pespin1_.0040D90F
0040D90E 95 xchg eax,ebp
0040D90F FF15 6CF34000 call dword ptr ds:[40F36C]
0040D915 EB 01 jmp short pespin1_.0040D918

于是就很快的找到了stolen code的所在了。

4.总结

上面的这个办法大概可以总结以下的步骤:

(1).直接或间接的断在“最上层的程序”的地方。

(2).得到“最上层的程序”的EBP的值。

(3).利用程序初始化的两个固定语句找到壳JMP到OEP的堆栈值。这个办法有很大的局限性,因为只有VC和delphi程序使用这个初始化的开头。

但是找到“最上层的程序”的办法除了内存断点还有很多办法,例如对于VC来说使用 bp ExitProcess也是一个很好的断点,可以直接得到EBP的数值。

5.后话

原来这个办法有很强的前提条件,不是一个很具普遍性的办法,我原来也不想单独的提出来,但是对于jney2兄弟的anti-ESP定律来说这个办法却是一个解决之道。

当然还有更多的办法,在这里我只想说很多事情有矛就有盾,没有什么办法是一定没有漏洞的,只是希望这篇文章给大家阔宽思路,起到抛砖引玉的作用。

EBP的妙用[无法使用ESP定律时]的更多相关文章

  1. “破解大牛是怎么炼成的”之壳与ESP定律

    文章难易度:★★★ 文章阅读点/知识点:逆向破解 文章作者:Sp4ce 文章来源:i春秋   关键字:网络 信息安全技术 本文参与i春秋社区原创文章奖励计划,未经许可禁止转载! 一.前言 通过前面几篇 ...

  2. 寻找真正的入口(OEP)--广义ESP定律

    1.前言 在论坛上看到很多朋友,不知道什么是ESP定律,ESP的适用范围是什么,ESP定律的原理是什么,如何使用ESP定律?看到了我在“”调查结果发现,大家对ESP定律很感兴趣,当然因为实在是太好用了 ...

  3. 菜鸟脱壳之脱壳的基础知识(四)——利用ESP定律来寻找OEP

    .上节说的是单步跟踪法,这节讲的是利用堆栈平衡(ESP定律)来进行脱壳!想必大家都听说过ESP定律这个大名吧!ESP定律运用的就是堆栈平衡原理!一般的加壳软件在执行时,首先要初始化,保存环境(保存各个 ...

  4. ESP定律脱壳

     ESP定律是比较常用的脱壳方式,作为新手用的也比较多简单写一下我的看法. esp定律的使用过程大致为: 1.开始就点F8,注意观察OD右上角的寄存器中ESP有没突现(变成红色),并且只有sp和ip为 ...

  5. 脱壳第一讲,手工脱壳ASPack2.12的壳.ESP定律

    脱壳第一讲,手工脱壳ASPack2.12的壳.ESP定律 一丶什么是ESP定律 首先我们要明白什么是壳.壳的作用就是加密PE的. 而ESP定律就是壳在加密之前,肯定会保存所有寄存器环境,而出来的时候, ...

  6. ESP定律学习

    ESP = 堆栈平衡 ESP定理脱壳: (1)开始就点F8,注意观察OD右上角的寄存器中ESP有没突现(变成红色)(这只是一  般情况下,更确切的说我们选择的ESP值是关键句之后的第一个ESP值) ( ...

  7. ESP定律脱壳——NsPack3.x脱壳

    首先进行查壳,NsPack 将程序拖入x64dbg 程序入口处标志性的push F8单步,发现仅有esp寄存器有变化 在esp上右键,在内存窗口查看,下硬件断点 F9运行程序,程序断在pop之后. 使 ...

  8. eax,ebx,ecx,edx,esi,edi,ebp,esp寄存器的作用

    位的寄存器.如果用C语言来解释,可以把这些寄存器当作变量看待. 比方说:add eax,-2 ;   //可以认为是给变量eax加上-2这样的一个值. 位寄存器有多种用途,但每一个都有"专长 ...

  9. esp跟ebp跟踪记录

    发现文字描述还是太没有快感.上几幅图,来说明这个调试过程更好.此文对于深刻理解ebp,esp是具有长远意义的 可以看到,初始情况下,ebp此时值为0012FEDC,也就是栈帧的地址,而栈顶地址esp值 ...

随机推荐

  1. UI1_ScrollViewHomeWork

    // // AppDelegate.m // UI1_ScrollViewHomeWork // // Created by zhangxueming on 15/7/13. // Copyright ...

  2. AMQ学习笔记 - 14. 实践方案:基于ZooKeeper + ActiveMQ + replicatedLevelDB的主从部署

    概述 基于ZooKeeper + ActiveMQ + replicatedLevelDB,在Windows平台的主从部署方案. 主从部署可以提供数据备份.容错[1]的功能,但是不能提供负载均衡的功能 ...

  3. (转)Linux概念架构的理解

    英文原文:Conceptual Architecture of the Linux Kernel 摘要 Linux kernel成功的两个原因:(1)架构设计支持大量的志愿开发者加入到开发过程中:(2 ...

  4. php魔术方法 http_build_query使用

    最近在做一个项目使用到 http_build_query 这个魔术方法很好用,它可以将一个数组转换成这样的格式: 比如 $_arr = array('action'=>'show','page' ...

  5. DNA RNA

    核糖体没有DNA,但是有RNA(rRNA 核糖体RNA) 有DNA的细胞器是线粒体和叶绿体.

  6. 《搭建DNS内外网的解析服务》RHEL6

    首先说下: 搭建的这个dns内外网的解析,是正向解析,反向解析自己根据正向解析把文件颠倒下就ok了 第一步我们先搭建一个DNS的正反向解析(参考上篇DNS正反向解析,这是上篇做过的) 第二部才是搭建内 ...

  7. Android String format 通过value 下的string.xml 文件

    <string name="format_coordinate" formatted="false">%s %d° %d\' %d\" % ...

  8. Nginx+Keepalived实现高可用站点

    Keepalived是一个基于VRRP协议来实现的服务高可用方案,可以利用其来避免IP单点故障,类似的工具还有heartbeat. corosync.pacemaker.但是它一般不会单独出现,而是与 ...

  9. 局域网实现 yum

    1 安装squid代理 ##### . 安装squid yum -y remove squid yum -y install squid ##### . 修改配置文件 vi /etc/squid/sq ...

  10. 判断php数组维度的小例子

    分享一例判断php数组维度的代码,供大家参考. 如下所示: <?php /** * 返回数组的维度 * @param [type] $arr [description] * @return [t ...