《逆向工程核心原理》学习笔记7 UPack加壳

《逆向工程核心原理》学习笔记7

UPack加壳

(好久没更了orz)

UPack是一款用于给软件加壳的程序,通过对PE头的变形和压缩,达到不让别人识别文件作用的功能。因此骇客经常使用这种加壳程序对他们所编写的病毒进行包装。有些杀毒软件会不加分辨的直接把所有用UPack压缩的文件全部识别为病毒。(本身这个软件没有恶意)

首先要下载UPack,下载链接在这
https://download.csdn.net/download/windyduy/10908118
首先声明,这不是我发的资源,我在此感谢这位发资源的大哥orz
(没有广告费)

下载以后,将要加壳的软件放在upack.exe所在的目录下(以notepad.exe为例),打开cmd,进入目录,然后输入以下命令行

upack notepad.exe

然后notepad.exe就被upack加了壳

于是我们尝试用PEviewer去打开加壳后的记事本,发现PEviewer似乎只识别了该文件的header部分,而且似乎很混乱,因此,我们使用stud_PE这个程序去看加壳后的文件,下载地址如下
https://download.csdn.net/download/yxnamespace/470359
同样,这也不是我上传的资源,同样感谢这位大哥orz

感动中国
然后我们在stud_PE中打开notepad.exe
出现如下的窗口

《逆向工程核心原理》学习笔记7 UPack加壳_第1张图片

有一说一,这个界面挺好的,左边是PE头当中非常关键的一些成员已经把值都列出来了,而且也会表明RVA和RAW的情况,就不用像以前那样在HxD里慢慢数着找了
《逆向工程核心原理》学习笔记7 UPack加壳_第2张图片
先打开右下角SAVE to file左边的按钮(看不到全貌qwq)然后就会出现类似在HxD里看到的
《逆向工程核心原理》学习笔记7 UPack加壳_第3张图片
我们看看这个图,我们发现DOS头当中的MZ签名和NT头的PE签名只差了16个字节,于是我们猜测,这个UPack将DOS头和NT头重叠了起来,为的就是要充分利用有限的空间将PE文件充分重叠,让人难以分辨
《逆向工程核心原理》学习笔记7 UPack加壳_第4张图片
在左边可以看到PE头结构体的各个成员,我们注意几个关键的成员
第一是SizeOfHeader,我们注意到它的值是200H,也就是说,到1FFH部分为止都是Header
我们再看看节区的情况,因为我们在Executable Headers窗口里没有找到节区头,而在COFF Header中的SizeOfOptionalHeader的大小很奇特,是148H,所以OptionalHeader的大小不止在Executable Headers里显示那么小,而应该到28+148=170H的位置了
如图是在Data_Directory后面显示的所谓的多出来的一部分,由于Data_Directory的成员个数是由NumberOfRvaAndSizes决定的,而NumberOfRvaAndSizes的大小为A,因此实际上Data_Directory只有10个成员,在窗口当中显示的后面6个作废,并不是Data_Directory的成员
如图多出的部分
《逆向工程核心原理》学习笔记7 UPack加壳_第5张图片
作为初学者的我,不禁在想,这一段是不是没有被识别出来的节区头,由于被重叠的太厉害,导致这个工具没有识别出来?
实际上并不是这样,我们看看原窗口当中的Section部分
《逆向工程核心原理》学习笔记7 UPack加壳_第6张图片
要知道,节区头应该保存关于节区的相关信息,然而这一段多出来的却没有保存节区的任何信息,比如这个窗口中显示的VirtualAddress,RawSize等等,所以它不是节区头
根据书上所提供的信息,我们终于知道了,这一段保存了Upack压缩的解压代码,用OD查看汇编代码,就长这样(当然先要找到这一段的RVA和ImageBase的值)
《逆向工程核心原理》学习笔记7 UPack加壳_第7张图片
比对一下机器语言,从40开始一直到AD都是解压代码

