• 标 题:Billy Belceb 病毒编写教程for Win32 ----PE文件头
  • 作 者:onlyu
  • 时 间:2004-05-28,12:32
  • 链 接:http://bbs.pediy.com

【PE文件头】
 ~~~~~~~~~~
    这是这篇文件的最重要的一章。仔细读!

%介绍%
~~~~~~
    对PE头的结构很清晰在写我们的Windows病毒很重要。下面我将给出我认为重要的东西,但是并不是关于PE文件的所有的信息,想要知道更多的东西,看看我在上面关于PE文件推荐的资料,在"有用的东西..."这一章。
 _______________________________
|                               |<-----OFFSET=00000000h
|          DOS stub             |
|_______________________________|
|                               |<-----OFFSET=[DOS Stub+3Ch]
|          PE stuff             |
|_______________________________|

    让我们对这两大部分进行深入的分析,让我们看看Micheal J. O'Leary的示意图:

 __________________________________
|                                  |<----Base of Image Header
|    DOS compatible EXE header     |--|
|__________________________________|  |
|                                  |  |
|             Unused               |  |
|__________________________________|  |
|                                  |  |
|         OEM identifier           |  |
|__________________________________|  |
|                                  |  |
|            OEM info              |  |-->Uninteresting(DOS Compatibility)
|__________________________________|  |
|                                  |  |
|        Offset to PE Header       |----->Very interesting
|__________________________________|  |
|                                  |  |
| DOS Stub program and reloc table |  |
|__________________________________|  |
|                                  |  |
|              Unused              |__|
|__________________________________|
|                                  |
|   PE header(IMAGE_FILE_HEADER)   |--|
|__________________________________|  |
|                                  |  |
| PE header(IMAGE_OPTIONAL_HEADER) |  |
|__________________________________|  |-->Very very interesting :)
|                                  |  |
|          Section Table           |  |
|__________________________________|  |
|                                  |  |
|            Sections              |__|
|__________________________________|

    现在你已经对PE文件头已经有了一个大体的了解,确实很新奇(但也很复杂),我们的新目标。Ok,ok,你对那些东西有了一个"大体"的了解,但是,你仍然需要知道PE文件头中IMAGE_FILE_HEADER本身的内部结构。勒紧你的裤腰带!

IMAGE_FILE_HEADER
^^^^^^^^^^^^^^^^^
 ________________________________
|            "PE\0\0"            |<----+00000000h
|________________________________|       Size:1 DWORD
|            Machine             |<----+00000004h
|________________________________|       Size:1 WORD
|       Number Of Section        |<----+00000006h
|________________________________|       Size:1 WORD
|        Time Date Stamp         |<----+00000008h
|________________________________|       Size:1 DWORD
|    pointer To Symbol Table     |<----+0000000Ch
|________________________________|       Size:1 DWORD
|       Number Of Symbols        |<----+00000010h
|________________________________|       Size:1 DWORD
|    Size Of Optional Header     |<----+000000014h
|________________________________|       Size:1 WORD
|        Characteristics         |<----+000000016h
|________________________________|       Size:1 WORD
                                  Total Size:18h BYTES
    我将继续对IMAGE_FILE_HEADER的各个域给出简要的描述。

    PE\0\0:

    它是每个PE文件都有的标志,只要在编写你的感染程序的时候检查它是否存在。如果它在那儿,它就不是一个PE文件,ok?

    Machine:

    因为我们所使用的计算机的理想可以是一个非PC兼容的(NT对这些东西有一个开放等级,你知道的),又因为PE文件是普遍的,在这个域中是这个应用程序所编写的代码的机器类型,可以为下面的值:

 IMAGE_FILE_MACHINE_I386    equ  14Ch    ; Intel 386.
 IMAGE_FILE_MACHINE_R3000   equ  162h    ; MIPS little-endian,160h big-endian
 IMAGE_FILE_MACHINE_R4000   equ  166h    ; MIPS little-endian
 IMAGE_FILE_MACHINE_R10000  equ  168h    ; MIPS little-endian
 IMAGE_FILE_MACHINE_ALPHA   equ  184h    ; Alpha_AXP
 IMAGE_FILE_MACHINE_POWERPC equ  1F0h    ; IBM PowerPC Little-Endian

    Number Of Sections:

    我们的感染程序的非常重要的域,它告诉我们这个文件的节(section)的个数。

    Time Date Stamp:

    保存了从1969.10.31 4:00到文件连结时所过的秒数。

    Pointer To Symbol Table:

    没意思,因为它仅仅被OBJ文件使用。

    Number Of Symbols:

    没意思,因为它仅仅被OBJ文件使用。

    Size Of Optional header:

    保存了IMAGE_OPTIONAL_HEADER域的字节数(看下面IMAGE_OPTIONAL_HEADER的描述)。

    Characteristics:

    这些标志给了我们关于这个文件的更多信息,对于我们所有人都没意思。

