Linux/Linux_technic

Object file - ELF 파일

sosal 2009. 10. 23. 02:01
반응형
/*
 
http://sosal.tistory.com/
 * made by so_Sal
 */




ELF
:: Executable and Linking Format의 약자로,
       실행 가능한 바이너리 또는 오브젝트 파일 등의 형식을 규정한것

ELF 파일은 ELF 헤더가 반드시 맨 앞에 위치하고,
프로그램 헤더 테이블과 섹션 헤더 테이블이 그 뒤에 위치합니다.
헤더의 구조는 elf.h를 참조하세요.
  b
ELF에서 사용하는 자료형
elf 바이너리에는 32비트와 64비트, 두가지가 있습니다.

자료형 N = 32 N = 64   설명
ElfN_Half uint16_t uint16_t   부호 없는 16 비트 값
ElfN_Word uint32_t uint32_t  부호 없는 32 비트 값 
ElfN_Sword int32_t int32_t  부호 없는 32 비트 값
ElfN_Xword uint64_t uint64_t  부호 없는 64 비트 값 
ElfN_Sxword int64_t int64_t  부호 없는 64 비트 값
ElfN_Addr uint32_t uint64_t  주소 
ElfN_Off uint32_t uint64_t  offset
ElfN_Section uint16_t uint16_t  섹션 인덱스
ElfN_Versym uint16_t uint16_t  버전 심볼 정보


ELF 헤더

ELF 헤더는 ELF 파일 맨 앞에 반드시 존재하며, 그 파일이 존재하며, 그 파일이 ELF 파일임을 나타냅니다.

readelf :: Display information about ELF files.
이 명령어에 -h (--file-header 옵션)을 사용하여 헤더의 내용을 볼 수 있습니다.

readelf -h /bin/ls



ELF 헤더는 (/usr/include/sys.h) 아래와 같은 구조로 되어있습니다.

unsigned char e_ident[EI_NIDENT];       /*Magic number and other info */
ElfN_Half          e_type;                         /*Object file type */
ElfN_Half          e_machine;                   /* Architecture */
ElfN_Word        e_version;                     /* Object file version */
ElfN_Addr         e_entry;                        /* Entry point virtual address */
ElfN_Off            e_phoff;                        /* Program header table file offset */
ElfN_Off            e_shoff;                        /* Section headr table file offset */
ElfN_Word        e_flags;                         /* Processor-specific flags */
ElfN_Half          e_ehsize;                      /* ELF header size in bytes */
ElfN_Half          e_phentsize;                  /* Program header table entry size */
ElfN_Half          e_phnum;                      /* Program header entry count */
ElfN_Half          e_shentsize;                  /* Section header table entry size */
ElfN_Half          e_shnum;                      /* Sectino header table entry count */
ElfN_Half          shstrndx;                       /* Sectino header string table index */

차례대로 하나씩 보겠습니다.


e_ident ::
ELF의 magic number와 기타 정보를 갖고 있음 (첫 4바이트에 아래와 같은 매직넘버를 갖는다.)
| 0x7F | 0x45 | 0x4C | 0x46 | ==  \177ELF (위 bin/bash의 ELF 헤더 내용을 보면 똑같은 것을 알 수 있다.)
이 다음 바이트는 32비트인 경우, 64비트인 경우에 따라 ELFCLASS32(1), ELFCLASS64(2)가 된다.
다음 바이트는 엔디안을 나타내고, 리틀 엔디안 :: ELFDATA2LSB(1), 빅 엔디안 :: ELFDATA2MSB(2)
나머지 바이트는 ELF 버전과 OS, ABI 등의 정보를 1바이트씩 나타낸다.

e_type ::
 Type   Value  설명
 ET_REL       1   재배치 가능한 파일 
 ET_EXEC      2  실행 가능한 파일
 ET_DYN      3  공유 오브젝트 파일
 ET_CORE      4  코어 파일

e_machine :: Architecture value. EM_으로 시작하는 상수로 정의됨
e_version   :: ELF 버전을 나타낸다. 위 bin/bash 예에서는 EV_CURRENT(1)이다.
e_entry      :: ELF에서 실행 시작하는 가상 주소
e_ehsize   :: ELF 헤더 자체의 크기
e_phoff, e_phentsize, e_phnum :: e_phoff :: 헤더 테이블의 위치, 크기, 해더 갯수
e_shoff, e_shentsize, e_shnum :: 섹션 헤더 테이블 위치 ,크기, 갯수
e_shstrndx :: 섹션명의 스트링 테이블을 갖는 섹션 헤더 인덱스를 나타냄

프로그램 헤더

프로그램 헤더 테이블은 ELF 헤더의 e_phoff로 지정된 오프셋에서 시작하고
e_phentsize와(크기) e_phnum(헤더 갯수)로 정해진 크기를 갖는 테이블.
프로그램 헤더는 readelf의 -l 옵션 (--program-headers)으로 표시된다.

readelf -l /bin/ls


