1、计算机病毒技术第5章 Windows文件型病毒,内容提要,概述宏病毒PE病毒,概述,所有通过操作系统的文件系统进行感染的病毒都称作文件型病毒数据文件PE文件,文件型病毒,典型的载入内存和传播方式被感染的程序运行,病毒控制后台如果病毒常驻内存,则监视文件运行和系统调用,满足感染条件时进行感染如果不常驻内存,则选择某个特殊的文件进行感染,取得文件控制权,宏病毒,宏的概念宏病毒的概念、原理和实例宏病毒的预防与清除宏病毒的正向应用,宏的概念,宏(Macro),是一种批量处理的称谓根据一系列预定义的规则替换一定的文本模式解释器或编译器在遇到宏时会自动进行这一模式替换对于编译语言,宏展开在编译时发生,进行
2、宏展开的工具常被称为宏展开器宏这一术语也常常被用于许多类似的环境中,绝大多数情况下,“宏”这个词的使用暗示着将小命令或动作转化为一系列指令,作为一个单独命令完成一个特定任务,用户可以创建并执行宏,以替代人工进行的一系列费时而单调的重复性操作,自动完成所需任务Microsoft office中的宏本质上是脚本程序(批处理程序)由VBA(Visual Basic for Applications)所编写的程序,可以访问许多操作系统函数并支持字处理文档、数据表格、数据库、演示文档等数据文件中的自动化任务实现一系列命令,使日常工作变得更容易演示:设置格式,宏病毒的概念和原理,宏病毒是基于宏机制和VBA
3、所编写的程序,可以在一些数据处理系统中运行,存在于某些数据文档中,利用程序的功能将自己复制并且繁殖到其他数据文档中宏病毒基本原理在office某个应用启动时,会自动加载Normal.dot模板,以及它们所包含的宏演示1.新建文件“test1.doc”,添加文件模块宏macrotest1,查看效果2.新建文件“test2.doc”,打开运行macrotest1,查看效果3.打开“test1.doc”,添加模板模块宏macrotest24.打开“test2.doc”,运行macrotest1和2两个宏,观察不同5.将宏macrotest1和2分别改为FileOpen宏,运行观察作用和不同6.将宏m
4、acrotest2改为AutoOpen宏,运行观察作用,宏病毒原理,Word宏事件普通宏自动宏,宏病毒原理,转换成文档模板的宏,当宏病毒获得运行权限之后,执行宏指令,把宏病毒复制到Normal模板之中,感染其它Word文档,当其它的Word文件打开时,由于自动调用模板因而会自动运行宏病毒导致被感染,15,改写Word宏,改写特定的文档宏,如AutoOpen等,宏病毒原理,无毒文件.doc,Normal.dot,有毒文件.doc,Normal.dot,宏病毒实例,代码宏病毒的触发宏病毒的传播宏病毒的破坏演示(实验2/实践题),宏病毒的预防与清除,预防:宏的安全性设置清除:从模板着手杀软,宏病毒的
5、正向应用,宏的合理合法应用,PE病毒,PE含义PE病毒演示PE文件结构PE病毒实例介绍基于PE病毒的正向应用,PE含义,PEPortable Executable基于WindowsNT架构的可执行文件,如EXE、DLL、SYS、OCX、COM等,都是PE文件从第一个NT操作系统诞生至今的19年,操作系统发生巨大变化,但是对PE格式的影响并不大PE有较好的数据组织方式和数据管理算法PE的数据组织是大量的字节码与数据结构的有机融合,PE病毒演示,图标修改文件感染,PE文件结构,PE文件使用一个地址空间把所有代码和数据都合并在一起,组成一个很大又比较复杂的数据结构由四部分组成DOS部分PE文件头节表
6、节数据,PE文件格式,节,PE文件的真正内容划分成块,称之为sections,节每节是一块拥有共同属性的数据,是PE文件中代码或数据的基本单元在PE文件中,代码、已初始化的数据、资源和重定位信息等数据被按照属性分类放到不同的Section(节)中,PE文件格式,节表,每个节的属性和位置等信息用一个特定结构来描述所有节的结构组成一个节表(Section Table)节表数据在PE文件中放在所有节数据的前面,PE文件格式,PE文件头,在PE文件中数据是按属性在节中放置的,不同用途但属性相同的数据(例如导入表、导出表以及指定的只读数据)可能是被放在同一节PE文件用一系列的数据目录结构分别指明这些数据
7、的位置,这些数据目录结构组合起来的称为数据目录结构表数据目录结构表和其它描述文件属性,如文件执行时的入口地址、文件被操作系统装入内存后的默认基地址等数据合在一起称为PE文件头,放于节和节表之前,PE文件格式,DOS部分,为了与DOS系统的文件格式兼容,在PE文件头之前有一个标准的DOS MZ格式的可执行部分,PE文件格式,DOS部分,PE文件中的DOS部分由MZ格式的文件头和可执行代码DOS块(DOS stub)组成MZ格式的文件头(MS-DOS头)由IMAGE_DOS_HEADER结构定义,占据PE文件最开始的64个字节对于PE文件而言,这个结构中有用的是最后的e_lfanew字段该字段在磁
8、盘文件中的偏移量为0000003CH,占四个字节该字段存储PE文件头在磁盘文件中距文件头的偏移量,Windows装载器找到这个偏移量就可以找到真正的PE文件头在文件中的位置DOS块一旦在DOS执行一个PE文件,系统可以将文件解释为DOS下的.EXE可执行格式,执行DOS块DOS块执行只是简单的显示一个“This program cannot be run in DOS mode”就退出DOS块的大小一般不能确定,并且利用链接器的某些参数可以替换这个程序,PE文件格式,PE文件头,紧接着DOS Stub的是PE文件头PE装载器将从DOS 文件头中找到PE文件头的起始偏移量,从而跳过DOS Stu
9、b直接定位到真正的PE文件头PE文件头中存放着PE整个文件信息分布的重要字段,包含了许多PE装载器用到的重要信息PE文件头由IMAGE_NT_HEADERS结构组成,IMAGE_NT_HEADERS,Signature是PE文件头的第一个双字占4个字节,是PE文件的标志。值是00004550H,即“PE00”FileHeader是PE的文件格式头,共占20个字节OptionalHeader是PE的可选头部,默认占用224/240个字节,IMAGE_NT_HEADERS,IMAGE_FILE_HEADER,PE文件格式,IMAGE_NT_HEADERS,Signature是PE文件头的第一个双字
10、占4个字节,是PE文件的标志。值是00004550H,即“PE00”FileHeader是PE的文件格式头,共占20个字节OptionalHeader是PE的扩展头部,共占IMAGE_FILE_HEADER.SizeOfOptionalHeader个字节,IMAGE_OPTIONAL_HEADERS32,表示文件类型,IMAGE_OPTIONAL_HEADERS32,Magic字段。该字段相对于PE文件头的偏移量是00000018H,占2字节,表示文件类型。值为0x10B,表示这是一个PE32文件;0x20B表示这是一个PE32+,即64位下的PE文件AddressOfEntryPoint字段
11、。该字段相对于PE文件头的偏移量是00000028H,占4字节。指出了文件被执行时的入口地址,这是一个RVA地址。如果在一个可执行文件上附加了一段代码并想让这段代码首先被执行,那么需要将这个入口地址指向附加的代码,IMAGE_OPTIONAL_HEADERS32,IMAGE_OPTIONAL_HEADERS32,ImageBase字段该字段相对于PE文件头的偏移量是00000034H,占4字节指出了文件的优先装入地址。当文件被执行时,如果可能的话,Windows优先将文件装入到ImageBase字段指定的地址中,只有指定的地址已经被其它模块使用时,文件才被装入到其它地址中,IMAGE_OPTI
12、ONAL_HEADERS32,SectionAlignment字段和FileAlignment字段这两个字段相对于PE文件头的偏移量分别是00000038H和0000003CH,各占4字节FileAlignment字段指定了节存储在磁盘文件中时对齐的字节单位为了减少磁盘文件的大小,文件对齐的单位一般以一个物理扇区的大小作为对齐粒度FileAlignment字段的值一般为200H,512字节SectionAlignment字段指定了节被装入内存时对齐的字节单位每个节被装入的地址必定是本字段指定数值的整数倍节在内存中的对齐单位必须至少是一个页的大小(Win32下这个值是4KB(1000H),IMA
13、GE_OPTIONAL_HEADERS32,IMAGE_OPTIONAL_HEADERS32,DataDirectory字段。该字段相对于PE文件头的偏移量是00000078H,由16个相同的IMAGE_DATA_DIRECTORY结构组成,被称为数据目录表数据按照用途可以分为导出表、导入表、资源、重定位表等数据块这16个IMAGE_DATA_DIRECTORY结构就是用来定义多种不同用途的数据块。该结构仅指出某种数据块的位置和长度,IMAGE_DATA_DIRECTORY,索引索引值在Windows.inc中的预定义值对应的数据块描述0IMAGE_DIRECTORY_ENTRY_EXPORT
14、导出表1IMAGE_DIRECTORY_ENTRY_IMPORT导入表2IMAGE_DIRECTORY_ENTRY_RESOURCE资源3IMAGE_DIRECTORY_ENTRY_EXCEPTION异常目录表4IMAGE_DIRECTORY_ENTRY_SECURITY安全目录表5IMAGE_DIRECTORY_ENTRY_BASERELOC基址重定位表6IMAGE_DIRECTORY_ENTRY_DEBUG调试信息表7IMAGE_DIRECTORY_ENTRY_ARCHITECTURE版权信息表8IMAGE_DIRECTORY_ENTRY_GLOBALPTR机器值(MIPS GP)9IMA
15、GE_DIRECTORY_ENTRY_TLS线程局部存储(TLS)表10IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG载入配置目录表11IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT绑定输入目录表12IMAGE_DIRECTORY_ENTRY_IAT导入函数地址表13IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT延迟导入描述符的地址和大小14IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTORCLR运行时头部的地址和大小15未使用,但要保留且必须为 0,IMAGE_DATA_DIRECTORY,PE文件格式,P
16、E文件格式,节表,PE文件中所有节的属性都定义在节表中节表由一系列IMAGE_SECITON_HEADER结构排列而成,每个结构用来描述一个节,结构的排列顺序和它们描述的节在文件中的排列顺序一致节表紧接着PE文件头的结束而存放节表中IMAGE_SECTION_HEADER结构的总数由PE文件头中的NumberOfSection字段指定有几个节就有几个IMAGE_SECTION_HEADER结构每个IMAGE_SECTION_HEADER结构占据40个字节,IMAGE_SECTION_HEAGER,节未对齐前的真实尺寸,IMAGE_SECTION_HEAGER,Namel字段定义了节的名称,字段
17、的长度为8个字节仅有标识作用,不能作为节的定位标准,IMAGE_SECTION_HEAGER,VirtualSize字段。占4个字节,代表节的数据在没有进行对齐处理前的实际大小SizeOfRawData字段。占4个字节,它指出了节在磁盘文件中所占的空间大小,这个数值按照文件头中的FileAlignment值对齐以后的大小VirtualAddress字段。占4字节,它指出节被装载到内存中后的偏移地址,是一个RVA地址。这个地址是按照PE文件头中的SectionAlignment值对齐PointerToRawData字段。占4个字节,它指出节在磁盘文件中所处的位置,这个数值是从文件头开始算起的偏移
18、量Characteristics字段。占4个字节,节的属性标志字段,IMAGE_SECTION_HEAGER,IMAGE_SECTION_HEAGER,依靠VirtualSize字段、VirtualAddress字段、SizeOfRawData字段和PointerToRawData字段这四个字段的值,装载器就可以从PE文件中找出某个节的数据,并将它映射到内存中去,PE文件加载过程,读取PE文件头中的NumberOfSections数据,获取节的个数信息定位节表起始位置:PE文件头的起始偏移量加上PE文件头的总大小循环读取并处理节表中的各个节信息读取结构中的PointerToRawData数据,
19、定位到该节在文件中的起始位置读取SizeOfRawData数据,获取该节映射到内存所占据的字节数X将本节的VirtualAddress数据加上PE文件头中的ImageBase数据,得到本节在虚拟内存中的起始地址VA按照该地址VA,将本节映射到内存该处开始占据的X个字节数按照Characteristics数据设置本节的访问标志,PE文件格式,节,PE文件的真正内容紧跟在节表之后所有的代码、初始化数据、未初始化数据、资源、导入函数、导出函数、调试信息等各类数据最终都按各自的特点存放在各个不同的节中每个节拥有共同属性的数据,如读、写、执行等当PE装载器映射节内容时,会检查相关节属性并置对应内存块为指
20、定属性,节,每个节的名称是唯一的,不能有同名的两个节出现节的名称不具有任何意义,它仅是为了查看方便而设置的一个标记,可以选择任何名称甚至将它空着也可以将包含代码的节命名为“DATA”或者将包含数据的节命名为“CODE”都是合法的每个节中的数据都位于由节表结构中的PointerToRawData字段指定的文件偏移处,大小则由SizeOfRawData字段给出,节,代码节(.text)Windows NT默认的做法是将所有的可执行代码组成了一个单独的节,名为“.text”或“.code”数据节(.data/.bss)已初始化数据节.data中存放的是在编译时已经确定的数据未初始化数据节.bss存放
21、的是没有初始化的全局变量和静态变量资源节(.rsrc)资源节.rsrc存放程序要用到的菜单、字符串表和对话框等资源。资源节是树形结构,有一个主目录,主目录下有子目录,子目录下又是子目录或数据 导入表(.idata)导入表保存函数名和其驻留的DLL名等动态链接所必需的信息导出表(.edata)导出表保存用于导出给其他程序所用的函数信息,导入表,在Win32编程中常用到“导入函数”(Import functions),导入函数就是被程序调用但其执行代码又不在程序中的函数这些函数的代码位于一个或多个DLL中,在调用者程序中只保留一些函数信息,包括函数名及其驻留的DLL名等,导入表,对于存储在磁盘上的
22、PE文件而言,它无法知道这些导入函数会在内存的哪里出现,只有当PE文件被装入内存时,Windows装载器才会将DLL装入,并将调用导入函数的指令和函数实际所处的地址联系起来,这就是“动态链接”的概念动态链接是通过PE文件中定义的“导入表”(Import Table)来完成的,导入表中保存的正是函数名和其驻留的DLL名等动态链接所必需的信息,导入表,导入表位置和大小从PE文件头中IMAGE_OPTIONAL_HEADERS32结构的数据目录中获取,其对应项目是DataDirectory字段中第2个IMAGE_DATA_DIRECTORY结构从IMAGE_DATA_DIRECTORY结构的Virt
23、ualAddress字段得到的是导入表的RVA值,如果在内存中查找导入表,则将RVA值加上PE文件装入的基址就是实际的地址;如果在PE文件中查找导入表,就需要先将RVA转换成文件偏移再去查找,IMAGE_DATA_DIRECTORY,索引索引值在Windows.inc中的预定义值对应的数据块描述0IMAGE_DIRECTORY_ENTRY_EXPORT导出表1IMAGE_DIRECTORY_ENTRY_IMPORT导入表2IMAGE_DIRECTORY_ENTRY_RESOURCE资源3IMAGE_DIRECTORY_ENTRY_EXCEPTION异常目录表4IMAGE_DIRECTORY_E
24、NTRY_SECURITY安全目录表5IMAGE_DIRECTORY_ENTRY_BASERELOC基址重定位表6IMAGE_DIRECTORY_ENTRY_DEBUG调试信息表7IMAGE_DIRECTORY_ENTRY_ARCHITECTURE版权信息表8IMAGE_DIRECTORY_ENTRY_GLOBALPTR机器值(MIPS GP)9IMAGE_DIRECTORY_ENTRY_TLS线程局部存储(TLS)表10IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG载入配置目录表11IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT绑定输入目录表12IM
25、AGE_DIRECTORY_ENTRY_IAT导入函数地址表13IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT延迟导入描述符的地址和大小14IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTORCLR运行时头部的地址和大小15未使用,但要保留且必须为 0,RVA和磁盘文件偏移之间的转换,使用RVA让文件装入内存后的数据定位变得方便,但却给处理磁盘上静态PE文件带来麻烦在处理PE文件时,任何RVA必须通过文件偏移的换算来定位并访问文件中的数据,否则无法正确定位所要寻找的数据位置,转换步骤,1.查询节表得到每个节在内存中的起始RVA(根据VirtualAdd
26、ress字段),并根据节的大小(SizeOfRawData字段)算出节的结束RVA,比较判断导入表的RVA 落在哪个节之内2.找到导入表RVA所在的节之后,用导入表RVA减去该节的起始RVA,这样可以得到目标RVA相对于节起始地址的偏移量RVA3.在节表中获取节在文件中所处的偏移(PointerToRawData字段),将这个偏移值加上上一步中得到的RVA值就可以得到数据在文件中的真正偏移位置,举例,1.找到导入表的RVA距离PE文件头80h开始的4个字节2.找到.text节起始RVA=节表中.text.VirtualAddress(节名之后的第二个双字)3.找到.text节大小=节表中.te
27、xt.sizeofRawData(节名之后的第三个双字)4.确定.text节的范围:AB5.确定导入表的RVA属于A,B范围6.用导入表的RVA-.text节的起始RVA,得到偏移量offset7.用offest加上.text节表.text.PointerToRawData(节名之后的第四个双字)8.得到导入表在文件中的起始偏移量,导入表,是由一系列IMAGE_IMPORT_DESCRIPTOR 结构组成,结构的数量由程序要使用的DLL文件数量决定每个结构占20个字节每一个IMAGE_IMPORT_DESCRIPTOR结构对应一个DLL文件若一个PE文件从10个不同的DLL文件中引入了函数,那
28、么就存在10个IMAGE_IMPORT_DESCRIPTOR 结构来描述这些DLL文件再多有这些结构的最后都是由一个内容全为0的IMAGE_IMPORT_DESCRIPTOR结构作为结束,导入表,导入表,OriginalFirstThunk字段,双字,是一个RVA,指向一个包含一系列IMAGE_THUNK_DATA结构的数组数组中每个IMAGE_THUNK_DATA结构定义了一个导入函数的信息数组的最后是以一个内容为0的IMAGE_THUNK_DATA结构作为结束此数组永不改变TimeDateStamp字段,双字,指向时间标志,在映像被绑定之前这个字段一直被设置为0。当映像被绑定之后,这个字段
29、被设置为这个DLL的日期时间戳。ForwarderChain字段,双字,是输入函数列表中第一个中转的32位的索引。Namel字段也是一个RVA,双字,指向此结构对应的导入DLL文件的名称,这个文件名是一个以NULL结尾的字符串FirstThunk字段,双字,也是一个RVA,指向一个IMAGE_THUNK_DATA结构数组数组中每个IMAGE_THUNK_DATA结构定义了一个导入函数的信息数组最后是以一个内容为0的MAGE_THUNK_DATA结构作为结束此数组是输入地址表IAT的一部分,在文件装载到内存时改变,IMAGE_THUNK_DATA,IMAGE_THUNK_DATA结构实际上就是一
30、个双字,占4字节该结构对应一个导入函数,该结构指定导入函数的方法如下:当双字(指该结构)的最高位为1时,表示函数是以序号的方式导入的,这时双字的低位就是函数的序号;当双字的最高位为0时,表示函数以字符串类型的函数名方式导入,这时双字的值是一个RVA,指向一个用来定义导入函数名称的IMAGE_IMPORT_BY_NAME结构,IMAGE_IMPORT_BY_NAME,该结构中的Hint字段表示函数的序号,指明了导入函数在DLL中的索引号。但是,这个字段是可选的,有些编译器总将它设置为0Namel字段定义了导入函数的名称字符串,它是个以0为结尾的字符串,导入表,以序号方式导入函数lstrcmp,0
31、010h,以函数名方式导入函数,指向的数组内容会被替换成导入函数的真正入口地址; 所有DLL对应的导入地址数组被排列在一起,称为导入地址表IAT;可以通过数据目录表中第13项找到IAT数据块的位置和大小,导入表,导出表,导出表是和DLL文件紧密联系在一起的DLL(动态链接库,Dynamic-link libraries)是包含函数和数据的模块,只有在需要调用模块时才会将他们装载到内存空间中,而且不管调用模块有多少,一个DLL在内存中只有一个实例DLL模块有两种导出函数的方法:用序号导出。序号是在该DLL模块中可以唯一标识一个导出函数的16bit数字用名字导出。如果用名字导出函数,则其他DLL文
32、件或可执行函数既可以用名字导入该函数,也可以用序号导入导出表用来描述DLL文件的导出函数。通过导出表,DLL文件向系统提供导出函数的名称、序号和入口地址等信息,以便windows装载器通过这些信息完成动态链接的过程,导出表,导出表,已知导出的函数名,获取函数地址的一般步骤定位到PE header从数据目录表读取导出表的虚拟地址定位导出表获取名字数目(NumberOfNames)并行遍历AddressOfNames和AddressOfNameOrdinals指向的数组匹配名字。如果在AddressOfNames指向的数组中找到匹配名字,从AddressOfNameOrdinals指向的数组中提取
33、索引值。例如,若发现匹配名字的RVA存放在AddressOfNames数组的第6个元素,那就提取AddressOfNameOrdinals数组的第6个元素作为索引值。如果遍历完NumberOfNames个元素,说明当前模块没有所要的名字从AddressOfNameOrdinals数组提取的数值作为AddressOfFunctions数组的索引。也就是说,如果值是5,就必须读取AddressOfFunctions数组的第5个元素,此值就是所要函数的RVA,导出表,已知导出函数的序号,获取函数地址的一般步骤定位到PE header从数据目录表读取导出表的虚拟地址定位引出表获取Base值减掉Base
34、值得到指向AddressOfFunctions数组的索引将该值与NumberOfFunctions作比较,大于等于后者则序数无效通过上面的索引就可以获取AddressOfFunctions数组中的RVA,资源,PE文件资源中的内容包括光标、图标、位图和菜单等十几种标准类型,此外还可以使用自定义类型。将各种类型的不同ID的资源,用类似于磁盘目录结构的方式即按照根目录资源类型资源ID的3层树型目录结构有序组织起来在第3层目录中放置的代码页“文件”不是资源本身而是一个用来描述资源的结构,只有通过这个结构中的指针才能最终找到资源数据,资源,资源,所有目录结构数据和所有资源数据都集中放在一个资源数据块中
35、。从PE文件头中IMAGE_OPTIONAL_HEADERS32结构的数据目录字段可以获取资源数据块的位置和大小与资源对应的项目是其中第3个IMAGE_DATA_DIRECTORY结构,从这个结构的VirtualAddress字段可以获取资源块地址的RVA值,资源,资源在PE文件中的组织方式类似资源管理器的树状逻辑结构:无论是根目录,还是第二层或第三层中的每个目录都是由一个IMAGE_RESOURCE_DIRECTORY结构和紧随其后的数个IMAGE_RESOURCE_DIRECTORY_ENTRY结构组成,这两种结构一起组成了一个目录块资源的基础是“资源目录”(IMAGE_RESOURCE_
36、DIRECTORY);它包含好几个“资源目录项”(IMAGE_RESOURCE_DIRECTORY_ENTRY),其中的每一项反过来又可能指向一个“资源目录”按照这种方式就可以得到一个以“资源目录项”为树叶的“资源目录”树,而它们的树叶指向实际的资源数据,PE病毒,PE含义PE病毒演示PE文件结构PE病毒实例介绍基于PE病毒的正向应用,PE病毒实例介绍,在PE文件中插入一个新节(病毒体)需要完成如下几件事情:1.构造描述该新节的节表2.将新节表追加到原PE文件节表最末尾3.构造该新节(病毒体本身)4.将该新节添加到原PE文件的最后(定位到文件末尾,直接写入)5.修改PE文件头中的相应信息Num
37、berOfSection的值增1将PE文件头中的AddressOfEntrypoint改为新添节节表中所记录的节的起始地址RVA将PE文件头中所记录的文件内存大小SizeOfImage的值改为原值加上新添节的VirtualSize按照内存粒度对其之后的值病毒体执行完返回原PE入口执行1.更改程序入口点之前先使用变量保存原入口点2.病毒程序最后将保存的该原入口点加上重定位基址后的数值压入堆栈3.使用ret指令返回/或使用JMP指令跳回,代码重定位,代码重定位是把可执行代码从内存的一个地方移动到另一个地方去,保证该部分代码还能正常执行的一种技术其中最主要的问题是操作数地址的变化问题。如果程序中有一
38、个全局变量Var,那么该变量实际在内存中的地址需要进行重定位代码演示Relocal的查看Relocal.exe的加载地址修改及查看,重定位方法,对变量Var进行重定位核心代码实现如下:call relocaterelocate: pop ebxsub ebx,offset relocatemov eax,ebx+offset Varcall语句执行之后,堆栈顶端为程序在当前环境下加载执行时标号relocate的现有地址 pop语句执行之后,ebx寄存器中存放标号relocate的现有地址Offset relocate取得作为操作数的全局标号relocate的地址 Sub语句执行之后,ebx为r
39、eloate标号在两种状态下的相对位移量mov语句执行之后,eax中存放着重定位后的变量Var的值,即在当前加载状态下内存中的有效地址代码演示DoRelocal的查看DoRelocal.exe的加载地址修改及查看,PE病毒,PE含义PE病毒演示PE文件结构PE病毒实例介绍基于PE病毒的正向应用,PE补丁技术,静态补丁替换PE文件部分修改PE文件代码存放空间PE最后一节PE新增节PE文件空闲空间对齐所补的0PE间隙节与节之间的间隙流程转向重定位技术DLL动态加载技术动态补丁进程间的通信,课后阅读,参见积分表验收时间5.24,5.25,5.26,上午下午晚上5.29(第14周)课后提交并确认最终版
40、考核方式选择表,本章小结,文件型病毒及原理宏病毒及相关技术PE病毒及相关技术,内存映像文件与PE内存映像,PE文件在静态打开时(如,使用winhex打开notepad.exe)会被映射为内存映像文件指将硬盘上的文件不做修改的装载到内存因为硬盘上文件实际存储时是按照簇号存放,并不连续,如果直接访问会影响速度,因此先映射到连续的内存空间,内存映像文件与PE内存映像,PE内存映像是指将PE文件按照一定的规则装入内存,装入后的文件头不会改变,但节的内容会按照内存对齐单位进行对齐通常执行该文件时,产生PE内存映像,相对虚拟地址RVA,它是一个“相对”地址,即,偏移量相对于PE文件装入地址的偏移量尽管PE
41、文件有一个首选的装入地址,但并非一定会装入指定的位置,在这种情况下需要根据实际的装入位置重新定位,这就需要各部分相对于基地址的偏移量若知道某数据的RVA,那么程序载入点的起始地址加上RVA就可以得到该结构的实际虚拟内存地址实际虚拟地址(VA)= 基地址(ImageBase)+ 相对虚拟地址(RVA),基地址ImageBase,当PE文件通过Windows加载器被装入内存后,内存中的版本被称作印象(Image)或模块(Module)这个初始内存地址就称为基地址(ImageBase)。基地址的值是由PE文件本身设定的,内存中的虚拟地址VA,当文件装入内存时,各数据在内存中的位置称为VA,文件中的地
42、址,也叫文件偏移地址(File Offset)或物理地址(RAW Offset)指当PE文件存贮在磁盘上时,某个数据的位置相对于文件开始的偏移量文件偏移地址从PE文件的第一个字节开始计数,起始值为0,不同的地址,PE文件结构中涉及到多种地址,这些地址对定位要查找的数据在PE文件中的具体位置具有重要意义起关键作用的地址主要有四种,分别是:文件中的地址基地址内存中的虚拟地址相对虚拟地址,构造描述该新节的节表,8字节的name1:随便填写节的实际大小VirtualSize:病毒体长度,可通过标号计算内存中节的RVA,VirtualAddress:整个文件在内存中的大小按内存粒度对齐之后的数值(可选头
43、中的sizeofimage成员信息)文件中节对齐后的大小SizeofRawData:节的实际大小按照文件粒度对齐之后的大小文件中节对齐后的偏移PointerToRawData:整个文件的大小按文件粒度对齐之后的数值;但是整个文件按文件对齐粒度对齐后的大小并没有信息记录,所以利用记录在当前文件节表中的最后一节的节偏移信息加上该最后一节按文件对齐的大小,就是新添节的在文件中的节偏移节的属性:可读可写可执行,0E0000020H,将新节表插入到原PE文件中,1.确定当前文件中现有的文件头和节之间是否还有足够的空隙写下一个40字节的新节表,如果空间足够,那么执行22.确定当前文件中最后一个节表结束的位
44、置PE文件头起始的位置+PE文件头大小+所有节表大小之和3.用2计算的结果作为新节表写入文件的偏移量信息,代码重定位,代码重定位是把可执行代码从内存的一个地方移动到另一个地方去,保证该部分代码还能正常执行的一种技术其中最主要的问题是操作数地址的变化问题。如果程序中有一个全局变量Var,那么该变量实际在内存中的地址需要进行重定位,重定位方法,对变量Var进行重定位核心代码实现如下:call relocate .relocate: pop ebp .lea eax,ebp+(offset Var-offset relocate). 这条语句执行之后,堆栈顶端为relocate在内存中的真正地址 这
45、条语句执行之后,ebp寄存器中存放relocate标号在内存中的真实地址 这条语句执行之后,eax中存放着Var在内存中的真实地址如果病毒程序中有一个变量Var,那么该变量实际在内存中的地址应该是ebp+(offset Var-offset relocate),即参考量relocate在内存中的地址+其它变量与参考量之间的距离=其它变量在内存中的真正地址等价于(ebp-offset relocate)+offset Var的形式,Dll动态加载技术,核心是对被调用函数的地址的获取,该被调用函数位于动态链接库中动态加载技术可以让程序设计者在程序空间中构造类似导入表的调用引入函数机制Dll的调用分
46、为两种方式静态调用动态调用,静态调用,原理:由编译系统对要调用的函数的符号进行描述并写入PE文件WIONDOWS系统负责对要加载的PE导入表中描述的DLL符号进行加载,对调用函数地址进行修正等方法:include相应的.lib和.inc文件,在程序中直接调用即可,动态调用,由编程者通过API函数加载和卸载DLL达到调用DLL函数的目的相关函数主要有:LoadlibraryGetprocaddressfreelibrary,动态加载技术编程,步骤1,获取kernel32.dll的基地址步骤2,获取GetProcAddress函数的地址步骤3,在代码中使用获取的函数地址编程,IMAGE_DOS_HEADER结构,PE文件到内存的映射,在执行一个PE文件时,Windows并不在一开始就将整个文件读入内存仅仅建立好虚拟地址和PE文件之间的映射关系,只有真正执行到某个内存页中的指令或者访问某一页中的数据时,这个页面才会被从磁盘提交到物理内存,PE文件到内存的映射,装载可执行文件的时候,有些数据在装入前会被预先处理(例如需要重定位的代码),而装入之后,数据之间的相对位置也可能发生改变,一个节的偏移和大小在装入内存前后可能是完全不同的,PE文件到内存的映射,PE文件到内存的映射,原因对齐属性不同某些数据的处理不同,如未初始化的数据节文件没空间但内存留空间重定位信息节内存没空间但文件占空间,