IMAGE_OPTIONAL_HEADER
^^^^^^^^^^^^^^^^^^^^^
 ________________________________
|             Magic              |<----+00000018h
|________________________________|        Size:1 WORD
|      Major Linker Version      |<----+0000001Ah
|________________________________|        Size:1 BYTE
|      Minor Linker Version      |<----+0000001Bh
|________________________________|        Size:1 BYTE
|          Size Of Code          |<----+0000001Ch
|________________________________|        Size:1 DWORD
|    Size Of Initialized Data    |<----+00000020h
|________________________________|        Size:1 DWORD
|   Size of UnInitialized Data   |<----+00000024h
|________________________________|        Size:1 DWORD
|     Address Of Entry Point     |<----+00000028h
|________________________________|        Size:1 DWORD
|         Base Of Code           |<----+0000002Ch
|________________________________|        Size:1 DWORD
|         Base Of Data           |<----+00000030h
|________________________________|        Size:1 DWORD
|          Image Base            |<----+00000034h
|________________________________|        Size:1 DWORD
|      Section ALignment         |<----+00000038h
|________________________________|        Size:1 DWORD
|        File Alignment          |<----+0000003Ch
|________________________________|        Size:1 DWORD
| Major Operating System Version |<----+00000040h
|________________________________|        Size:1 WORD
| Minor Operating System Version |<----+00000042h
|________________________________|        Size:1 WORD
|      Major Image Version       |<----+00000044h
|________________________________|        Size:1 WORD
|      Minor Image Version       |<----+00000046h
|________________________________|        Size:1 WORD
|    Major Subsystem Version     |<----+00000048h
|________________________________|        Size:1 WORD
|    Minor Subsystem Version     |<----+0000004Ah
|________________________________|        Size:1 WORD
|           Reserved1            |<----+0000004Ch
|________________________________|        Size:1 DWORD
|        Size Of Headers         |<----+00000050h
|________________________________|        Size:1 DWORD
|            CheckSum            |<----+00000054h
|________________________________|        Size:1 DWORD
|            SubSystem           |<----+00000058h
|________________________________|        Size:1 DWORD
|       Dll Characteristics      |<----+0000005Eh
|________________________________|        Size:1 WORD
|      Size Of Stack Reserve     |<----+00000060h
|________________________________|        Size:1 DWORD
|      Size Of Stack Commit      |<----+00000064h
|________________________________|        Size:1 DWORD
|      Size OF Heap Reserve      |<----+00000068h
|________________________________|        Size:1 DWORD
|      Size Of Heap Commit       |<----+0000006Ch
|________________________________|        Size:1 DWORD
|          Loader Flags          |<----+00000070h
|________________________________|        Size:1 DWORD
|    Number Of Rva And Sizes     |<----+00000074h
|________________________________|        Size:1 DWORD
                                  Total Size:78h BYTES
                      (加上IMAGE_FILE_HEADER ^^^^^^^^^)

   Magic:

   看起来总为010Bh,实际上会使我们认为它是一种签名,没有意思。

   Major Linker Version and Minor Linker Version:

   产生这个文件的连结器的版本,没有意思。

   Size of Code:

   它是所有包含可执行代码的段的总字节数。

   Size of Initialized Data:

   它是所有包含初始数据的段的总大小。

   Size of Uninitialized data

   未初始数据不占磁盘空间,但是当系统装载这个文件的时候,它会分配一些内存(实际上是虚拟内存)。

   Address of EntryPoint:

   是装载器开始执行代码的地方。它是一个RVA,当系统装载这个文件的时候和image base相关。非常有意思。

   Base Of Code:

   是文件的code段开始的RVA。code段在内存中通常在data段之前,在PE文件头之后。这个RVA在用Microsoft连结器产生的EXE文件中通常为0x1000。Borland的TLINK32看起来把image base加到了第一个code段的RVA处,并把结果存储在这个域中。

   Base Of Data:

   是文件的data段开始的RVA,data段通常在内存中处于最后,在PE文件头和code段之后。

   Image Base(基址):

   当连结器创造一个可执行文件的时候,它会假定将会内存映射到内存的某个地址当中。这个地址被保存在这个域中,假定的一个装载地址来允许连结器进行优化。如果这个文件确实被装载器内存映射到那个地址,在它可以运行之前代码就不需要任何补丁了。在为Windows NT产生的可执行文件中,缺省的Image Base为0x10000。对DLL来说,缺省的为0x400000。在Win9X中,地址0x10000不能被用来装载EXE文件因为它在被所有进程的共享地址中。因为这个,Microsoft就把Win32的缺省Image Base改为0x400000。老的以基址0x10000进行连结而成的可执行文件在Win9x下装载将会花费更长的时间,因为装载器需要进行基址重定位。

   Section Alignment:

   当映射到内存中的时候,每一节要保证是这个值的一个倍数的虚拟地址作为开始地址。对于按页的时候,缺省的节对齐方式是0x1000。

   File Alingnment:

   在PE文件中,构成每一节的原始数据要保证从这个值的倍数开始。缺省的值为0x200字节,可能是为了保证各节总是以磁盘节(disk sector,它的长度也为0x200)的开始作为开始。这个域在NE文件中等价于segment/resource alignment。和NE文件不同的是,PE文件通常不会有成百个节,所以由于对齐文件的节而浪费的空间几乎很少。

   Major Operating System Version and Minor Operating System Version:

   使用这种类型的可执行文件的操作系统的最低版本号。既然subsystem fields目的看起来和它相类似,这个域有点摸棱两可。这个域在所有的Win32 EXE文件中缺省为1.0。

   Major Image Version and Minor Image Version:
 
   是一个用户可定义的域,它允许你可以有不同版本的EXE或DLL。你可以通过连结器的/VERSION开关来设置这个域。如:"LINK /VERSION:2.0 muobj.obj"。

   Major Subsystem Version and Minor Subsystem Version:

   包含了运行这个可执行文件所需要的最小子系统版本。这个域的一个经典值为3.10(意思为Windows NT 3.1)。

   Reserved1:

   看起来总为0(最为感染标志太完美了)。

   Size Of Headers:

   PE文件头的大小和节(对象)表。这些节的原始数据就从这些所有文件头组件之后开始。

   Checksum:

   为这个文件的CRC校验值。正如在其它的Microsoft可执行文件格式中,这个域是忽略的并总设为0,这个规则的例外是这些EXE文件必须有合法的校验值。

   SubSystem:

   这些可执行文件的子系统的类型被它用来用户界面。WINNT.h定义了下面的值:

 NATIVE         1       Doesn't require a subsystem (such as a device driver)
 WINDOWS_GUI    2       Runs in the Windows GUI subsystem
 WINDOWS_CUI    3       Runs in the Windows character subsystem (console app)
 OS2_CUI        5       Runs in the OS/2 character subsystem (OS/2 1.x  only)
 POSIX_CUI      7       Runs in the Posix character subsystem

     一个标志集表明了在什么环境下一个DLL的初始函数(如DLLMain)将会调用。这个值看起来总是设置为0,然而操作系统仍然对所有四个事件调用DLL初始函数。下面是定义的值:

