使用hexdump工具追蹤EXT4文件系統中的一個文件

  昨天追蹤EXT4文件系統的過程當中出了點問題,就是找不到文件,因而試了一下追蹤FAT32文件系統的,成功以後有了點信心,今天繼續嗑EXT4文件系統,終於找到啦,記錄一下。linux

  • 操做系統:linux(centos 6.5)
  • 文件系統:EXT4
  • 工具:hexdump,windows自帶計算器
  • 參考資源:《數據重現-文件系統原理精解與數據恢復最佳實踐》(馬林 著)

         《基於EXT4文件系統的數據恢復方法研究》(徐國天)windows

         題爲《Ext4文件系統架構分析》的系列博客centos

         題爲《 深刻理解ext4(一)----extent區段》的博客數據結構

         題爲《ext4的Extent解析》的博客架構

         題爲《ext4_ext_find_extent解析》的博客工具

        

EXT4文件系統架構(非原創):flex

  

補充說明:EXT4文件系統中只有0號塊組的超級塊和塊組描述符表的位置是固定的,其餘都不固定。其中,超級塊老是開始於偏移位置1024(字節),佔據1024個字節,塊組描述符表緊隨超級塊後面,佔用的大小是不定。spa

步驟:操作系統

一、查看文件系統基本狀況,新建子目錄和文件設計

  

能夠看到掛載在/boot目錄下的文件系統類型是EXT4,所以在改目錄下新建子目錄及文件:

文件內容爲:「This test is belong to Boot folder!」文件基本信息以下:

二、查看超級塊,找到0號塊組起始塊號、塊大小、每塊組所含塊數、每塊組i節點數、第一個非保留i節點、每一個i節點大小。

命令:hexdump -s 1024 -n 1024 -C /dev/sda1

查看結果:

首先能夠看到0x38-0x39是EXT系列文件系統的簽名標誌:「53 ef」

0x14-0x17是0號塊組起始塊號:0x01,說明超級塊前面有一個塊爲保留塊,用來存儲引導程序。

0x18-0x1b是塊大小:0x00,這裏的值指的是將1024字節左移的位數,移動0位也就是1024字節,移動一位至關於乘以2,就是2048字節。

0x20-0x23是每塊組所含塊數:0x2000(十進制8192)

0x28-0x2b是每塊組所含i節點數:0x07f0(十進制2032)

0x54-0x57是第一個非保留i節點號:0x0b(11),通常爲lost+found目錄

0x58-0x59是每一個i節點結構的大小:0x80(十進制128),也就是每一個i節點表項佔用128個字節。

三、查看塊組描述符表,找到塊位圖塊、i節點位圖塊、i節點表起始塊號、塊組目錄數。

命令:hexdump -s 2048 -n 1024 -C /dev/sda1

查看結果:

塊組描述符表中每一個塊組使用32個字節來描述,所以第一個32字節描述的就是0號塊組。

0x00-0x04是塊位圖塊起始塊號:0x0104

0x05-0x07是i節點位圖塊起始塊號:0x0114

0x08-0x0b是i節點表起始塊號:0x0124

0x10-0x11是該塊組的目錄數:0x02

這裏獲取的起始塊號是邏輯塊號(將文件系統全部的塊從0開始遞增編號),所以在計算偏移量時能夠直接乘以每塊字節數(0x400,也就是十進制的1024)

這裏補充說明一下:EXT3文件系統的塊位圖塊號、i節點位圖塊和i節點表起始塊號是遞增的,而這裏他們三個之間倒是相差一個常量:16。

由於這裏使用了一個EXT4新引進的結構:Flexible 塊組(flex_bg)

Flexible 塊組

  Flexible 塊組的設計目的是組成更大的邏輯塊組,儘可能讓大文件連續,將元數據彙集加快元數據載入。所以它的作法是將幾個塊組的塊位圖塊,i節點位圖塊,i節點表塊放在這個邏輯塊組的第一個塊組中,這樣剩下的塊組中就只存儲了該塊組的超級塊和塊組描述表。

