1. 程式人生 > >你所不瞭解的Linux二進位制

你所不瞭解的Linux二進位制

點選標題下「非同步圖書」可快速關注

二進位制分析屬於資訊保安業界逆向工程中的一種技術,通過利用可執行的機器程式碼(二進位制)來分析應用程式的控制結構和執行方式,它有助於資訊保安從業人員更好地分析各種漏洞、病毒以及惡意軟體,從而找到相應的解決方案。

要反編譯Linux二進位制檔案,首先需要理解二進位制格式本身。ELF目前已經成為UNIX和類UNIX作業系統的標準二進位制格式。在Linux、BSD變體以及其他作業系統中,ELF格式可用於可執行檔案、共享庫、目標檔案、coredump檔案,甚至核心引導映象檔案。因此,對於那些想要更好地理解反編譯、二進位制攻破和程式執行的人來說,學習ELF至關重要。要想學習ELF這樣的二進位制格式,可不是一蹴而就的,需要隨著對不同元件的學習來逐步掌握並加以實際應用。要達到熟練應用的效果,還需要實際的動手經驗。ELF二進位制格式比較複雜,也很枯燥,不過可以在進行反編譯或者程式設計任務中應用ELF二進位制格式相關的程式設計知識,通過這樣的方式學習,倒是一種很有趣的嘗試。ELF跟程式載入、動態連結、符號表查詢和許多其他精心設計的元件一樣,都是電腦科學非常重要的一部分。

在本文中,你將會更加深入地瞭解程式如何對映到磁碟並載入到記憶體中。程式執行的內部邏輯比較複雜,對於有抱負的二進位制黑客、逆向工程師或者普通的程式設計師來說,對二進位制格式的理解將會是非常寶貴的知識財富。在Linux中,程式就是以ELF二進位制的格式執行的。

像許多Linux反編譯工程師一樣,我也是先了解ELF的說明規範,然後把學到的內容以一種創造性的方式進行應用,通過這樣的方式來進行ELF的學習。

2.1 ELF檔案型別

一個ELF檔案可以被標記為以下幾種型別之一。

  • ET_NONE:未知型別。這個標記表明檔案型別不確定,或者還未定義。

  • ET_REL

    :重定位檔案。ELF型別標記為relocatable意味著該檔案被標記為了一段可重定位的程式碼,有時也稱為目標檔案。可重定位目標檔案通常是還未被連結到可執行程式的一段位置獨立的程式碼(position independent code)。在編譯完程式碼之後通常可以看到一個.o格式的檔案,這種檔案包含了建立可執行檔案所需要的程式碼和資料。

  • ET_EXEC:可執行檔案。ELF型別為executable,表明這個檔案被標記為可執行檔案。這種型別的檔案也稱為程式,是一個程序開始執行的入口。

  • ET_DYN:共享目標檔案。ELF型別為dynamic,意味著該檔案被標記為了一個動態的可連結的目標檔案,也稱為共享庫。這類共享庫會在程式執行時被裝載並連結到程式的程序映象中。

  • ET_CORE:核心檔案。在程式崩潰或者程序傳遞了一個SIGSEGV訊號(分段違規)時,會在核心檔案中記錄整個程序的映象資訊。可以使用GDB讀取這類檔案來輔助除錯並查詢程式崩潰的原因。

使用readelf–h命令檢視ELF檔案,可以看到原始的ELF檔案頭。ELF檔案頭從檔案的0偏移量開始,是除了檔案頭之後剩餘部分檔案的一個對映。檔案頭主要標記了ELF型別、結構和程式開始執行的入口地址,並提供了其他ELF頭(節頭和程式頭)的偏移量,稍後會細講。一旦理解了節頭和程式頭的含義,就容易理解檔案頭了。通過檢視Linux的ELF(5)手冊,可以瞭解ELF頭部的結構:

#define EI_NIDENT 16 
               typedefstruct{ 
                   unsignedchar e_ident[EI_NIDENT]; 
                   uint16_t      e_type; 
                   uint16_t      e_machine; 
                   uint32_t      e_version; 
                   ElfN_Addr     e_entry; 
                   ElfN_Off      e_phoff; 
                   ElfN_Off      e_shoff; 
                   uint32_t      e_flags; 
                   uint16_t      e_ehsize; 
                   uint16_t      e_phentsize; 
                   uint16_t      e_phnum; 
                   uint16_t      e_shentsize; 
                   uint16_t      e_shnum; 
                   uint16_t      e_shstrndx; 
                }ElfN_Ehdr;

