结合PE格式对linker分析1

原创 2005年05月23日 20:22:00

这是以前我学习PE的时候的一些摘要。
分析摘要:
(*1*): 写程序。a.cpp 和 foo.cpp
其中a.cpp的内容为:

extern void Foo();
void main()
{
 Foo();
}

foo.cpp的内容为:

#include "stdio.h"
void Foo()
{
 printf("I am Foo!");
}
编译程序产生a.obj foo.obj a.exe.

(*2*):Copy以上3个文件到../VisualStdio/VC98/BIN目录下
用以下命令解析:
dumpbin /all a.obj >aobj.txt <Enter>
dumpbin /all foo.obj >fooobj.txt  <Enter>
dumpbin /all a.exe >aexe.txt  <Enter>

(*3*):
打开文件a.obj,找到代码节。内容如下:
SECTION HEADER #3
   .text name
       0 physical address
       0 virtual address
      2E size of raw data
     355 file pointer to raw data                    //Attention!!~!~
     383 file pointer to relocation table
     397 file pointer to line numbers
       2 number of relocations
       3 number of line numbers
60501020 flags
         Code
         Communal; sym= _main
         16 byte align
         Execute Read

RAW DATA #3
  00000000: 55 8B EC 83 EC 40 53 56 57 8D 7D C0 B9 10 00 00  U....@SVW.}.....
  00000010: 00 B8 CC CC CC CC F3 AB E8 00 00 00 00 5F 5E 5B  ............._^[
  00000020: 83 C4 40 3B EC E8 00 00 00 00 8B E5 5D C3        ..@;........].
(*4*):反编译a.obj的代码节。
打开工具URSoft W32Dasm (我用的是VERSION 8.93)
在打开文件时选择所有文件,因为本软件主要是针对PE,LE,NE等文件格式的。所以对于用来
反编译OBJ文件需指定偏移量。如上Attention!处所示。即为代码节的文件偏移。
所以在打开OBJ文件的提示对话框中输入:00000355
Start Disassembly from Offset 00000355 Hex.
无需选中Check For 16 Bit Disassembly .
反编译之后的代码节内容如下:

:00000000 55                      push ebp
:00000001 8BEC                    mov ebp, esp
:00000003 83EC40                  sub esp, 00000040
:00000006 53                      push ebx
:00000007 56                      push esi
:00000008 57                      push edi
:00000009 8D7DC0                  lea edi, dword ptr [ebp-40]
:0000000C B910000000              mov ecx, 00000010
:00000011 B8CCCCCCCC              mov eax, CCCCCCCC
:00000016 F3                      repz
:00000017 AB                      stosd
:00000018 E800000000              call 0000001D    //Attention!!!
:0000001D 5F                      pop edi
:0000001E 5E                      pop esi
:0000001F 5B                      pop ebx
:00000020 83C440                  add esp, 00000040
:00000023 3BEC                    cmp ebp, esp
:00000025 E800000000              call 0000002A
:0000002A 8BE5                    mov esp, ebp
:0000002C 5D                      pop ebp
:0000002D C3                      ret
简要说明:
The 0xE8 is the CALL instruction opcode. The next DWORD should contain the offset to the Foo function (relative to the CALL instruction). It's pretty clear that Foo probably isn't zero bytes away from the CALL instruction. Simply put, this code wouldn't work as expected if you were to execute it. The code is broken, and needs to be fixed up.

 In the above example of a call to function Foo, there will be a REL32 fixup record, and it will have the offset of the DWORD that the linker needs to overwrite with the appropriate value.

(*5*):查看紧跟代码节后的RELOCATIONS:
RELOCATIONS #3
                                    Symbol        Symbol
 Offset    Type       Applied To    Index          Name
 --------  -------  -------------  ------      --------------
 00000019  REL32       00000000     12     ?Foo@@YAXXZ (void __cdecl Foo(void))
 00000026  REL32       00000000     13     __chkesp

this(first) fixup record says that the linker needs to calculate the relative offset to
 function Foo, and write that value to offset four in the section.