1     当DLL第一次装载到一个进程的地址空间中时调用
2     当一个线程终止时调用
3     当一个线程开始时调用
4     当DLL已经存在时调用

   Size Of Stack Reserve: 

   为初始线程的堆栈而保留的虚拟内存数量,然而并不是所有的内存都可以做(看下一个域)。这个域的缺省值为0x100000(1MB)。如果你用CreateThread把0作为堆栈的大小,那么创建出来的堆栈就会有相同的大小。

   Size Of Stack Commit:

   保证初始线程的堆栈时的内存数量。对于Microsoft的连结器这个域的初始值为0x1000字节(1页)而TLINK32为2页。

   Size Of Heap Reserve:

   用来保留给初始进程堆时的虚拟内存,这个堆的句柄可以通过调用GetProcessHeap函数来获得。并不能保证所有内存(看下一个域)。

   Size Of Heap Commit:

   在进程堆中初始时的内存数量。缺省值为1页。
 
   Loader Flags:

   从WINNT.h来看,这个域和调试支持相关。我还没有看到任何一个这些位都有效的可执行文件,也没有看到这些位都清空的。怎么用连结器设置它们呢,下面是定义的值:
1   在开始进程前唤醒一个断点指令
2  当进程已经载入后唤醒一个调试器

   Number Of Rva and Sizes:

   DataDirectory 数组(下面)的入口个数,这个值用当前的工具总是设置为16。