在本文的後續內容中,我們會用一個簡單的C程式來展示如何利用上面結構中的欄位對映一個ELF檔案。我們先繼續介紹現存的其他型別的ELF頭。

2.2 ELF程式頭

ELF程式頭是對二進位制檔案中段的描述,是程式裝載必需的一部分。段(segment)是在核心裝載時被解析的,描述了磁碟上可執行檔案的記憶體佈局以及如何對映到記憶體中。可以通過引用原始ELF頭中名為e_phoff(程式頭表偏移量)的偏移量來得到程式頭表,如前面ElfN_Ehdr結構中所示。

下面討論5種常見的程式頭型別。程式頭描述了可執行檔案(包括共享庫)中的段及其型別(為哪種型別的資料或程式碼而保留的段)。首先,我們來看一下Elf32_Phdr的結構,它構成了32位ELF可執行檔案程式頭表的一個程式頭條目。

在本書的後續內容中有時還會引用Phdr的程式頭結構。

下面是Elf32_Phdr結構體:

typedefstruct { 
        uint32_t   p_type;   (segment type) 
        Elf32_Off  p_offset; (segment offset) 
        Elf32_Addr p_vaddr;   (segment virtual address) 
        Elf32_Addr p_paddr;    (segment physical address) 
        uint32_t   p_filesz;   (size of segment in the file) 
        uint32_t   p_memsz; (size of segment in memory) 
        uint32_t   p_flags; (segment flags, I.E execute|read|read)
        uint32_t   p_align;   (segment alignment in memory) 
      } Elf32_Phdr;

2.2.1 PT_LOAD

一個可執行檔案至少有一個PT_LOAD型別的段。這類程式頭描述的是可裝載的段,也就是說,這種型別的段將被裝載或者對映到記憶體中。

例如,一個需要動態連結的ELF可執行檔案通常包含以下兩個可裝載的段(型別為PT_LOAD):

  • 存放程式程式碼的text段;

  • 存放全域性變數和動態連結資訊的data段。

上面的兩個段將會被對映到記憶體中,並根據p_align中存放的值在記憶體中對齊。建議讀者閱讀一下Linux的ELF手冊,以便理解Phdr結構體中所有變數的含義,這些變數描述了段在檔案和記憶體中的佈局。

程式頭主要描述了程式執行時在記憶體中的佈局。本章稍後會使用Phdr來說明什麼是程式頭,以及如何在反編譯軟體中使用程式頭。

通常將text段(也稱程式碼段)的許可權設定為PF_X | PF_R(讀和可執行)。

通常將data段的許可權設定為PF_W | PF_R(讀和寫)。

感染了千面人病毒(polymorphic virus)檔案的text段或data段的許可權可能會被修改,如通過在程式頭的段標記(p_flags)處增加PF_W標記來修改text段的許可權。

2.2.2 PT_DYNAMIC——動態段的Phdr

動態段是動態連結可執行檔案所特有的,包含了動態連結器所必需的一些資訊。在動態段中包含了一些標記值和指標,包括但不限於以下內容:

  • 執行時需要連結的共享庫列表;

  • 全域性偏移表(GOT)的地址——ELF動態連結部分(2.6節)會討論;

  • 重定位條目的相關資訊。

表2-1是完整的標記名列表。

表2-1

標 記 名

描  述

DT _ HASH

符號散列表的地址

DT _ STRTAB

字串表的地址

DT _ SYMTAB

符號表地址

DT _ RELA

相對地址重定位表的地址

DT _ RELASZ

Rela表的位元組大小

DT _ RELAENT

Rela表條目的位元組大小

DT _ STRSZ

字串表的位元組大小

DT _ SYMENT

符號表條目的位元組大小

DT _ INIT

初始化函式的地址

DT _ FINI

終止函式的地址

DT _ SONAME

共享目標檔名的字串表偏移量

DT _ RPATH

庫搜尋路徑的字串表偏移量

DT _ SYMBOLIC

修改連結器,在可執行檔案之前的共享目標檔案中搜索符號

DT _ REL

