2014-02-07 36 views
1

我試圖使用objcopy --writable-text executable_name來使elf二進制文件的.text部分可寫。該命令正常執行,沒有任何錯誤。Objcopy - 可寫文本不能使elf二進制文本段可寫?

在通過readelf檢查部分權限時,我可以看到文本部分仍然只具有讀取和執行權限。

在通過objcopy這個特定選項的手冊頁被提到,該選項對所有二進制格式都沒有意義。 (這是我無法這樣做的原因嗎?)。

任何人都可以指出我在這裏失蹤。

感謝

(Ubuntu的x86_64的位機,GNU objcopy命令(GNU Binutils的爲Ubuntu)2.22.90.20120924)

回答

1

在通過objcopy把手冊頁這個特殊的選項會被提到的是選項對所有的二進制格式都沒有意義。 (這是我無法這樣做的原因嗎?)。

是。

在這個rather detailed description of special sections the ELF format,你看到.textSHF_ALLOC + SHF_EXECINSTR屬性(有空間爲它分配和空間中有可執行代碼),而不是SHF_WRITE(空間可以寫入)。您所要求的objcopy只是簡單地對ELF .text部分無效。

1

在Debian我可以只是-N鏈接併產生具有可寫可執行的.text

這樣:LD-N obj.o

0

首先完成此: objcopy把--writable文本--set-section-flags .text = CONTENTS,ALLOC,LOAD,CODE

然後objdump -x或readelf -a查看通常在程序頭後的加載段表。請參閱ELF的手冊頁。對於32位可執行文件,例如:

用hexedit打開二進制文件並查看文件偏移量0x1C(通常爲0x34)處的值,然後遍歷0x20字節結構(文件偏移量爲0x2a處列出的大小),直到找到在前面轉儲中標識爲包含.text部分的那個。倒數第二個值爲00000005(05 00 00 00),需要添加寫入00000007(07 00 00 00)。現在它將按預期工作,沒有任何限制,例如與-Wl,omagic共享庫問題。有點技術性,但需要幾秒鐘的時間。

無論如何,這一位標誌已經造成了無數的問題,沒有任何解釋澄清了這一點,使它能夠完美地工作。

A碼的解決方案可以與GCC輕易地編譯,如果經常做它做這很可能是更容易的改變和更好的解決方案:

#include <stdlib.h> 
#include <stdio.h> 
#include <elf.h> 

int main(int argc, char** argv) 
{ 
    if (argc <= 1) return -1; 
    FILE* fp = fopen(argv[1], "r+"); 
    Elf64_Ehdr teh; 
    fread(&teh, sizeof(teh), 1, fp); 
    fseek(fp, 0, SEEK_SET); 
    if (teh.e_ident[EI_CLASS] == ELFCLASS64) { 
     Elf64_Ehdr eh; 
     fread(&eh, sizeof(eh), 1, fp); 
     Elf64_Phdr* ph = malloc(eh.e_phnum * eh.e_phentsize); 
     Elf64_Shdr* sh = malloc(eh.e_shnum * eh.e_shentsize); 
     fseek(fp, eh.e_phoff, SEEK_SET); 
     fread(ph, eh.e_phentsize, eh.e_phnum, fp); 
     fseek(fp, eh.e_shoff, SEEK_SET); 
     fread(sh, eh.e_shentsize, eh.e_shnum, fp); 
     for (int i = 0; i < eh.e_phnum; i++) { 
      if (ph[i].p_vaddr <= eh.e_entry && ph[i].p_vaddr + ph[i].p_memsz > eh.e_entry) { 
      fseek(fp, eh.e_phoff + i * eh.e_phentsize + (unsigned int)&((Elf64_Phdr*)0)->p_flags, SEEK_SET); 
      ph[i].p_flags |= PF_W; 
      fwrite(&ph[i].p_flags, sizeof(ph[i].p_flags), 1, fp); 
      } 
     } 
     for (int i = 0; i < eh.e_shnum; i++) { 
      if (sh[i].sh_addr <= eh.e_entry && sh[i].sh_addr + sh[i].sh_size > eh.e_entry) { 
      fseek(fp, eh.e_shoff + i * eh.e_shentsize + (unsigned int)&((Elf64_Shdr*)0)->sh_flags, SEEK_SET); 
      sh[i].sh_flags |= SHF_WRITE; 
      fwrite(&sh[i].sh_flags, sizeof(sh[i].sh_flags), 1, fp); 
      }  
     } 
     free(ph); 
     free(sh); 
    } else { 
     Elf32_Ehdr eh; 
     fread(&eh, sizeof(eh), 1, fp); 
     Elf32_Phdr* ph = malloc(eh.e_phnum * eh.e_phentsize); 
     Elf32_Shdr* sh = malloc(eh.e_shnum * eh.e_shentsize); 
     fseek(fp, eh.e_phoff, SEEK_SET); 
     fread(ph, eh.e_phentsize, eh.e_phnum, fp); 
     fseek(fp, eh.e_shoff, SEEK_SET); 
     fread(sh, eh.e_shentsize, eh.e_shnum, fp); 
     for (int i = 0; i < eh.e_phnum; i++) { 
      if (ph[i].p_vaddr <= eh.e_entry && ph[i].p_vaddr + ph[i].p_memsz > eh.e_entry) { 
      fseek(fp, eh.e_phoff + i * eh.e_phentsize + (unsigned int)&((Elf32_Phdr*)0)->p_flags, SEEK_SET); 
      ph[i].p_flags |= PF_W; 
      fwrite(&ph[i].p_flags, sizeof(ph[i].p_flags), 1, fp); 
      } 
     } 
     for (int i = 0; i < eh.e_shnum; i++) { 
      if (sh[i].sh_addr <= eh.e_entry && sh[i].sh_addr + sh[i].sh_size > eh.e_entry) { 
      fseek(fp, eh.e_shoff + i * eh.e_shentsize + (unsigned int)&((Elf32_Shdr*)0)->sh_flags, SEEK_SET); 
      sh[i].sh_flags |= SHF_WRITE; 
      fwrite(&sh[i].sh_flags, sizeof(sh[i].sh_flags), 1, fp); 
      }  
     } 
     free(ph); 
     free(sh); 
    } 
    fflush(fp); 
    fclose(fp); 
    return 0; 
} 
相關問題