第四课 脱壳必备知识要点及方法

                             第四课  脱壳必备知识要点及方法

 

    今天所要讲的是这高级篇中最为关键,最为重要的一课,希望大家能认真学习,反复推敲,举一反三学习脱壳的各种方法,当然有的时候可能需要几种方法一起使用,今后我们也会一点一点接触到,今天我们先学习大体的几种脱壳法。

 

一:常见脱壳调试法

 

二:预备知识

   

    OEP是Original Entry Point缩写,即程序加壳前的真正的入口点。

    外壳初始化的现场环境(各寄存器值)与原程序的现场环境是相同的。加壳程序初始化时保存各寄存器的值,外壳执行完毕,会恢复各寄存器内容。其代码形式一般如下:

 

    PUSHFD         ; 将标志寄存器入栈保存

    PUSHAD         ; push eax, ecx, edx, ebx, esp, ebp, esi, edi

    ……           ; 外壳代码部分

    POPAD          ; pop edi, esi, ebp, esp, ebx, edx, ecx, eax

    POPFD          ; 恢复标志寄存器

    JMP OEP        ; 大的跳转

    OEP: ……      ; 解压后的程序原代码

 

    PUSHAD (压栈) 代表程序的入口点,

    POPAD  (出栈) 代表程序的出口点,与PUSHAD想对应,一般找到这个OEP就在附近

 

三:脱壳方法之单步跟踪找OEP

   

    1.用OD载入,如果有提示是否分析代码,就点“ 不分析代码!”

    2.F8单步向下跟踪调试,没有实现的向上的跳,向下的跳都可以步过,阻止实现的向上的跳。

    3.遇到会跑飞的CALL我们就F7步入。

   

Btw:遇到程序无法向下跟踪调试的时候,在附近(上下均可)找一个大跳转(像下的实现的,跳的大小看线的长短)(如果找不到大的跳就找一个不跳的跳(没有线),FSG2.0就是这样),F4运行到该跳处,然后右键→跟随或者回车到达跟随的地址按F2下断点,然后shift+F9(忽略异常运行)运行到跟随的地址,然后再F2取消断点,接着就可以F8继续单步调试了(对于FSG2.0的课可能直接就到oep了,另外老版的OD可能会出现要你分析代码,解决办法:右键-->分析-->从模块删除目标文件)。另:在F8单步跟踪的时候并不一定非要是在实现的向上的跳的下一句F4,如果是像:je,jne,ja,jna,等有条件的跳也可以继续F8单步,因为你跟着循环个次它的条件一般就会改变然后向后走(它本身变成了为实现的跳了)。但是如果是像jmp这样非条件的跳,如果你还F8单步的话它会一直循环,所以这种跳就必须F4。

 

清除OD的使用记录:OD菜单-〉插件-〉文件清除-〉全部文件

退出OD,在OD目录里有个UDD文件夹,把里面的东西删除干净,这样就清除了OD的历史记录。

 

四:脱壳方法之根据堆栈平衡原理找OEP(ESP定律法)

   

    堆栈平衡原理找OEP,Lenus写过一篇文章《寻找真正的入口(OEP)--广义ESP定律》我会打包给大家,有兴趣的可以自己看一下堆栈平衡原理,做免杀自己写花指令也需要用到这个原理,所以这文章对大家相当有帮助。

 

    1.F8单步跟踪调试在关键句的下一句,在OD寄存器窗口ESP突显为红色

    2.在OD命令行下输入(dd ESP突显红色的地址) 或者 (hr ESP突显红色的地址)

    3.下硬件访问断点

    4.F9运行(然后删除硬件断点),继续F8单步向下调试。

 

五:脱壳方法之内存断点法找OEP(内存镜像法)

 

    1.OD载入程序后,我们直接对code段下内存访问断点

    2.Shift+F9运行 (code段没有解压完毕,所以会不断得中断,连续按F9。当然这种方法是不可取的)

 

正确的方法是:我们使用两次断点法。