Rel relocs表的地址

DT _ RELSZ

Rel表的位元組大小

DT _ RELENT

Rel表條目的位元組大小

DT _ PLTREL

PLT引用的reloc型別(Rela或Rel)

DT _ DEBUG

還未進行定義,為除錯保留

DT _ TEXTREL

缺少此項表明重定位只能應用於可寫段

DT _ JMPREL

僅用於PLT的重定位條目地址

DT BIND NOW

指示動態連結器在將控制權交給可執行檔案之前處理所有的重定位

DT _ RUNPATH

庫搜尋路徑的字串表偏移量

動態段包含了一些結構體,在這些結構體中存放著與動態連結相關的資訊。d_tag成員變數控制著d_un的含義。

32位ELF檔案的動態段結構體如下:

typedefstruct{
    Elf32_Sword   d_tag; 
        union{ 
    Elf32_Word d_val; 
    Elf32_Addr d_ptr; 
        } d_un; 
    } Elf32_Dyn; 
    externElf32_Dyn _DYNAMIC[];

本文稍後會繼續對動態連結進行更深入的探討。

2.2.3 PT_NOTE

PT_NOTE型別的段可能儲存了與特定供應商或者系統相關的附加資訊。下面是標準ELF規範中對PT_NOTE的定義:

有時供應商或者系統構建者需要在目標檔案上標記特定的資訊,以便於其他程式對一致性、相容性等進行檢查。SHT_NOTE型別的節(section)和PT_NOTE型別的程式頭元素就可以用於這一目的。節或者程式頭元素中的備註資訊可以有任意數量的條目,每個條目都是一個4位元組的目標處理器格式的陣列。下面的標籤可以解釋備註資訊的組織結構,不過這些標籤並不是規範中的內容。

比較有意思的一點:事實上,這一段只儲存了作業系統的規範資訊,在可執行檔案執行時是不需要這個段的(因為系統會假設一個可執行檔案是本地的),這個段成了很容易被病毒感染的一個地方。由於篇幅限制,就不具體介紹了。更多NOTE段病毒感染相關的資訊可以從http://vxheavens.com/ lib/vhe06.html瞭解到。

2.2.4 PT_INTERP

PT_INTERP段只將位置和大小資訊存放在一個以null為終止符的字串中,是對程式直譯器位置的描述。例如,/lib/linux-ld.so.2一般是指動態連結器的位置,也即程式直譯器的位置。

2.2.5 PT_PHDR

PT_PHDR段儲存了程式頭表本身的位置和大小。Phdr表儲存了所有的Phdr對檔案(以及記憶體映象)中段的描述資訊。

可以查閱ELF(5)手冊或者ELF規範文件來檢視所有的Phdr型別。我們已經介紹了一些最常用的Phdr型別,其中一些對程式執行至關重要,有一些在反編譯時會經常用到。

可以使用readelf–l <filename>命令檢視檔案的Phdr表:

Elf file type is EXEC (Executable file) Entry point 0x8049a30 There are 9 program headers, starting at offset 52 ProgramHeaders:
  TypeOffsetVirtAddrPhysAddrFileSizMemSizFlgAlign
  PHDR          0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4 
  INTERP        0x000154 0x08048154 0x08048154 0x00013 0x00013 R   0x1 
      [Requesting program interpreter: /lib/ld-linux.so.2] 
  LOAD          0x000000 0x08048000 0x08048000 0x1622c 0x1622c R E 0x1000
  LOAD          0x016ef8 0x0805fef8 0x0805fef8 0x003c8 0x00fe8 RW  0x1000
  DYNAMIC       0x016f0c 0x0805ff0c 0x0805ff0c 0x000e0 0x000e0 RW 0x4 
  NOTE          0x000168 0x08048168 0x08048168 0x00044 0x00044 R  0x4 
  GNU_EH_FRAME  0x016104 0x0805e104 0x0805e104 0x0002c 0x0002c R  0x4 
  GNU_STACK     0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 
  GNU_RELRO     0x016ef8 0x0805fef8 0x0805fef8 0x00108 0x00108 R  0x1

從上面的片段中,可以看到可執行程式的入口點,還有剛剛討論的不同段的型別。注意看中間部分的PT_LOAD段,從最左邊的偏移量到最右邊的許可權標識和對齊標識。

