Post

ELF header 에 대한 고찰

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 를 실제로 수정해보는 작업을 진행해보겠다.

This post is licensed under CC BY 4.0 by the author.
If you find any errors, please let me know by comment or email. Thank you.

© Ruffalo. Some rights reserved.

I'm

Using the Chirpy theme for Jekyll.