2013-12-10 29 views
2

ELF文件是靜態鏈接我可以將所有部分「Objdump -S -d elf-file」生成爲可重新組合的文件嗎?

而目前objdump的輸出是一樣的東西:

Disassembly of section: .init: 

xxxxxx 

Disassembly of section: .plt: 

xxxxxx 

Disassembly of section: .text: 

xxxxxx 

基本上是我想要實現的是

「ELF文件 - (通過objdump的反彙編) - >彙編文件 - (重新編譯) - >相同的功能

我不需要重新編譯的二進制具有與原來的二進制內容相同,只有功能相同就夠了。

快速搜索後,基本上答案是沒有,他們認爲,拆機文件丟失了一些東西,如符號信息或其他人,但我想用靜態鏈接,我可以擺脫這個問題.. 。

謝謝!

回答

5

objdump -S -d elf-file通常並不足夠,因爲它缺少.data部分。

但似乎objdump -S -D elf-file就足夠了。

爲了試試這個,我寫了一個小的x86-64彙編文件,它使用extern printf,與YASM彙編而沒有調試符號,並與GCC鏈接。

 
[bits 64] 

; yasm -f elf64 -m amd64 1st_generation.asm -o 1st_generation.o; gcc -o 1st_generation 1st_generation.o 

section .text 
global main 
extern printf 

main: 
    push rbp 
    mov  rbp,rsp 
    lea  rdi,[msg] 
    mov  rsi,[num] 
    xor  eax,eax 
    call printf 
    mov  eax,60 
    xor  ebx,ebx 
    syscall 

section .data 

msg db 'abcdef = %d', 0xa, 0 
num dd 1337 

testmsg1: 
db "test 01", 0x0a, 0 

然後我用objdump -S -D -M intel elf-file >objdump_output.txt拆開它。 -M intel產生英特爾格式的反彙編。 AT & T也可以工作,但爲了清晰起見,我更喜歡英特爾格式。

然後我寫了一個小的gawk程序objdump_to_asmobjdump -S -D -M intel elf-file >objdump_output.txt產生的拆卸轉換成YASM的合適格式。假定x86-64代碼和main作爲入口點。可以很容易地編輯到不同類型的環境(x86是微不足道的,其他可能需要更多的工作)。用法./objdump_to_asm objdump_output.txt。有趣的是,第一代可執行文件的大小爲6598字節,而第二代可執行文件的大小僅爲6496字節。第三代彙編代碼與第二代彙編代碼相同。

下面的代碼:

#!/usr/bin/awk -f 
BEGIN{ 
    disassembly_of_section_string = "Disassembly of section "; 

    sections_to_discard[1] = ".interp"; 
    sections_to_discard[2] = ".note.ABI-tag"; 
    sections_to_discard[3] = ".note.gnu.build-id"; 
    sections_to_discard[4] = ".dynsym"; 
    sections_to_discard[5] = ".dynstr"; 
    sections_to_discard[6] = ".hash"; 
    sections_to_discard[7] = ".gnu.hash"; 
    sections_to_discard[8] = ".gnu.version"; 
    sections_to_discard[9] = ".gnu.version_r"; 
    sections_to_discard[10] = ".rela.dyn"; 
    sections_to_discard[11] = ".rela.init"; 
    sections_to_discard[12] = ".eh_frame"; 
    sections_to_discard[13] = ".dynamic"; 
    sections_to_discard[14] = ".got"; 
    sections_to_discard[15] = ".got.plt"; 
    sections_to_discard[16] = ".jcr"; 
    sections_to_discard[17] = ".init_array"; 
    sections_to_discard[18] = ".comment"; 
    sections_to_discard[19] = ".note.gnu.gold-version"; 

    number_of_sections_to_discard = length(sections_to_discard); 

    sections_to_handle[1] = ".plt"; 
    sections_to_handle[2] = ".text"; 
    sections_to_handle[3] = ".data"; 
    sections_to_handle[4] = ".bss"; 

    number_of_sections_to_handle = length(sections_to_handle); 

    blocks_to_discard_in_text[1] = "<call_gmon_start>:"; 
    blocks_to_discard_in_text[2] = "<deregister_tm_clones>:"; 
    blocks_to_discard_in_text[3] = "<register_tm_clones>:"; 
    blocks_to_discard_in_text[4] = "<__do_global_dtors_aux>:"; 
    blocks_to_discard_in_text[5] = "<frame_dummy>:" 
    blocks_to_discard_in_text[6] = "<__libc_csu_fini>:" 
    blocks_to_discard_in_text[7] = "<__libc_csu_init>:" 
    blocks_to_discard_in_text[8] = "<_start>:"; # !!! 

    number_of_blocks_to_discard_in_text = length(blocks_to_discard_in_text); 

    blocks_to_handle_in_text[1] = "main" 

    number_of_blocks_to_handle_in_text = length(blocks_to_handle_in_text); 

    blocks_to_handle_in_data[1] = "__dso_handle" 

    number_of_blocks_to_handle_in_data = length(blocks_to_handle_in_data); 

    externs_to_handle[1] = "printf"; 

    number_of_externs_to_handle = length(externs_to_handle); 

    hexdump_start_byte = 11; 
    disassembly_start_byte = 33; 

    current_section = ""; 

    getline; 
    getline; 

    file_format_index = match($0, "file format elf64-x86-64") 
    if (file_format_index > 0) 
    { 
     print "[bits 64]"; 
    } 
} 
{ 
    match_index = 0; # 0 : no match, > 0 : match. 
    i = 1;   # index to sections_to_handle . 
    while (i <= number_of_sections_to_handle) 
    { 
     match_index = match($0, (disassembly_of_section_string sections_to_handle[i])); 
     if (match_index > 0) # we have a section to handle. 
     { 
      current_section = sections_to_handle[i]; 
      getline; 
      break; 
     } 
     i++; 
    } 

    match_index = 0; # 0 : no match, > 0 : match. 
    i = 1;   # index to sections_to_discard . 
    while (i <= number_of_sections_to_discard) 
    { 
     match_index = match($0, (disassembly_of_section_string sections_to_discard[i])); 
     if (match_index > 0) # we have a section to discard. 
     { 
      current_section = sections_to_discard[i]; 
      getline; 
      break; 
     } 
     i++; 
    } 

    if (match (current_section, ".plt")) 
    { 
     match_index = 0; # 0 : no match, > 0 : match. 
     i = 1;   # index to externs_to_handle. 

     while (i <= number_of_externs_to_handle) 
     { 
      match_index = match($0, ("<" externs_to_handle[i] "@plt>:")); 

      if (match_index > 0) # we have an extern to handle. 
      { 
       print "extern " externs_to_handle[i]; 
       getline; 
       break; 
      } 
      i++; 
     } 
    } 
    if (match (current_section, ".text")) 
    { 
     match_index = 0; # 0 : no match, > 0 : match. 
     i = 1;   # index to the blocks of section .text . 

     while (i <= number_of_blocks_to_handle_in_text) 
     { 
      match_index = match($0, ("<" blocks_to_handle_in_text[i] ">:")); 

      if (match_index > 0) # we have a block to handle. 
      { 
       print "section .text"; 
       print "global main"; 
       print blocks_to_handle_in_text[i] ":"; 
       getline; 

       while ((length ($0)) > 0) 
       { 
        disassembly_without_hex_bytes = substr($0, disassembly_start_byte); 
        disassembly_without_hex_bytes = gensub(/PTR /, "", "g", disassembly_without_hex_bytes); 
        disassembly_without_hex_bytes = gensub(/(ds:)([a-z0-9]*)/, "[\\2]", "g", disassembly_without_hex_bytes); 

        match_index = 0; # 0 : no match, > 0 : match. 
        j = 1;   # index to externs to handle. 

        while (j <= number_of_externs_to_handle) 
        { 
         match_index = match(disassembly_without_hex_bytes, ("<" externs_to_handle[i] "@plt>")); 

         if (match_index > 0) # we have an extern to handle. 
         { 
          current_extern_to_handle = externs_to_handle[j]; 
          "echo '" disassembly_without_hex_bytes "' | sed 's/\\([0-9]*\\)\\(<\\)\\(" current_extern_to_handle "\\)\\(@plt>\\)/\\3/g'" |& getline disassembly_without_hex_bytes; 
          close("echo '" disassembly_without_hex_bytes "' | sed 's/\\([0-9]*\\)\\(<\\)\\(" current_extern_to_handle "\\)\\(@plt>\\)/\\3/g'"); 
          break; 
         } 
         j++; 
        } 

        if (match(disassembly_without_hex_bytes, "data32") != 1) 
        { 
         print disassembly_without_hex_bytes; 
        } 
        getline; 
       } 
       break; 
      } 
      i++; 
     } 
    } 

    if (match (current_section, ".data")) 
    { 
     match_index = 0; # 0 : no match, > 0 : match. 
     i = 1;   # index to the blocks of section .data . 

     while (i <= number_of_blocks_to_handle_in_data) 
     { 
      match_index = match($0, ("<" blocks_to_handle_in_data[i] ">:")); 

      if (match_index > 0) # we have a block to handle. 
      { 
       print "section .data"; 
       getline; 

       while ((length ($0)) > 0) 
       { 
        getline; 
        hexdump_only = substr($0, hexdump_start_byte, (disassembly_start_byte - hexdump_start_byte)); 
        hexdump_only = gensub(/([[:alnum:]]+)/, "0x\\1", "g", hexdump_only); 
        hexdump_only = gensub(/(0x[[:alnum:]]+)()(0x[[:alnum:]]+)/, "\\1, \\3", "g", hexdump_only); 
        hexdump_only = gensub(/(0x[[:alnum:]]+)()(0x[[:alnum:]]+)/, "\\1, \\3", "g", hexdump_only); 
        if (match (hexdump_only, "0x") > 0) 
        { 
         print "db " hexdump_only; 
        } 
       } 
       break; 
      } 
      i++; 
     } 
    } 
} 

執行./objdump_to_asm objdump_output.txt >2nd_generation.asm產生以下彙編文件。與YASM組裝,與GCC鏈接。彙編和鏈接的可執行文件與原始文件不完全相同,實際上它是6496字節,而原始可執行文件的大小爲6568字節。

 
[bits 64] 
extern printf 
section .text 
global main 
main: 
push rbp 
mov rbp,rsp 
lea rdi,[0x401958] 

mov rsi,QWORD [0x401965] 

xor eax,eax 
call printf 
mov eax,0x3c 
xor ebx,ebx 
syscall 

section .data 
db 0x61      
db 0x62      
db 0x63, 0x64, 0x65, 0x66   
db 0x20, 0x3d, 0x20, 0x25, 0x64, 0x0a  
db 0x00, 0x39     
db 0x05, 0x00, 0x00, 0x74, 0x65   
db 0x73, 0x74     
db 0x20, 0x30     
db 0x31, 0x0a     
db 0x00, 0x00     
+0

這很棒!謝謝你nrz! – computereasy

+0

@computereasy不客氣。 – nrz

1

可能需要至少一些「中間階段」才能使reloc-info進入彙編程序接受的形式。我所看到的(Linux),代碼部分(內部)鏈接,然後標籤信息由reloc info取代。

你可以看到它們跳轉到跳轉指令本身,並在加載時將reloc信息發送到跳轉目標地址。

相關問題