IMAGE_SECTION_HEADER
^^^^^^^^^^^^^^^^^^^^
 _____________________________
|       Section Name          |<-----Begin of section header
|_____________________________|        Size:8 BYTES
|       Virtual Size          |<-----+00000008h
|_____________________________|        Size:1 DWORD
|      Virtual Address        |<-----+0000000Ch
|_____________________________|        Size:1 DWORD
|      Size Of Raw Data       |<-----+00000010h
|_____________________________|        Size:1 DWORD
|    Pointer To Raw Data      |<-----+00000014h
|_____________________________|        Size:1 DWORD
|   Pointer To Relocations    |<-----+00000018h
|_____________________________|        Size:1 DWORD
|   Pointer To Line Numbers   |<-----+0000001Ch
|_____________________________|        Size:1 DWORD
|    Number Of Relocations    |<-----+00000020h
|_____________________________|        Size:1 WORD
|   Number Of Line Numbers    |<-----+00000022h
|_____________________________|        Size:1 WORD
|      Characteristics        |<-----+00000024h
|_____________________________|        Size:1 DWORD
                                Total Size: 28h BYTES

Section Name:

    命名节用的是一个8-byte的ANSI名字(非UNICODE),大多数的节的名字以一个.(如".text")作为开始,但是这不是必须的,你可以在一些关于PE的文章里验证这一点。你可以直接用汇编语言来命名你的节,或者在Microsoft C/C++编译器下用"#pragma data_seg"和"pragma code_seg"。注意节名是否占了满满8个字节很重要,没有NULL终止符。如果你是一个printf的热爱者,你可以使用%.8s来避免把名字字符串拷贝到另外一个你可以用NULL来终止的缓冲区里面。

Virtual Size:

    这个域在EXE或者OBJ中有不同的意思。在一个EXE中,它存储代码或者数据的实际大小。这个大小是在把文件凑整到文件对齐大小的倍数之前的大小。后面的SizeOfRawData域(看起来有点用词不当)存储的是凑整之后的值。Borland的连接器把这两个域的意思颠倒过来了,看起来是正确的。对于OBJ文件,这个域表示节的物理地址。第一个节是从地址0开始的。为了寻找在一个OBJ文件中的下一个节的物理地址,把当前节的物理地址加上SizeOfRawData值就可以了。

Virtual Address:
 
   在EXE中,这个域指装载器应该对节进行映射的RVA。为了计算一个给定的节在内存中的真正起始地址,把映象的基址加上存储在这个域中的VirtualAddress就可以了。利用Microsoft的工具,第一个节的缺省的RVA为0x1000。在OBJ文件中,这个域是没有意义的并设置成0。

Size Of Raw Data:

     在EXE中,这个域包含了节在按文件对齐大小凑整之后的大小。例如,假设一个文件的对齐大小为0x200,如果上述的VirtualSize域的节的长度为0x35A,这个域就会以0x400作为节长。在OBJ文件中,这个域包含了由编译器或汇编程序所设置的精确大小。也就是说,对于OBJ文件来说,它等于EXE中的VirtualSize域的值。

Pointer To Raw Data:

    这是节基于文件的偏移量,原始数据是由编译器或汇编器设置的。如果你的程序内存映射了一个PE文件或者COFF文件本身(而不是由操作系统来装载它),这个域比VirtualAddress域重要。在这种情况下,你将会拥有完全的线形文件映射,所以你将会发现在这个偏移地址出的节的数据,而不是在VirtualAddress处的特定RVA。

Pointer To Relocations

    在OBJ文件中这个是节基于文件的偏移量的重定位信息,对于每一个节的重定位信息直接跟在那个节的原始数据后面。在EXE文件中这个域(和子域)是没有意义的并设置成0。当连接器产生EXE文件的时候,它解决了大多数的修正问题,只剩基址重定位和输入函数。关于基址重定位和输入函数的信息是保存在它们自己的节中,所以没有必要使一个EXE文件的每一个节的重定位数据在原始节数据后面。

Pointer To Line Numbers:

      这是基于文件的行号表的偏移量,一个行号表使源文件的行号和一个给定的行所产生的代码地址相关联。在现代的调试格式如CodeView格式中,行号信息是作为调试信息的一部分存储的。在COFF调试格式中,然而,行号信息是和符号名/符号类型分开存储的。通常,只有code节(如.text)有行号。在EXE文件中,行号是在节的raw data(原始数据)之后向文件尾累加的。在OBJ文件中,一个节的行号表是在原始节数据和这个节的重定位表之后开始的。

