2014-02-07 3 views
1

objcopy --writable-text executable_name을 사용하여 elf 바이너리의 .text 섹션을 쓰기 가능으로 만들려고했습니다. 명령은 정상적으로 오류없이 실행됩니다.Objcopy - 쓰기 가능 텍스트로 인해 elf 바이너리 텍스트 섹션이 쓰기 가능하지 않습니까?

readelf을 통해 섹션 권한을 확인하면 텍스트 섹션에 여전히 읽기 및 실행 권한 만 있음을 알 수 있습니다.

objcopy이 특정 옵션에 대한 매뉴얼 페이지는이 옵션이 모든 이진 형식에 의미가 없음을 언급합니다. (이것이 제가 그렇게 할 수없는 이유입니까?).

누구나 내가 누락 된 부분을 지적 할 수 있습니까?

감사

(우분투 x86_64의 비트 기계, GNU의 objcopy의 (우분투 GNU Binutils의) 2.22.90.20120924)이 특정 옵션에 대한 objcopy의 맨 페이지를 거치지에

답변

1

이 옵션이 언급되어있다 모든 바이너리 형식에는 의미가 없습니다. (이것이 제가 그렇게 할 수없는 이유입니까?).

예. 이 rather detailed description of special sections the ELF format에서

, 당신은 .textSHF_ALLOC + SHF_EXECINSTR 특성을가집니다 (공간이 그것을 위해 할당하고 공간이 거기에 실행 코드를 가지고) 볼 수 있지만 SHF_WRITE (공간에 기록 될 수 있습니다.) objcopy을 단순히 묻는 것은 ELF .text 섹션에는 유효하지 않습니다.

1

데비안에 내가 -N와 연결 만 할 수 있고 그 때문에

는 .text 쓰기 가능한을 가진 실행 파일을 생성합니다 LD -N obj.o

0

먼저이 완료 objcopy의 --writable 텍스트를 --set-section-flags .text = CONTENTS, ALLOC, LOAD, CODE

그런 다음 objdump -x 또는 readelf -a를 사용하여 일반적으로 프로그램 헤더 뒤의로드 섹션 테이블을 봅니다. ELF 매뉴얼 페이지를 참조하십시오.

hexedit를 사용하여 이진 파일을 열고 파일 오프셋 0x1C (종종 0x34)에서 값을 확인한 다음 찾을 때까지 0x20 바이트 구조 (파일 오프셋 0x2a에 나열된 크기)를 탐색합니다. 이전 덤프에서 .text 섹션을 포함하는 것으로 식별 한 파일. 마지막 두 번째 값은 00000005 (05 00 00 00)가되며 쓰기가 추가되어야 00000007 (07 00 00 00)이됩니다. 이제는 -Wl, - omagic의 공유 라이브러리 문제와 같은 제한없이 예상대로 작동합니다. 조금 기술적이지만, 몇 초가 걸립니다.

이 1 비트 플래그는 수많은 문제를 일으켰으며 아무런 설명없이이 작은 점이 완벽하게 작동합니다.

코드 솔루션을 쉽게 일상적으로 그 일을하면 가능성이 쉽게 변화와 더 나은 솔루션을 수행하는 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; 
}