text段是可讀可執行的,data段是可讀可寫的,這兩個段都有0x1000(4096)的對齊標識,剛好是32位可執行檔案一頁的大小,該標識用於在程式裝載時對齊。

本書是目前為止唯一一本剖析Linux ELF工作機制的圖書,共分為9章,其內容涵蓋了Linux環境和相關工具、ELF二進位制格式、Linux程序追蹤、ELF病毒技術、Linux二進位制保護、Linux中的ELF二進位制取證分析、程序記憶體取證分析、擴充套件核心檔案快照技術、Linux/proc/kcore分析等。 
本書適合具有一定的Linux操作知識,且瞭解C語言程式設計技巧的資訊保安從業人員閱讀。

目  錄

第1章 Linux環境和相關工具1

1.1 Linux工具1

1.1.1 GDB2

1.1.2 GNU binutils中的objdump2

1.1.3 GNU binutils中的objcopy3

1.1.4 strace3

1.1.5 ltrace4

1.1.6 基本的ltrace命令4

1.1.7 ftrace4

1.1.8 readelf4

1.1.9 ERESI——ELF反編譯系統介面5

1.2 有用的裝置和檔案6

1.2.1 /proc//maps6

相關推薦

瞭解Linux二進位制

點選標題下「非同步圖書」可快速關注 二進位制分析屬於資訊保安業界逆向工程中的一種技術,通過利用可執行的機器程式碼(二進位制)來分析應用程式的控制結構和執行方式,它有助於資訊保安從業人員更好

瞭解Linux(文末有福利)

稻盛和夫先生在《活法》中有段一直激勵著我的話,現在轉送給正在閱讀本文的你: “工作馬馬虎虎,只想在興趣和遊戲中尋覓快活,充其量只能獲得一時的快感,絕不能嚐到從心底湧出的驚喜和快樂,但來自工作的

[轉載]瞭解的DevOps

DevOps開發運維訓練營 一旦建立了創新的文化,即使那些並非科學家或者工程師的人——詩人、演員、記者——也能以團體的形式,接受科學文化的意義。他們信奉創新文化的概念。他們以促進這種文化的方式投票。他們不會反對科學,也不會反對技術。 ——Neil deGrasse Tyson

MyBatis-瞭解的sql和include

今天在大致講解一下 <sql> 和 <include> 節點的使用。 <sql> 節點的基礎 對於 <sql> 節點, 很多人的理解估計就是用來包含資料庫的欄位的, 以便用來替換所有欄位 「*」 符號, 以此來提高 SQL 的執行速度。 類似這樣 <

知道的linux匿名管道知識

相信很多在linux平臺工作的童鞋, 都很熟悉管道符 '|', 通過它, 我們能夠很靈活的將幾種不同的命令協同起來完成一件任務。就好像下面的命令: 不過這次咱們不來說這些用法, 而是來探討一些更加有意思的, 那就是 管道兩邊的資料流"實時性" 和 管道使用的小提示。 其實我們在利用管道的時