프로그램 헤더는 다음과 같은 구조를 갖는다.



p_type에는 아래와 같다.


 p_type    Value  설명 
 PT_LOAD      1  로드된 프로그램 세그먼트
 PT_DYNAMIC      2  동적 링크 정보
 PT_INTERP      3  프로그램 인터프리터
 PT_NOTE      4  추가 정보
 PT_PHDR      5  프로그램 헤더 테이블 자신
 PT_TLS      6  스레드 지역 저장소
 PT_GNU_EH_FRAME  0x6474e550  GNU .eh_frame_hdr 세그먼트
 PT_GNU_STACK  0x6474e551  스택 실행 가능성

Section to Segment mapping 이후에 서술되는 정보들은
Program Headers의 각 프로그램 헤더에 나타난 세그먼트에
메모리 범위를 포함하는 섹션명을 나열

program header : 와
section to segment mapping : 이 둘을 연결시키면 됩니다.
type      ::  section
PHDR    :: 00. no section
INTERP :: 01. .interp
LOAD    :: 02. .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version ..... 등등

섹션 헤더

섹션 헤더 테이블은 ELF 헤더의 e_shoff로 지정된 오프셋에서 시작
E_shentsize, e_shnum으로 크기와 갯수가 정해져 있는 테이블들
따라서 전체 테이블 크기는 E_shentsize * e_shnum

섹션 헤더는 readelf -S 옵션(--section-heades) 사용

-readelf -S /bin/ls

섹션 헤더는 다음과 같은 구조를 갖는다.

위 구조체 정보는 readelf -S 로 표시되는 Section Headers의 각 행에 해당합니다.
Section Headers : Name Type Addr Offset ... 등등에 저장되는 값들이
모두 Elf32_Shdr, Elf64_Shdr 구조체에 저장됩니다.
섹션명은 ELF 헤더의 e_shstrndx 섹션 스트링 테이블의 인덱스로 저장되어 있다.
위 그림에서 /bin/ls의 경우, e_shstrndx는 31이므로 31개의 섹션 헤더가 그 스트링 테이블을 갖는 섹션이 됨

마지막 e_shstrtab을 보면 offset이 0x016884이고 크기가 0x000119 바이트인 스트링 테이블(STRTAB)임을 알 수 있다.

Type 표
 섹션 타입  값   설명
 SHT_PROGBITS  1  프로그램 데이터
 SHT_STRTAB  2  심볼 테이블
 SHT_STRTAB  3  스트링 테이블
 SHT_RELA  4  재배치 엔트리
 SHT_HASH  5  심볼 해시 테이블
 SHT_DYNAMIC  6  동적 링크 정보
 SHT_NOTE  7  Notes (호환 체크정보)
 SHT_NOBITS  8  데이터 없는 부분
 SHT_REL  9  재배치 엔트리
 SHT_DYNSYM  11  동적링크의 심볼테이블
 SHT_INIT_ARRAY  14  생성자 배열 (.init) 
 SHT_FINI_ARRAY  15  소멸자 배열 (.fini)
 SHT_GNU_verdef  0x6ffffffd  버전 정의 섹션
 SHT_GNU_verneed   0x6ffffffe  필요한 버전 섹션
 SHT_GNU_versym  0x6fffffff  버전 심볼 테이블

스트링 테이블

스트링 테이블은 단순 문자열 리스트이다. /bin/ls의 경우 다음 섹션이 스트렝 테이블이다.


shstrtab의 offset은 0x016884, 크기는 0x000119 이므로, od를 사용하여 테이블을 확인하자.

od --skip-bytes 0x016884 --read-bytes 0x000119 -t x1z /bin/ls
위에 출력된 내용을 통하여 스트링 테이블을 알아낼 수 있다. (00의 위치)
따라서
.shstrtab의 index :: 1
.interp의    index :: 11
.note 의     index :: 19
등등...

심볼 테이블

심볼 테이블은 심볼과 그 값 등을 대응시키는 테이블이다.
/bin/ls의 경우 strip 되어 있으므로 동적 심볼 테이블만 있다.
readelf -s 옵션으로 볼 수 있다.
(이하 생략)

'.dynym' contains 118 entries: //dynsym(동적링크 심볼) 테이블들이 나열되고 있다.
이것을 ELF 헤더로부터 찾아보자.
섹션 헤더에서 dynsym이라는 심볼 테이블을 보면

offset은 1cc, 크기는 760이므로
1cc부터 760까지 보면 되겠다.
od --skip-bytes 0x1cc --read-bytes 760 -t x1z /bin/ls

'Linux > Linux_technic' 카테고리의 다른 글

Hackerschool Level11 Exploit  (0) 2010.01.10
strings - 의미 있는 문자열 dump  (0) 2009.11.08
od - 바이너리 파일 덤프  (0) 2009.10.23
File - 파일종류 확인  (0) 2009.10.22
커널 분석기 Vi + ctags + cscope  (4) 2009.10.01