假设我是程序作者,一个程序有code段,data段,rsrc段....依次排列在你的内存空间中。那么我会怎么解码呢?程序会先将code段解码,然后再将data段解码,接着是rsrc段....只要你在data段或者rsrc段下内存访问断点,那么中断的时候code段就已经解压完毕了。这时我们再对code段下内存访问断点,不就可以直接到达OEP了吗?

 

综上正确的操作方法是:

1, 1.OD载入程序-->查看-->内存-->在程序块(属主名和程序名一样)的rsrc段F2-->Shift+F9(忽略异常运行到该断点)-->然后再对code段(一般它的地址是:00401000)F2下断-->Shift+F9(对于tElock直接就到OEP了,也不再F2-->Shift+9运行到该处了,因为这里对应的就是我们在code段设断点的地方)。注:两个断点不用删除

 

    总结一下:如果我们知道壳在什么地方对code段解压完毕我们就可以使用内存断点,找到OEP。如果不知道,那么我们就依靠2次内存断点去找,如果还不行就用多次内存断点。总之明白了原理再多次的内存断点其实都一样。

 

    局限性:当一个壳如果它在JMP到OEP前的一行代码仍在对code段解压,那么我们就不能再使用这种办法了。更贴切得说,是我们没必要使用这种方法。(如UPX,ASPACK)

 

六:脱壳方法之最后一次异常法

 

    1.OD载入程序后

    2.设置异常选项:选项——调试设置——异常(一般情况我们忽略所有的异常选项(去掉所有的勾选),当然后面根据猛壳的特点我们可以自己选择设置异常选项,注意:只有用这种方法是需要设置这里,其它方法一定要全部勾选上,不然不能跟踪下去的)

    3.重载下OD(然后,插件-->隐藏od-->隐藏(不然OD会跑飞的),然后不用重载了),我们按SHIFT+F9,直到程序跑起来为止,我们把按的次数记住

    4.再次重载OD,再次按SHIFT+F9,我们按到程序跑起来的前一次。(第一次如果按了21下程序跑起来了,那么我们第二次就按20次,跑起来的前一次)

    5.在OD的右下角(堆栈窗口)看见一个"SE句柄",这时我们按CTRL+G,输入SE句柄前的数值(注:不是地址)! 

    6.来到SE句柄的地方我们按F2下断,F9运行至断点这,然后再F2取消断点

    7.接着我们F8单步继续向下调试

 

 

经验:popad

      Jmp  XXXX

      看到这两句就应该引起我的注意,特别当jmp 没注明short时,那么这里很可能就是壳的出口,也即OEP入口。

七:脱壳方法之其他方法

   

八:模拟跟踪法

   

1.F9运行程序,确定是否有暗桩。看程序能不能跑起来,如果程序能正常跑起来说明没有暗桩(有暗桩才能用这种方法)

2,用“脱壳方法之最后一次异常法”(到6)(目的是把暗桩给过掉)

    2.打开内存镜像,找到包含有SFX,imports,relocations的区段

    3.命令行下输入tc eip<区段地址(上面找到的包含有SFX,imports(输入表),relocations(重定向)的区段的地址)。回车后会自动跟踪出OEP地址。

 

九:根据编译语言特点找OEP

 

    (一).delphi程序

    1.执行程序。

    2.用LordPE脱壳。

    3.接着用16进制编辑器(如Hex Workshop,winhex,UE等)打开脱壳程序。

    4.搜索文本“runtime”,搜到后,向前查找离“runtime”最近的十六进制数字“55 8B EC”,

    数字所在的地址就是程序的OEP。

 

    (二).Visual C程序

    利用Visual C启动部分的几个函数GetCommandLineA(W)、GetVersion、GetModuleHandleA(W)、

    GetStartupInfoA(W) 等来定位程序的OEP。

 

十. 一步到达OEP

   

    1.开始按ctrl+f,输入:popad(适合少数壳,如UPX,ASPACK等)

    2.F2下断,F9运行到此断点处,再F2取消断点

    3.F8继续向下调试

