Android安全–ELF文件格式解析

来源:http://www.cnblogs.com/8hao/archive/2016/03/08/5253194.html
-Advertisement-
Play Games

一、簡介 可執行鏈接格式(Executable and Linking Format)最初是由 UNIX 系統實驗室(UNIX System Laboratories,USL)開發併發布的,作為應用程式二進位介面(Application Binary Interface,ABI)的一部分。工具介面標


一、簡介

   可執行鏈接格式(Executable and Linking Format)最初是由 UNIX 系統實驗室(UNIX System Laboratories,USL)開發併發布的,作為應用程式二進位介面(Application Binary Interface,ABI)的一部分。工具介面標準(Tool Interface Standards,TIS)委員會將還在發展的 ELF 標準選作為一種可移植的目標文件格式,可以在 32 位 Intel 體繫結構上的很多操作系統中使用。

   目標文件有三種類型:

  • 可重定位文件(Relocatable File)包含適合於與其他目標文件鏈接來創建可執行文件或者共用目標文件的代碼和數據。

  • 可執行文件(Executable File)包含適合於執行的一個程式,此文件規定了exec() 如何創建一個程式的進程映像。

  • 共用目標文件(Shared Object File)包含可在兩種上下文中鏈接的代碼和數據。首先鏈接編輯器可以將它和其它可重定位文件和共用目標文件一起處理,生成另外一個目標文件。其次,動態鏈接器(Dynamic Linker)可能將它與某個可執行文件以及其它共用目標一起組合,創建進程映像。

  • 目標文件全部是程式的二進位表示,目的是直接在某種處理器上直接執行。

二、目標文件格式

   目標文件既要參與程式鏈接又要參與程式執行。出於方便性和效率考慮,目標文件格式提供了兩種並行視圖,分別反映了這些活動的不同需求。

   image

   文件開始處是一個ELF 頭部(ELF Header),用來描述整個文件的組織。節區部分包含鏈接視圖的大量信息:指令、數據、符號表、重定位信息等等。
程式頭部表(Program Header Table),如果存在的話,告訴系統如何創建進程映像。用來構造進程映像的目標文件必須具有程式頭部表,可重定位文件不需要這個表。
節區頭部表(Section Heade Table)包含了描述文件節區的信息,每個節區在表中都有一項,每一項給出諸如節區名稱、節區大小這類信息。用於鏈接的目標文件必須包含節區頭部表,其他目標文件可以有,也可以沒有這個表。

   註意:儘管圖中顯示的各個組成部分是有順序的,實際上除了 ELF 頭部表以外,其他節區和段都沒有規定的順序

   目標文件中的數據表示

   image

   目標文件中的所有數據結構都遵從“自然”大小和對齊規則。如果必要,數據結構可以包含顯式的補齊,例如為了確保4位元組對象按4位元組邊界對齊。數據對齊同樣適用於文件內部。

   這裡使用android-ndk下麵的例子hello-jni.so來分析。

三、ELF Header部分

   elf header數據如下:

   image

   ELF Header部分可以用下圖中的數據結構表示:

   #define EI_NIDENT 16
