Post

ELF format templates 수정하기

PT_DYNAMIC 일 때 offset data 를 각 구조체로 파싱하기

ELF format templates 수정하기

Introduction

hex-Editor 로 ELF 파일을 보다가 phdr 의 type 이 Dynamic 일 떼 offset 부분이 이쁘게 안 나와서 해당 부분을 수정해주고자 한다.

How We Got Here

기존 방식

ELF format layout

기존에는 아래와 같이 char 배열로 1 바이트씩 파싱하는 것이 표준이었다.

1
char p_data[p_filesz_SEGMENT_FILE_LENGTH] <comment="Segment data">;

그러면 아래와 같이 나온다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
p_data[648]		  3E90h	288h	char	Fg: Bg:	Segment data
  p_data[0]	  0	3E90h	1h	char	Fg: Bg:	Segment data
  p_data[1]	  0	3E91h	1h	char	Fg: Bg:	Segment data
  p_data[2]	  0	3E92h	1h	char	Fg: Bg:	Segment data
  p_data[3]	  0	3E93h	1h	char	Fg: Bg:	Segment data

      { . . . }

  p_data[30]	0	3EAEh	1h	char	Fg: Bg:	Segment data
  p_data[31]	0	3EAFh	1h	char	Fg: Bg:	Segment data
  p_data[32]	50 '2'	3EB0h	1h	char	Fg: Bg:	Segment data
  p_data[33]	1	3EB1h	1h	char	Fg: Bg:	Segment data
  p_data[34]	0	3EB2h	1h	char	Fg: Bg:	Segment data
  p_data[35]	0	3EB3h	1h	char	Fg: Bg:	Segment data
  p_data[36]	0	3EB4h	1h	char	Fg: Bg:	Segment data

이렇게 확인은 할 수 있으나 ELF 의 dyn 자료형은 아래와 같다.

Elf32_Dyn/Elf64_Dyn 자료형

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef struct dynamic {
  Elf32_Sword d_tag;
  union {
    Elf32_Sword d_val;
    Elf32_Addr d_ptr;
  } d_un;
} Elf32_Dyn;

typedef struct {
  Elf64_Sxword d_tag;
  union {
    Elf64_Xword d_val;
    Elf64_Addr d_ptr;
  } d_un;
} Elf64_Dyn;

따라서 32 bit 경우 8 바이트씩, 64 bit 일 경우 16 바이트씩 structure 로 묶어주면 보기 편할 거 같다.

템플릿 수정하기

Elf64_Sxword 의 대한 자료형을 알려준다.

1
typedef uint64 Elf64_Sxword;

원래는 enum 값 형태로 지정하면 파싱했을 때 갑을 좀 더 명확히 보여줄 수 있다는 편리함이 있다.

PT_DYNAMIC 일 때는 structure 형태로 묶어줘야 하니 condition 을 열어 알맞는 structure 를 작성해준다.

1
2
3
4
5
6
7
8
9
10
11
if (p_type == PT_DYNAMIC) {
  typedef struct {
      Elf32_Sword d_tag;
      union {
          Elf32_Sword d_val;
          Elf32_Addr d_ptr;
      } d_un;
  } Elf32_Dyn;

  Elf32_Dyn p_dynamic_data[p_filesz_SEGMENT_FILE_LENGTH / sizeof(Elf32_Dyn)] <comment="Dynamic section entries">;
}

여기서 union 은 공용체로 메모리 하나의 영역을 공유하여 사용하는 것으로 d_val, d_ptr 같은 값이 할당된다.

p_dynamic_data 에 길이는 전체 길이(p_filesz_SEGMENT_FILE_LENGTH)를 자료형 크기(Elf32_Dyn)만큼 나눈 갯수이다.

실행해보면 아래와 같이 나온다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
p_dynamic_data[28]		3EA8h	1C0h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
  p_dynamic_data[0]		3EA8h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
  p_dynamic_data[1]		3EB8h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
  p_dynamic_data[2]		3EC8h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
  p_dynamic_data[3]		3ED8h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
  p_dynamic_data[4]		3EE8h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
  p_dynamic_data[5]		3EF8h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
  p_dynamic_data[6]		3F08h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
  p_dynamic_data[7]		3F18h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
  p_dynamic_data[8]		3F28h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
    d_tag	7	3F28h	8h	Elf64_Sxword	Fg: Bg:	
    d_un		3F30h	8h	union	Fg: Bg:	
  p_dynamic_data[9]		3F38h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
    d_tag	8	3F38h	8h	Elf64_Sxword	Fg: Bg:	
    d_un		3F40h	8h	union	Fg: Bg:	
  p_dynamic_data[10]		3F48h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
  p_dynamic_data[11]		3F58h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
  p_dynamic_data[12]		3F68h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries
  p_dynamic_data[13]		3F78h	10h	struct Elf64_Dyn	Fg: Bg:	Dynamic section entries

The Game-Changer

최종적으로 정리된 코드를 확인해보면 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// Elf32_Sword 에 대한 자료형
typedef uint32 Elf32_Sword;

// Elf64_Sxword 에 대한 자료형
typedef uint64 Elf64_Sxword;

// Elf32_Dyn with descriptive d_tag
typedef struct {
    Elf32_Sword d_tag;
    union {
        Elf32_Sword d_val <comment="Value or index">;
        Elf32_Addr  d_ptr <comment="Pointer (address in memory)">;
    } d_un;
} Elf32_Dyn;

// Elf64_Dyn with descriptive d_tag
typedef struct {
    Elf64_Sxword d_tag;
    union {
        Elf64_Xword d_val <comment="Value or index">;
        Elf64_Addr  d_ptr <comment="Pointer (address in memory)">;
    } d_un;
} Elf64_Dyn;

// 32 bit 에서 조건문
if (p_type == PT_DYNAMIC) {
    Elf32_Dyn p_dynamic_data[p_filesz_SEGMENT_FILE_LENGTH / sizeof(Elf32_Dyn)] <comment="Dynamic section entries">;
} else {
    char p_data[p_filesz_SEGMENT_FILE_LENGTH] <comment="Segment data">;
}

// 64 bit 에서 조건문
if (p_type == PT_DYNAMIC) {
    Elf64_Dyn p_dynamic_data[p_filesz_SEGMENT_FILE_LENGTH / sizeof(Elf64_Dyn)] <comment="Dynamic section entries">;
} else {
    char p_data[p_filesz_SEGMENT_FILE_LENGTH] <comment="Segment data">;
}        

Conclusion

당장 보기 위해서 엉거주춤 모자라게 작성했는데 d_tag 값도 볼 수 있도록 수정하는 편이 좋을 거 같다.

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.