(*6*):实际的a.exe代码节内容:
:00401000 55                      push ebp
:00401001 8BEC                    mov ebp, esp
:00401003 83EC40                  sub esp, 00000040
:00401006 53                      push ebx
:00401007 56                      push esi
:00401008 57                      push edi
:00401009 8D7DC0                  lea edi, dword ptr [ebp-40]
:0040100C B910000000              mov ecx, 00000010
:00401011 B8CCCCCCCC              mov eax, CCCCCCCC
:00401016 F3                      repz
:00401017 AB                      stosd
:00401018 E813000000              call 00401030
:0040101D 5F                      pop edi
:0040101E 5E                      pop esi
:0040101F 5B                      pop ebx
:00401020 83C440                  add esp, 00000040
:00401023 3BEC                    cmp ebp, esp
:00401025 E846000000              call 00401070
:0040102A 8BE5                    mov esp, ebp
:0040102C 5D                      pop ebp
:0040102D C3                      ret

:0040102E CC                      int 03
:0040102F CC                      int 03
 //中间无内容省略。
* Referenced by a CALL at Address:
|:00401018  
|
:00401030 55                      push ebp
:00401031 8BEC                    mov ebp, esp
:00401033 83EC40                  sub esp, 00000040
:00401036 53                      push ebx
:00401037 56                      push esi
:00401038 57                      push edi
:00401039 8D7DC0                  lea edi, dword ptr [ebp-40]
:0040103C B910000000              mov ecx, 00000010
:00401041 B8CCCCCCCC              mov eax, CCCCCCCC
:00401046 F3                      repz
:00401047 AB                      stosd
:00401048 68ECC04000              push 0040C0EC
:0040104D E85E000000              call 004010B0
:00401052 83C404                  add esp, 00000004
:00401055 5F                      pop edi
:00401056 5E                      pop esi
:00401057 5B                      pop ebx
:00401058 83C440                  add esp, 00000040
:0040105B 3BEC                    cmp ebp, esp
:0040105D E80E000000              call 00401070
:00401062 8BE5                    mov esp, ebp
:00401064 5D                      pop ebp
:00401065 C3                      ret

(*7*)看一下FOO.OBJ的内容:(由分析FOOOBJ.TXT中代码节的偏移为0x000003bf,从而用W32Dasm反编译。)
:00000000 55                      push ebp
:00000001 8BEC                    mov ebp, esp
:00000003 83EC40                  sub esp, 00000040
:00000006 53                      push ebx
:00000007 56                      push esi
:00000008 57                      push edi
:00000009 8D7DC0                  lea edi, dword ptr [ebp-40]
:0000000C B910000000              mov ecx, 00000010
:00000011 B8CCCCCCCC              mov eax, CCCCCCCC
:00000016 F3                      repz
:00000017 AB                      stosd
:00000018 6800000000              push 00000000
:0000001D E800000000              call 00000022
:00000022 83C404                  add esp, 00000004
:00000025 5F                      pop edi
:00000026 5E                      pop esi
:00000027 5B                      pop ebx
:00000028 83C440                  add esp, 00000040
:0000002B 3BEC                    cmp ebp, esp
:0000002D E800000000              call 00000032
:00000032 8BE5                    mov esp, ebp
:00000034 5D                      pop ebp
:00000035 C3                      ret
综上分析可知:连接器在整合各个编译单元(.obj)时,如上A.OBJ和FOO.OBJ已记录下需要调整的数据,
比如a.obj中的FOO函数位置,即
:00000018 E800000000              call 0000001D    //Attention!!!

RAW DATA #3
  00000000: 55 8B EC 83 EC 40 53 56 57 8D 7D C0 B9 10 00 00  U....@SVW.}.....
  00000010: 00 B8 CC CC CC CC F3 AB E8 00 00 00 00 5F 5E 5B  ............._^[
  00000020: 83 C4 40 3B EC E8 00 00 00 00 8B E5 5D C3        ..@;........].