然而,Upack并没有把节区头丢掉,一般来说,节区头紧跟OptionalHeader之后的,但是由于Upack经常做一些奇怪的事,比如重叠DOS头和NT头(迷惑行为),在可选头里埋了一些解压代码,所以我才会产生一些奇怪的想法。
因为我的智力条件你也知道
Header部分大小为200H,而OptionalHeader结束时的位置在16F,所以自然而然想到在这之后都是节区头部分了
显然节区头的重要信息已经在这个工具的Section部分展示了,我们看看这个Section部分的数据
《逆向工程核心原理》学习笔记7 UPack加壳_第8张图片
如图显示的是3个节区的信息,我们有一个巨大的发现,就是第1节区的文件偏移和第3节区的文件偏移都是10H,大小都是1F0,加起来正好到PE头结束
《逆向工程核心原理》学习笔记7 UPack加壳_第9张图片
Upack把PE头和第一第三节区全重叠在一起了?
《逆向工程核心原理》学习笔记7 UPack加壳_第10张图片
值得注意的是,第一节区的文件大小虽然是1F0H,然而,在内存当中的大小是14000H,也就是说,在程序运行瞬间,解压代码会把数据解压到第一节区当中去
在这里,我们不能把这三个节区当作原PE文件当中的.txt 、.data、.rsrc来看,由于第一节区非常大,所以在解压的时候,三个节区的数据都会解压到第一节区当中

下面讨论在Upack压缩的文件中怎么将RVA转换为RAW
显然,转换公式大家都很熟悉
RAW=RVA-VirtualAddress+PointerToRawData
但如果在这里使用就会出现问题
我们知道可选头成员FileAlignment的大小和PointToRawSize密切相关,在一般的PE文件当中PointToRawSize是FileAlignment的整数倍
然而,在这个文件当中,由于第一节区的文件偏移是10H,而FileAlignment的大小为200H,取整,等于0
所以如果要找某个数据的位置,就不能把PointToRawSize当作10H来看待了,只能用0来计算,因为PointToRawSize的大小是由FileAlignment决定的

比如说,我们要找程序的EP在文件中的位置
那么我们首先找到可选头当中的AddressOfEntryPoint,其值为1018H,这个是RVA,显然在内存当中处于第一节区,所以我们找到第一节区的VirtualAddress是1000H,然后PointToRawSize的值当作0来看,所以计算出来的EP的位置是18H
《逆向工程核心原理》学习笔记7 UPack加壳_第11张图片
如图选中的代码(蓝色的)就是程序的EP

最后我们来讨论一下导入表
首先我们查看一下Data_Directory的Import Table成员,前四个字节是IMAGE_IMPORT_DIRECTORY的地址(RVA),后四个字节是IMAGE_IMPORT_DIRECTORY的大小,如图所示
《逆向工程核心原理》学习笔记7 UPack加壳_第12张图片
首先确定IMAGE_IMPORT_DIRECTORY在文件中的位置,RVA是271EE,所以处于第三节区,计算后得到它的RAW是1EE
《逆向工程核心原理》学习笔记7 UPack加壳_第13张图片
我们知道,IMAGE_IMPORT_DIRECTORY是由5个DWORD大小的成员组成的,其大小为14H字节,在正常的PE文件中,一个IMAGE_IMPORT_DIRECTORY对应着一个函数,它们组成数组,最后一个是由NULL填充的IMAGE_IMPORT_DIRECTORY的结构体
然鹅,我们找到的这个结构体后面既没有NULL结构体,也没有出现其他的IMAGE_IMPORT_DIRECTORY结构体,难道出错了?

不!

并没有出错,我们仔细思考一下,这个结构体实际上是被加载到内存当中去的,在加载到内存的时候,它的位置处于第三节区比较靠前的位置,而由于1FF是在第三节区的末尾,所以200H以后的数据不会出现在第三节区的映像当中。

我们在OD里打开这个程序,查看这段内存的情况(ImageBase=1000000H,RVA=271EE)
《逆向工程核心原理》学习笔记7 UPack加壳_第14张图片
我们看到后面全都被填充为NULL
所以没有问题,重点是:重要的不是文件中的情况,而是被加载到内存中是否符合规范,运行是否有问题
我们想知道这个UPack压缩后的notepad.exe加载了哪些API,那么我们根据IMAGE_IMPORT_DIRECTORY中的Name成员,其值为2,找到库名(因为在头部,所以不用转换了)
《逆向工程核心原理》学习笔记7 UPack加壳_第15张图片
我们看到它引入了KERNEL32.DLL
之后我们再看看IAT的位置
IMAGE_IMPORT_DIRECTORY最后的成员是FirstThunk,指出了IAT的位置,我们看到其值为11E8,转换为RAW就是1E8
如图选中的部分就是IAT
《逆向工程核心原理》学习笔记7 UPack加壳_第16张图片
所以在28和BE处引入了两个API,在Hex中查看就行了,分别是
LoadLibrary和GetProcAddress

OK,这就是关于Upack加壳的我所学的内容,望各位大佬多多指点
《逆向工程核心原理》学习笔记7 UPack加壳_第17张图片

你可能感兴趣的:(《逆向工程核心原理》学习笔记7 UPack加壳)