使用hexdump工具追踪EXT4文件系统中的一个文件

  昨天追踪EXT4文件系统的过程中出了点问题,就是找不到文件,于是试了一下追踪FAT32文件系统的,成功之后有了点信心,今天继续嗑EXT4文件系统,终于找到啦,记录一下。

  • 操作系统:linux(centos 6.5)
  • 文件系统:EXT4
  • 工具:hexdump,windows自带计算器
  • 参考书目:《数据重现-文件系统原理精解与数据恢复最佳实践》(马林 著),题为《Ext4文件系统架构分析》的系列博客,不知道原作是谁了。

EXT4文件系统架构:

  

补充说明:EXT4文件系统中只有0号块组的超级块和块组描述符表的位置是固定的,其他都不固定。其中,超级块总是开始于偏移位置1024(字节),占据1024个字节,块组描述符表紧随超级块后面,占用的大小是不定。

步骤:

1、查看文件系统基本情况,新建子目录和文件

  

可以看到挂载在/boot目录下的文件系统类型是EXT4,因此在改目录下新建子目录及文件:

文件内容为:“This test is belong to Boot folder!”文件基本信息如下:

2、查看超级块,找到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个字节。

3、查看块组描述符表,找到块位图块、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)

3、从根目录中找到子目录

  第一步我们提到了第一个非保留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个直接块指针,其中四个字节为一个单位,表示一个块号。

图中可以看出根目录只占用了一个块,块号为: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补齐。

4、从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节点表项值:

从0x28-0x57是12个直接块指针,以4个字节为单位读取,其中有的指向超级块(0x01)。0x21002指向的块存储的是子目录内容。

该块的偏移字节:0x8400800

5、从子目录对应的i节点号得到目标文件块号

查看结果第4步中子目录块内容:

加黑色底纹的是本目录(“.”)和根目录(“..”)接下来就是目标文件:BOOTTEXT.txt,他的i节点号为:0x7f04

 查看i节点表,找到目标文件的块号:

  改i节点表项的偏移字节为:0x020021*0x400+(0x7f04%0x7f0-1)*0x80=0x8008580

读取该偏移字节处开始的128字节内容:

得到的目标文件所在块号为0x024005(偏移字节为0x9001400),接下来读取该块内容:

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

时间: 2024-10-04 21:34:52

使用hexdump工具追踪EXT4文件系统中的一个文件的相关文章

使用seek()方法,将Hadoop文件系统中的一个文件在标准输出上显示两次

//使用seek()方法,将Hadoop文件系统中的一个文件在标准输出上显示两次 package com; import java.io.IOException; import java.net.URI; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FileSystem; import org.apac

在/proc文件系统中增加一个目录hello,并在这个目录中增加一个文件world,文件的内容为hello world

一.题目 编写一个内核模块,在/proc文件系统中增加一个目录hello,并在这个目录中增加一个文件world,文件的内容为hello world.内核版本要求2.6.18 ? 二.实验环境 物理主机:win7 64bit, i5双核,8G内存 虚拟机:Vmware Workstation 10.0.2 虚拟主机: CentOs-5.11,内核2.6.18 ? 三.实验思路 在着手解决问题之前,我在网上查阅了一些资料,大多是关于模块的介绍.linux内核采用的是模块化编程,这样可以很容易的添加或

获取列表中某一个文件夹下的列表项集合(不包含子文件夹对象,也不包含子文件夹中的列表项)

RT,方法如下: 1 SPListItemCollection GetSubItemsWithoutFoldersInParrentFolder(SPFolder parrent) 2 { 3 SPList list = parrent.Item.ParentList; 4 SPQuery query = new SPQuery(); 5 query.Folder = parrent; 6 query.Query = "<Where><Eq><FieldRef Na

比较两个文件中,一个文件比另一个文件多的行

1. 该脚本用来比较两个文件中,其中一个文件比另一个文件多的行,常用来工作环境中,对比得出多余的ip地址 #!/bin/bash #different in file1 and file2 #author:vaedit #date:2017/8/20 #read -p "请输入第一个文件路径" file1 #read -p "请输入第二个文件路径" file2 function print_help(){ echo "该脚本只用来对比一个文件比另一个文件多

利用extundelete工具恢复Centos6.5中误删除的文件

实验目的:利用extundelete工具恢复误删除的文件实验环境:在Linux系统中安装一台Centos6.5在Centos6.5中新增磁盘并创建分区,模拟删除并进行回复的操作设置文件共享权限,使虚拟机可使用宿主机上的文件(需要使用宿主机上的安装包)yum仓库提前安装完成,可直接使用实验安装包:e2fsprogs-libs-1.41.12-18.e16.x86_64.rpmlibcom err-devel-1.41.12-18.el6.x86_64.rpme2fsprogs-devel-1.41

安装kali 开机登陆 Ping 主机可达 Ctrl+c键来强行终止 ifconfig 查看网络状态 创建一个用户,并将其纳入root组,然后将用户删除 创建用户, 创建文件夹,文件夹中创建一些文件,将文件夹打包,最后解包到另一个文件中 创建一个文件。

安装linus操作系统 直接按回车确定 Live(amd64),就可以直接自动安装进入操作系统 安装完成后,进入界面. 创建用户zfh,密码123456 将用户zfh删除 利用ifconfig查看网络状态 创建zfh17文件夹,在文件夹里面创建17.txt,和18.txt. 利用rm,删除17.txt 利用ps-ef显示进程 查看磁盘容量 显示目录中所有文件的大小 在zfh200里面创建两个文件夹zfh201和zfh202,将zfh201压缩到zfh202中 解压缩 windows操作系统命令使

分别应用include指令和include动作标识在一个jsp页面中包含一个文件。

hello.jsp <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+re

导航窗格中添加一个文件夹(类似OneDrive 和 Dropbox)

Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Classes\Wow6432Node\CLSID\{7854FF7A-470F-4D04-9FC5-4CFC7B2A0E89}]@="WiBoxTest""System.IsPinnedToNamespaceTree"=dword:00000001"SortOrderIndex"=dword:00000042 [HK

C#获取路径中最后一个文件夹的名字

1 using System; 2 using System.IO; 3 4 namespace ConsoleApplication1 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 string path1 = @"E:\uniuProject5.6.2\art\UnityArt(u3d5.6.2)\Assets\Cloth\FBX\Character\Models"; 11 string path2