上面的塊組描述表中能夠看出這個Flexible 塊組是將16個塊組合成了一個邏輯塊組。

  提及Flexible 塊組就要提起元塊組(Media Block Group),由於他和Flexible 塊組是「有你沒我」的關係。Flexible 塊組是移動了塊位圖塊、i節點位圖塊、i節點表塊,元塊組是減小了塊組描述符表的備份,本來塊組描述符表和超級塊一塊兒備份在塊組號爲0或者三、五、7的冪的塊組,元塊組是隻在一個元塊組的第1、二個塊組和最後一個塊組中備份塊組描述符表,增長元塊組存儲數據的空間。

 

 

 

 

 

 

 

 

 

 

三、從根目錄中找到子目錄

  第一步咱們提到了第一個非保留i節點號爲11,那麼前面的10個保留i節點的做用是什麼呢(i節點號從1開始編號),這裏只說明2號節點是存儲的是根目錄i節點號,所以咱們讀取i節點表的2號表項值就能夠找到根目錄所在塊號了。

  計算i節點表項的偏移量涉及到了塊組描述符表中的i節點表起始塊號:0x0124。

  某i節點表項起始字節=i節點起始塊號*每塊所佔字節數+(該i節點號-1)*每一個i節點表項所佔字節數

   0x0124*0x400+(0x02-0x01)*0x80=0x49080

下面就能夠讀取根目錄i節點表項值了。

命令:hexdump -s 0x49080 -n 128 -C /dev/sda1

查看結果:

0xa8-0xd7是12個直接塊指針,其中四個字節爲一個單位,表示一個塊號。

(這裏要解釋的是:EXt4文件系統將12個直接塊指針、1個一級間接塊指針、1個二級間接塊指針、1個三級間接塊指針,一共60個字節用extent結構來替換,但前提是偏移0xa0-0xa3處的標誌位置爲「00 00 08 00」,而這裏全爲0,則證實沒有使用extent結構,所以依舊按照塊指針形式查找根目錄)

圖中能夠看出根目錄只佔用了一個塊,塊號爲:0x1104

  根目錄的起始偏移字節爲=根目錄所在塊號*每塊所佔字節數

則根目錄的起始偏移字節:0x1104*0x400=0x441000

使用命令:hexdump -s 0x441000 -n 1024 -C /dev/sda1 查看根目錄內容:

查看/boot目錄下的文件:

能夠看到二者的內容是相符的,說明咱們找的沒有錯。根目錄中BOOTDIR的目錄項用黑色底紋標註。

0x6c-0x6f是該文件內容所在i節點號:0x7f01

0x70-0x71是本目錄項長度:0x10(16字節)

0x72是本目錄項名字長度0x07(7個字節)

0x73是本文件類型:0x02(表示目錄)

0x74開始是文件名的ASCCI碼:「42 4f 4f 54 44 49 52 00」

在這一步中與FAT32文件系統的區別有兩個:

  一是怎麼尋找根目錄。FAT32中根目錄在數據區的開頭,所以咱們能夠直接去數據區讀取;而EXT4文件系統中,咱們須要經過2號i節點表找到根目錄所在的塊號,才能看到根目錄內容,這裏就能夠看出EXT4文件系統將目錄也看做文件了,由於他的讀取方式和普通文件是同樣的,只不過普通文件須要從目錄中獲得i節點號,而根目錄是一開始就定好了i節點號。

  二是目錄的大小。FAT32中目錄的大小是固定的(短文件名目錄佔32字節,長文件名目錄佔多個32字節),因此當文件名過長時,使用了長文件名機制來解決,而EXT4文件系統的目錄項大小是在目錄項中靈活定的。好比這一步中咱們查看到的根目錄結果中,開始的12個字節是本目錄項,緊接着12個字節是根目錄項,而咱們要找的目標目錄項的長度是16個字節,其中說明部分(i節點號,本目錄項長度字節數,名字長度,文件類型)佔用都是同樣的,差就差在文件名部分。但咱們也看到文件名後面總有「00」補齊,這是由於目錄項的長度總要是4的倍數,所以不夠時會用0補齊。

