반응형
/*
* http://sosal.tistory.com/
* made by so_Sal
*/
ELF :: Executable and Linking Format의 약자로,
실행 가능한 바이너리 또는 오브젝트 파일 등의 형식을 규정한것
ELF 파일은 ELF 헤더가 반드시 맨 앞에 위치하고,
프로그램 헤더 테이블과 섹션 헤더 테이블이 그 뒤에 위치합니다.
헤더의 구조는 elf.h를 참조하세요.
b
ELF에서 사용하는 자료형
elf 바이너리에는 32비트와 64비트, 두가지가 있습니다.
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 ::
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에는 아래와 같다.
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 표
스트링 테이블
스트링 테이블은 단순 문자열 리스트이다. /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
* 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 |