十一: “SFX”法

   

    1.设置OD,忽略所有异常(去掉所有勾选)

    2.切换到SFX选项卡,选择“字节模式跟踪实际入口(速度非常慢)”

3.重载程序(自动走到OEP停下来)

(注:用完之后记得还原设置:停在解压入口)

 

十二: 内存另类断点法

 

    1.OD载入程序

    2.在内存镜像中找到包含code/text(代码)的区段,双击,然后在数据窗口第一个下内存访问断点

3.不断的按F9,直到从程序领空到系统领空,记录下按了几下(如:9次)(按得过程注意可能反应比较慢,要按一下等一会儿,即到暂停状态再按,(文件按钮下显示状态))

    4.重载,继续上面的操作,不同的是我们按8次F9 。

    5.然后继续用单步跟踪法调试

 

    Btw:OEP可能会在我们到达的地方的上面,我们可以倒着走,向下跳转不让实现,实现向上跳转。也可以在程序跑起来的前两次开始F8跟踪,大家多多实验。

 

    好了,我们今天的课程就到这里,部分资料会打包给大家。大家有空好好复习下,今天给大家留下作业就是用多种方法找到课件中的FSG2.0和TELOCK的OEP。

转载于:https://www.cnblogs.com/eldn/archive/2012/08/28/2660896.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/576282.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++Primer学习之二#define,const,constexpr

一&#xff0e;#define 是预处理操作符&#xff08;宏定义&#xff09;&#xff0c;编译器将在编译过程中用到该变量的地方替换成对应的值。 二&#xff0e;Const const是声明常量的限定符&#xff0c;它可以约定一个变量为常量。 如: Const int buffsize 1024; 编译器将…

SQL - 18.触发器

触发器是一种特殊类型的存储过程&#xff0c;它不同于前面介绍过的一般的存储过程。一般的存储过程通过存储过程名称被直接调用&#xff0c;而触发器主要是通过事件进行触发而被执行。触发器是一个功能强大的工具&#xff0c;在表中数据发生变化时自动强制执行。触发器可以用于…

C++求三位数的水仙花数

#include<iostream>using namespace std;int main() {/**个数的3次方十位的三次方百位的三次方这个数的本身*/for (int i 100; i < 999; i){int a i / 100; //百位数int b (i / 10)%10; //十位数int c i % 10; //个位数if (i a * a*a b * b*b c * …

行 转 列

第一种&#xff1a; CREATE TABLE #T1(C1 VARCHAR(10),C2 VARCHAR(20),C3 VARCHAR(10)) INSERT INTO #T1(C1,C2,C3) VALUES(1,DCP,5)INSERT INTO #T1(C1,C2,C3) VALUES(2,PCB,8)INSERT INTO #T1(C1,C2,C3) VALUES(6,ECD,9)INSERT INTO #T1(C1,C2,C3) VALUES(6,PCB,2)INSERT…

字符串移位包含

题目&#xff1a;给定两个字符串s1和s2&#xff0c;要求判定s2是否能够被s1做循环移位得到的字符串包含。例如&#xff0c;给定s1AABCD和s2CDAA,返回true;给定s1ABCD和s2ACBD,返回false。 答&#xff1a; #include "stdafx.h" #include <iostream>using namesp…

C++分文件的编写函数

不分文件编写函数&#xff1a; #include<iostream>using namespace std;//函数的声明 void swap(int a, int b); //函数的定义void swap(int a, int b) {int temp a;a b;b temp;cout << "a的值" << a << endl;cout << "b的值…

多线程socket 端口扫描程序,实现了,但是速度不行,求指点。

#pragma comment(lib,"ws2_32.lib")#include <stdio.h>#include <winsock2.h>#define MAXTHREAD 500#define PORTSTART 1#define PORTEND 60000#define TIMEOUT 1#define WAITTIME 10#define IP "61.135.169.105" //百度地址FILE * logHandle…

好的学习网址收藏

ASP.Net: http://www.189works.com/tech/devlodoc/donet/ 统一系统管理平台&#xff1a; http://www.cnblogs.com/umplatform/转载于:https://www.cnblogs.com/Qiaoyq/archive/2012/09/05/2672371.html

