最近分析一个病毒文件,它是加了一个自己写的壳。单步到OEP后查看文件内容如下,有点懵逼,不是标准的PE文件。
用exeinfo查看,显示文件既不是EXE也不是DLL。
IDA识别成了NE文件,可能是文件头有字符串“NE”的原因。
然而并不能正确加载,所以这个文件并不是一个标准的可执行文件,要想用IDA正确载入分析,就需要将其修改为正确的PE格式。
我们在分析PE文件的时候,常规思路是从文件开头开始,从前往后分析,首先是DOS头,然后根据DOS头的字段索引到PE头,以此类推。
然而这个PE文件被修改了,从前往后并不一定能正确索引到。所以要换个思路,从后往前倒推。
具体应该从哪里开始倒推呢?应该从块表开始,因为块表跟第一个区块之间有一段用0填充的空白,比较容易识别。
直接往后面拖,找到块表的结束的地址0x20297。由于块表是由IMAGE_SECTION_HEADER结构体组成的数组,而IMAGE_SECTION_HEADER结构体的大小是0x28个字节,我们这里直接标出最后一个IMAGE_SECTION_HEADER,如下图:
现在来验证一下这个IMAGE_SECTION_HEADER是否正确。
IMAGE_SECTION_HEADER结构定义如下:
对照IMAGE_SECTION_HEADER结构,其前8个字节应该是其对应区块名,如“.text”,但这里却是0,应该是被去掉了。
继续往下看,它的第4个DWORD应该是其对应区块的RVA地址,这里为0x4780,对应的内存地址为0x24780。
找到对应的内存区域,可以看到正好在它前面有一块用0填充的区域。我们知道内存中区块之间为了对齐,会用0来进行填充,所以0x24780应该是正确的区块起始地址,也就是说获取到的是正确的IMAGE_SECTION_HEADER结构体。
按照同样的方法找到了5个IMAGE_SECTION_HEADER结构体,它们共同组成了PE文件的区块表。这里我们将区块名全部补上。
确定了块表后,继续往前找。前面应该是可选映像头(IMAGE_OPTIONAL_HEADER)。
我们先找可选映像头的最后一个成员——数据目录表(DataDirectory)。数据目录表是由16个IMAGE_DATA_DIRECTORY结构体组成的数组。
IMAGE_DATA_DIRECTORY结构定义如下:
IMAGE_DATA_DIRECTORY为2个DWORD大小,所以整个数据目录表应该为32个DOWRD大小。我们选中32个DWORD,如下:
为了进行验证,我们找到其第2个IMAGE_DATA_DIRECTORY,它指向输入表。
RVA为0x3D80,大小为0xC8,找到其指向的输入表,如下:
上面这块区域应该是一个IMAGE_IMPORT_DESCRIPTOR(简称IID)数组,它是输入表的开始。
IID结构定义如下:
直接找到第一个IID结构,如下:
那么它的第4个DWORD应该是其对应DLL名字的指针。同样的找到RVA 0x40FA对应的内存地址0x240FA,其指向字符串“ntdll.dll”。因此,这里的数据目录表也是正确的。
继续往下,可选映像头的剩余成员总大小是0x60,即如下区域:
可选映像头结构定义如下:
其第5个DWORD应该为程序执行入口RVA,这里为0x0E1E,对应内存地址为0x20E1E。
在反汇编窗口跳到地址0x20E1E,可以看到其为函数的起始地址。
再继续往前找,为IMAGE_FILE_HEADER(映像文件头),大小为0x14个字节,如下:
IMAGE_FILE_HEADER结构定义如下:
其第2个WORD为文件的区块数,这里是0x05,能够与前面找到的区块数相对应。其第1个WORD标志运行平台,对应关系如下:
这里可以看到这个标志被置为0了,所以需要进行填写,这里填写为0x14C。
继续往前,是Signature字段,也是被置为0了,同样的将其补上。
最后是DOS头。其大小为0x40,我们直接到开头选中0x40大小的内存。
DOS头结构如下:
将开头改为“MZ”,倒数第3个WORD改为PE头的RVA 0xD8。
至此,就完成了PE文件的修复。将其dump下来,再用exeinfo查看,可以看到被识别为了sys文件。
IDA也加载正常:
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2019-1-4 21:16
被Le0编辑
,原因: