吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 2752|回复: 6

[转载技术] 第二十五章-异常处理

[复制链接]
Shark恒 发表于 2015-1-20 16:38 | 显示全部楼层 |阅读模式

                            第25章-异常处理
本章,我们将介绍异常处理,这一块通常是初学者的绊脚石,但是如果研究深入一点的话,你会发现它并不难。
那么异常是如何产生的呢?当处理器执行了一个错误的操作的时候,程序中就会产生异常。好了,我们来看几个异常例子吧,我们用OD打开cruehead’a 的CrackMe。
image002.jpg
可以看到断在了入口点处,我们在第一行输入会引发异常的指令,这里我们采用Mr Silver写的异常例子中指令。
内存访问异常:当线程中尝试访问没有访问权限的内存的时候会发生该类异常。例如:一个线程尝试向只具有读权限的内存写入数据的时候就会产生内存访问异常。
我们在OD中输入如下指令:
image004.jpg
这里我们可以看到401057开始的内存单元只具有读取和执行权限,并不具有写入权限。因此如果尝试向该内存单元写入数据的话就会产生异常,我们按F8键。
image006.jpg
程序会根据PE头中的相关信息设置区段的初始权限,当然也可以使用诸如VirutalProtect这类API函数在运行时修改权限。
那么在OllyDbg中我们如何查看各个区段的初始权限呢,还有就是如何修改这些权限呢?
我们可以通过单击工具栏中的M按钮来查看各个区段的情况。
image008.jpg
我们可以看到主模块的所在的区段开始于400000,首先是PE头,占1000个字节,PE头中保存了各个区段的名称,长度以及程序运行所必须的一些信息。
我们在数据窗口中定位到PE头。
image010.jpg
由于PE头开始于400000,所以我们输入400000。
image012.jpg
其实OllyDbg中有一个可以解析PE头的各个字段的选项,我们可以在数据窗口中单击鼠标右键。
image014.jpg
image016.jpg
我们可以看到显示出了DOS头的各个字段信息。
image018.jpg
如果我们继续往下看,我们首先会看到Offsetto PE signature,这是告诉我们PE头的偏移量,我们可以看到偏移量为100。那么起始地址400000加上100就是400100,我们定位到400100处。
image020.jpg
这里你所看到的,这里是关于程序的重要信息。
下面让我们来看看部分字节详细的解释。
image022.jpg
也就是说基地址400000加上1000就是程序的入口点。如果你想修改入口点的话,例如把入口点修改为2000,我们可以在入口点这一行上单击鼠标右键。
image024.jpg
这里我们可以输入任意数值,例如:如果你想让程序从402000处开始执行,我们可以输入2000。这个2000是相对于映像基址400000的偏移量。
image026.jpg
修改完毕以后,我们可以单击鼠标右键选择-Copyto executable file,然后在弹出的窗口中单击鼠标右键选择-Save file,这样就可以保存到文件了,我们并不修改入口点,只要知道可以这么做就行了。
好了,我们继续往下看。
image028.jpg
下面各个区段的信息,首先我们看到的这个区段起始虚拟地址为1000,注意这里是偏移量,实际上内存地址为401000,并且Characteristics(特征)为CODE,EXECUTE,READ(代码段,可执行,可读)。
如果我们想让该区段具有可写权限的话,我们可以将Characteristics这个字段的60000020修改为E0000020,这样该区段就具有了所有权限,嘿嘿,我们来验证一下。
image030.jpg
好了,我们现在来将修改保存到文件。
image032.jpg
image034.jpg
我们将名称修改为CRACKME 3,标识这个文件是修改版。
image036.jpg
好了,我们现在用OllyDbg打开这个CRACKME3.EXE。
image038.jpg
image040.jpg
现在我们将数据窗口显示模式切换为正常模式。
image042.jpg
我们按F8键单步,会发生并没有产生异常,EAX的值被成功写入了401057内存单元中了。
下面介绍另外一种异常:
0异常:试图除以0时会产生该异常。
例如,我们在OllyDbg中输入如下指令:
image044.jpg
(PS:原作者这个地方讲错了,他是直接DIV ECX,ECX这个时候并不为零,EAX为零,EDX指向了7C92E514,所以按照作者的做法,只会产生整数溢出异常,并不会产生除0异常。)
寄存器的如下:
image046.jpg
好了,我们F8单步一次。
寄存器的情况如下:
image048.jpg
这里时候除数ECX为0了。我们继续F8单步。
image050.jpg
我们可以看到提示Integer division by zero(整数除0)异常。
无效指令,尝试执行特权指令异常:
当CPU试图执行越权指令的话就会产生该异常。
由于OllyDbg不允许我们输入CPU不可识别的指令,所以我们无法验证。但是程序员可以自己设计一些处理器并不支持的指令,当执行到指令时显示相应的错误即可。
最为典型就是INT 3指令,INT 3指令会产生一个异常,并且该异常会被调试器捕获到,比如,我们可以设置BPX断点来让程序中断下来,然后就可以对该程序进行相应的控制了。
另外,有一些程序会直接写入INT3指令,所以说INT 3产生的异常是最常见的。
其实还有很多其他的异常,这里我们就不一一介绍了。下面我们看一个简单的例子。
现在我们只知道该程序会产生异常,但是到底会产生哪种异常呢?我们现在先来看看下面这个示意图:
image052.jpg
这个图是我从Mr Silver的教程中截取出来的,这里我们可以看到一个异常是被处理的流程,首先系统会判断当前进程是否正在被调试。
根据上图来看可以知道异常发生后,如果当前程序正在被调试的话,那么此时控制权就会交予调试器。如果调试器的调试选项勾选了跳过对应的异常类型的话,这个时候控制权又会重新归还给当前程序,如果没有勾选跳过对应的异常的话,那么我们就需要按Shift+ F9键来跳过该异常并将控制权交予程序了。但是控制权交予程序以后的流程该如何走上图中并没有标注出来。所以我们接着来看下面的流程图。
image054.jpg
这里我补全了整个流程图,见上图的红色箭头。
接下来我们可以看到,当前控制权由调试器归还给程序以后,系统会检查当前程序是否安装了SEH,如果安装了SEH,就转向SEH的异常处理程序执行,如果没有安装SEH,就会调用系统默认的异常处理程序。以上介绍听起来可能有点复杂,其实并不复杂,我们再来详细介绍一下什么是SEH。
什么是SEH?
SEH或者结构化异常处理,它是用来确保该程序可以从错误中恢复,也就是说,如果你没有设置SEH,那么当程序中有异常发生时,程序就会弹出一个错误信息框,告诉我们程序即将关闭。如果我们设置了SEH的话,异常处理程序就能够捕获到程序中发生的异常,进行相应的处理后,就会把控制权重新交予程序继续执行,程序并不会终止也不会弹出那个烦人的错误消息框。
此外,我们需要知道每个线程都可以有自己的异常处理程序,如果当前异常处理程序不予处理的话,可以将异常将于SEH链中的其他异常处理程序来处理。
如何定位异常处理程序
好了,我们用OD重新加载cruehead’a 的CrackMe。
我们来看看堆栈的情况。
image056.jpg
这是系统默认安装的异常处理程序,无论什么异常交予该默认异常处理程序处理的话,它都会弹出错误消息框。现在我们来定位到该默认异常处理函数。
我们看到,FS:[0]就是指向了当前异常处理程序。
我们在数据窗口中定位到FS:[0]。
image058.jpg
这里我们可以看到FS:[0]指向的内存单元中内容是多少,可能不同的机器上这个值会不一样,我这里FS:[0]指向内存单元中保存的值是12FFE0。
image060.jpg
从堆栈中我们可以看到,12FFE0指向的是SEH链的最后一个结点,当前异常被交予该结点的异常处理程序的话,就会弹出一个我们熟悉的错误消息框。
image062.jpg
我们来查看一下SEH链的情况。
image064.jpg
我们可以看到只有系统默认的异常处理程序被安装了,当有多个异常处理程序的话,当捕获到异常的话,异常会依次由SEH链的顶部向底部传递。
由于cruehead’a 的CrackMe并没有安装自己的异常处理程序,所以这里我们再看另一个例子smartmouse111。
我们用OD加载这个例子。
image066.jpg
你可以看到程序开始处在安装自己的异常处理程序,OllyBbg中也以注释标注出来了SEhandler installation。
image068.jpg
我们到达OllyDbg提示SE handlerinstallation(安装异常处理程序)指令处,首先是一个PUSH 4066D8指令,当程序发生异常时,将会调用4066D8地址处的异常处理程序。
image070.jpg
执行PUSH指令后,4066D8被保存到堆栈中了。
image072.jpg
接下来一行是将FS:[0]的值保存到EAX中,我们在数据窗口中来看看FS:[0]指向的内存单元中保存的内容是多少。
image074.jpg
我们在数据窗口中定位到7FFDE000地址处。
image076.jpg
我们可以看到FS:[0]内存单元中的值为12FFE0。OD提示窗口中也显示了。
image078.jpg
我们执行这条指令。
image080.jpg
EAX的值变为了12FFE0,接着这个值被压入堆栈。
image082.jpg
我们可以看到之所以叫SEH链,因为它是一个链表,这里的12FFE0就指向了上一个异常处理程序。
image084.jpg
下面一行指令就是将FS:[0]的内容设置为ESP的内容,这样一个异常处理程序就被安装好了。
image086.jpg
image088.jpg
我们执行这一行指令。
image090.jpg
这样12FFB0处就是我们安装的 新的SEH结点了,也就是FS:[0]指向了我们新安装的SEH结点。
image092.jpg
OllyDbg也标注出来了,提示这是一个SEH结点,首先的4个字节的值指向了老的SEH结点,接下来的4个字节值即当前的异常处理程序入口地址。
所以当该程序发生异常后,异常被处理流程如下:
image094.jpg
判断当前是否被调试,由于当前正在被调试,所以系统将控制权交予调试器,然后如果你勾选了忽略对应异常的选项的话(如果你没有勾选忽略对应异常选项的话,你也可以按Shift + F9键来忽略异常),那么控制权将重新交予程序,如图所示,接着判断是否安装了SEH,这里安装了,所以将会执行4066D8处的异常处理程序。
我们来看看SEH链的情况:
image096.jpg
我们可以看到SEH链的顶部是程序自己安装的异常处理程序,接下来才是系统默认的异常处理程序,如果发生异常,应该是调用4066D8处异常处理程序,而并不是调用系统默认的异常处理程序,我们来手工制造一个异常试试。
image098.jpg
我们来将该行修改为如下指令:
image100.jpg
这样会产生一个异常,因为0地址不能写入。我们确保调试选项中忽略各类异常的选项没有被勾选,但是第一个选项还是要勾选的。
image102.jpg
我们运行起来。
image104.jpg
OD左下方显示错误,程序将被终止。
image106.jpg
现在程序继续执行的话可以尝试从错误中恢复。
我们在4066D8指向的异常处理程序入口处设置一个断点。
image108.jpg
我们可以看到OD提示我们,按Shift + F9键可以忽略异常,继续执行程序,嘿嘿。
image110.jpg
我们可以看到断在了异常处理程序的入口处,我们运行起来看看程序会不会从错误中恢复过来。
image112.jpg
我们可以看到程序崩溃,弹出了错误消息框,这该程序表明调用了系统默认的异常处理程序。
image114.jpg
显示这个错误提示框是因为程序自己安装SEH异常处理程序中并没有修复刚刚那个异常,所以异常继续传递,最后交予了系统默认的异常处理程序,将弹出了一个错误消息框,程序就终止掉了。
显然,程序自己安装的异常处理程序是用来处理别的类型的异常的,并不能处理向0地址处写入导致的异常。
为了能看到异常被成功处理的效果,我们再来看一个例子SDUE1。
我们用OD加载该程序,可以看到OD提示说该程序可能被加壳了。
image116.jpg
我们依然不勾选调试选项中的忽略各类异常的选项,除了忽略第一个异常以外。
image118.jpg
我们运行起来。
image120.jpg
我们可以看到发生了异常,断了下来。
image122.jpg
我们来看看异常处理程序在哪里。
image124.jpg
在你的机器上,这个地址可能会不一样,因为该地址属于一个动态创建的区段。我们现在来给该异常处理程序设置一个断点。
image126.jpg
我们定位到了该异常处理程序的入口地址,现在我们该它设置一个断点。
image128.jpg
我们按Shift + F9键运行起来。
image130.jpg
我们可以看到断在了异常处理程序的入口处,如果成功从异常中恢复了的话,那么程序将会从刚刚发生异常的指令的下一条指令处继续往下执行。
image132.jpg
我们给产生异常的指令的下一条指令设置一个断点,然后运行起来。
image134.jpg
我们可以看到程序继续执行起来了,并弹出提示错误消息框,说明异常已经成功被修复了。
其实设置异常处理程序还可以使用SetUnhandledExceptionFilter这个API函数,可以通过其参数来设置异常处理程序的入口地址。
好了,本章介绍了我们以后逆向过程中会用到的一些知识点,下一章开始我们将介绍VB相关的内容。

