转载请注明版权:http://a1pass.blog.163.com/ 作者:A1Pass
黑客反病毒论坛 http://bbs.hackav.com
不知道通过上一节的学习与大家自己的努力,许多以前曾困惑不解的问题现在是否已经有了满意的答案。如果自己认为理解的还不够,就多实践一下,多思考一会,多搜索一次,相信你会因此而变得不再平凡。
这一节就让我带领大家走进文件系统的底层——PE文件结构的学习与探究。
其实PE文件就是指Windows里的DLL与EXE文件,PE的意思就是 Portable Executable,即可移植的执行体。大家也可以将其与JPG文件或MP3文件等对应理解,也许这样就会揭开它的神秘面纱,显得更为亲近一些。当然,PE文件要远比MP3等文件复杂得多,但是作为Windows操作系统里特有的一种可执行文件格式,只要我们能对其有一个大体的了解,就会使我们了解更多的免杀技术的本质,从而更加有效与正确的利用这些技术。
一、PE文件入门
PE文件总的来说是由DOS文件头、DOS加载模块、PE文件头、区段表与区段5部分构成。其实,如果在纯Windows环境下运行,DOS文件头、DOS加载模块根本是用不上的,加上两个DOS相关的结构完全是为了兼容性问题。
为了方便观察与理解,我们可以通过观察图1大体了解PE文件的结构。
如图可知,整个程序就是以DOS文件头“MZ”开始的,接下来就是DOS加载模块“This program cannot be run in DOS mode”,几乎每个Windows程序的前面都是这样一些信息!
下面有一个以字母“PE”为开头的文件块,这就是大名鼎鼎的PE文件头了,PE文件头的标准大小为224个字节,由图可见,里面有一个画了横线标记的问号与左面的十六进制信息“E0”相对应,这便是PE文件头体积的描述标记,十六进制的“E0”等于十进制的“224”由此也不难看出PE文件头的大小为224个字节。
再往下就是以“.text”、“ .data”与“.rsrc”组成的区段表了。区段表也称节表,它的作用就相当于一本书中的目录,你想看哪一章哪一节,只要按着目录标注的页数去找就可以,PE文件的区段表也是起同样的作用,但是区段表除此之外还包含有各个区段的读写权限信息。而图中的“.text”、“ .data”与“.rsrc”则是这个程序里的区段名称,也称为“节”。由此可见这个程序是由“.text”、“ .data”与“.rsrc”这3个区段组成的,如图2。
其实通过区段名称就可以大体猜出来这个区段里包含什么信息,在整个程序中能起到什么作用等等。
由此可见,PE文件是一种结构组成十分科学的文件格式,因此也对我们快速的认识它起到了助推器的作用,只要你记住PE文件的这5个构成的结构,你就可以向别人说,我了解PE文件!
二、深入了解PE文件与文件头
下面让我们抽象的了解一下PE文件的构成:
DOS MZ header <
DOS stub <
PE header <
Section table <<区段表
Section 1 <<区段1
Section 2 <<区段2
Section ...
Section n <<区段n
如果要详细介绍PE文件,恐怕就是这一期X档案也介绍不完,所以我就为大家简单的说明一下,如果你喜欢,可以当作一种知识储备给背下来。
DOS MZ header:也称之DOS文件头,亦或DOS MZ文件头,它是一段以关键字MZ为开头的数据,偏移量3C处包含着PE文件头的起始位置信息。
DOS stub:这个区块是以一段“This program cannot be run in DOS mode”为标志,当运行环境不匹配时则弹出这句话,对于WIN32位的操作系统来讲,存在的意义不大,完全可以删除。
PE header:这就是需要我们着重研究的PE文件头了,他是一段以关键字“PE”为开头的数据,默认大小224字节,里面包含着许多信息,不过对我们有用的就是描述自身大小的一个字段,他家可以仔细观察图1中PE文件头里的画横线部分。
Section table:区段表,也称为节表,这是一段记录着整个文件中区段的大小与位置信息表。
Section 1:区段,也称之为节,大家可以将其理解为一个个存放数据的抽屉,每个抽屉都有自己不同的名字,往往通过名字就可判断里面包含着真么样的数据。由于这些区段的数量并没有限制,所以用了“Section 2”“Section ...”“Section n”表示剩余部分。
希望通过以上的介绍,大家能对PE文件有一个比较宽泛的了解,但是除此之外,对于免杀技术来说,还有输入表也是我们必须了解的,而对于输入表,就不这么简单了。
输入表也称“导入表”,要想了解导入表,我们还要从导入函数讲起,一看到类似的术语,也许有一些初学的朋友又要嘀咕着埋怨俺了。其实大家不用担心,电脑中的术语与你的名字没有什么区别,你不需要理解它究竟是什么意思,只要知道他代表什么就可以了。
我们知道,如果一个程序需要运行的话,它执行的就是文件内部代码,而导入函数恰恰不属于这个定义,也就是说,导入函数就是代表被程序调用执行,但其执行的代码却不再程序中的一小部分函数。这些函数的真正代码位于某些DLL文件中,这调用者的程序中只保留一些调用这些函数的信息,包括需调用的函数名与DLL文件的名称等等。
但是对于这些硬盘上静态的PE文件来说,在自己被映射到内存之前,无法得知这些导入函数会在哪个地方出现。只有当文件被装入内存后,Windows才会将相应的DLL文件装入,并将导入函数与DLL中的实际函数地址联系起来,这便是“动态链接”的概念,也就是为什么DLL文件会被称为“动态链接库文件”的原因。
说了这么一大堆,归根结底就是要大家明白,动态链接就是由“导入表”来完成的。
三、由这些知识想到的
看完这些,不知道大家有什么想法没有,我想现在肯定仍然有些朋友还被一种叫做“修改PE段”的免杀技巧所困惑,为什么自己总是不成功呢?
记得我曾经在X档案07年第7期中发表一篇名为《木马免杀全攻略》的文章,其中就涉及到了“修改PE段”的免杀技巧,写完之后有一些朋友反映操作不成功,其实就是因为我当时对PE文件结构不了解造成的。
这里我就针对PE文件头的修改在这里详细的介绍一遍。
我们就针对WebHacking[A1Pass干净版]为例,做一次PE文件头的免杀。首先,为了能有一个比较“干净”的修改场所,我们需要将其PE头部的垃圾信息清理一下,这里使用的工具是PeClean,我们只需将WebHacking拖放到PeClean的界面即可完成清理,如图3所示,然后通过反汇编工具WinHex打开。
打开后如图4所示,通过与图1的典型PE文件对比,我们发现许多没用的信息现在已经能够清理干净了,这样更有利于我们的修改操作。
接下来就是计算PE文件头的大小了,我们沿着PE文件头开始标志“PE”往下找,第一个问号处所对应的16进制信息就是PE文件头的大小了,如图5所示。其实这种查找方法是有一定的局限性的,我们也可以这样找,在关键字“PE”后的第17个字节处的数据就是代表PE文件头大小的信息。
我们由图5得知,与之相对应的16进制信息为“E0”,转换为10进制也就是“224”,如图6所示。
由此我们得知了PE文件头的大小为224字节。也许看到这里有的朋友会有疑问,前面介绍PE文件的时候不是说过PE文件头的大小为224字节了吗?为什么这里有讲一遍呢?其实这样做只是考虑到怕大家遇到特殊情况,例如PE文件有已经被做了手脚,如果再详细的介绍一遍,这样可保证大家可以轻松应对任何情况。
下面我们就有关键字“PE”开始向下复制224+24=248个字节,其实还有更方便一些的方法我们可以边复制,边注意WinHex右下角的“大小”信息,当其显示为16进制的F8时,即说明我们已经选择了248个字节的信息了,如图7所示。
下面我们按快捷键【Ctrl】+【C】复制这段数据,然后在刚刚选取PE文件中部,由下向上选取248字节的区域,同理,我们看“大小”信息后显示16进制信息F8后即可停止,如图8。
通过图8可知,我们的光标停留在所选区域最前方。也就是偏移量80上,下面我们按快捷键【Ctrl】+【B】,会弹出一个对话框,提示“剪切板数据将写入在偏移量80”,我们点击确定即可,结果如图9所示。
这里一定要注意,在按快捷键之前,一定要确定光标在所选择区域最前方,否则会导致程序不能运行,甚至执行后会导致系统崩溃。
现在我们要将原PE文件头的剩余部分如图10所示用00填充。
然后我们在区段表的第一个节表“.nsp0”前开始选择,一直到PE文件头的头部,如图11所示。
与图可知,我们选择区域的大小为16进制的140,也就是10进制的320字节。我们只需将这个数值减去24,等于296,这就是现在位移后的PE文件头的真正大小。
也就是说,实际上我们PE文件头大小此时已经由原来的224变为现在的296,转换为16进制就是128,现在通过以上的PE文件知识推理可知,我们应该将上面的E0改为现在的128,但是实际应用时我们却不能这么改,因为涉及到高低位的问题,关于高低位的问题这里大家不必了解,只要记住它的规律即可。
就拿我们精要更改的128为例,真正应用时要输入为28 01,如图12所示。
而如果大小是567的话,那么就应输入为67 05,而ABC自然就是BC 0A。
明白了修改PE文件头大小的方法后,我们还应该修改记录PE文件头位置的信息,这个就比较容易了,通过PE文件的基础知识我们知道,记录PE文件头的字段位于DOS文件头的偏移量3C处,如图13所示。
我们可以知道原来的PE文件头位于偏移量C8处,但是现在我们PE文件头位于偏移量80处,所以我们只要将C8改为80即可,如图14所示。
最后保存即可,运行一下试试功能也完全正常。
也许这节讲的难度略微提高了一些,对于新手可能有些障碍,如果你想快速入门,推荐你先读一读我写的《木马免杀全攻略》,也许会让你快速入门。
后记:由于很多爱较真的朋友始终在问我有关于为什么要减24的问题,因此这里贴出一个我回答一位网友的留言。
如果我的回答与我的文章风格相符的话,那么就是“这就是个公式,你只管这样去做”。
因为如果你要搞清楚其中的原因,是需要扎实的PE文件结构基础的。下面是原因与原理:
1、文章着眼点:我们应该清楚,用简单的思路与语言讲述复杂的东西,必然伴随着知识的丢失,就像将double型强制转换为int型一样,这就是说我这篇文章为了保证初学者能看懂,所以偷换了一些概念。
2、E0真正的意思:是表示IMAGE_OPTIONAL_HEADER32结构加 数据目录表 的大小,也就是不包括以“PE00”起始的IMAGE_FILE_HEADER的大小,而IMAGE_FILE_HEADER的大小就是24字节。因此我们在计算时将其包括在内是不对的,要减去它才行。(详情参见我写的《手工构造典型PE文件》)
3、为什么不在文章中说清:我认为在给初学者讲解的时候,把其看做是一个整体来讲解要比分成三部分来讲解要容易理解的多。况且初学者只需要这个思想与修改的方法,对于其“原理”的对错并不重要,而当其深入研究下去之后,到时发现了我文章中的“错误”,没准应该会比较有成就感,不是嘛?