C++ 空指针和野指针

//1&#xff0c;指针变量指向内存中编号为0的空间为空指针 //2&#xff0c;空指针指向的内存空间是不可以访问的 #include<iostream> using namespace std; int main() {int a 10;int * p &a;cout << p << endl;cout << &a << e…

sql 大数据量插入优化

在做一IOS项目时&#xff0c;因为要动态根据文件导入创建数据库,刚开始的时候因为使用动态查询的方式&#xff0c;就是每次插入数据之前查询当前数据是否已经存在,这样的效率极低.6w条纪录3个关联表,使用了30-50分钟的样子. 后来使用动态保存索引号的方式&#xff0c;耗时只是3…

const修饰是指针和常量

1. const修饰指针——常量指针 int a10: int b10: int *p&a;const int* p&a; 常量指针 特点:指针的指向可以修改&#xff0c;但是指针指向的值不可以改&#xff08;p可以改&#xff0c;*p不可以改&#xff09;*p 20;错误&#xff0c;指针指向的值不可以改 p &b; 正…

GL 与 CV 管线 (pipeline) 比较与相互转换

这里把二者作一个比较&#xff0c;并对相关的矩阵做一个联系以使能够相互转换。 1. CV中图像形成过程 (transformation stages) 这一过程可概括为四个坐标系的转换&#xff0c;分别为&#xff1a;世界坐标系、相机坐标系、图像坐标系、像素坐标系&#xff0c;如下图&#xff1a…

C++结构体作为函数参数传参

#include<iostream> using namespace std;#include<string>//结构体 struct Student {string name;int age;int score;}st3;/**结构体作为函数参数传参*/ //值传递 void printStufdent1(struct Student st3) {cout << "子函数" << endl;st3.…

三层架构笔记

1.窗口属性 { IsMdiContainer:True 指定该窗体是否是MDI容器 windowState:Maximized窗口最大化 (4)设置StartPotion:CenterParent 窗口位置居中 (5)Icon:自定义图标 (6)MaximizeBox:False 无最大化选项 (7)FormBorderStyle:FixedSingle 不可改变窗口大小 (8)AcceptButton:bt…

C++结构体中const使用场景

看如下代码&#xff1a; #include<iostream> using namespace std;#include<string>//结构体 struct Student {string name;int age;int score;}st3;//值传递 void printStufdents(struct Student st2) {cout << "子函数" << endl;st2.age…

基于外键关联的一对多单向关联

基于外键关联的单向一对多关联是一种很少见的情况&#xff0c;并不推荐使用。 <class name"Person"><id name"id" column"personId"><generator class"native"/></id><set name"addresses">…

C++结构体案例

#include<iostream> using namespace std;#include<string>//学生结构体 struct Student {string name;int age;int score; };struct Teacher {string tName;struct Student sArray[5];};//定义一个给老师学生赋值的函数 void allocateSpace(struct Teacher tArray…

php程序设计简明教程

序 编写一本有关PHP的简明教程&#xff0c;对PHP选修课程而言&#xff0c;是很必要的。 PHP语言是开放源代码语言&#xff0c;由PHP开发小组及全世界的PHP爱好者时刻进行着维护和更新&#xff0c;不断增强其功能&#xff0c;所以在网络上不断地会涌现大量的PHP的电子参考手册&a…

C++ rand()函数和srand()函数

随机数和伪随机的区别 &#xff1a; #include<iostream> using namespace std; #include<string>#include<string> #include <stdlib.h> #include <time.h> #define MIN 0 //随机数产生的范围 #define MAX 99 //函数声明…

301重定向IIS设置,及伪静态后 301重定向出错案例分享

301重定向&#xff0c;网络上的知识已经很多了&#xff0c;我在这第一次实践过程中&#xff0c;出现了一个算是低级的错误&#xff0c;但也比较典型&#xff0c;也许其它新手也会碰到&#xff0c;分享一下&#xff1a; 一、301重定向实施&#xff1a; 我们哪里体检网&#xff0…