peexplorer1.9: PE文件格式 1.9版 完整译文(附注释)(3)

  正如你所见我计划只用2个节个用于代码个用于所有剩余东西(数据、常量和输入目录等)没有重定位和象资源的类其它东西我也不用BSS节并将变量“written”放入已化数据文件和RAM中节对齐都是(32字节);这将有助于使任务简单否则我就得来回地计算RVA很多次

  现在我们设置数据目录开始于0xb8字节有0x80字节长:

   地址     大小
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_EXPORT(0)
  ????????  ????????    ;IMAGE_DIRECTORY_ENTRY_IMPORT(1)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_RESOURCE(2)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_EXCEPTION(3)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_SECURITY(4)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_BASERELOC(5)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_DEBUG(6)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_COPYRIGHT(7)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_GLOBALPTR(8)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_TLS(9)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG(10)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT(11)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_IAT(12)
  00000000  00000000    ;13
  00000000  00000000    ;14
  00000000  00000000    ;15
  仅使用输入目录

  下个使节头首先我们做代码节代码节将包含前面所编汇编语句它有32字节长所以代码节也就是这么长节头从0x138处开始有0x28字节长:

  Name      2e636f6465000000  ;".code"ASCII码值
  VirtualSize    00000000      ;未用
  VirtualAddress   ????????      ;待定
  SizeOfRawData   20000000      ;代码大小
  PoerToRawData  ????????      ;待定
  PoerToRelocations00000000      ;未用
  PoerToLinenumbers00000000      ;未用
  NumberOfRelocations 0000         ;未用
  NumberOfLinenumbers 0000         ;未用
  Characteristics  20000060      ;代码节可执行可读
  第 2节将包含数据节头开始于0x160处有0x28字节长:

  Name      2e64617461000000  ;".data"ASCII码值
  VirtualSize    00000000      ;未用
  VirtualAddress   ????????      ;待定
  SizeOfRawData   ????????      ;待定
  PoerToRawData  ????????      ;待定
  PoerToRelocations00000000      ;未用
  PoerToLinenumbers00000000      ;未用
  NumberOfRelocations 0000         ;未用
  NumberOfLinenumbers 0000         ;未用
  Characteristics  400000c0      ;已可读可写
  下个字节位于0x188处但节需要按32字节(倍数)对齐(我是这样选择)所以我们需要添些(0)字节直到0x1a0处:

  000000000000   ;填充
  000000000000
  000000000000
  000000000000
  现在第就是上面所汇编代码节“到”了它开始于0x1a0处有0x20字节长:

  6A00          ;push   0x00000000
  68????????     ;push   off_written
  6A0D          ;push   0x0000000d
  68????????     ;push   offhello_
  6AF5          ;push   0xfffffff5
  2EFF15????????  ;call   dwordptrcs:__imp__GetStdHandle@4
  50           ;push   eax
  2EFF15????????  ;call   dwordptrcs:__imp__WriteConsoleA@20
  C3           ;ret
   

  长度(刚好32字节)在下节(数据节)前我们不需要填充任何字节节到了从0x1c0处开始:

    68656C6C6F2C20776F726C640A ;"hello,world "ASCII码值
  000000                ;填充几个0以和_written对齐
  00000000              ;_written
  现在剩下只有输入目录了本文件将从"kernel32.dll"库中输入2个输入目录将从本节变量后面立即开始首先我们先将上面数据按32字节对齐:

  000000000000000000000000  ;填充

  在0x1e0处开始输入描述(IMAGE_IMPORT_DESCRIPTOR):

  OriginalFirstThunk   ????????  ;待定
  TimeDateStamp     00000000  ;未绑定
  ForwarderChain     ffffffff  ;无中转
  Name          ????????  ;待定
  FirstThunk       ????????  ;待定
  我们需要用个0字节项来结束输入目录(我们现在位于0x1f4):

  OriginalFirstThunk   00000000  ;结束符号
  TimeDateStamp     00000000  ;
  ForwarderChain     00000000  ;
  Name          00000000  ;
  FirstThunk       00000000  ;
  现在只剩下DLL名字还有2个换长以及换长数据和名字了但现在我们真很快就要完成了

  DLL名字以0结尾开始于0x208处:

  6b65726e656c33322e646c6c00 ;"kernel32.dll"ASCII码值
  000000                ;填充到32位边界
  原始第个换长开始于0x218处:

  AddressOfData ????????      ;"WriteConsoleA"RVA
  AddressOfData ????????      ;"GetStdHandle"RVA
          00000000      ;结束符号
  第个换长就是同样列表开始于0x224处:

(__imp__WriteConsoleA@20,at0x224)
  AddressOfData ????????      ;"WriteConsoleA"RVA
(__imp__GetStdHandle@4,at0x228)
  AddressOfData ????????      ;"GetStdHandle"RVA
          00000000      ;结束符号
  现在剩下只有输入名字(IMAGE_IMPORT_BY_NAME)形式两个名了我们现处于0x230字节

  0100                   ;序数不需要正确
  5772697465436f6e736f6c654100 ;"WriteConsoleA"ASCII码值
  0200                   ;序数不需要正确
  47657453746448616e646c6500  ;"GetStdHandle"ASCII码值
  Ok,这就全部结束了个字节我们并不真正需要是0x24f我们必须将节填充到0x260处:

  00000000000000000000000000000000;填充
  00
  ------------

  我们已经完成了我们已经知道了所有字节偏移量我们可以应用我们修正到所有原先被用“??”符号标为“未知”地址和大小了

  我将不强迫你步地去读它(很好懂)只直接给出结果来:

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

  DOS-头,开始于0x0:

  00|4d5a0000000000000000000000000000
  10|00000000000000000000000000000000
  20|00000000000000000000000000000000
  30|00000000000000000000000040000000
  签名,开始于0x40:

  50450000

  文件头,开始于0x44:

  Machine          4c01   ;i386
  NumberOfSections      0200   ;代码和数据
  TimeDateStamp       00000000;谁管它?
  PoerToSymbolTable    00000000;未用
  NumberOfSymbols      00000000;未用
  SizeOfOptionalHeader    e000   ;常量
  Characteristics      0201   ;可执行于32位机器上
  可选头,开始于0x58:

  Magic           0b01   ;常量
  MajorLinkerVersion     00     ;我是0.0版:-)
  MinorLinkerVersion     00     ;
  SizeOfCode         20000000;32字节代码
  SizeOfInitializedData   a0000000;数据节大小
  SizeOfUninitializedData  00000000;我们没有BSS节
  AddressOfEntryPo    a0010000;代码节开始处
  BaseOfCode         a0010000;代码节RVA
  BaseOfData         c0010000;数据节RVA
  ImageBase         00001000;1MB,任意选择
  SectionAlignment      20000000;32字节对齐
  FileAlignment       20000000;32字节对齐
  MajorOperatingVersion 0400   ;NT4.0
  MinorOperatingVersion 0000   ;
  MajorImageVersion     0000   ;0.0版本
  MinorImageVersion     0000   ;
  MajorSubsystemVersion   0400   ;Win324.0
  MinorSubsystemVersion   0000   ;
  Win32VersionValue     00000000;未用?
  SizeOfImage        c0000000;所有节大小总数
  SizeOfHeaders       a0010000;第偏移量
  CheckSum          00000000;非驱动不须用
  Subsystem         0300   ;Win32控制台
  DllCharacteristics     0000   ;未用(不是个DLL)
  SizeOfStackReserve     00001000;1MB栈
  SizeOfStackCommit     00100000;开始时4KB
  SizeOfHeapReserve     00001000;1MB堆
  SizeOfHeapCommit      00100000;开始时4KB
  LoaderFlags        00000000;未知
  NumberOfRvaAndSizes    10000000;常量
  数据目录开始于0xb8:

   地址      大小
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_EXPORT(0)
  e0010000  6f000000    ;IMAGE_DIRECTORY_ENTRY_IMPORT(1)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_RESOURCE(2)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_EXCEPTION(3)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_SECURITY(4)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_BASERELOC(5)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_DEBUG(6)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_COPYRIGHT(7)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_GLOBALPTR(8)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_TLS(9)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG(10)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT(11)
  00000000  00000000    ;IMAGE_DIRECTORY_ENTRY_IAT(12)
  00000000  00000000    ;13
  00000000  00000000    ;14
  00000000  00000000    ;15
  节头(代码节),开始于0x138:

  Name      2e636f6465000000  ;".code"
  VirtualSize    00000000      ;未用
  VirtualAddress   a0010000      ;代码节RVA
  SizeOfRawData   20000000      ;代码大小
  PoerToRawData  a0010000      ;代码节文件偏移量
  PoerToRelocations00000000      ;未用
  PoerToLinenumbers00000000      ;未用
  NumberOfRelocations 0000         ;未用
  NumberOfLinenumbers 0000         ;未用
  Characteristics  20000060      ;代码节可执行可读
  节头(数据节),开始于0x160:

  Name      2e64617461000000  ;".data"
  VirtualSize    00000000      ;未用
  VirtualAddress   c0010000      ;数据节RVA
  SizeOfRawData   a0000000      ;数据节大小
  PoerToRawData  c0010000      ;数据节文件偏移量
  PoerToRelocations00000000      ;未用
  PoerToLinenumbers00000000      ;未用
  NumberOfRelocations 0000         ;未用
  NumberOfLinenumbers 0000         ;未用
  Characteristics  400000c0      ;已可读可写
