티스토리 뷰

Security

ELF 파일 구조

on1ystar 2019. 5. 15. 21:55
728x90
반응형
본 포스팅은 간단한 디스어셈블을 위한 elf 파일 구조를 정리하기 위함입니다.

ELF (Executable and Linkable Format)

유닉스 계열 운영체제에서 사용되는 표준 바이너리 파일 포맷이다. ELF는 다양한 하드웨어 아키텍처 및 운영체제에서 사용되며, 리눅스의 기본 실행 파일 형식으로 널리 활용되고 있다.

파일 유형으로는 다음과 같다.

  • 실행 파일 : 독립적으로 실행 가능한 바이너리 파일
  • 오브젝트 파일 : 다른 오브젝트 파일과 링크되어야 실행 가능
  • 공유 라이브러리 : 동적 라이브러리를 의미함
  • 코어 덤프 : 프로세스의 메모리 상태를 저장하는 파일

보통 ELF 파일은 ELF Header + Program header table + Section header table로 구성된다.

ELF 파일 형식

  • ELF header : ELF 파일의 시작 부분에 위치하며, 파일의 구조 및 속성을 정의하는 로드맵과 같은 역할
  • Program header table : 실행 가능한 파일에서 메모리에 적재해야할 세그먼트 정보를 포함한다. 시스템에 프로세스 이미지를 어떻게 만들지 지시하는 역할
  • Section header table : 링킹과 재배치 정보를 가지는 섹션 포함

섹션(Section) vs 세그먼트(Segment)

섹션은 링커(Linker)가 사용하며, 실행 파일을 구성하는 코드, 데이터, 심볼 테이블 등을 포함하는 세부적인 논리적 단위다. 예를 들어 위 ELF 파일 형식 그림에 있는 .text, .rodata, .data 하나하나가 다 섹션이다.

반면에, 세그먼트는 파일 실행 시 운영체제가 메모리에 적재하는 데이터의 논리적 단위다. 즉, 프로그램이 실행될 때 메모리에 로드되는 단위로, 주로 코드, 데이터, 스택 등의 정보가 포함된다. 하나의 세그먼트는 여러 개의 섹션을 포함할 수 있다.

예를 들어, 운영체제가 위 ELF 파일 형식으로 이루어 진 파일을 실행하기 위해 메모리에 올린다고 해 보자. 그럼 .text, .rodata 를 하나하나 메모리에 올리는게 아니라, LOAD 라는 세그먼트 단위로 묶어서 올리게 된다.

ELF Header 구조

#define EI_NIDENT 16
typedef struct {
    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 header 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;                /* Section header table entry count */
    ElfN_Half e_shstrndx;             /* Section header string table index */
} Elf32_Ehdr;
  • e_ident : 파일의 내용을 해석하고 디코딩하기 위해 필요한 정보들
    • 0x00 ~ 0x03(File indentification) : ELF 파일임을 식별하기 위한 4바이트 매직 넘버로 0x7f, 45(E) ,4c(L), 46(F) 값이 할당
    • 0x04(Class) : 파일의 클래스나 용량을 나타냄
      • 0 = ELFCLASSNONE(Invalid class)
      • 1 = ELFCLASS32(32bit)
      • 2 = ELFCLASS64(64bit)
    • 0x05 : Data encoding : 데이터의 인코딩 방식 정보
      • 0 = ELFDATANONE(Invalid data encoding)
      • 1 = ELFDATA2LSB(가장 오른쪽에 있는 비트가 가장 낮은 주소)
      • 2 = ELFDATA2MSB(가장 왼쪽에 있는 비트가 가장 낮은 주소)
    • 0x06 : File Version : ELF header version number로 현재로서는 EV_CURRENT = 1이 사용
    • 0x07 : Start of padding bytes
  • e_type : Object 파일의 타입
    • 0 = ET_NONE(No file type)
    • 1 = ET_REL(Relocatable file)
    • 2 = ET_EXEC(Executable file)
    • 3 = ET_DYN(Shared object file)
    • 4 = ET_CORE(Core file)
  • e_machine : architecture 정보
    • 0 = EM_NONE(No machine)
    • 1 = EM_M32(AT&TWE 32100)
    • 2 = EM_SPARC(SPARC)
    • 3 = EM_386(Intel 80386)
  • e_version : Object 파일의 버전 정보
    • 0 = EV_NONE(Invalid version)
    • 1 = EV_CURRENT(Current version)
  • e_entry : 시스템이 실행하기 위해 제어를 옮길 때 참조하는 가상 주소(진입점)로 프로그램의 시작 주소 (main)를 찾을 수 있음
  • e_phoff : 프로그램 헤더 테이블의 파일 offset
  • e_flags : 파일과 관련해서 프로세서에 specific flag를 가짐
  • e_ehsize : ELF 헤더의 크기
  • e_phentsize : 프로그램 헤더 테이블에 있는 한 엔트리의 크기
  • e_phum : 프로그램 헤더 테이블에 있는 모든 엔트리의 수
  • e_phentsize, e_phum = 프로그램 헤더 테이블의 크기
  • e_shentsize : 섹션 헤더의 크기
  • e_shum : 섹션 헤더 테이블에 있는 엔트리 수
  • e_shstrndx : 섹션의 이름을 나타내는 스트링 테이블과 관련된 엔트리의 섹션 헤더 테이블 인덱스

