ELF 기초 공부중

2017. 12. 5. 00:260x03 Reversing Theory

728x90


기초 공부 중이기 때문에 다른 사람들의 블로그들을 참고하고, 이해하기 위해 적어보고 있습니다. 중간중간에 사전적 정의부분이 아닌 부분에 의해서는 직접 생각해보고 느낀것들에 대해서도 명시할 것입니다.



ELF : Executable and Linkable Format 


ELF는 Unix, Linux 계열에서 실행 가능한 오브젝트 파일을 규정한 것이라고 한다.


PE와 똑같이 실행에 필요한 기계어, 심볼 테이블, 디버그 정보, 재배치 정보등을 저장하고 있다. 


ELF 파일은 머리부분인 ELF Header가 가장 앞부분에 위치하게 되고, 그 다음 순서대로 Program Header Table, Section Header Table이 존재하게 된다.


이러한 헤더들의 정보를 자세히 알고 싶으면 elf.h에서 확인할 수 있다고 한다.


[ELF 헤더 구조체]

typedef struct EIF32_EHDR

{


   unsigned char e_ident[EI_NIDENT]; 

   // File Signature and other info 


   Elf32_Half   e_type; 

   // Object file type


   Elf32_Half   e_machine;

   // Architecture


   Elf32_Word  e_version;

   // Object file version


   Elf32_Addr e_entry;

   // Entry point virtual address


   Elf32_Off   e_phoff;

   // Program header table file offset


   Elf32_Off   e_shoff;

   // Section header table file offset


   Elf32_Word   e_flags;

   // Processor-specifie flags


   Elf32_Half    e_ehsize;

   // ELF header size in bytes


   Elf32_Half    e_phentsize;

   // Program header table entry size


   Elf32_Half   e_shentsize;

   // Section header table entry size


   Elf32_Half   e_shnum;

   // Section header table entry count


   Elf32_Half   e_shstrndx;

   // Section header string table index


} Elf32_Ehdr;



리눅스 상에서 readelf -h 명령과 옵션을 부과하면 ELF Header를 터미널창에서 들여다볼 수 있게 된다.


ELF 헤더는 Segment -> Section 단위로 이렇게 나누어진다.


[ELF 프로그램 헤더]

typedef struct ELF32_PROGRAM_HEADER

{

  

  Elf32_Word   p_type;

  // Segment type

  

  Elf32_Off      p_offset;

  // Segment file offset


  Elf32_Addr   p_vaddr;

  // Segment virtual address  


  Elf32_Word   p_paddr;

  // Segment physical address

  

  Elf32_Word   p_filesz;

  // Segment szie in file 


  Elf32_Word   p_memsz;

  // Segment size in memory


  Elf32_Word   p_align;

  // Segment alignment


} Elf32_Phdr;



이 말은 단일 Segment를 Section 단위로 세부적으로 나눈다는 말과 같다.


Segment에 대한 정보는 Program Header Table에 저장 

Section에 대한 정보는 Section Header Table에 저장 되어 있다고 한다.


Section은 Section Header Table이라 쉽게 테이블 명이 연관이 되는데 

Segment는 Program Header Table이니까 조심해서 이해하도록 하자.


ELF의 파일시그니처는 7F 45 4C 46


헤더에서 알 수 있는 점은 Endian, Version, OS의 정보, 파일 타입, Program Header, Section Header에 대한 정보, Entrypoint, String Table 들의 인덱스가 명시되어 있다고 한다.


윈도우즈 PE에서 실행가능파일이 EXE이지만 ELF는 EXEC 


재배치 가능파일 : REL

공유 오브젝트 파일 : DYN

코어파일 CORE 로 나뉘어져 있다고 한다.


ELF Header를 읽은 후 각 부분의 offset과 size를 가지고 파일을 실행해 나갈 수 있다.

윈도우즈 파일과 마찬가지로 ELF 역시 파일포인터가 제공되는 것을 알 수 있다.

파일포인터가 제공되기 때문에 OFFSET 값으로 트레이싱이 가능하다.


Program Header의 요소를 살펴보면 Segment의 데이터가 쓰여져 있는 파일 위치, 실제 메모리에 적재되는 주소, 크기 그리고 접근 권한 등에 대한 정보도 저장이 되어있다. 프로그램 헤더 테이블 (PHDR) 프로그램 인터프리터(INTERP), 메모리에 적재되는 세그먼트 LOAD, 동적 링크 정보 DYNAMIC, 프로그램 추가 정보 NOTE 등으로 나누어지게 된다. 

왠지 모르게 중요해보이는 문장은 "NOTE 세그먼트는 프로그램의 실행에 지장을 주지 않는다"는 것이다. NOTE하면 필기를 생각할 수 있고 필기를 하면 프로그래밍에서는 주석을 생각할 수가 있다. 하지만 여기서는 프로그램의 추가적인 정보를 NOTE라고 표현한다. 추가적인 정보 역시 실행에는 지장이 없다는 것을 알 수가 있다.



[ELF Segment Header]

typedef struct ELF32_SEGMENT_HEADER

{

 

  Elf32_Word     sh_name; 

  // Section name


  Elf32_Word     sh_type;

  // Section type


  Elf32_Word     sh_flags;

  // Section flags


  Elf32_Addr      sh_addr;

  // Section virtual addr at execution


  Elf32_Off        sh_offset;

  // Section file offset


  Elf32_Word     sh_size;

  // Section size in bytes


  Elf32_Word     sh_link;

  // Link to another section


  Elf32_Word     sh_addralign;

  // Section alignment


  Elf32_Word    sh_entsize;

  // Entry size if section holds table


} Elf32_Shdr; 


Section의 이름과 종류, 적재되는 주소, 파일 내 오프셋, 크기 그리고 성격등이 명시되어 있다. 


FLG라는 옵션이 있는데 이는 Section의 특징 중 메모리 할당 여부, 실행 여부, rw여부 등을 볼 수 있다. 


Type은 프로그램 데이터(PROGBITS), 심볼 테이블(SYMTAB), 스트링 테이블(STRTAB), 재배치 엔트리(REL), 심볼 해시 테이블(HASH), 동적링크정보(DYNAMIC), 프로그램추가정보(NOTE), 데이터가 없는(NOBITS), 동적링크용심볼테이블(DYNSYM)이 있다.


Section Header에는 이 뿐만 아니라 프로그램 정보 저장(Symbol Talbe), 문자열 정보 저장(Stirng Table)이 존재한다.



적어두었으니 수시로 보면서 개념을 익힙시다.