當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 嵌入式大雜燴
[導(dǎo)讀]點(diǎn)擊上方「嵌入式大雜燴」,選擇「置頂公眾號(hào)」第一時(shí)間查看嵌入式筆記! 幾種常見的ELF文件 在Linux下,我們經(jīng)gcc編譯之后生成的可執(zhí)行文件屬于ELF文件: ELF是一類文件類型,而不是特指某一后綴的文件。ELF(Executable and Linkable Format,可執(zhí)行與可鏈

點(diǎn)擊上方「嵌入式大雜燴」,選擇「置頂公眾號(hào)」第一時(shí)間查看嵌入式筆記!

幾種常見的ELF文件

在Linux下,我們經(jīng)gcc編譯之后生成的可執(zhí)行文件屬于ELF文件:


ELF是一類文件類型,而不是特指某一后綴的文件。ELF(Executable and Linkable Format,可執(zhí)行與可鏈接格式)文件格式,在Linux下主要有如下三種文件:

  • 可執(zhí)行文件(.out):Executable File,包含代碼和數(shù)據(jù),是可以直接運(yùn)行的程序。其代碼和數(shù)據(jù)都有固定的地址 (或相對(duì)于基地址的偏移 ),系統(tǒng)可根據(jù)這些地址信息把程序加載到內(nèi)存執(zhí)行。
  • 可重定位文件(.o文件):Relocatable File,包含基礎(chǔ)代碼和數(shù)據(jù),但它的代碼及數(shù)據(jù)都沒(méi)有指定絕對(duì)地址,因此它適合于與其他目標(biāo)文件鏈接來(lái)創(chuàng)建可執(zhí)行文件或者共享目標(biāo)文件。
  • 共享目標(biāo)文件(.so):Shared Object File,也稱動(dòng)態(tài)庫(kù)文件,包含了代碼和數(shù)據(jù),這些數(shù)據(jù)是在鏈接時(shí)被鏈接器(ld)和運(yùn)行時(shí)動(dòng)態(tài)鏈接器(ld.so.l、libc.so.l、ld-linux.so.l)使用的。

ELF格式可結(jié)構(gòu)大致為:

(圖片來(lái)源:百度百科)


ELF文件由4部分組成,分別是ELF頭(ELF header)、程序頭表(Program header table)節(jié)(Section)節(jié)頭表(Section header table)。

實(shí)際上,一個(gè)文件中不一定包含全部?jī)?nèi)容,而且它們的位置也未必如同所示這樣安排,只有ELF頭的位置是固定的,其余各部分的位置、大小等信息由ELF頭中的各項(xiàng)值來(lái)決定。

readelf工具的使用

在Linux下,我們可以使用readelf 命令工具可以查看ELF格式文件的一些信息。

下面我們先準(zhǔn)備一個(gè)動(dòng)態(tài)鏈接相關(guān)的demo,就拿我們之前分享的文章:靜態(tài)鏈接與動(dòng)態(tài)鏈接補(bǔ)充(Linux)中的demo來(lái)做演示:

文件1(main.c):

#include "test.h"

int main(void)
{
 print_hello();
 return 0;
}

文件2(test.c):

#include "test.h"

void print_hello(void)
{
 printf("hello world\n");
}

文件3(test.h):

#ifndef __TEST_H
#define __TEST_H

#include <stdio.h>

void print_hello(void);

#endif

執(zhí)行相關(guān)命令生成相關(guān)文件:.out文件.o文件、.so文件。如:


下面我們使用readelf命令來(lái)查看這三類文件的一些信息。readelf命令格式為:

readelf <option(s)> elf-file(s)

查看可執(zhí)行文件頭部信息:


查看可執(zhí)行文件頭部信息是,我們發(fā)現(xiàn)這樣一個(gè)問(wèn)題,頭部信息中的類型竟然是共享庫(kù)文件,而我們查看的是可執(zhí)行文件,自相矛盾?