typedef struct{
unsigned char e_ident[EI_NIDENT];    //目標文件標識信息
Elf32_Half e_type;                             //目標文件類型
Elf32_Half e_machine;                       //目標體繫結構類型
Elf32_Word e_version;                      //目標文件版本
Elf32_Addr e_entry;                          //程式入口的虛擬地址,若沒有,可為0
Elf32_Off e_phoff;                            //程式頭部表格(Program Header Table)的偏移量(按位元組計算),若沒有,可為0
Elf32_Off e_shoff;                            //節區頭部表格(Section Header Table)的偏移量(按位元組計算),若沒有,可為0
Elf32_Word e_flags;                        //保存與文件相關的,特定於處理器的標誌。標誌名稱採用 EF_machine_flag的格式。
Elf32_Half e_ehsize;                        //ELF 頭部的大小(以位元組計算)。
Elf32_Half e_phentsize;                 //程式頭部表格的表項大小(按位元組計算)。
Elf32_Half e_phnum;                      //程式頭部表格的表項數目。可以為 0。
Elf32_Half e_shentsize;                  //節區頭部表格的表項大小(按位元組計算)。
Elf32_Half e_shnum;                      //節區頭部表格的表項數目。可以為 0。
Elf32_Half e_shstrndx;                  //節區頭部表格中與節區名稱字元串表相關的表項的索引。如果文件沒有節區名稱字元串表,此參數可以為 SHN_UNDEF。
}Elf32_Ehdr;

   其中,e_ident數組給出了ELF的一些標識信息,這個數組中不同下標的含義如表:

   image

   數據說明:

   ①e_ident[EI_MAG0]~e_ident[EI_MAG3]即e_ident[0]~e_ident[3]被稱為魔數(Magic Number),其值一般為0x7f,’E’,’L’,’F’。

   ②e_ident[EI_CLASS](即e_ident[4])識別目標文件運行在目標機器的類別,取值可為三種值:ELFCLASSNONE(0)非法類別;ELFCLASS32(1)32位目標;ELFCLASS64(2)64位目標。

   ③e_ident[EI_DATA](即e_ident[5])給出處理器特定數據的數據編碼方式。即大端還是小端方式。取值可為3種:ELFDATANONE(0)非法數據編碼;ELFDATA2LSB(1)高位在前;ELFDATA2MSB(2)低位在前。

   ④e_ident[EI_VERSION]](即e_ident[6])ELF頭部的版本號碼,此值必須是EV_CURRENT。

   ⑤e_ident[EI_PAD](即e_ident[7])標記e_ident中未使用位元組的開始,初始化為0。

   其它各個欄位的含義如下:

   image

四、Program Header Table部分

   數據結構如下所示:

   /* Program segment header. */ typedef struct { Elf32_Word p_type; /* Segment type */ Elf32_Off p_offset; /* Segment file offset */ Elf32_Addr p_vaddr; /* Segment virtual address */ Elf32_Addr p_paddr; /* Segment physical address */ Elf32_Word p_filesz; /* Segment size in file */ Elf32_Word p_memsz; /* Segment size in memory */ Elf32_Word p_flags; /* Segment flags */ Elf32_Word p_align; /* Segment alignment */ } Elf32_Phdr;

   其中p_type的定義如下:

/* Legal values for p_type (segment type).  */

#define PT_NULL         0               /* Program header table entry unused */
#define PT_LOAD         1               /* Loadable program segment */
#define PT_DYNAMIC      2               /* Dynamic linking information */
#define PT_INTERP       3               /* Program interpreter */
#define PT_NOTE         4               /* Auxiliary information */
#define PT_SHLIB        5               /* Reserved */
#define PT_PHDR         6               /* Entry for header table itself */
#define PT_TLS          7               /* Thread-local storage segment */
#define PT_NUM          8               /* Number of defined types */
#define PT_LOOS         0x60000000      /* Start of OS-specific */
#define PT_GNU_EH_FRAME 0x6474e550      /* GCC .eh_frame_hdr segment */
#define PT_LOSUNW       0x6ffffffa
#define PT_SUNWBSS      0x6ffffffa      /* Sun Specific segment */
#define PT_SUNWSTACK    0x6ffffffb      /* Stack segment */
#define PT_HISUNW       0x6fffffff
#define PT_HIOS         0x6fffffff      /* End of OS-specific */
#define PT_LOPROC       0x70000000      /* Start of processor-specific */
#define PT_HIPROC       0x7fffffff      /* End of processor-specific */

   p_flag表示該該段是否可讀可寫可執行

/* Legal values for p_flags (segment flags).  */

#define PF_X            (1 << 0)        /* Segment is executable */
#define PF_W            (1 << 1)        /* Segment is writable */
#define PF_R            (1 << 2)        /* Segment is readable */
#define PF_MASKOS       0x0ff00000      /* OS-specific */
#define PF_MASKPROC     0xf0000000      /* Processor-specific */

