现在的位置: 首页 > 综合 > 正文

最短小的PE文件之破译

2013年09月18日 ⁄ 综合 ⁄ 共 4540字 ⁄ 字号 评论关闭

发信人: rufi (如飞), 信区: Arch_Compiler
标  题: 最短小的PE文件之破译
发信站: 日月光华 (2004年03月24日23:45:03 星期三), 站内信件

最短小的PE文件之破译

研究PE格式是从看到chsoft的说明档开始的:
chsoft (Get busy living or get busy dying) 共上站 2086 次  [狮子座]
上 次 在:[2004年03月24日10:54:22 星期三] 从 [10.100.118.60] 到本站一游。
目前在线:[讯息器:(打开) 呼叫器:(打开)] 表现值:[资深人士] 信箱:[  ]
文 章 数:[3549] 经 验 值:[#         ] 生命力:[149]
目前 chsoft 状态如下:
品味文章   览新文章
史上最短小精悍的PE File完整版
00000000h: 4D 5A B8 EC 00 40 00 E9 B0 00 00 00 50 45 00 00 4C 01 01 00
00000014h: 75 73 65 72 33 32 2E 64 6C 6C 00 00 C8 00 03 01 0B 01 00 00
00000028h: 00 10 00 00 00 10 00 00 00 00 00 00 02 00 00 00 02 00 00 00
0000003Ch: 0C 00 00 00 00 00 40 00 00 10 00 00 00 02 00 00 02 01 00 00
00000050h: 00 00 00 00 04 00 00 00 00 00 00 00 00 20 00 00 00 02 00 00
00000064h: 00 00 00 00 02 00 00 00 00 00 10 00 00 20 00 00 00 00 10 00
00000078h: 00 10 00 00 00 00 00 00 0D 00 00 00 00 00 00 00 00 00 00 00
0000008Ch: 94 00 00 00 28 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF
000000A0h: 14 00 00 00 4C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000B4h: 00 00 00 00 00 00 00 00 6A 00 50 50 6A 00 FF 15 4C 00 40 00
000000C8h: C3 90 90 90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000DCh: 00 00 00 00 00 00 00 00 94 00 00 00 28 00 00 00 48 65 6C 6C
000000F0h: 6F 21 00 00 00 10 00 00 00 10 00 00 00 00 00 00 00 00 00 00
00000104h: 4D 65 73 73 61 67 65 42 6F 78 41 00 60 00 00 E0
共276个字节,猜猜看运行结果是什么?

这个文件字节数不多,分析起来不是很难,分析一个标准的PE文件反而花了很多的时间.
搞清楚标准的PE格式之后,对这个文件的机理也就明白了.

下面是破译出来的源程序:

org 0x400000   ;ImageBase
origin:

DOS_MZ_header:
  .e_magic   db "MZ"
  start:
  use32
  mov eax,Section_Table.Name              ;  ASCII "Hello!"
  jmp main

PE_header:
  .Signature          db "PE",0,0
  FileHeader:
    .Machine          dw 0x014C         ;Machine = IMAGE_FILE_MACHINE_I386
(14Ch)
    .NumberOfSections     dw 0x01
    .TimeDateStamp    dd "user"         ;db "user32.dll",0
    .PointerToSymbolTable dd "32.d"
    .NumberOfSymbols      dd "ll"
    .SizeOfOptionalHeader dw 0x00C8
    .Characteristics      dw 0x0103         ;exe or dll
  OptionalHeader:               ;OptionalHeader has 31 fields
    .Magic        dw 0x010B
    .MajorLinkerVersion   db 0
    .MinerLinkerVersion   db 0
    .SizeOfCode       dd 0x1000
    .SizeOfInitializedData   dd 0x1000
    .SizeOfUnInitializedData dd 0
    .AddressOfEntryPoint  dd start-origin
    .BaseOfCode       dd start-origin
    .BaseOfData       dd PE_header-origin      ;e_lfanew
    .ImageBase        dd origin
    .SectionAlignment     dd 0x1000
    .FileAlignment    dd 0x0200
                     messagebox:
    .MajorOSVersion       dw 0x0102  ;point to dword before "MessageBoxA"
    .MinorOSVersion       dw 0x0000
    .MajorImageVersion    dw 0
    .MinorImageVersion    dw 0
    .MajorSubSystemVerion dw 4
    .MinorSubSystemVerion dw 0
    .Win32VersionValue    dd 0
    .SizeOfImage      dd 0x2000
    .SizeOfHeaders    dd 0x0200
    .CheckSum         dd 0
    .SubSystem        dw 2
    .DllCharacteristics   dw 0
    .SizeOfStackReserve   dd 0x100000
    .SizeOfStackCommit    dd 0x2000
    .SizeOfHeapReserve    dd 0x100000
    .SizeOfHeapRCommit    dd 0x1000
    .LoaderFlags      dd 0
    .NumberOfDataDirectories  dd 0x0D     ;13

    Data_Directories:
      .Export_Table        dd 0,0      ; Rva,Size
      .Import_Table        dd 0x94,0x28    ; Rva,Size
      .Resource_Table      dd 0,0      ; Rva,Size
      .Exception_Table     dd 0xFFFFFFFF,0x14  ; Rva,Size
      .Security_Table      dd 0x4C,0  ; Rva,Size
      .Relocation_Table        dd 0,0  ; Rva,Size
      .Debug           dd 0,0  ; Rva,Size
     ;.Description             dd 0x5050006A,0x15FF006A  ; Rva,Size
     ;.Global_PTR              dd 0x0040004C,0x909090C3  ; Rva,Size
   main:
     PUSH 0               ; /Style = MB_OK|M
     PUSH EAX             ; |Title
     PUSH EAX             ; |Text
     PUSH 0               ; |hOwner = NULL
     CALL DWORD  [DS:messagebox]  ; /MessageBoxA
     RETN
     NOP
     NOP
     NOP
     .TLS_Table           dd 0,0  ; Rva,Size
     .Load_Config_Table       dd 0,0  ; Rva,Size
     .Bound_Import    dd 0,0  ; Rva,Size
     .ImportAddressTable  dd 0x94,0x28  ; Rva,Size

Section_Table:
  .Name           db "Hello!",0,0
  .VirtualSize        dd 0x1000
  .VirtaulAddress     dd 0x1000
  .SizeOfRawData      dd 0
  .PointerToRawData       dd 0        ; after five dwords, appear
"user32.dll"
  .PointerToRelocations   dd "Mess"   ; db "MessageBoxA",0
  .PointerToLinenumbers   dd "ageB"
  .NumberOfRelocations    dw "ox"
  .NumberOfLinenumbers    dw "A"
  .Characteristics    dd 0xE0000060

编译后就得到了那276个字节,运行的结果是显示一个标题和内容都要是"Hello!"的消息
框.
分析这个源程序就会发现:
1.程序的入口点在DOS header内,之后又跳转到Data_Directories的Debug之后,于是
Data_Directories的Description和Global_PTR中的内容为Code.
2.PE header的BaseOfData字段同时又是DOS header的
e_lfanew字段,指向PE header的位置.
3.NumberOfDataDirectories设为了13,而正常情况下为16.
4.Section_Table中只有一个节,而这个节内容分散在前面的数据中,以致于整个文件的he
ader
之后没有RawData.
5.PointerToRawData为0,这样从文件开头数过5个DWORD后,找到dll的文件名.
6.Import_Table的RVA是0x94,这样Ox94之后的第5个DWORD,相当于ImageImportDescripto
r的
FirstThunk,这个字段的内容为0x4C, 而Ox4C处的字段为MajorOSVersion,所这个地方的
内容(0x0102)
相当于ThunkValue,指向一个ImageImportByName结构,0x0102处的双字节为Hint,Hint之
后的则是
函数名MessageBoxA.
概括地说,这个文件的机理就把文件头不重要的平常没有用到的字节,填充为有用的数据
或代码.
然后一些关键字段的内容为指针时,巧妙指向那些数据或代码,于是文件可以被执行.
--

add life,coding
push limits
mov reality,ideas

 

抱歉!评论已关闭.