最小x 86 ELF Hello Worldプログラムの誕生


注:ここの最小は私ができることです.
最終サイズ:142バイト
紹介する
この文章は私がUbuntu Linuxで最小のx 86 ELFバイナリHello Worldファイルの記録を作成しようとしたと言えるでしょう.あなたもそれをガイドとすることができます.私の試みはまずcから始まり、x 86アセンブリに向かい、最後に16進数エディタで終わりましたが、私の最終的な成果は実際には「Hi World」しか印刷できません.これは純粋に最終的な数字をより目立たせるためであり、最終的なx 86 ELFバイナリは破壊されているが、最も重要なのは通常通りに動作することである.
スタート
  • 私と一緒にやってみたいなら、最初にしなければならないことは環境を構成することです.
  • Ubuntu(または任意の他の好きなリリース版)
  • をインストール
  • 運転:sudo apt-get install g++gcc nasm
  • システムバージョン
  • を表示
    user@computer:~$ lsb_release -a
    No LSB modules are available.
    Distributor ID: Ubuntu
    Description:    Ubuntu 8.04.1
    Release:        8.04
    Codename:       hardy
    user@computer:~$ uname -a
    Linux ryanh-desktop 2.6.24-19-generic #1 SMP Wed Jun 18 14:43:41 UTC 2008
     i686 GNU/Linux
    user@computer:~$ gcc --version
    gcc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu7)
    Copyright (C) 2007 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    user@computer:~$ nasm -version
    NASM version 0.99.06-20071101 compiled on Nov 15 2007
    

    私の試みはCから始まります.次は私が書いたCプログラムです.chello.c
    #include
  • int main()

  • {
  • printf ("Hi World");

  • return0;
  • }
  • #include 
      
       
    int main()
    {
      printf ("Hi World
    "); return0; }

    コンパイル:
    user@computer:~$ gcc -o chello chello.c
    user@computer:~$ ./chello
    Hi World

    私が最初に得た実行可能ファイルのサイズは6363バイトで、readelfを使用してELFファイルのヘッダ情報を表示することができます.コマンド:
    user@computer:~$ readelf -h chello
    ELF Header:
      Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
      Class:                             ELF32
      Data:                              2's complement, little endian
      Version:                           1 (current)
      OS/ABI:                            UNIX - System V
      ABI Version:                       0
      Type:                              EXEC (Executable file)
      Machine:                           Intel 80386
      Version:                           0x1
      Entry point address:               0x80482f0
      Start of program headers:          52 (bytes into file)
      Start of section headers:          3220 (bytes into file)
      Flags:                             0x0
      Size of this header:               52 (bytes)
      Size of program headers:           32 (bytes)
      Number of program headers:         7
      Size of section headers:           40 (bytes)
      Number of section headers:         36
      Section header string table index: 33
    

    lddは、このcプログラムがどのダイナミックライブラリにリンクされているかを表示するのに役立つコマンドです.
    user@computer:~$ ldd chello
        linux-gate.so.1 =>  (0xb7f77000)
        libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7e18000)
        /lib/ld-linux.so.2 (0xb7f78000)
    

    fileコマンドはこのファイルの基本情報を教えてくれます
    user@computer:~$ file chello
    chello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.8, dynamically linked (uses shared libs), not stripped
    

    fileコマンドが「not stripped」を返すのを見ました.つまり、このバイナリにはデバッグ用のシンボル情報が含まれています.stripコマンドを使用してダイエットをしましょう.
    user@computer:~$ strip -s chello
    user@computer:~$ strip -s chello
    

    ダイエットした后、今このバイナリの大きさは2984バイトになって、やはり受け入れることができなくて、难しい决定をする时、そこで私はCとprintfを放弃して、nasm x 86のアセンブリを使って、次はhelloです.asm:
            SECTION .data
    msg:	db "Hi World",10
    len:	equ $-msg
    
    	SECTION .text
    
            global main
    main:
    	mov	edx,len
    	mov	ecx,msg
    	mov	ebx,1
    	mov	eax,4
    
    	int	0x80
    	mov	ebx,0
    	mov	eax,1
    	int	0x80
    

    コンパイル
    user@computer:~$ nasm -f elf hello.asm
    user@computer:~$ gcc -o hello hello.o -nostartfiles -nostdlib -nodefaultlibs
    user@computer:~$ strip -s hello
    user@computer:~$ ./hello
    Hi World
    

    stripは770バイト、448バイトでしたが、このバイナリには無駄なヘッダとsection情報が含まれていました.今、あなたが一番簡単な16進エディタを探してこのバイナリを開きます.私は一般的にcurses hexeditorとghex 2を使っています.
    0 xADの後ろの内容を削除して、今大きさは173バイトになりました
    0 x 7の後ろに無駄な空間が見え、Hi World文字列を保存するすべてのデータブロックを0 x A 4-0 xACから0 x 7に移動し、0 x 86の文字列への参照を0 x A 4から新しいアドレス0 x 7に変更し、最後に0 x A 2と0 x A 3を削除する.
    ファイルサイズは164バイトになるはずですが、最終段階に入る時です.残りの部分は説明する必要があります.基本的には、ELFのヘッダを変えてみますが、segfault faultを避けて、jmpをたくさん追加して元の実行可能ファイルを完全に破壊しました.それでも実行できます.ここでは、x 86アセンブリの0 xD 9 D 0、すなわちnopオペレータについて、空白を埋める必要がある場合にこのコマンドが役立ちます.また、0 xEBの後ろにシンボルバイトが付いて相対ジャンプを完了する場合は、intel x 86のアセンブリコマンドドキュメントA-M N-Zを参照してください.
    view plain copy to clipboard print ?
    typedef struct {
  • unsigned char e_ident[EI_NIDENT];

  • Elf32_Half e_type;
  • Elf32_Half e_machine;

  • Elf32_Word e_version;
  • Elf32_Addr e_entry;

  • Elf32_Off e_phoff;
  • Elf32_Off e_shoff;

  • Elf32_Word e_flags;
  • Elf32_Half e_ehsize;

  • Elf32_Half e_phentsize;
  • Elf32_Half e_phnum;

  • Elf32_Half e_shentsize;
  • Elf32_Half e_shnum;

  • Elf32_Half e_shtrndx;
  • } Elf32_Ehdr;
  • typedef struct {
        unsigned char   e_ident[EI_NIDENT];
        Elf32_Half      e_type;
        Elf32_Half      e_machine;
        Elf32_Word      e_version;
        Elf32_Addr      e_entry;
        Elf32_Off       e_phoff;
        Elf32_Off       e_shoff;
        Elf32_Word      e_flags;
        Elf32_Half      e_ehsize;
        Elf32_Half      e_phentsize;
        Elf32_Half      e_phnum;
        Elf32_Half      e_shentsize;
        Elf32_Half      e_shnum;
        Elf32_Half      e_shtrndx;
    } Elf32_Ehdr;
    

    結論
    最終サイズ:142バイト
    helloworld.tar.gz
    もっと小さくする方法があると確信しています.頭から無駄なデータを取り除くことができるはずですが、ELFの頭のフォーマットを研究するのにあまり時間がかかりたくありません.もう一つの方法は、ELFの代わりにa.outフォーマットを使うかもしれません.
    もしあなたが意見があれば、提案したり批判したりして、私にメールを歓迎してください:henszey#gmail.com
    --------本稿は、「Smallest x 86 ELF Hello World」、著者:henszey