以芯片直读方式得到的全盘镜像解析及ext4日志区域解析
之前在centos中分析了/dev/sda1下的结构,但当对象是一块以芯片直读方式作出来的全盘镜像呢?
这次以安卓手机的全盘镜像为对象,尝试按照ext4文件系统结构手动解析,加强对ext4文件系统、EFI系统分区、GPT磁盘的理解,补充ext4文件系统的日志结构的描述。
我得到的全盘镜像有两种格式,一种.img,一种是.bin,两种镜像的组织方式是比较类似的,但可能因为是不同的直读机做出的原因,.img格式的镜像在“真正的数据”前附加了机器的标志信息。
.bin格式镜像分析
.bin格式全盘镜像是以GPT分区的方式进行管理的,GPT磁盘的总体布局如下:

.bin格式的全盘镜像头512个字节也就是0号扇区的内容是一个DOS分区,分区表的内容如下:

该分区表只有一个表项被使用,记录的分区起始扇区号是0x01,分区扇区数是:0xDA BF FF,0号扇区最后两个字节就是MBR扇区的有效标志0x55 AA。当然在dos分区表前面还有446个字节的引导代码区域,这里的引导代码没有写,就没有截图了。
接下来我们看1号扇区的内容,按照GPT磁盘的总体布局,1号扇区是EFI信息区也就是GPT头,他对解析GPT分区是很关键的存在,因为其中记录了GPT分区表、GPT分区区域的位置以及大小,分区表中每个表项的大小(字节数),下面是1号扇区部分内容:

可以看到前7个字节是EFI分区的签名“EFI PART”,0x28-0x2F处是GTP分区区域的起始块号,接下来8个字节是终止块号,0x47-0x4F处的8个字节是GPT分区表的起始块号,接下来的4个字节是GPT分区表表的项数,然后四个字节是GPT分区表每一项的字节数。
从2号扇区到33号扇区存储的就是GPT分区表,包括我们表熟悉的/system,/boot,/userdata分区等等,以/userdata分区为例,查看他的GPT分区表项:

前16个字节是分区类型GUID,接下来16个字节是分区的唯一GUID,然后8个字节是分区起始扇区号,接下来是分区终止扇区号,再8个字节是分区属性,后面一直到这个表项结束都是分区名的Unicode码。
我们查看0x564000号扇区的内容(偏移0x564000*0x200=0xac800000)发现内容是全0,然后在偏移量增加0x400后发现了ext4的超级块结构,这和对单个分区的解析结果是一致的,说明我们解析全盘镜像的时候,与解析单个分区相比,只是增加了解析EFI分区和GPT分区的部分。
/userdata分区日志分析
接下来通过解析一下/userdata分区的日志部分,来记录ext4的日志结构。
查看/userdata分区的超级块,得到该分区中块的0号块组的起始块号是0,每个块组有0x8000个块、0x2000个i节点,每个块大小是0x1000个字节,i节点表的每个表项长度是0x100个字节。
接下来我们需要通过查看块组描述符表来得知每个块组的i节点表起始块号。块组描述符表的起始块号分三种情况:
1、当块的大小为0x400时,块组描述符表在2号块(偏移0x800处)
2、当块的大小为0x800时,块组描述符表在1号块(偏移0x800处)
3、当块的大小为0x1000时,块组描述符表在1号块(偏移0x1000处)
这里计算块组描述符表的时候需要加上分区的起始偏移0xac800000,也就是0xac801000

可以看到0号块组的i节点表起始块号是0x0303,我们知道ext4文件系统的8号i节点是日志节点,我们来查看8号i节点的内容以找到日志所在块号。
8号i节点所在的偏移为:0xac800000+0x0303*0x1000+(8-1)*0x100=oxacb03700:

可以看到该i节点的extent结构中,有两个有效的entry,extent_header的深度为0,第一个extent结构记录的块号是0x0503,第二个extent记录的块号是0x0504。
我们查看0x0503块号的内容,计算该块的偏移位置:0xac800000+0x0503*0x1000=0xacd03000
在查看日志内容前我们需要清楚一点,ext4文件系统整个是小端模式,但ext4的日志区域确实大端模式

上面是一个日志的超级块部分内容,前12个字节是ext4日志的标准头,通过他我们可以区分某个块是否是日志块,是日志块的哪个部分。前4个字节ext4的日志签名“c0 3B 39 98”,然后四个字节是日志块类型,0x04是超级块(版本2),0x01是描述符块,0x02是提交块,0x03是超级块(版本1),0x05是废除块,然后四个字节是序号。接下来就进入了超级块的内容,前4个自己是日志块的大小,一般和普通文件的块大小是相同的,接下来4个字节是日志块的数量,然后4个字节是日志的实际起始块号,然后4个字节是第一个事务序号,接下来4个字节是第一个事务序号的日志块号,这里所提到的日志块号都是相对于日志区域的,因此在使用的时候需要进行转换。
接下来我们查看1号日志块的内容,

1号块开始4个字节是日志标准头的签名,接下来的4个字节的属性值为0x01,说明这是一个描述符块,标准头结束后就是真正的描述符块的内容,0x2E 00 02是这组记录的文件系统块号,接下来4个字节是项标志。项标志有四种,分别为:0x01(日志块避开),0x02(与前面具有相同的UUID,此时没有后面的UUID区域),0x04(本块已经被事务删除),0x08(本描述项为描述块中的最后一个描述项)。红框框出本描述符块记录的部分块号。接下来的块将按照描述符块中记录的块号顺序“抄写”文件系统块。