java.net.BindException: Cannot assign requested address 知道的另一個原因(linux

轉載:https://blog.csdn.net/zqz_zqz/article/details/79736498 剛剛通過qq幫同事處理了一個客戶執行緒問題,都這麼晚了,還在現場部署應用,真實夠拼的,客戶不能連線外網,不能下載檔案,只能通過手機拍照錯誤日誌排查問題; 問題現象就是tomca

知道的AWS 雲服務清單(71種)

亞馬遜 系統管理員 雲計算 應用程序 可擴展性 導讀AWS,即亞馬遜 Web 服務,是一個提供了一系列按使用計費的 web 服務的雲平臺。 它是迄今為止最為著名的雲平臺之一。由於其靈活性、有效性、彈性、可測量性和無須維護,所以有一些企業正逐步把他們的業務遷移到雲端。 由於許多公司目前在使用

知道的單例模式和多線程並發在單例模式中的影響

影響 編程問題 rop key 是我 提升 註意 特性 是不是 單例對象(Singleton)是一種常用的設計模式。在Java應用中,單例對象能保證在一個JVM中,該對象只有一個實例存在。這樣的模式有幾個好處: 1、某些類創建比較頻繁,對於一些大型的對象,這是一筆很大的系

重拾JavaScript(2)之console的知道的功能

斷言 adding devel bcf dev ces com 字符 bom JavaScript最常用的調試工具就是console.info()了。console是瀏覽器中window對象的屬性之一,由瀏覽器對象模型(BOM)提供,作用是訪問瀏覽器控制臺,你可以通過

java中知道的CAS操作

sta mar 一個 swap 不知道 通過 樂觀 變換 沒有 1.CAS是什麽   Compare and Swap(比較並操作),由處理器架構支持,語義是如果當前值V和舊值A相同,則將當前值修改為B,如果不相同則不修改。CAS操作采用的是樂觀鎖技術,當多線程同時修改某個

知道的 【ModuleNotFoundError: No module named ''; '' is not a package】

is not a package一、背景介紹 1. 工具目錄結構 為了便於統一管理一些小工具,在本地創建了一個mytools的目錄,子目錄的結構如下: 2.python搜索路徑在環境變量中,增加了PYTHONPATH的設置,value為‘e:\mytools\lib\python‘。二、問題

Go基礎之--位操作中知道的用法

turn 自己 use 應用 const 代碼 只需要 寫法 直接 之前一直忽略的就是所有語言中關於位操作,覺得用處並不多,可能用到也非常簡單的用法,但是其實一直忽略的是它們的用處還是非常大的,下面先回顧一下位操作符的基礎 位操作符 與操作:&1 & 1 =

知道的,Java 中操作符的秘密?

tint 正常的 示例 itl 相等 params obi equal 拷貝 在 Java 編程的過程中,我們對數據的處理,都是通過操作符來實現的。例如,用於賦值的賦值操作符、用於運算的運算操作符等、用於比較的比較操作符,還包括邏輯操作符、按位操作符、移位操作符、三元操作符

知道的String(String系列一)

String1、String定義 >通過源碼,String是由final修飾的,不能被繼承,實現序列化,其中序列化的標識是由定義的變量處理,serialVersionUID和serialPersistentFields。其中另外兩個變量是char數組和hash。 ![](http://i2.51c

直播源碼:關於直播行業知道的事情

手機直播源碼 直播源碼網上流傳著一個段子:“直播發於秀場,興於網紅,盛於明星,衰於廣告,毀於×××”。在這個處處充滿機遇和挑戰,精神需求被無限放大的互聯網時代,直播行業如雨後春筍一樣迅速崛起。目前這一行業的競爭已進入白熱化階段。刷榜、僵屍粉、燒錢等問題鋪面而來,在秀場和網紅的吹捧下,直播泡沫也被放大,賽道越

知道的:大神與一般程序猿的區別》讀書筆記

難度 真的是 自己 上網 相關 知識點 代碼 獨立 思維方式   看了這本書,有一些共鳴。   現在程序猿那麽多,但是為什麽他們的技術水平,他們的薪酬會相差那麽懸殊呢?   大神和菜鳥,真的是差在技術上嗎?   如何評判一個程序猿的優劣?答案是,看他的代碼, 程序猿和其他的

let和const----知道的JavaScript系列

err 刪除 read AS 對象 ble 試題 都是 AR let 眾所周知,在ES6之前,聲明變量的關鍵字就只有var。var 聲明變量要麽是全局的,要麽是函數級的,而無法是塊級的。 var a=1; console.log(a); //1 console.log(

關於鳳凰娛樂,知道的鳳凰?

業界 客服 公開 http follow 服務商 ofo 聯系我們 娛樂平臺 鳳凰娛樂是中國最權威的一個擁有核心技術的互聯網遊戲開放服務商,鳳凰娛樂平臺是 隸屬亞馬遜集團子公司,鳳凰娛樂也是領先的互聯網服務提供商和會員產品提供商。鳳凰娛樂自2003年成立以來,已經穩定運營了

知道的限流

mit 快的 方法 容災 優點 font 基本 很多 效應 在系統架構設計當中,限流是一個不得不說的話題,因為他太不起眼,但是也太重要了。這點有些像古代鎮守邊陲的將士,據守隘口,抵擋住外族的千軍萬馬,一旦隘口失守,各種饕餮湧入城內,勢必將我們苦心經營的朝堂廟店洗劫一空,之前

知道的pm2

【pm2】 如官網介紹的,pm2是nodejs下先進的,生產程序管理器, 安裝 1 npm  install