• binary hacks读数笔记(ld 链接讲解 一)


    首先我们先看两段代码:

    a.c

    extern int shared;
     
    int main(){
           int a=100;
            swap(&a,&shared);
    }

    b.c

    int shared=1;
    
    void swap(int* a,int* b){
         *a^=*b^=*a^=*b;
    }

    gcc  -c a.c b.c 得到a.o 与b.o

    1、查看a.o:

    [root@tlinux misc]# objdump -h a.o
    
    a.o:     file format elf64-x86-64
    
    Sections:
    Idx Name          Size      VMA               LMA               File off  Algn
      0 .text         00000027  0000000000000000  0000000000000000  00000040  2**0
                      CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
      1 .data         00000000  0000000000000000  0000000000000000  00000067  2**0
                      CONTENTS, ALLOC, LOAD, DATA
      2 .bss          00000000  0000000000000000  0000000000000000  00000067  2**0
                      ALLOC
      3 .comment      0000002e  0000000000000000  0000000000000000  00000067  2**0
                      CONTENTS, READONLY
      4 .note.GNU-stack 00000000  0000000000000000  0000000000000000  00000095  2**0
                      CONTENTS, READONLY
      5 .eh_frame     00000038  0000000000000000  0000000000000000  00000098  2**3
                      CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

    2、查看b.o:

    [root@tlinux misc]# objdump -h b.o
    
    b.o:     file format elf64-x86-64
    
    Sections:
    Idx Name          Size      VMA               LMA               File off  Algn
      0 .text         0000004a  0000000000000000  0000000000000000  00000040  2**0
                      CONTENTS, ALLOC, LOAD, READONLY, CODE
      1 .data         00000004  0000000000000000  0000000000000000  0000008c  2**2
                      CONTENTS, ALLOC, LOAD, DATA
      2 .bss          00000000  0000000000000000  0000000000000000  00000090  2**0
                      ALLOC
      3 .comment      0000002e  0000000000000000  0000000000000000  00000090  2**0
                      CONTENTS, READONLY
      4 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000be  2**0
                      CONTENTS, READONLY
      5 .eh_frame     00000038  0000000000000000  0000000000000000  000000c0  2**3
                      CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

    3、链接之前,VMA与LMA都是0,即目标文件的虚拟空间地址与装载地址都无效。经过链接ld过程,才会给链接文件分配虚拟地址空间。

    ld a.o b.o -e main -o ab

    链接过程,合并了a.o与b.o的代码段、数据段,具体的位置与大小如下所示:

    具体信息如下所示

    [root@tlinux misc]# objdump -h ab
    
    ab:     file format elf64-x86-64
    
    Sections:
    Idx Name          Size      VMA               LMA               File off  Algn
      0 .text         00000071  00000000004000e8  00000000004000e8  000000e8  2**0
                      CONTENTS, ALLOC, LOAD, READONLY, CODE
      1 .eh_frame     00000058  0000000000400160  0000000000400160  00000160  2**3
                      CONTENTS, ALLOC, LOAD, READONLY, DATA
      2 .data         00000004  0000000000601000  0000000000601000  00001000  2**2
                      CONTENTS, ALLOC, LOAD, DATA
      3 .comment      0000002d  0000000000000000  0000000000000000  00001004  2**0
                      CONTENTS, READONLY

     同时,我们可以看一下,链接后,各个源文件的符号表也合成一张全局符号表,且符号表中表明各个符号的虚拟空间位置:

    readelf -s ab

    Symbol table '.symtab' contains 13 entries:
       Num:    Value          Size Type    Bind   Vis      Ndx Name
         0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
         1: 00000000004000e8     0 SECTION LOCAL  DEFAULT    1 
         2: 0000000000400160     0 SECTION LOCAL  DEFAULT    2 
         3: 0000000000601000     0 SECTION LOCAL  DEFAULT    3 
         4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
         5: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS a.c
         6: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS b.c
         7: 000000000040010f    74 FUNC    GLOBAL DEFAULT    1 swap
         8: 0000000000601000     4 OBJECT  GLOBAL DEFAULT    3 shared
         9: 0000000000601004     0 NOTYPE  GLOBAL DEFAULT    3 __bss_start
        10: 00000000004000e8    39 FUNC    GLOBAL DEFAULT    1 main
        11: 0000000000601004     0 NOTYPE  GLOBAL DEFAULT    3 _edata
        12: 0000000000601008     0 NOTYPE  GLOBAL DEFAULT    3 _end

    4、接下来介绍一下符号的解析与重定位:

    首先查看一下未重定位之前,a.o中是怎么处理shared变量与swap函数的:

    利用 objdump -d a.o查看一下,a.o的反汇编代码

    [root@tlinux misc]# objdump -d a.o
    
    a.o:     file format elf64-x86-64
    
    
    Disassembly of section .text:
    
    0000000000000000 <main>:
       0:    55                       push   %rbp
       1:    48 89 e5                 mov    %rsp,%rbp
       4:    48 83 ec 10              sub    $0x10,%rsp
       8:    c7 45 fc 64 00 00 00     movl   $0x64,-0x4(%rbp)
       f:    48 8d 45 fc              lea    -0x4(%rbp),%rax
      13:    be 00 00 00 00           mov    $0x0,%esi     //00 00 00 00 shared 未给地址
      18:    48 89 c7                 mov    %rax,%rdi
      1b:    b8 00 00 00 00           mov    $0x0,%eax
      20:    e8 00 00 00 00           callq  25 <main+0x25> //swap函数也未给地址
      25:    c9                       leaveq 
      26:    c3                       retq   

    5、经过ld链接之后,在最后文件ab中,shared 与 swap都知道了地址。因为链接过程会分配虚拟地址,那么根据前面第三点链接过后的信息,可以知道各个段的虚拟地址,那么

    其中各个符号的地址也会知道。那么,经过连接之后,ab中的代码反汇编结果如何,如下所示:

    [root@tlinux misc]# objdump -d ab
    
    ab:     file format elf64-x86-64
    
    
    Disassembly of section .text:
    
    00000000004000e8 <main>:
      4000e8:    55                       push   %rbp
      4000e9:    48 89 e5                 mov    %rsp,%rbp
      4000ec:    48 83 ec 10              sub    $0x10,%rsp
      4000f0:    c7 45 fc 64 00 00 00     movl   $0x64,-0x4(%rbp)
      4000f7:    48 8d 45 fc              lea    -0x4(%rbp),%rax
      4000fb:    be 00 10 60 00           mov    $0x601000,%esi        //00 60 10 00 详见ab文件的数据段
      400100:    48 89 c7                 mov    %rax,%rdi
      400103:    b8 00 00 00 00           mov    $0x0,%eax
      400108:    e8 02 00 00 00(相对下一行命令偏移 02)           callq  40010f <swap>   // 由下面swap在 40010f处可知,a.o  b.o链接到一起后,swap的函数虚拟地址可知   call 命令: 40010d+00000002
      40010d:    c9                       leaveq 
      40010e:    c3                       retq   
    
    000000000040010f <swap>:
      40010f:    55                       push   %rbp
      400110:    48 89 e5                 mov    %rsp,%rbp
      400113:    48 89 7d f8              mov    %rdi,-0x8(%rbp)
      400117:    48 89 75 f0              mov    %rsi,-0x10(%rbp)
      40011b:    48 8b 45 f8              mov    -0x8(%rbp),%rax
      40011f:    8b 10                    mov    (%rax),%edx
      400121:    48 8b 45 f0              mov    -0x10(%rbp),%rax
      400125:    8b 08                    mov    (%rax),%ecx
      400127:    48 8b 45 f8              mov    -0x8(%rbp),%rax
      40012b:    8b 30                    mov    (%rax),%esi
      40012d:    48 8b 45 f0              mov    -0x10(%rbp),%rax
      400131:    8b 00                    mov    (%rax),%eax
      400133:    31 c6                    xor    %eax,%esi
      400135:    48 8b 45 f8              mov    -0x8(%rbp),%rax
      400139:    89 30                    mov    %esi,(%rax)
      40013b:    48 8b 45 f8              mov    -0x8(%rbp),%rax
      40013f:    8b 00                    mov    (%rax),%eax
      400141:    31 c1                    xor    %eax,%ecx
      400143:    48 8b 45 f0              mov    -0x10(%rbp),%rax
      400147:    89 08                    mov    %ecx,(%rax)
      400149:    48 8b 45 f0              mov    -0x10(%rbp),%rax
      40014d:    8b 00                    mov    (%rax),%eax
      40014f:    31 c2                    xor    %eax,%edx
      400151:    48 8b 45 f8              mov    -0x8(%rbp),%rax
      400155:    89 10                    mov    %edx,(%rax)
      400157:    5d                       pop    %rbp
      400158:    c3                       retq  

     6、重定位表信息:

    对于可重定位文件,必须包含重定位表,用来描述如何修改相应的段。可以利用objdump  -r  a.o查看重定位表

    [root@tlinux misc]# objdump -r a.o
    
    a.o:     file format elf64-x86-64
    
    RELOCATION RECORDS FOR [.text]:
    OFFSET           TYPE              VALUE 
    0000000000000014 R_X86_64_32       shared
    0000000000000021 R_X86_64_PC32     swap-0x0000000000000004
    OFFSET指的是需要被重定位的内容在可重定位文件中的位置,看第4点的反汇编内容可知,0x14位置和0x21位置分别为shared 与 swap.需要被重定位
  • 相关阅读:
    php CI框架基础知识
    1206 多表单提交,强类型
    1205 Mvc的Razor语法
    1204 Mvc
    1117 邮件验证
    1115 模板页
    1113 Ajax
    1110 Jquary动画
    1108 Jquary
    1107 Linq高级查询
  • 原文地址:https://www.cnblogs.com/wsw-seu/p/10622736.html
Copyright © 2020-2023  润新知