• 静态链接学习之 ELF 文件 DIY


    目的

    编写一个最小的 ELF 程序,来加强对 ELF 文件格式的掌握和理解。(参考:《程序员的自我修养》一书)

    源代码

    这里采用 GCC 内置汇编代码的编写来避免 libc 中自带的库函数代码

    • 汇编代码采用 AT&T 格式
    char *str="H3ll0
    ";
    
    void print(){
            asm(
                    "movl $6,%%edx 
    	"
                    "movl %0,%%ecx 
    	"
                    "movl $0,%%ebx 
    	"
                    "movl $4,%%eax 
    	"
                    "int $0x80 
    	"
                    ::"r"(str):"edx","ecx","ebx"
            );
    }
    
    
    void exit(){
            asm(
                    "movl $42,%ebx 
    	"
                    "movl $1,%eax 
    	"
                    "int $0x80 
    	"
            );
    }
    
    
    
    void nomain(){
            print();
            exit();
    }
    
    

    这里采用系统调用号来进行系统调用。

    参考:http://syscalls.kernelgrok.com/

    编译

    这里需要编译成 32 位的程序,在 64 位机器下需要使用下面的命令:

    gcc -c -m32 -fno-builtin tiny.c
    ld -m elf_i386 -static -e nomain -o tiny tiny.o
    

    参考:https://blog.csdn.net/neuq_jtxw007/article/details/78112672

    执行、查看大小

    1112 个字节。还可以继续削减他的大小。

    自定义程序段

    先查看他有哪些段,再决定去掉哪些无用的段。

    nick@nick-machine:~/testelf$ readelf -S ./tiny
    There are 9 section headers, starting at offset 0x2f0:
    
    Section Headers:
      [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
      [ 0]                   NULL            00000000 000000 000000 00      0   0  0
      [ 1] .text             PROGBITS        08048094 000094 000042 00  AX  0   0  1
      [ 2] .rodata           PROGBITS        080480d6 0000d6 000007 00   A  0   0  1
      [ 3] .eh_frame         PROGBITS        080480e0 0000e0 00007c 00   A  0   0  4
      [ 4] .data             PROGBITS        0804915c 00015c 000004 00  WA  0   0  4
      [ 5] .comment          PROGBITS        00000000 000160 000035 01  MS  0   0  1
      [ 6] .shstrtab         STRTAB          00000000 0002ae 000042 00      0   0  1
      [ 7] .symtab           SYMTAB          00000000 000198 0000e0 10      8   7  4
      [ 8] .strtab           STRTAB          00000000 000278 000036 00      0   0  1
    Key to Flags:
      W (write), A (alloc), X (execute), M (merge), S (strings)
      I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
      O (extra OS processing required) o (OS specific), p (processor specific)
    
    

    9 个段,首先 text 、rodata、data 这三个段可能是需要的,我们可以把他合成为一个段(代码和数据混合),这样就可以缩减描述各自属性段的字节大小。eh_framecomment 可以直接去除。

    • eh_frame 是用于调试的段,没有这个段在 gdb 中调试会出错。

    自定义 ld 脚本

    通过自定义 ld 脚本的方法,来控制 ld 链接器的行为。

    脚本如下:

    ENTRY(nomain)
    
    SECTIONS{
            . = 0x8048000+SIZEOF_HEADERS;
            tinytext : { *(.text) *(.data) *(.nodata) }
            /DISCARD/ : { *(.comment)  *(.eh_frame)}
    }
    

    编译

    nick@nick-machine:~/testelf$ gcc -m32 -c ./tiny.c -fno-builtin -o tiny.o
    nick@nick-machine:~/testelf$ ld -static -m elf_i386 -T tiny.lds ./tiny.o -o tiny
    

    运行之后还是正常的。

    查看段信息,这是被合并成了一个段 tinytext,权限是 WAX。

    nick@nick-machine:~/testelf$ readelf -S tiny
    There are 6 section headers, starting at offset 0x190:
    
    Section Headers:
      [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
      [ 0]                   NULL            00000000 000000 000000 00      0   0  0
      [ 1] .rodata           PROGBITS        08048074 000074 000007 00   A  0   0  1
      [ 2] tinytext          PROGBITS        0804807c 00007c 000048 00 WAX  0   0  4
      [ 3] .shstrtab         STRTAB          00000000 000162 00002c 00      0   0  1
      [ 4] .symtab           SYMTAB          00000000 0000c4 000080 10      5   4  4
      [ 5] .strtab           STRTAB          00000000 000144 00001e 00      0   0  1
    Key to Flags:
      W (write), A (alloc), X (execute), M (merge), S (strings)
      I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
      O (extra OS processing required) o (OS specific), p (processor specific)
    

    查看大小

    640 个字节,还可以使用 strip 来去除 symbol 信息。

    nick@nick-machine:~/testelf$ ls -al ./tiny
    -rwxrwxr-x 1 nick nick 640 5月   7 16:40 ./tiny
    

    这里就只有 384 字节。

    nick@nick-machine:~/testelf$ strip tiny
    nick@nick-machine:~/testelf$ ls -al ./tiny
    -rwxrwxr-x 1 nick nick 384 5月   7 16:45 ./tiny
    

    应该还能再削减大小,先填坑。。

    总结

    用这个大小的程序来进行 ELF 文件格式分析,会简单很多

  • 相关阅读:
    如何提高沟通能力?
    如何做到科学决策?推荐你看这本《决策必读12篇》
    领导者如何让员工真心服从自己?
    MBA看什么书,MBA教材书目推荐
    有关战略管理的书,哪本最值得推荐?
    市场营销必看书籍推荐
    P1208 混合牛奶题解
    P5019 铺设道路题解
    P1728 陶陶摘苹果题解
    P1106 删数问题题解
  • 原文地址:https://www.cnblogs.com/H4lo/p/10826245.html
Copyright © 2020-2023  润新知