陈明,叶培顺
(1.西安文理学院计算机科学系,陕西西安710065;2.榆林学院信息工程学院,陕西榆林719000)
可移植的执行体(Portable Executable,PE)文件格式是微软制定的一种文件标准,它是从普遍运用于UNIX操作系统的COFF(Common Object File Format)发展而来,是目前Windows平台上的主流可执行文件的文件格式,应用于所有的32位Windows[1]。
从某种意义上讲,可执行文件的格式是操作系统本身执行机制的反映。基于PE文件格式的研究层出不穷,及这方面的漏洞分析不容忽视,本文就此作了探讨。
PE文件主要由DOS部首,PE文件头,节表,节和辅助结构等5部分组成,如图1所示。其中的数据结构通常定义在WINNT.H[2]。
图1 PE文件架构Fig.1 PE file structure
行信息嵌入的方法,但只适用于未编译的PE文件源代码中进行信息隐藏)和文件病毒领域。
PE文件的数据结构在磁盘和内存中是一样的,装载一个可执行文件到内存中,它不是作为单一内存映射文件被载入内存的,Windows加载器遍历PE文件并决定文件的哪一部分被映射。依据PE文件的存储结构及其加载过程,得出两种典型的向PE文件中添加代码的方法[3]。
2.1.1 插 入方式
PE文件在磁盘中,节与节之间必须遵循文件对齐原则,
结合PE文件自身的结构特点,2.1阐述PE文件的修改思想,很多进一步的应用开发都是建立在此原理之上,比如在加密解密领域(在PE文件的冗余空间中插入加密解密程序的代码),信息隐藏领域(主流的方法是利用PE文件中存在的冗余空间和冗余字段进行信息嵌入,该方法不会改变PE文件长度和结构。也可利用静态分配字符串存储空间进以利于PE文件快速定位,而程序的代码或数据可能没有占满该节,造成冗余空间,可乘机插入代码,实现思想如下:
由DOS头结构字段e_lfanew定位PE头结构位置;读取PE头,得到节个数字段Number Of Sections;依据节个数分配节表缓冲区读取所有节表到缓冲区;遍历每个节,空白区的文件偏移等于(Pointer To Raw Data+Virtual Size);空白区大小为该节实际占用磁盘空间减去该节实际大小(Size Of Raw Data-Virtual Size);修改节表结构让缓冲区中每个节表的字段Virtual Size等于字段Size Of Raw Data;将缓冲区数据写入。
2.1.2 附 加方式
对于绝大多数编译器生成的PE文件,在最后一个节表结构和第一个节数据区之间存在一个空白区,如图1所示的UNUSED区。往往足以插入一个新的节表结构(每个节表结构大小是28HB),实现思想如下:
计算Number Of Sections*0x28+e_l fanew+size of(IMAGE_NT_HEADER),得到要添加新节头的起始地址;根据Pointer To Raw Data=(最后一节的Pointer To Raw Data+最后一节的Size Of Raw Data)和Size Of Raw Data/Virtual Size=((要添加的代码长度/File Alignment+1)*File Alignment)赋值给节头结构中的对应变量。修改Number Of Sections,Size Of Image等字段。在这里一定要注意,依照Section Alignment对齐Virtual Size和Virtual Address同样依照File Alignment Size Of Raw Data和Pointer To Raw Data;根据不同需要设置属性字段等。
以插入方式添加的病毒代码,如CIH病毒。对于存在空白空间的节,可以通过修改节表结构,让Virtual Size等于Size Of Raw Data,然后在空白空间中插入随机数据欺骗病毒,使它无法以这种方式感染PE文件。
以附加方式添加的病毒代码,如劳拉病毒。修改PE文件时在最后一个节表和第一个节数据区的空白区插入了一个新的节表结构,用以描述在文件尾部附加一个新的节存放病毒代码。由于PE头文件、节表结构是相连的,如果将这两个结构往下移动到与第一个节数据区相连,病毒就无法插入。PE头文件和节表结构在文件中的位置是由DOS头结构中的字段e_lfanew决定,修改该值并把两个结构向下移动到连接第一个节就可以防范病毒插入节表结构,有效禁止了添加新节。
最新的研究是建立自免疫防病毒系统:在文件中某个不固定的空白位置存储文件的重要数据,如果非覆盖型文件病毒修改文件的任何一个字节,程序启动时会计算当前的CRC32校验值并和原来存储的CRC32值相比较,若相等,则跳转到原来程序入口继续运行,否则从自身释放出一个修复程序,并关闭当前程序由修复程序对文件进行恢复操作,完成修复后调用被修复文件然后删除自己,删除方法是是先生成一个批处理文件,然后用函数ShellExecute调用批处理文件后退出进程,在批处理文件中循环删除主文件,直到主文件的进程退出,批处理程序才能删除主文件,然后让批处理文件删除自身。
PE文件在编译和连接成功后,会有一个IAT。当需要执行API的时候,会先在IAT中得到API的地址,然后调用它。当往PE文件中插入可执行代码时,情况不同,可执行代码是在PE文件编译好之后才插入,它本身没有导入表,为了在插入代码中调用API函数,必须获取API函数的线性地址[4]。(某些情况下可以搜索宿主的导入表获得GetProcAddress和GetModuleHandleA函数,然后通过它们返回系统的DLL,进而获得其中的API函数,但在宿主没有使用GetProcAddree函数的时候,这种方法行不通。)而要得到API的地址,必须用到Loadlibrary和GetProcAddress函数,这两个函数在Kernel32.dll中。如图2,CreatProcess函数在完成装载应用程序后,会将一个返回地址压入堆栈并转而执行应用程序,这个保存在堆栈顶的数据就在Kernal32.dll中的返回地址。因此只要从返回地址按照页对齐的边界一页页地往低地址搜索,就必然可以找到Kernel32.dll文件头地址,搜索它的导出表,并从导出表的信息中查找到Loadlibrary和GetProcAddress函数的地址,利用这两个函数得到想要的API函数。(对于给定的API函数,也可以直接在Kernel32.dll的导出表中搜索其地址。)
图2 Win32可执行文件的执行过程Fig.2 Executing process of Win32 EXE files
上面的研究表明:由于节的对齐粒度固定,造成节与节之间可能存在虚拟自由空间,这些空间成为嵌入代码的隐藏地和更具规模的移动代码的发射台,从而引起安全危机。具体漏洞如下所示:
1)模糊的将DLL可执行体链接到进程,尤其是GetProcAddress和LoadLibrary这两个API函数,在方便了普通程序开发者链接到他们的DLL之外有更深远的影响。这两个API函数使得挖掘代码,嵌入代码,及其他高度移动代码的行为成为可能。
2)完整的PE头信息,包括导入导出库信息,留在进程的内存中方便了GetProcAddress函数和Kernel32模块基础获得信息,埋下隐患[5]。
3)在发布可执行文件的准备时期,对运行在操作系统(和/或者,防病毒程序)的可执行文件的整体性缺乏检测机制,或者很薄弱的不充分的检测机制,这使得修改可执行文件和运行新的可移动代码相对容易,很多组件都没能检测到对可行性文件的修改。
4)可执行体一旦被编译,链接并传送,就易于被其他程序修改,大部分没有实施运行时自我保护机制[6]。这一缺陷不局限于Win32应用程序,许多其他操作系统的可执行文件也同样未能在运行时进行自检,但Win32提供的动态链接机能使移动代码的嵌入尤其危险。
掌握PE文件的结构和装入机理,不仅可以帮助深层了解32位的Windows操作系统,而且是在Win32下开发信息隐藏,加密解密,PE病毒等应用程序的重要基础知识。结合在探索Win32PE病毒的过程中的认知,提出了Win32体系结构下基于PE文件格式的若干漏洞,由于这些漏洞属于基础型的,因此修复问题有待解决。
[1]Microsoft Corporation.Microsoft portable exectuable and common object file format specification[M].MSDN.2002.
[2]罗云彬.Windows环境下32位汇编语言程序设计[M].北京:电子工业出版社,2002.
[3]Danehkar A.Inject your code to a portable executable file[EB/OL].(2005)http://www.codeproject.com/.
[4]Richter J.Windows核心编程[M].北京:机械工业出版社,2005.
[5]何迎生,段明秀.32位Windows系统下的PE文件结构及其应用[J].吉首大学学报:自然科学版,2003(1):77-79.
HE Ying-sheng,DUAN Ming-xiu.PE structure under the 32-bit Windows system and its application[J].Journal of Jishou University:Natural Science Edition 2003(1):77-79.
[6]胡珊.向PE文件中插入可执行代码的研究[J].鞍山科技大学学报,2005(2):119-122.HU Shan.Study on inserting executable codes into PE files[J].Journal of Anshan University of Science and Technology,2005(2):119-122.