节后紧跟的RELOCATIONS #3
                                    Symbol        Symbol
 Offset    Type       Applied To    Index          Name
 --------  -------  -------------  ------      --------------
 00000019  REL32       00000000     12     ?Foo@@YAXXZ (void __cdecl Foo(void))
在连接时,连接器整合代码节,将FOO.OBJ的代码节接在A.OBJ的代码节之后。如下:
:00401000 55                      push ebp
     ....
:00401018 E813000000              call 00401030
     ....
:0040102D C3                      ret
:0040102E CC                      int 03
:0040102F CC                      int 03
 //中间无内容省略。
* Referenced by a CALL at Address:
|:00401018  
|
:00401030 55                      push ebp
    ....
:00401065 C3                      ret
其中CALL 00401030中的00400000为代码优先载入基地址。
而E813000000中的13000000即为偏移值。事实上为00000013,这是INTEL CPU的特性
a peculiarity of Intel processors where numerical data is stored in
 reverse order to character data.

To copy a 32 bit value (56 A7 00 FE) into the eax register, you will find the opcode, A1 (MOV EAX) followed by (FE 00 A7 56).
    A1 FE 00 A7 56

从偏移00401018跳到00401030。如此可以得出指令为:E813000000
手工算法:
         因为CALL指令本身占用5个字节(1个为CALL nmemonic(E8),另4个为偏移值)。
         而0040101D-00401018=5所以偏移事实上应该从0040101D算起。   
         故00401030-0040101D=13
         所以产生的CALL指令为E813000000
借助软件:
         oPcodeR--由Cool McCool编写。非常好用。

PE文件格式 - 节的原始数据 1(Sections' raw data)

http://hi.baidu.com/softopen/blog/item/7ef2c2cc60b6fa570fb3452a.html 八、节的原始数据(Sections' raw d...
  • zhgn2
  • zhgn2
  • 2012年07月09日 21:16
  • 1997

PE文件格式学习心得【1】

PE文件是Protable Executable File Format(可移至的执行体),是目前Windows平台上的主流可执行文件格式。 PE可以简单理解为一个结构,这个结构用来告诉Window...
  • BetaBin
  • BetaBin
  • 2012年03月26日 10:23
  • 1314

PE文件格式详解(1)

PE头由许多结构体组成,接下来分别解释一下各部分。 1.DOS头     微软最初创建PE格式的时候,DOS文件被人们广泛的使用,为了实现PE文件对DOS文件的兼容性。结果是在PE头的最前面...

pe格式研究1

小E qq592646022 PE(Portable Excute)格式,是微软Win32环境可执行文件的标准格式,PE文件使用的是一个平面地址空间,所有代码和数据都合并在一起,组成一个很大的结构。...

PE文件格式分析及修改(续)

2.3 IMAGE_SECTION_HEADER PE文件头后是节表,在winnt.h下如下定义 typedef struct _IMAGE_SECTION_HEADER { B...

PE文件和COFF文件格式分析--概述

刚工作的时候,我听说某某大牛在做病毒分析时,只是用notepad打开病毒文件,就能大致猜到病毒的工作原理。当时我是佩服的很啊,同时我也在心中埋下了一个种子:我也得有这天。随着后来的工作进行,一些任务的...

PE文件和COFF文件格式分析——导出表的应用——一种摘掉Inline钩子(Unhook)的方法

本文讲述如何使用导出表,还原inline hook。

PE格式全分析

我们知道,很多PE分析工具都可以查看一个EXE文件的引用DLL文件函数表,其实,这个本身就是存储在EXE头部的一个重要信息,今天,我们就来研究一下: 我们借用一张PE结构图来分析: ...

PE文件格式分析及修改

PE 的意思是 Portable Executable(可移植的执行体)。它是 Win32环境自身所带的执行文件格式。它的一些特性继承自Unix的Coff(common object file for...

PE文件格式分析

在shellcode的编写过程中,关于API的定位会涉及到“exe”和“dll”文件格式问题,下面给一详细说明: PE文件结构    PE文件格式被组织为一个线性的数据流,它由一个MS-DO...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:结合PE格式对linker分析1
举报原因:
原因补充:

(最多只允许输入30个字)