ELF header 에 대한 고찰
ELF header 살펴보기
Introduction
Android 네이티브 바이너리를 분석해보면서 ELF Malware 에서는 UPX-DEC 의 실행압축이 적용된 바이너리들이 있다. 이때 자세히 살펴본 elf file (header) format layout 을 정리해본다.
hex 에서 보면 64 비트 elf 에 대한 헤더는 아래와 같다.
1
2
3
4
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0300 b700 0100 0000 0000 0000 0000 0000 ................
00000020: 4000 0000 0000 0000 7043 0000 0000 0000 @.......pC......
00000030: 0000 0000 4000 3800 0900 4000 1900 1800 ....@.8...@.....
32 비트 elf 에 대한 헤더는 아래와 같다.
1
2
3
4
00000000: 7f45 4c46 0101 0100 0000 0000 0000 0000 .ELF............
00000010: 0300 0300 0100 0000 0000 0000 3400 0000 ............4...
00000020: 8c46 0000 0000 0000 3400 2000 0a00 2800 .F......4. ...(.
00000030: 1900 1800 ....
비슷해보이지만 64 bit 는 0x40 32 bit 는 0x34 크기로 총 12 bytes 의 차이가 있다.
그러면 하나하나 보면서 어디가 어떻게 다른지 살펴보며 헤더 파일을 정리해보겠다.
ELF header
elf_header:40h/34h struct The main elf header basically tells us where everything is located in the file.
32 bit 에서는 0x34, 64 bit 에서는 0x40 의 크기를 가지고 있다.
모든 항목은
항목이름:사이즈(hex)
로 표기하였다.
e_ident
1
e_ident:10h
ELF 객체를 식별하는 16바이트 배열이며, 항상 “\x7fELF”로 시작한다. 파일 매직 이외 다른 정보도 포함하고 있다.
file_identification[]
1
file_identification[4]:4h
\x7fELF
라는 고정된 시그니처를 가지고 있다.
ei_class_2
1
ei_class_2:1h
64 bit 인지 32 bit 인지 확인할 수 있다.
ei_data
1
ei_data:1h
BE 과 LE 를 구분하기 위한 방식.
ei_version
1
ei_version:1h
ELF 파일 형식의 버전 번호.
ei_osabi
1
ei_osabi:1h
파일을 사용할 수 있는 운영체제에 대한 정보.
ei_abiversion
1
ei_abiversion:1h
ELF 파일을 실행할 수 있는 API 버전.
ei_pad[]
1
ei_pad[6]:6h
패딩 비트.
ei_nident_SIZE
1
ei_nident_SIZE:1h
추가적인 정보가 없지만 1 Bytes 를 차지하고 있다.
e_type
1
e_type:2h
ELF 유형을 지정.
e_machine
1
e_machine:2h
타겟 아키텍처.
e_version
1
e_version:4h
ELF 파일 버전.
아키텍쳐에서 다른 부분 (e_entry, e_phoff, e_shoff)
이 부분에서 64 bit 와 32 bit 간 차이가 있다. 64 bit 에서는 3가지 항목 필드가 각각 0x8 이지만 32 bit 에서는 0x4 이다.
따라서 3가지 항목 크기 차이는 0x4 * 3 = 0xC (12 bytes), 64 bit 헤더 크기(0x40) - 32 bit 헤더 크기(0x34) = 0xC 이다.
64 bit
e_entry_START_ADDRESS
1
e_entry_START_ADDRESS:8h
진입점 주소.
e_phoff_PROGRAM_HEADER_OFFSET_IN_FILE
1
e_phoff_PROGRAM_HEADER_OFFSET_IN_FILE:8h
Program header 오프셋.
e_shoff_SECTION_HEADER_OFFSET_IN_FILE
1
e_shoff_SECTION_HEADER_OFFSET_IN_FILE:8h
Section header 오프셋.
32 bit
e_entry_START_ADDRESS
1
e_entry_START_ADDRESS:4h
진입점 주소.
e_phoff_PROGRAM_HEADER_OFFSET_IN_FILE
1
e_phoff_PROGRAM_HEADER_OFFSET_IN_FILE:4h
Program header 오프셋.
e_shoff_SECTION_HEADER_OFFSET_IN_FILE
1
e_shoff_SECTION_HEADER_OFFSET_IN_FILE:4h
Section header 오프셋.
e_flags
1
e_flags:4h
프로세서별 플래그.
e_ehsize_ELF_HEADER_SIZE
1
e_ehsize_ELF_HEADER_SIZE:2h
e_ehsizeEHDR 크기(바이트), 일반적으로 64비트 ELF에서는 64바이트, 32비트에서는 52바이트.
e_phentsize_PROGRAM_HEADER_ENTRY_SIZE_IN_FILE
1
e_phentsize_PROGRAM_HEADER_ENTRY_SIZE_IN_FILE:2h
프로그램 헤더 학위 항목 크기.
e_phnum_NUMBER_OF_PROGRAM_HEADER_ENTRIES
1
e_phnum_NUMBER_OF_PROGRAM_HEADER_ENTRIES:2h
프로그램 헤더 학위 항목 갯수.
e_shentsize_SECTION_HEADER_ENTRY_SIZE
1
e_shentsize_SECTION_HEADER_ENTRY_SIZE:2h
Section header 엔트리 크기.
e_shnum_NUMBER_OF_SECTION_HEADER_ENTRIES
1
e_shnum_NUMBER_OF_SECTION_HEADER_ENTRIES:2h
Section header 항목 갯수.
e_shtrndx_STRING_TABLE_INDEX
1
e_shtrndx_STRING_TABLE_INDEX:2h
Section header 문자열 테이블 인덱스( .shstrtab각 섹션의 이름이 있는 null로 끝나는 문자열을 포함함)
Conclusion
다음에 기회가 되면 ELF 를 실제로 수정해보는 작업을 진행해보겠다.
If you find any errors, please let me know by comment or email. Thank you.