上面是下一个块的部分内容,可以看到这是对i节点表所在块的“抄写”,当然读这块内容的时候需要依照小端模式读取。
在描述符块中记录的块号被“抄写”完成后,会有一个日志提交块紧随其后,表明一个日志记录的完成

观察可发现,该日志提交块的事务序号和日志描述符块的事务序号是相同的。
以上就是简单解析一个ext4日志区域的过程。
另外.img格式的镜像,我目前看到的除了在EFI分区信息前面添加了制作镜像的机器信息外,其他结构和.bin是一样的。
以芯片直读方式得到的全盘镜像解析及ext4日志区域解析的更多相关文章
- kafka直连方式消费多个topic
一个消费者组可以消费多个topic,以前写过一篇一个消费者消费一个topic的,这次的是一个消费者组通过直连方式消费多个topic,做了小测试,结果是正确的,通过查看zookeeper的客户端,zoo ...
- SRAM(静态)存储器芯片的读/写周期
一. 要保证正确地读/写,必须注意CPU时序与存储器读/写周期的配合.一般存储器芯片手册都会给出芯片读/写周期的时序图. Intel 2114芯片的读.写周期时序如图所示. 二. 读周期 读操作时,必 ...
- Dubbo直连方式
目录 一.dubbo概述 1. 基本架构 2. dubbo 支持的协议 二.直连方法 三.创建服务提供者 1. 思路 1. 创建maven web 2. pom.xml 3. 创建实体 4. 创建服务 ...
- SparkStreaming直连方式读取kafka数据,使用MySQL保存偏移量
SparkStreaming直连方式读取kafka数据,使用MySQL保存偏移量 1. ScalikeJDBC 2.配置文件 3.导入依赖的jar包 4.源码测试 通过MySQL保存kafka的偏移量 ...
- STM32-对芯片启动读保护,实现加密(详解)
STM32可以对存储在flash上的程序进行读保护. 启动读保护后,用户就不能再读写程序了. 所以,在烧写程序之前,需要程序调用关闭读保护.关闭读保护后,会自动清空flash上的程序 头文件位于:#i ...
- 内存直读技术DMA
DMA(Direct Memory Access) DMA(Direct Memory Access)即直接存储器存取,是一种快速传送数据的机制. 工作原理 DMA是指外部设备不通过CPU而直接与系统 ...
- 直读Innodb datafile
这两天有空翻了翻大神写的<innodb存储引擎>,手痒亲身实践.由于此书出版了有段时日,没有用其推荐的python工具,通过点滴推敲,略微发现其中冰山一角的奥秘.对于今后对于一些问题查证或 ...
- css水平竖直居中方式
CSS水平和垂直居中的几种实现方法: 1.单行垂直居中 文字在层中垂直居中vertical-align 属性是做不到的.我们这里有个比较巧妙的方法就是:设置height的高度与line-height的 ...
- Dubbo直连方式改造
目录 一.dubbo 服务化最佳实践 1. 分包 2. 粒度 3. 版本 二.改造 dubbo 项目 三.link-interface 1. pom.xml 2. 实体类 3. 公共接口 四.提供者 ...
随机推荐
- 如何安装Elasticsearch?
最近工作中要用到搜索引擎,由于目前用的搜索引擎是LeanCloud 提供的 ,不太好用,不支持范围等搜索,而且每天还收费30元,请求次数也有限制.基于这些原因,我们只好在自己的服务器上部署搜索引擎了. ...
- 【CSS Cookbook】笔记摘要(一)
概要 CSS的优点:将表现和内容相分离:更好地控制页面布局:大大减少了文件尺寸:缩短了改版时间:提高了易用性. CSS全称层叠式样表(Cascading Style Sheets). 1.问题:如何最 ...
- .net后台获取DataTable数据,转换成json数组后传递到前台,通过jquery去操作json数据
一,后台获取json数据 protected void Page_Load(object sender, EventArgs e){ DataTable dt = DBhepler.GetDataT ...
- CoreCLR源码探索(六) NullReferenceException是如何发生的
NullReferenceException可能是.Net程序员遇到最多的例外了, 这个例外发生的如此频繁, 以至于人们付出了巨大的努力来使用各种特性和约束试图防止它发生, 但时至今日它仍然让很多程序 ...
- Grid search in the tidyverse
@drsimonj here to share a tidyverse method of grid search for optimizing a model's hyperparameters. ...
- A Bayesian election prediction, implemented with R and Stan
If the media coverage is anything to go by, people are desperate to know who will win the US electio ...
- 【2017-06-06】Ajax完整结构、三级联动的制作
一.Ajax完整结构 $.ajax({ url:"Main.ashx", data:{}, dataType:"json", type:"post&q ...
- Vivado简单调试技能
Vivado简单调试技能 1.关于VIO核的使用 首先配置VIO核: 配置输入输出口的数量5,5 配置输入口的位宽 配置输出口位宽和初始值. 例化与使用: vio_0 U1 ( .clk(clk_27 ...
- python基础操作_文件读写操作
#文件读写# r只能读不能写,且文件必须存在,w只能写不能读,a只能写不能读# w+是写读模式,清空原文件内容# r+是读写模式,没有清空原文件内容,# 只要有r,文件必须存在,只要有w,都会清空原文 ...
- C语言进制转换的一个小错误
今天学妹问了一个问题,问题是这样的 有以下程序 #include <stdio.h> void main(){ int m=0256,n=256; printf("%o %o& ...