本系列文章汉化版转载看雪论坛

感谢原作者:RicardoNarvaja(西班牙人)
原作者个人主页:http://www.ricardonarvaja.info/

感谢热心翻译的朋友:
1~3章译者:BGCoder
4~58章译者:安于此生

全集配套程序下载地址:
链接: http://pan.baidu.com/s/1eQzTWfo 密码: vytv



评分

参与人数 12HB +8 THX +9 收起 理由
花盗睡鼠 + 2 + 1 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!
厘子 + 2 + 1 [吾爱汇编论坛52HB.COM]-吃水不忘打井人,给个评分懂感恩!
游侠啊 + 1
Jawon + 1
太阳神 + 2 [吾爱汇编论坛52HB.COM]-吃水不忘打井人,给个评分懂感恩!
一路走来不容易 + 1
Soul1999 + 1
消逝的过去 + 1
l278785481 + 1
jaunic + 1
hnymsh + 1
lies + 1

查看全部评分

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
hackysh 发表于 2022-2-20 00:28 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
头像被屏蔽
别管我了行 发表于 2022-3-1 03:45 | 显示全部楼层

提示: 作者被禁止或删除 内容自动屏蔽
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
曾经沧海 发表于 2022-11-19 17:35 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
曾经沧海 发表于 2023-4-4 10:19 | 显示全部楼层

有帮助,多多支持!
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
一生逍遥 发表于 2023-4-20 14:46 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
游侠啊 发表于 2023-4-21 16:13 | 显示全部楼层

整理不易,感谢分享
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层
3层
4层
5层
6层
7层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

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