Number Of Relocations:

    在节的行号表中的行号的数值(上面的PointerToLinenumbers域)。

Characteristics:

    大多数程序员叫做标志(flag),在COFF/PE格式中叫做特征(characterstic)。这个域是一些表面节属性(如代码/数据,可读,或可写)的标志。要看所有可能的节属性的列表,看看定义在WINNT.H中的IMAGE_SCN_XXX_XXX。下面给出一些比较重要的标志:

0x00000020 这个节包含代码。通常和可执行标志(0x80000000)联合设置。

0x00000040 这个节包含了初始化了的数据(initialized data)。除了可执行和.bss节之外几乎所有的节都有这个标志。

0x00000080 这个节包含了未初始化的数据(uninitialized data),如.bss节。

0x00000200 这个节包含了一些注释或者一些其它类型的信息。这个节的一个典型利用是由编译器所设置的.drectve节,这个节包含了连接器的命令。

0x00000800 这个节的内容是不应该放在最终的EXE文件中的。这些节被编译器/汇编器用来传递信息给连接器。

0x02000000 在它被装载之后,进程就不再需要它了,这个节就可以被丢弃。最普通的可丢弃的节是基址重定位节(.reloc)。

0x10000000 这个节是可共享的。当使用一个DLL时,这个节中的数据将会通过DLL来给所有的进程共享。数据节的默认是不共享的。用更专业的术语,一个共享节告诉内存管理器设置这个节的页映射使得所有使用这个DLL的进程指向内存中的同一个物理页。要使一个节可共享的,在连接的时候使用共享(SHARED)属性。如:

LINK /SECTION:MYDATA,RWS...

就告诉了连接器一个叫做MYDATA的节是可读的,可写的,而且是共享的。

0x20000000 这个节是可执行的。这个标志通常在"包含代码"的标志(0x00000020)被设置后设置。

0x40000000 这个节是可读的。这个标志几乎在EXE文件的所有节中都被设置。

0x80000000 这个节是可写的。如果这个标志在一个EXE文件的节中没有被设置,装载器就会标志内存映射页为只读的或只能执行的。有这个属性的典型的节是.data和.bss。有趣的是,.idata节也设置了这个属性。

