♧ ELF :: Executable and Linking Format 의 약자로, 실행 가능한 바이너리 또는 오브젝트 파일 등의 형식을 규정한 것. |
▷ ELF 파일은 ELF헤더가 맨 앞에 위치.
▷ 프로그램 헤더 테이블과 섹션 헤더 테이블이 그 뒤에 위치.
▷ 이러한 헤더의 구조는 elf.h 참조
:: ELF 에서 사용하는 자료형 |
||||||||||||||||||||||||||||||||||||||||
▷ ELF 바이너리에는 32bit와 64비트, 두 가지가 있다.
|
:: [ ELF 헤더 ] readelf 의 -h옵션 (--file-header) |
|||||||||||||||
▷ ELF헤더는 ELF파일 맨 앞에 반드시 존재하며, 그 파일이 ELF 파일임을 나타냄.
[ ELF헤더 구조 ] (/usr/include/elf.h)
▷ e_ident:: ELF의 매직 넘버(MAGIC NUMBER)와 기타 정보를 갖고 있다. ELF 파일은 첫 4바이트에 다음과 같은 매직 넘버를 갖는다 | 0x7F | 0x45 | 0x4c | 0x46 | → "\177ELF"가 된다. 그 다음 바이트는 32비트인 경우 ELFCLASS32(1), 64바이트인 경우 ELFCLASS(2)가 된다. 다음 바이트는 엔디안을 나타냄.(리틀 엔디안인=ELFDATA2LSB(1),빅 엔디안인=ELFDATA2MSB(2)) 나머지 바이트는 ELF버전과 OS, ABI 등의 정보를 1바이트씩을 사용해 나타냄.
▷ e_type:: 다음 타입 중 하나를 나타낸다.
▷ e_machine:: 아키텍처 타입을 타나낸다. (EM_으로 시작하는 상수로 정의되어 있음.) ▷ e_version:: ELF 버전을 나타낸다. (위 예(/bin/ls)는 EV_CURRENT(1)이다) ▷ e_entry:: 이 ELF에서 실행 시작하는 가상 주소. ▷ e_ehsize:: ELF 헤더 자체의 크기. ▷ e_phoff, e_phentsize, e_phnum:: 프로그램 헤더 테이블의 위치, 크기, 헤더 개수. ▷ e_shoff, e_shentsize, e_shnum:: 섹션 헤더 테이블의 위치, 크기, 개수. ▷ e_shstrndx:: 섹션명의 스트링 테이블을 갖는 섹션 헤더 인덱스를 나타냄. |
:: [ 프로그램 헤더 ] readelf의 -l 옵션 (--program-headers) |
|||||||||||||||||||||||||||||||||||||||
▷ 프로그램 헤더 테이블은 ELF 헤더의 e_phoff로 지정된 오프셋에서 시작. ▷ e_phentsize(헤더크기)와 e_phnum(프로그램 헤더 개수)으로 정해진 크기를 갖는 테이블. (※ 즉, 프로그램 헤더 테이블의 전체 크기 = e_phentsize * e_phnum)
[ 프로그램 헤더 구조 ]
▷ 『Program Headers:』의 각 행에 해당. ▷ p_type:: 다음과 같다.
▷ 『Section to Segment mapping:』 이후의 행에 나타난 정보는 『Program Headers:』의 각 프로그램 헤더에 나타난 세그먼트에 그 세그먼트 메모리 범위를 포함하는 섹션명을 나열하고 있다.
(인덱스 00) 프로그램 헤더에 표시된 세그먼트는 PHDR 타입이고 그에 속하는 섹션은 없다. (인덱스 01) 프로그램 헤더에 표시된 세그먼트는 INTERP 타입이고 그에 속하는 섹션은 .interp가 있다. (인덱스 02) 프로그램 헤더에 표시된 세그먼트는 LOAD 타입이고 그 안에는 .interp, .note.ABI-tag, ...등등 ▷ 『Section to Segment mapping:』 ↔ 『Program Headers:』 이 둘을 연결해서 봄.
|
:: [ 섹션 헤더 ] readelf의 -S 옵션 (--section-headers) |
||||||||||||||||||||||||||||||||||||||||||||||||
▷ 섹션 헤더 테이블은 ELF 헤더의 e_shoff로 지정된 오프셋에서 시작. ▷ e_shentsize(섹션 헤더 크기)와 e_shnum(섹션 헤더 개수)으로 정해진 크기를 갖는 테이블. (※ 즉, 섹션 헤더 테이블의 전체 크기 = e_shentsize * e_shnum)
[ 섹션 헤더 구조 ]
▷ 『Section Headers:』의 각 행에 해당. ▷ 섹션명(Section name)은 ELF 헤더의 e_shstrndx로 지정된 섹션에 포함된 스트링 테이블의 인덱스로 지정. ▷ 위의 /bin/ls 예의 경우, e_shstrndx는 28이므로, 28번째 섹션 헤더가 그 스트링 테이블을 갖는 섹션이 된다.
- sh_offset이 '0x0192d4' 이고, 크기가 '0x0000f2' 바이트인 스트링 테이블(STRTAB)임을 알 수 있다.
▷ 섹션 타입(sh_type):
|
:: [ 스트링 테이블 ] |
||||||||
▷ 스트링 테이블은 단순한 문자열 리스트이다. ▷ /bin/ls의 경우 다음 섹션이 스트링 테이블이다.
▷ 예를 들어 [28] .shstrtab의 오프셋은 '0x0192d4', 크기는 '0xf2'이므로 od를 사용하여 테이블을 확인하자. # od --skip-bytes 0x192d4 --read-bytes 0xf2 -t x1z /bin/ls
▷ 이 경우 스트링 테이블은 다음과 같이 되어 있다.
즉, .shstrtab의 맨 앞부터의 오프셋이 스트링 테이블의 인섹스가 된다. |
:: [ 심볼 테이블 ] readelf의 -s 옵션 (--syms) |
|||||||||||||||||||||||||||||||||||||||||||||
▷ 심볼 테이블은 심볼과 그 값 등을 대응시키는 테이블이다. ▷ /bin/ls의 경우 strip되어 있으므로 동적 심볼 테이블만 있다.
...(중략)... ▷ 이를 ELF 헤더로부터 찾아 보자. 우선 섹션 헤더에서 .dynsym이라는 심볼 테이블이 있다는 것을 알 수 있다.
▷ 덤프해 보면 다음과 같다.
...(중략)... ▷ 심볼 테이블은 다음과 같은 구조 테이블이다. 32비트와 64비트 ELF 바이너리에서는 st_value의 정렬 순서에 따라 변한다.
▷ st_name=스트링 테이블의 인덱스, st_value=심볼 값, st_size=심볼크기. ▷ st_info의 하위 4비트는 심볼 테이블 등의 정보로 다음과 같은 것이 있다.
▷ 또한 st_info의 상위 4비트는 그 심볼의 바인딩 방법을 타나낸다.
▷ st_shndx는 관련된 섹션을 나타낸다.
▷ /bin/ls의 예를 보자. 0번째 심볼 정보는 다음과 같이 비어 있다.
▷ /bin/ls의 위의 예에서 맨 마지막에 있는 심볼 정보를 알아 보자.
주소 0006104 부터 시작하는 이 바이트 열은 다음과 같은 의미를 갖는다. ( ※ 아키텍처(x86) 리틀 엔디안 이기 때문에 반대로 읽는다) st_name = 0x2db st_value = 0x08061320 st_size = 0x4 st_intfo = 0x11 = (STB_GLOBAL | STT_OBJECT) st_other = 0 st_shndx = 0x1a = 26
▷ 여기서 심볼명을 가리키는 오프셋 값 st_name은 '0x2db'로 되어 있다. .dynstr 섹션을 보면 스트링 테이블은 시작 위치로부터 '0xc54' 바이트 떨어진 위치에서 시작한다.
- 여기서 '0xc54'에 0x2db(st_name)를 더한 값인 '0xf2f' 위치에서 시작하는 문자열을 보면, ' optarg'라는 문자열을 찾을 수 있다.
- 이와 같이 st_name = '0x2db'에 해당하는 심볼은 'optarg'임을 알 수 있다.
▷ 이는 readelf -s 출력 결과에서 위의 심볼 정보를 확인 할 수 있다.
|
:: [ 재배치 정보 ] |
▷ SHT_RELA 또는 SHT_REL 타입의 섹션은 재배치 정보를 갖는다. ▷ SHT_RELA는 다음과 같은 Rela 구조의 테이블을 갖는다.
▷ SHT_REL의 경우는 다음과 같이 r_addend가 없는 Rel 구조의 테이블을 갖는다.
▷ r_offset은 재배치를 해야 하는 위치를 가리키는, 섹션 첫 위치로부터의 오프셋이다. ▷ r_info는 재배치 타입 또는 심볼테이블의 인덱스 등의 정보를 포함한다. ▷ Rela의 경우 재배치할 경우에 항상 더해야 할 값을 r_addend로 갖고 있다. |
'컴퓨터 서적 정리 > Binary Hacks' 카테고리의 다른 글
[Hack #7] ldd - 공유 라이브러리 의존관계 확인 (0) | 2011.07.02 |
---|---|
[Hack #6] 정적 라이브러리와 공유 라이브러리 (1) | 2011.07.02 |
[Hack #4] od - 바이너리 파일 덤프 (0) | 2011.06.29 |
[Hack #3] file – 파일 종류 확인 (1) | 2011.06.29 |
[Hack #2] Binary Hack 용어 정리 (1) | 2011.06.29 |