(填充)
  000000000000   ;填充
  000000000000
  000000000000
  000000000000
  代码节,开始于0x1a0:

  6A00          ;push   0x00000000
  68d0011000     ;push   off_written
  6A0D          ;push   0x0000000d
  68c0011000     ;push   offhello_
  6AF5          ;push   0xfffffff5
  2EFF1528021000  ;call   dwordptrcs:__imp__GetStdHandle@4
  50           ;push   eax
  2EFF1524021000  ;call   dwordptrcs:__imp__WriteConsoleA@20
  C3           ;ret
   

  数据节开始于0x1c0:

    68656C6C6F2C20776F726C640A ;"hello,world "
  000000                ;填充到和_written对齐
  00000000              ;_written
  填充:

  000000000000000000000000  ;填充

  输入描述(IMAGE_IMPORT_DESCRIPTOR)开始于0x1e0:

  OriginalFirstThunk   18020000  ;原始第个换长RVA
  TimeDateStamp     00000000  ;未绑定
  ForwarderChain     ffffffff  ;-1无中转
  Name          08020000  ;DLL名字RVA
  FirstThunk       24020000  ;第个换长RVA
  结束标志(0x1f4):

  OriginalFirstThunk   00000000  ;结束标志
  TimeDateStamp     00000000  ;
  ForwarderChain     00000000  ;
  Name          00000000  ;
  FirstThunk       00000000  ;
  DLL名字,开始于0x208:

  6b65726e656c33322e646c6c00 ;"kernel32.dll"
  000000                ;填充到32位边界
  原始第个换长,开始于0x218:

  AddressOfData 30020000      ;名"WriteConsoleA"RVA
  AddressOfData 40020000      ;名"GetStdHandle"RVA
          00000000      ;结束标志
  第个换长,开始于0x224:

  AddressOfData 30020000      ;名"WriteConsoleA"RVA
  AddressOfData 40020000      ;名"GetStdHandle"RVA
          00000000      ;结束标志
  输入名称(IMAGE_IMPORT_BY_NAME)开始于0x230:



  IMAGE_IMPORT_BY_NAME,开始于0x240:

  0200                   ;序数不需要正确
  47657453746448616e646c6500  ;"GetStdHandle"ASCII码值
(填充)
  00000000000000000000000000000000;填充
  00
  第个未使用字节开始于:0x260

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

  噢这个文件能在NT上却不能在windows95上运行windows95不能运行按32字节节对齐应用它要求节对齐为4KB;并且很明显文件对齐也应为512字节因此要想在windows95上运行你得插入很多0字节(为了对齐)并调整RVA感谢D.Binette在windows95上(运行)试验



Tags:  pe文件格式 peexplorer1.9

延伸阅读

最新评论

发表评论