查了一些資料:

https://blog.csdn.net/cclethe/article/details/83387685

發(fā)現(xiàn):gcc編譯默認(rèn)加了--enable-default-pie選項(xiàng):


Position-Independent-Executable是Binutils,glibc和gcc的一個(gè)功能,能用來(lái)創(chuàng)建介于共享庫(kù)和通??蓤?zhí)行代碼之間的代碼–能像共享庫(kù)一樣可重分配地址的程序,這種程序必須連接到Scrt1.o。

標(biāo)準(zhǔn)的可執(zhí)行程序需要固定的地址,并且只有被裝載到這個(gè)地址時(shí),程序才能正確執(zhí)行。

PIE能使程序像共享庫(kù)一樣在主存任何位置裝載,這需要將程序編譯成位置無(wú)關(guān),并鏈接為ELF共享對(duì)象。

引入PIE的原因是讓程序能裝載在隨機(jī)的地址,通常情況下,內(nèi)核都在固定的地址運(yùn)行,如果能改用位置無(wú)關(guān),那攻擊者就很難借助系統(tǒng)中的可執(zhí)行碼實(shí)施攻擊了。

類似緩沖區(qū)溢出之類的攻擊將無(wú)法實(shí)施。而且這種安全提升的代價(jià)很小。

也就是說(shuō),pie這是一種保護(hù)我們可執(zhí)行程序的一種手段。這里我們只是做實(shí)驗(yàn),我們可以加-no-pie參數(shù)先把pie給關(guān)掉:


可以看到,類型終于對(duì)得上了。ELF頭部信息還包含有Entry point address(入口地址)、Start of program headers(程序頭的起始字節(jié))、Start of section headers(節(jié)頭的起始字節(jié))等信息。

查看可重定位文件頭部信息:


查看共享目標(biāo)文件頭部信息:


同樣的,readelf 搭配其它參數(shù)可以查看ELF文件的其它信息:

objdump工具的使用

objdump工具用于顯示一個(gè)或多個(gè)目標(biāo)文件的信息。objdump命令格式:

objdump <option(s)> <file(s)>

可執(zhí)行文件、可重定位文件與共享目標(biāo)文件都屬于目標(biāo)文件,所以都可以使用這個(gè)命令來(lái)查看一些信息。

查看可重定位文件反匯編信息:


查看可執(zhí)行文件反匯編信息:


查看共享目標(biāo)文件反匯編信息:

總結(jié)

以上就是本次的分享。簡(jiǎn)單地介紹了ELF文件的一些信息,同時(shí)介紹了分析ELF文件的兩個(gè)工具。

ELF文件的內(nèi)容很多,并且比較抽象,詳細(xì)分析起來(lái)是個(gè)深坑。我們大致先進(jìn)行一個(gè)簡(jiǎn)單的了解,之后如果深入學(xué)習(xí)時(shí)再做另外的分享。

上就是本次的分享,如有錯(cuò)誤,歡迎指出!謝謝

歡迎大家進(jìn)群交流、共同進(jìn)步。同時(shí),我也會(huì)關(guān)注一些大家問(wèn)的一些問(wèn)題,從中挑選一些具有代表性的、并且在我知識(shí)范圍內(nèi)的問(wèn)題寫出相關(guān)文章做分享。

猜你喜歡

Linux下socket編程實(shí)例

Linux下應(yīng)用開發(fā)基礎(chǔ)

Linux下能編譯成功,而Windows下編譯不過(guò)?

【Linux筆記】Vi/Vim編輯器

C語(yǔ)言、嵌入式中幾個(gè)非常實(shí)用的宏技巧

C語(yǔ)言、嵌入式應(yīng)用:TCP通信實(shí)例分析

C語(yǔ)言、嵌入式重點(diǎn)知識(shí):回調(diào)函數(shù)

C語(yǔ)言、嵌入式位操作精華技巧大匯總

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