다음 명령어는 binary utililty로 해당 ELF 파일의 구조 정보를 보기 쉽게 나타낸다.

$ readelf 파일명
  • -h : ELF 헤더 정보
  • -l : 프로그램 헤더 정보
  • -s : 섹션 헤더 정보
  • -S : 심볼 테이블 정보

multi 파일의 elf 헤더 구조

multi라는 object 파일은 ELF 64bit 파일이며 little endian 구조라는 점을 간편하게 알 수 있다. 이를 알면 디스어셈블을 할 때 저장된 바이트 정보를 읽는 방법이나 레지스터를 읽을 때 참고할 수 있다.

또한 중요한 게 Entry point address0x4003b2라는 것인데, 이를 이용해 디스어셈블 시 첫 포인트(main)를 잡을 수 있다.

Program Header

프로그램 헤더 정보

잘린 부분이 있지만, 위 그림에 나와있는 정보만 분석해 보겠다.

  • PHDR(value = 6) : 프로그램 헤더 테이블 자신의 위치와 크기 정보
  • INTERP(value = 3) : 인터프리터 호출을 위한 내용
  • LOAD(value = 1) : 로드 된 프로그램 세그먼트
  • DYNAMIC(value = 2) : 동적 링크 정보

참고로 각 컬럼이 의미하는 아래 표와 같다.

| 데이터 타입    | 데이터명   | 설명                     |
|-------------|----------|-------------------------|
| ElfN_Word   | p_type   | 세그먼트 타입.             |
| ElfN_Off    | p_offset | 세그먼트 파일 오프셋         |
| ElfN_Addr   | p_vaddr  | 세그먼트 가상 주소          |
| ElfN_Addr   | p_paddr  | 세그먼트 물리 주소          |
| ElfN_Word   | p_filesz | 파일에서 세그먼트 크기       |
| ElfN_Word   | p_memsz  | 메모리에서 세그먼트 크기      |
| ElfN_Word   | p_flags  | 세그먼트 flags            |
| ElfN_Word   | p_align  | 세그먼트 alignment        |

Section Header

섹션 헤더 정보 - 1
섹션 헤더 정보 - 2

이 역시 위의 나와있는 섹션 정보만 정리해 보겠다.

  • Interp : 인터프리터의 경로 명을 가지는 섹션
  • Hash : 심볼 해쉬 테이블을 가지는 섹션
  • Dynamic : 동적 링킹 정보를 가지는 섹션
  • Dynstr : 동적 링킹을 위해 필요한 문자열
  • Plt : procedure의 링크 테이블
  • Got.plt : global offset table을 가지는 섹션
  • Text : 프로그램의 실행 가능한 명령어 정보
  • Data : 초기화된 데이터를 가지는 섹션
  • Bss : 초기화되지 않은 데이터를 가지는 섹션
  • Shstrtab : 섹션들의 이름들을 가지는 섹션
  • Symtab : 심볼 테이블 정보
  • Strtab : 문자열 테이블 정보

섹션 헤더의 컬럼들이 나타내는 의미는 아래 표와 같다.

| 데이터 타입    | 데이터명       | 설명                                  |
|-------------|--------------|--------------------------------------|
| ElfN_Word   | sh_name      | 섹션 이름                              |
| ElfN_Word   | sh_type      | 섹션 타입                              |
| ElfN_Word   | sh_flags     | 섹션 플래그                            |
| ElfN_Addr   | sh_addr      | 실행할 섹션의 가상 주소                   |
| ElfN_Off    | sh_offset    | 섹션의 오프셋 위치                       |
| ElfN_Word   | sh_size      | 섹션 크기                              |
| ElfN_Word   | sh_link      | 다른 섹션으로의 링크(테이블 인덱스)          |
| ElfN_Word   | sh_info      | 섹션 추가 정보                          |
| ElfN_Word   | sh_addralign | 섹션 정렬 단위                          |
| ElfN_Word   | sh_entsize   | 가지고 있는 고정크기의 entry들의 크기       |

 

Symbol table

사용한 함수나 변수들이 symbol table에 저장되어 있는데, 디스어셈블을 하기 전에 참고해 보면 도움이 된다.

심볼 테이블 정보 - 1
심볼 테이블 정보 - 2

References

728x90
반응형

'Security' 카테고리의 다른 글

Easy CrackMe 리버싱  (1) 2019.05.08
어셈블리로 구구단 짜기(nasm)  (1) 2019.04.02
RTL (Return to Libc)  (0) 2019.02.05
plt got  (1) 2019.02.03
리버싱 실습(Easy_ELF)  (0) 2019.01.24
댓글