iT邦幫忙

2026 iThome 鐵人賽

DAY 3
0

昨天在最後有提到,
不管是 hello.o 還是最後產生的 hello

如果使用 file 指令去查看的話,都會看到一個東西:

file hello.o
file hello

可能會分別看到:

hello.o: ELF 64-bit LSB relocatable, x86-64, ...

以及:

hello: ELF 64-bit LSB pie executable, x86-64, ...

所以今天就來看看:

ELF 到底是什麼?

0x01 ELF

ELF 的全名是:

Executable and Linkable Format

它是一種常見的 Executable File Format

在 Linux 上
Executable、Object File、Shared Library 等等
很多其實都是使用 ELF 格式

所以像昨天產生的:

hello.o

以及:

hello

雖然一個是 Object File,一個是 Executable ,其實都是 ELF
只是 Type 不一樣而已

如果直接用:

file hello

查看:

ELF 64-bit LSB pie executable, x86-64, ...

這邊已經可以看到一些資訊:

  • ELF 64-bit
  • LSB
  • pie executable
  • x86-64

這些資訊都可以從 ELF Header 裡面找到

0x02 ELF Header

可以使用:

readelf -h hello

查看 ELF Header

可能會看到:

ELF Header:
  Magic:   7f 45 4c 46 ...
  Class:                             ELF64
  Data:                              2's complement, little endian
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Entry point address:               0x1050

這邊先看幾個比較重要的東西

Magic

7f 45 4c 46

其中:

45 = E
4c = L
46 = F

所以 ELF 檔案的開頭其實會是:

\x7fELF

這種放在檔案開頭
用來辨識檔案格式的值通常會被稱作 Magic Number

也可以直接使用:

xxd hello | head

查看 Binary 最前面的內容

Class

如果看到:

Class: ELF64

代表這是一個 64-bit ELF

如果是:

ELF32

則代表是 32-bit

Data

像是:

Data: 2's complement, little endian

這邊的 little endian
是在描述 Multi-byte Data 在 Memory 中的儲存順序。

例如:

0x12345678

使用 Little Endian 儲存時,
可能會看到:

78 56 34 12

這個東西之後在 Pwn 裡面會一直遇到

Machine

Machine: Advanced Micro Devices X86-64

代表這個 Binary 使用的 Architecture 是:

x86-64

也就是說
之後如果把 Machine Code Disassemble 回 Assembly
就會按照 x86-64 的 Instruction Set 去解析

0x03 Entry Point

在 ELF Header 中還會看到:

Entry point address: 0x1050

Entry Point 可以先理解成:

程式開始執行的位置

也就是當這個 ELF 被 Loader 載入並開始執行時
會從這個 Address 開始執行

不過這邊先記得一件事:

Entry Point 不一定就是 main()

在 C 程式真正進到 main() 之前
其實還會經過一些初始化流程

這部分之後再繼續看

0x04 Section

除了 ELF Header 之外
ELF 裡面還會被分成很多不同的 Section

可以使用:

readelf -S hello

查看。

會看到很多像是:

.text
.data
.bss
.rodata

這些不同的 Section 會拿來存放不同種類的資料

.text

.text 主要存放:

Machine Code

也就是 CPU 實際會執行的 Instructions

.data

.data 通常會放已經初始化的 Global Variable 或 Static Variable

例如:

int number = 1337;

.bss

.bss 通常會放沒有明確初始化的 Global Variable 或 Static Variable

例如:

int number;

.rodata

.rodata 是 Read Only Data。

像是程式裡面的字串:

printf("Hello World!\n");

其中:

Hello World!

就可能會被放到 .rodata

可以使用:

readelf -p .rodata hello

查看 .rodata 裡面的 String

可能會看到:

String dump of section '.rodata':

  [     4]  Hello World!

所以我們原本寫在 Source Code 裡面的字串
最後真的會被放進 Binary 中

0x05 strings

如果只是想快速看看一個 Binary 裡面有哪些可讀字串
可以使用:

strings hello

可能會看到:

/lib64/ld-linux-x86-64.so.2
libc.so.6
Hello World!
...

strings 會從 Binary 中把看起來像是可讀字串的內容找出來

在 Reverse Engineering 時
這通常也是一個很簡單但是很有用的起手式

比如說今天拿到一個 CTF Challenge,
執行後只看到:

Wrong Password!

那就可以先:

strings challenge

看看 Binary 裡面還有哪些字串

有時候可以從這些 String 中找到:

  • Error Message
  • Function 相關資訊
  • File Path
  • URL
  • Password Prompt
  • Flag Format

等等線索

0x06 結論

所以 ELF 並不是只有一整坨 Machine Code。

裡面其實會包含很多不同的資訊,
像是:

ELF Header
Section
Machine Code
Read Only Data
Global Data
...

今天先知道幾個常見的工具:

file hello
readelf -h hello
readelf -S hello
readelf -p .rodata hello
xxd hello | head
strings hello

透過這些工具
已經可以開始從 Binary 本身取得不少資訊

而剛剛有提到:

.text

裡面放的是 CPU 真正會執行的 Machine Code
如果把這些 Machine Code 轉成人比較能閱讀的形式
就會變成我們接下來很常看到的 Assembly
所以下一篇就來看看:Assembly 到底在寫什麼?


上一篇
Day02| 從 C Code 到 Binary
系列文
從零開始の Binary CTF:30 天系統化學習 Rev & Pwn3
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言