.elf 형식 내부 확인

.elf 형식 내부 확인

엘프 헤더, 프로그램 헤더, 섹션, 세그먼트 등을 포함하여 이 모든 것을 알려주는 ELF 형식 사양을 읽고 있습니다. 이들 모두는 다양한 필드와 값을 갖는 구조로 참조됩니다.

그렇다면 문제는 이 모든 것이 어디로 가는가입니다. 내 말은, readelfutil의 출력 대신 구조로 처리할 수 있습니까 ?

이 모든 것이 포함된 중간 파일이 있습니까?엘프 마법존재하고 소스 코드에 병합되었나요? 아니면 단지 컴파일러의 내부 구조이고 그 구조는 인간만을 위한 사양서에 언급되어 있는 걸까요? )

나에게 이것은 "닭과 달걀 문제"(컴파일된 코드에 대해 이야기하기 위해 코드를 사용하는 것)처럼 보입니다.

답변1

이러한 구조는 ELF 파일에 존재합니다.

ELF 헤더를 살펴보겠습니다.

#define EI_NIDENT (16)

typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf32_Half    e_type;                 /* Object file type */
  Elf32_Half    e_machine;              /* Architecture */
  Elf32_Word    e_version;              /* Object file version */
  Elf32_Addr    e_entry;                /* Entry point virtual address */
  Elf32_Off     e_phoff;                /* Program header table file offset */
  Elf32_Off     e_shoff;                /* Section header table file offset */
  Elf32_Word    e_flags;                /* Processor-specific flags */
  Elf32_Half    e_ehsize;               /* ELF header size in bytes */
  Elf32_Half    e_phentsize;            /* Program header table entry size */
  Elf32_Half    e_phnum;                /* Program header table entry count */
  Elf32_Half    e_shentsize;            /* Section header table entry size */
  Elf32_Half    e_shnum;                /* Section header table entry count */
  Elf32_Half    e_shstrndx;             /* Section header string table index */
} Elf32_Ehdr;

typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf64_Half    e_type;                 /* Object file type */
  Elf64_Half    e_machine;              /* Architecture */
  Elf64_Word    e_version;              /* Object file version */
  Elf64_Addr    e_entry;                /* Entry point virtual address */
  Elf64_Off     e_phoff;                /* Program header table file offset */
  Elf64_Off     e_shoff;                /* Section header table file offset */
  Elf64_Word    e_flags;                /* Processor-specific flags */
  Elf64_Half    e_ehsize;               /* ELF header size in bytes */
  Elf64_Half    e_phentsize;            /* Program header table entry size */
  Elf64_Half    e_phnum;                /* Program header table entry count */
  Elf64_Half    e_shentsize;            /* Section header table entry size */
  Elf64_Half    e_shnum;                /* Section header table entry count */
  Elf64_Half    e_shstrndx;             /* Section header string table index */
} Elf64_Ehdr;

ELF 헤더는 다음 위치에 있습니다.모든ELF 파일.

이것이 실제로 의미하는 바는 ELF 파일의 처음 16바이트가 e_identELF 헤더의 필드라는 것입니다.

  • 첫 번째 바이트는 0x7f입니다.

  • 두 번째는 'E';

  • 세 번째는 'L';

  • 네 번째는 'F';

  • 다섯 번째는 수업입니다.

  • 여섯 번째는 데이터 인코딩입니다.

  • 일곱 번째는 파일 버전입니다.

  • 여덟 번째는 운영 체제 ABI입니다.

  • 등.

이 필드 e_ident다음의 2바이트는 입니다 e_type.

그게 당신이라면 시작 부분에 가까운 것을 head /bin/bash볼 수 있을 것입니다 .ELF

이제 ELF 파일 시작 부분의 16진 덤프를 얻으면:

$ xxd /bin/bash | xxd 헤더 |
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF..............
00000010: 0200 3e00 0100 0000 7005 4200 0000 0000 ..>.....pB....
00000020: 4000 0000 0000 0000 c0cd 0f00 0000 0000 @...........
00000030: 0000 0000 4000 3800 0900 4000 1d00 1c00  [이메일 보호됨]...@.....
00000040: 0600 0000 0500 0000 4000 0000 0000 0000 .......@.......
00000050: 4000 4000 0000 0000 4000 4000 0000 0000 @.@.....@.@.....
00000060: f801 0000 0000 0000 f801 0000 0000 0000 ........
00000070: 0800 0000 0000 0000 0300 0000 0400 0000 ............
00000080: 3802 0000 0000 0000 3802 4000 0000 0000 8.......8.@.....
00000090: 3802 4000 0000 0000 1c00 0000 0000 0000 8.@........................

이 16진수 덤프의 첫 번째 줄은 처음 16바이트( e_ident)입니다.

  • 첫 번째 바이트는 실제로 0x7f;

  • 그러다가 "ELF";

  • 그 다음에는 (ELF64) 0x02클래스가 있습니다.ELFCLASS64

  • 0x01그런 다음 인코딩이 옵니다 ELFDATA2LSB.

  • 등.

두 번째 줄의 처음 2바이트는 입니다 e_type. LSB로 인코딩되므로(때문에 ELFDATA2LSB) 값은 실제로 는 실행 파일임을 0x0002의미합니다 .ET_EXEC

다음 2바이트는 아키텍처( e_machine)입니다. 이는 실행 파일이기 0x003e때문 입니다 .EM_X86_64x86_64

ELF 헤더의 모든 필드를 수동으로 디코딩할 수 있어야 하며 주어진 값과 동일한 값을 찾아야 합니다 readelf. 이를 통해 파일에서 ElfXX_Shdr또는 와 같은 다른 ELF 구조를 찾아 ElfXX_Phdr해당 정의에 따라 디코딩할 수 있습니다(주어진 정보와 동일한 정보를 찾아야 합니다 readelf).

답변2

사용 xxd하고awk

$ xxd hello_arm64   | awk '{for(i=2;i<NF;i++){a=a$i;c++;if(c>9){print a;exit;}}}'
7f454c460201010000000000000000000200b700
$ cat /proc/sys/fs/binfmt_misc/qemu-aarch64
enabled
interpreter /usr/bin/qemu-aarch64-static
flags: F
offset 0
magic 7f454c460201010000000000000000000200b700
mask ffffffffffffff00fffffffffffffffffeffffff

관련 정보