%要改变的东西%
~~~~~~~~~~~~~~
    下面,我将介绍在编写一个普通的PE病毒时的一些改变。假设你要编写一个会增加PE文件的最后一个节内容的病毒,这个在我们看来更容易成功的技术,然而添加一个节更容易。让我们看看一个病毒是怎么来改变一个可执行文件的头。我使用了Lord Julus[SLAM]的INFO-PE程序。

 -------- DOS INFORMATION ---------------------------------------------------

 Analyzed File: GOAT002.EXE

 DOS Reports: 
              ?File Size  - 2000H      (08192d)
              ?File Time  - 17:19:46   (hh:mm:ss)
              ?File Date  - 11/06/1999 (dd/mm/yy)
              ?Attributes : Archive 

 [...]

 -------- PE Header ----------------------------------------------------------
 
  ---------------
 ‖O_DOS |O_PE  ‖(Offset from Dos Header / PE Header
 ‖------|------‖
 |0100H  |0000H | PE Header Signature - PE/0/0
 |0104H  |0004H | The machine for this EXE is Intel 386 (value = 014CH)
 |0106H  |0006H | Number of sections in the file - 0004H
 |0108H  |0008H | File was linked at : 23/03/2049
 |010CH  |000CH | Pointer to Symbol Table : 00000000H
 |0110H  |0010H | Number of Symbols : 00000000H
 |0114H  |0014H | Size of the Optional Header : 00E0H
 |       |      |
 |0116H  |0016H | File Characteristics - 818EH : 
 |       |      | ?File is executable
 |       |      | ?Line numbers stripped from file
 |       |      | ?Local symbols stripped from file
 |       |      | ?Bytes of machine word are reversed
 |       |      | ?32 bit word machine
 |       |      | ?Bytes of machine word are reversed
 ‖_______|_____‖
 
 
-------- PE Optional Header -----------------------------------
 
  ---------------
 ‖O_DOS |O_PE  ‖(Offset from Dos Header / PE Header
 ‖------|------‖
 |0118H  |0018H | Magic Value                : 010BH (`Θ`)
 |011AH  |001AH | Major Linker Version       : 2
 |011BH  |001BH | Minor Linker Version       : 25
 |       |      | Linker Version             : 2.25
 |011CH  |001CH | Size of Code               : 00001200H
 |0120H  |0020H | Size of Initialized Data   : 00000600H
 |0124H  |0024H | Size of Uninitialized Data : 00000000H
 |0128H  |0028H | Address of Entry Point     : 00001000H
 |012CH  |002CH | Base of Code (.text ofs.)  : 00001000H
 |0130H  |0030H | Base of Data (.bss ofs.)   : 00003000H
 |0134H  |0034H | Image Base                 : 00400000H
 |0138H  |0038H | Section Alignment          : 00001000H
 |013CH  |003CH | File Alignment             : 00000200H
 |0140H  |0040H | Major Operating System Version : 1
 |0142H  |0042H | Minor Operating System Version : 0
 |0144H  |0044H | Major Image Version        : 0
 |0146H  |0046H | Minor Image Version        : 0
 |0148H  |0048H | Major SubSystem Version    : 3
 |014AH  |004AH | Minor SubSystem Version    : 10
 |014CH  |004CH | Reserved Long              : 00000000H
 |0150H  |0050H | Size of Image              : 00006000H
 |0154H  |0054H | Size of Headers            : 00000400H
 |0158H  |0058H | File Checksum              : 00000000H
 |015CH  |005CH | SubSystem                  : 2
 |       |      |  Image runs in the Windows GUI subsystem
 |015EH  |005EH | DLL Characteristics        : 0000H
 |0160H  |0060H | Size of Stack Reserve      : 00100000H
 |0164H  |0064H | Size of Stack Commit       : 00002000H
 |0168H  |0068H | Size of Heap Reserve       : 00100000H
 |016CH  |006CH | Size of Heap Commit        : 00001000H
 |0170H  |0070H | Loader Flags               : 00000000H
 |0174H  |0074H | Number Directories         : 00000010H
 
 [...]
 
------- PE Section Headers ---------------------------------

  ---------------------------
 ‖O_DOS |O_PE  ‖(Offset from Dos Header / PE Header
 ‖------|------‖[...]
 |0270H  |0170H | Section name            : .reloc
 |0278H  |0178H | Physical Address        : 00001000H
 |027CH  |017CH | Virtual Address         : 00005000H
 |0280H  |0180H | Size of RAW data        : 00000200H
 |0284H  |0184H | Pointer to RAW data     : 00001C00H
 |0288H  |0188H | Pointer to relocations  : 00000000H
 |028CH  |018CH | Pointer to line numbers : 00000000H
 |0290H  |0190H | Number of Relocations   : 0000H
 |0292H  |0192H | Number of line numbers  : 0000H
 |0294H  |0194H | Characteristics         : 50000040H
 |       |      | ?Section contains initialized data.
 |       |      | ?Section is shareable.
 |       |      | ?Section is readable.
 |       |      |
 ‖______|______‖
 
    这是一个正常文件,没有被感染。下面是同一个文件,但是被我的Aztec病毒(一个Ring-3病毒例子,看下面的)感染了。

------------ DOS INFORMATION ----------------------------------------------------------------- 

 Analyzed File: GOAT002.EXE

 DOS Reports: 
             ?File Size  - 2600H      (09728d)
             ?File Time  - 23:20:58   (hh:mm:ss)
             ?File Date  - 22/06/1999 (dd/mm/yy)
             ?Attributes : Archive 

 [...]

 -------------- PE Header -----------------------------------------------------------------

 --------------- 
‖O_DOS |O_PE  ‖(Offset from Dos Header / PE Header
‖------|------‖[...]
 |0100H |0000H  | PE Header Signature - PE/0/0
 |0104H |0004H  | The machine for this EXE is Intel 386 (value = 014CH)
 |0106H |0006H  | Number of sections in the file - 0004H
 |0108H |0008H  | File was linked at : 23/03/2049
 |010CH |000CH  | Pointer to Symbol Table : 00000000H
 |0110H |0010H  | Number of Symbols : 00000000H
 |0114H |0014H  | Size of the Optional Header : 00E0H
 |      |       |
 |0116H |0016H  | File Characteristics - 818EH : 
 |      |       | ?File is executable
 |      |       | ?Line numbers stripped from file
 |      |       | ?Local symbols stripped from file
 |      |       | ?Bytes of machine word are reversed
 |      |       | ?32 bit word machine
 |      |       | ?Bytes of machine word are reversed
 ‖_____|_______‖


 --------- PE Optional Header ------------------------------------------------------

 ---------------
‖O_DOS |O_PE  ‖(Offset from Dos Header / PE Header
‖------|------‖
 |0118H |0018H | Magic Value                : 010BH
 |      |      |
 |011AH |001AH | Major Linker Version       : 2
 |011BH |001BH | Minor Linker Version       : 25
 |      |      | Linker Version             : 2.25
 |011CH |001CH | Size of Code               : 00001200H
 |0120H |0020H | Size of Initialized Data   : 00000600H
 |0124H |0024H | Size of Uninitialized Data : 00000000H
 |0128H |0028H | Address of Entry Point     : 00005200H
 |012CH |002CH | Base of Code (.text ofs.)  : 00001000H
 |0130H |0030H | Base of Data (.bss ofs.)   : 00003000H
 |0134H |0034H | Image Base                 : 00400000H
 |0138H |0038H | Section Alignment          : 00001000H
 |013CH |003CH | File Alignment             : 00000200H
 |0140H |0040H | Major Operating System Version : 1
 |0142H |0042H | Minor Operating System Version : 0
 |0144H |0044H | Major Image Version        : 0
 |0146H |0046H | Minor Image Version        : 0
 |0148H |0048H | Major SubSystem Version    : 3
 |014AH |004AH | Minor SubSystem Version    : 10
 |014CH |004CH | Reserved Long              : 43545A41H
 |0150H |0050H | Size of Image              : 00006600H
 |0154H |0054H | Size of Headers            : 00000400H
 |0158H |0058H | File Checksum              : 00000000H
 |015CH |005CH | SubSystem                  : 2
 |      |      |     -Image runs in the Windows GUI subsystem
 |15EH  |005E  | DLL Characteristics        : 0000H
 |160H  |0060H | Size of Stack Reserve      : 00100000H
 |0164H |0064H | Size of Stack Commit       : 00002000H
 |0168H |0068H | Size of Heap Reserve       : 00100000H
 |016CH |006CH | Size of Heap Commit        : 00001000H
 |0170H |0070H | Loader Flags               : 00000000H
 |0174H |0074H | Number Directories         : 00000010H
 ‖___________‖
 
 [...]

 ---------PE Section Headers------------------------------------------

 ----------------
 ‖O_DOS |O_PE  ‖(Offset from Dos Header / PE Header
 ‖------|------‖[...] 
 |0270H  |0170H | Section name            : .reloc
 |0278H  |0178H | Physical Address        : 00001600H
 |027CH  |017CH | Virtual Address         : 00005000H
 |0280H  |0180H | Size of RAW data        : 00001600H
 |0284H  |0184H | Pointer to RAW data     : 00001C00H
 |0288H  |0188H | Pointer to relocations  : 00000000H
 |028CH  |018CH | Pointer to line numbers : 00000000H
 |0290H  |0190H | Number of Relocations   : 0000H
 |0292H  |0192H | Number of line numbers  : 0000H
 |0294H  |0194H | Characteristics         : F0000060H
 |       |      |  -Section contains code.
 |       |      | -Section contains initialized data.
 |       |      | -Section is shareable.
 |       |      | -Section is executable.
 |       |      | -Section is readable.
 |       |      | -Section is writeable.
 |       |      |
 |_______|______|

    那一个正常的文件,没有被感染。下面给出的是同一个文件,但是被我的Aztec(Ring-3例子病毒,看下文)感染了。


 ---------------------------------------------------------------------------------------------------

-------DOS INFORMATION ------------------------------------------------- 

 Analyzed File: GOAT002.EXE

 DOS Reports: 
             ?File Size  - 2600H      (09728d)
             ?File Time  - 23:20:58   (hh:mm:ss)
             ?File Date  - 22/06/1999 (dd/mm/yy)
             ?Attributes : Archive 

 [...]

 -------PE Header-------------------------------------------------------

 ----------------
‖O_DOS |O_PE   ‖(Offset from Dos Header / PE Header
‖------|-------‖
 |0100H |0000H  | PE Header Signature - PE/0/0
 |0104H |0004H  | The machine for this EXE is Intel 386 (value = 014CH)
 |0106H |0006H  | Number of sections in the file - 0004H
 |0108H |0008H  | File was linked at : 23/03/2049
 |010CH |000CH  | Pointer to Symbol Table : 00000000H
 |0110H |0010H  | Number of Symbols : 00000000H
 |0114H |0014H  | Size of the Optional Header : 00E0H
 |      |       | 
 |0116H |0016H  | File Characteristics - 818EH : 
 |      |       | -File is executable
 |      |       | -Line numbers stripped from file
 |      |       | -Local symbols stripped from file
 |      |       | -Bytes of machine word are reversed
 |      |       | -32 bit word machine
 |      |       | -Bytes of machine word are reversed
 |______|_______|


 ---------PE Optional Header---------------------------------------

 -----------------
‖O_DOS  |O_PE   ‖(Offset from Dos Header / PE Header
‖-------|-------‖
 |0118H  |0018H  | Magic Value                : 010BH 
 |011AH  |001AH  | Major Linker Version       : 2
 |011BH  |001BH  | Minor Linker Version       : 25
 |       |       | Linker Version             : 2.25
 |011CH  |001CH  | Size of Code               : 00001200H
 |0120H  |0020H  | Size of Initialized Data   : 00000600H
 |0124H  |0024H  | Size of Uninitialized Data : 00000000H
 |0128H  |0028H  | Address of Entry Point     : 00005200H
 |012CH  |002CH  | Base of Code (.text ofs.)  : 00001000H
 |0130H  |0030H  | Base of Data (.bss ofs.)   : 00003000H
 |0134H  |0034H  | Image Base                 : 00400000H
 |0138H  |0038H  | Section Alignment          : 00001000H
 |013CH  |003CH  | File Alignment             : 00000200H
 |0140H  |0040H  | Major Operating System Version : 1
 |0142H  |0042H  | Minor Operating System Version : 0
 |0144H  |0044H  | Major Image Version        : 0
 |0146H  |0046H  | Minor Image Version        : 0
 |0148H  |0048H  | Major SubSystem Version    : 3
 |014AH  |004AH  | Minor SubSystem Version    : 10
 |014CH  |004CH  | Reserved Long              : 43545A41H
 |0150H  |0050H  | Size of Image              : 00006600H
 |0154H  |0054H  | Size of Headers            : 00000400H
 |0158H  |0058H  | File Checksum              : 00000000H
 |015CH  |005CH  | SubSystem                  : 2
 |       |       |     -Image runs in the Windows GUI subsystem
 |015EH  |005EH  | DLL Characteristics        : 0000H
 |0160H  |0060H  | Size of Stack Reserve      : 00100000H
 |0164H  |0064H  | Size of Stack Commit       : 00002000H
 |0168H  |0068H  | Size of Heap Reserve       : 00100000H
 |016CH  |006CH  | Size of Heap Commit        : 00001000H
 |0170H  |0070H  | Loader Flags               : 00000000H
 |0174H  |0074H  | Number Directories         : 00000010H
 |_______|_______|
 
 [...]

 ----------PE Section Headers---------------------------------------

 -----------------
‖O_DOS  | O_PE  ‖(Offset from Dos Header / PE Header
‖-------|-------‖[...] 
 |0270H  | 0170H | Section name            : .reloc
 |0278H  | 0178H | Physical Address        : 00001600H
 |027CH  | 017CH | Virtual Address         : 00005000H
 |0280H  | 0180H | Size of RAW data        : 00001600H
 |0284H  | 0184H | Pointer to RAW data     : 00001C00H
 |0288H  | 0188H | Pointer to relocations  : 00000000H
 |028CH  | 018CH | Pointer to line numbers : 00000000H
 |0290H  | 0190H | Number of Relocations   : 0000H
 |0292H  | 0192H | Number of line numbers  : 0000H
 |0294H  | 0194H | Characteristics         : F0000060H
 |       |       | -Section contains code.
 |       |       | -Section contains initialized data.
 |       |       | -Section is shareable.
 |       |       | -Section is executable.
 |       |       | -Section is readable.
 |       |       | -Section is writeable.
 |       |       |
 |_______|_______|
 --------------------------------------------------------------------------------

     好了,我希望这已经帮助你更理解在通过增加它的最后一节来感染PE文件的时候,做了些什么。为了避免你在比较这些每一个表时花更多的精力,我给出了一个列表:


  ==============================================================
  |  Values to change     |Before    |After     |Location      |
  ==============================================================
  |Address Of Entrypoint |00001000h |00005200h |Image File Hdr |
  --------------------------------------------------------------
  |Reserved1 (inf. mark) |00000000h |43545A41h |Image File Hdr |
  --------------------------------------------------------------
  |Virtual Size          |00001000h |00001600h |Section header |
  --------------------------------------------------------------
  |Size Of Raw Data      |00000200h |00001600h |Section header |
  --------------------------------------------------------------
  |Characteristics       |50000040h |F0000060h |Section header |
  --------------------------------------------------------------

    实现这个的代码非常简单。对于那些没有看到代码还没有理解的人,可以看看Win32.Aztec,在下一章将详细描述。