四、從i節點表中找到子目錄所在塊號

第三步中咱們找到指向子目錄的i節點號爲0x7f01,也是邏輯i節點號,所以咱們要先找到0x7f01在哪一個塊組中:

  某i節點所在塊組=該i節點號/每塊組i節點個數

  0x7f01/0x7f0=0x10(十進制16)

  某i節點所在i節點表號=該i節點號%每塊組i節點個數

  0x7f01%0x7f0=0x01

所以0x7f01在16號塊組的i節點表中,在改i節點表的1號表項中。

接下來咱們要從塊組描述符表中找到16號塊組的i節點表起始塊號,以便找到子目錄所在塊號。

  某塊組在塊組描述符表中偏移字節=塊組描述符表起始字節+塊組號*每塊組描述符表項字節數

  2048+16*32=2560字節

咱們讀取2560偏移字節開始的32字節:

能夠看到:0x08-0x0b爲i節點表起始塊號:0x020021

讀取16號塊組i節點表的1號i節點表項值:

這裏須要重點注意:0x20-0x23處的標誌內容爲「00 00 08 00」也就是0x080000,表示使用了extent結構,所以這裏文件子目錄的搜索就須要按照extent結構來讀取0x28-0x63這60個字節的內容。

有個疑問:EXT4文件系統何時使用extent結構,查看0號塊組的10個保留i節點時,看到只有8號也就是日誌節點啓用了extent結構,其餘都沒有使用,而其餘塊組中彷佛是都默認啓用extent結構,但也發現了例外,所以不能肯定EXT4關於啓用extent結構的規定,後續須要注意!

下面介紹一下extent的結構,內容有參考。

每一個extent結構佔用12個字節,因此每一個i節點表項中能夠有60/12=5個extent結構,這其中第一個extent做爲extent頭(extent header是一個B+樹的描述頭),剩下的4個是extent體(extent body,因爲extent樹中的節點有兩種:索引節點和葉子節點,所以當節點爲索引節點時(能夠從extent header中區分索引節點和葉子節點)extent body存儲的是下一級extent樹節點信息,當節點爲葉子節點時extent body 中存儲的是數據塊塊號信息)

extent樹結構

 

extent數據結構

extent header

 

這裏要說明的是:魔數是一個校驗值,只有當校驗結果是0xf30a時B+樹的塊才正確

        節點在extent樹中的深度是從葉子節點算起,所以根節點的深度是最深的(看到有人說根節點的最大深度不超過5),當深度爲0時代表是葉子節點,那麼這個節點就是數據節點,他後面的extent body就是指向的數據塊,存儲數據塊號;當深度大於0,後面的extent body表示索引節點。

extent body

當爲索引節點時

當爲葉子節點時

 

補充說明:當extent body表示索引節點時最後最後兩個節點冗餘是爲了遷就葉子節點。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

從0x28-0x63是extent結構。

extent頭中說明的信息有:本區段有一個extent body,最大區段個數爲4,本段在extent樹中深度爲0,是葉子節點。

後面緊着的12個字節是extent body說明的信息有:本區段的第一個塊號是0,本區段含有一個塊,本區段指向的數據塊塊號爲0x021002。

該塊的偏移字節:0x8400800

五、從子目錄對應的i節點號獲得目標文件塊號

查看結果第4步中子目錄塊內容:

加黑色底紋的是本目錄(「.」)和根目錄(「..」)接下來就是目標文件:BOOTTEXT.txt,他的i節點號爲:0x7f04

 查看i節點表,找到目標文件的塊號:

  該i節點表項的偏移字節爲:0x020021*0x400+(0x7f04%0x7f0-1)*0x80=0x8008580

讀取該偏移字節處開始的128字節內容:

一樣目標文件的i節點表項也啓用了extent結構,按照與第4步一樣的方法分析,得帶目標文件所在塊號0x024005(偏移字節爲0x9001400)。

接下來讀取該塊內容:

找到啦!和第一步中使用cat命令查看的文件內容一致。

相關文章
相關標籤/搜索