五、Section Header Table部分

   ELF 頭部中,e_shoff 成員給出從文件頭到節區頭部表格的偏移位元組數;e_shnum給出表格中條目數目;e_shentsize 給出每個項目的位元組數。從這些信息中可以確切地定位節區的具體位置、長度。

   數據結構如下:

   typedef struct{
Elf32_Word sh_name;   //節區名,是節區頭部字元串表節區(Section Header String Table Section)的索引。名字是一個 NULL 結尾的字元串。
Elf32_Word sh_type;    //為節區類型
Elf32_Word sh_flags;    //節區標誌
Elf32_Addr sh_addr;    //如果節區將出現在進程的記憶體映像中,此成員給出節區的第一個位元組應處的位置。否則,此欄位為 0。
Elf32_Off sh_offset;    //此成員的取值給出節區的第一個位元組與文件頭之間的偏移。
Elf32_Word sh_size;   //此 成 員 給 出 節 區 的 長 度 ( 字 節 數 )。
Elf32_Word sh_link;   //此成員給出節區頭部表索引鏈接。其具體的解釋依賴於節區類型。
Elf32_Word sh_info;       //此成員給出附加信息,其解釋依賴於節區類型。
Elf32_Word sh_addralign;    //某些節區帶有地址對齊約束.
Elf32_Word sh_entsize;    //某些節區中包含固定大小的項目,如符號表。對於這類節區,此成員給出每個表項的長度位元組數。
}Elf32_Shdr;

   sh_type欄位:

   image

   sh_flags欄位:

   sh_flags欄位定義了一個節區中包含的內容是否可以修改、是否可以執行等信息。如果一個標誌位被設置,則該位取值為1。未定義的各位都設置為0。

   SHF_WRITE   0×1

   SHF_ALLOC   0×2

   SHF_EXECINSTR   0×4

   SHF_MASKPROC   0xF0000000

   其中已經定義了的各位含義如下:

   SHF_WRITE: 節區包含進程執行過程中將可寫的數據。

   SHF_ALLOC: 此節區在進程執行過程中占用記憶體。某些控制節區並不出現於目標文件的記憶體映像中,對於那些節區,此位應設置為 0。

   SHF_EXECINSTR: 節區包含可執行的機器指令。

   SHF_MASKPROC: 所有包含於此掩碼中的四位都用於處理器專用的語義。

   sh_link和sh_info欄位:

   根據節區類型的不同,sh_link 和 sh_info 的具體含義也有所不同:

   image

六、特殊節區

   image在分析這些節區的時候,需要註意如下事項:

   ①以“.”開頭的節區名稱是系統保留的。應用程式可以使用沒有首碼的節區名稱,以避免與系統節區衝突。

   ②目標文件格式允許人們定義不在上述列表中的節區。

   ③目標文件中也可以包含多個名字相同的節區。

   ④保留給處理器體繫結構的節區名稱一般構成為:處理器體繫結構名稱簡寫 + 節區名稱。

   ⑤處理器名稱應該與 e_machine 中使用的名稱相同。例如 .FOO.psect 街區是由FOO 體繫結構定義的 psect 節區。

七、字元串表(String Table)

   首先要知道,字元串表它本身就是一個節區,從第二章描述中可知,每一個節區都存在一個節區頭部表項與之對應,所以字元串表這個節區也存在一個節區頭部表項對應,而在elf文件頭部結構中存在一個成員e_shstrndx給出這個節區頭部表項的索引位置。因此可以通過

   shstrab  = (rt_uint8_t *)module_ptr +shdr[elf_module->e_shstrndx].sh_offset;

   字元串表節區包含以NULL(ASCII碼0)結尾的字元序列,通常稱為字元串。ELF目標文件通常使用字元串來表示符號和節區名稱。對字元串的引用通常以字元串在字元串表中的下標給出。
一般,第一個位元組(索引為 0)定義為一個空字元串。類似的,字元串表的最後一個位元組也定義為 NULL,以確保所有的字元串都以NULL結尾。索引為0的字元串在不同的上下文中可以表示無名或者名字為 NULL的字元串。
允許存在空的字元串表節區,其節區頭部的sh_size成員應該為0。對空的字元串表而言,非0的索引值是非法的。

   在使用、分析字元串表時,要註意以下幾點:

   ①字元串表索引可以引用節區中任意位元組

   ②字元串可以出現多次

   ③可以存在對子字元串的引用

   ④同一個字元串可以被引用多次

   ⑤字元串表中也可以存在未引用的字元串

   

   先介紹這麼多,其它的信息大家自己參考:

   非蟲大大附圖:http://bbs.pediy.com/attachment.php?attachmentid=74501&d=1355835585

   ELF文件格式分析:http://staff.ustc.edu.cn/~sycheng/sst/exp_crack/ELF.pdf

   ELF文件格式官方文檔:http://download.csdn.net/detail/walkingman321/3016369

  作者:AloneMonkey    來源: Coder

問啊-定製化IT教育平臺,牛人一對一服務,有問必答,開發編程社交頭條 官方網站:www.wenaaa.com 下載問啊APP,參與官方懸賞,賺百元現金。

QQ群290551701 聚集很多互聯網精英,技術總監,架構師,項目經理!開源技術研究,歡迎業內人士,大牛及新手有志於從事IT行業人員進入!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • android事件分發機制,給控制項設置ontouch監聽事件,當ontouch返回true時,他就不會走onTouchEvent方法,要想走onTouchEvent方法只需要返回ontouch返回false即可,特別註意的是按鈕都是預設可以點擊的,當使用imageview設置ontouch監聽時,要
  • 這個是我在學習Swift過程中利用業餘時間邊學邊做的山寨優酷項目,希望可以幫助到想學習Swift的人。原版的首頁板塊數量較多,我只做了2個板塊,也就是可重用的cell,要增加板塊只要套我寫好的模板增加新的cell就可以了。所有數據都是通過介面獲得的,以達到更加真實的效果。 源碼下載:http://c
  • 當前視頻直播非常火爆,手機端的視頻直播也非常火爆,PGC、UGC的視頻直播門檻都降低了很多。 本文介紹一個:IOS 客戶端直播的SDK,代碼完全開源。 直播時代:讓IOS普通開發者一天內做出一個RTMP直播客戶端,並且帶有美艷直播功能 包含一下功能: 源碼下載:http://code.662p.co
  • 有幾篇博客寫到了怎麼實現環形進度條,大多是使用Core Graph來實現,實現比較麻煩且效率略低,只是一個小小的進度條而已,我們當然是用最簡單而且效率高的方式來實現。 先看一下這篇博客,博客地址:http://www.brighttj.com/ios/ios-implement-loop-progr
  • 改下build.gradle文件,將裡面的compileSdkVersion改為23即可 apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion "23.0.2" default
  • 該APP堪比陌陌、微信的即時通訊,功能齊全,運行正常,是一個做即時通訊軟體參考的好源碼。具體的功能有獲取好友,設置頭像,發表說說,查看好友說說,相冊,上傳圖片,與好友聊天,發送圖片,位置,文件,語音消息,表情等等功能,效果直接看下圖。測試賬號:[email protected]密碼:123456 詳細說明:
  • 我為何要封裝DialogFragment 最近在重構項目代碼,項目中創建對話框用的是Dialog,AlertDialog。但是官方推出了DialogFragment來代替Dialog。那我就去認真的瞭解下DialogFragment。 DialogFragment DialogFragment是在A
  • 仿大眾點評UI項目,實現了搜全城、餐廳排行榜頁面、按分類、地區展示、商品詳情頁面、留言點評頁面、單獨的分類頁面、登錄註冊頁面、簽到展示頁面、個人中心頁面、更多頁面等效果。 詳細說明:http://android.662p.com<ignore_js_op><ignore_js_op><ignore_
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...