如何找到ext4文件系统的偏移量?


9

我的硬盘驱动器出现故障,无法写入或读取磁盘的第一个扇区。它仅给出I / O错误,仅此而已。磁盘上的其他区域似乎(大部分)正常。我正在尝试挂载分区(ext4),看看是否可以访问一些我想恢复的文件。由于该mount命令支持一个offset选项,因此即使分区表不可读也不可写,我也应该能够挂载文件系统。问题是如何找到偏移量。ext4工具似乎都没有这个特殊功能。


1
尝试使用testdisk和随附的photorec
jippie 2013年

@jippie testdisk花了6个小时来扫描整个磁盘,最后没有找到任何分区。我认为最好的策略是尝试直接找到文件系统的位置并挂载它。
欧内斯特

photorec也许可以将文件从磁盘中取出,但是文件名和路径名将丢失。如果您设法装载文件系统,这当然是您更好的选择,但是如果testdisk没有找到任何文件,则很有可能文件系统的启动也已损坏。
jippie

Answers:


13

暂时没有标准偏移量,因为您当然可以在任意位置启动分区。但是让我们假设您正在寻找第一个分区,并且该分区或多或少地接受了默认设置。假设您使用的是传统的DOS分区表,那么可能有两个地方可以找到它:

  1. 从(512字节)扇区63开始。这是很长一段时间的传统,并且一直有效到有人提出4K磁盘...
  2. 从(512字节)扇区2048开始。这是容纳4K磁盘的新传统。
  3. 奖励选项!在扇区56处Sarting。如果有人移动63开始的分区以使其与4K扇区对齐,则会发生这种情况。

现在,继续,您将要选择自己喜欢的十六进制转储工具,并了解一些有关ext4 Disk Layout的知识。特别是,它以1024字节的填充开始,而ext4会忽略该填充。接下来是超级块。您可以通过在偏移量0x38(从超级块开始,或从分区开始,从0x438或十进制1080)处检查幻数0xEF53来识别超级块。幻数为little-endian。因此,它实际上以0x53EF的形式存储在磁盘上。

这是这样的xxd -a

0000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................ * 0000400: 0040 5d00 0084 7401 33a0 1200 33db a600 .@]...t.3...3... 0000410: 4963 5300 0000 0000 0200 0000 0200 0000 IcS............. 0000420: 0080 0000 0080 0000 0020 0000 6637 0952 ......... ..f7.R 0000430: 6637 0952 0200 1600 53ef 0100 0100 0000 f7.R....S....... 0000440: 9938 f851 004e ed00 0000 0000 0100 0000 .8.Q.N..........

请注意,当您将偏移量设置为挂载(或lostup)时,必须将偏移量填充到填充开始的位置,而不是超级块。

现在,如果它不是第一个分区,或者不是在两个(三个)预期位置之一中,则基本上可以搜索魔术数字0xEF53。这就是testdisk(建议在评论中)为您做的。


2
成功!!!我必须编写自己的脚本。testdisk找不到。谢谢大家的帮助。
欧内斯特(Arnest A)

基于此,您可以使用类似的方法dd if=/dev/sda skip=$start_sector | xxd -a | grep '[02468]30: .... .... .... .... 53ef'来获取一些可能的匹配项。可能不是很快,但是您可以在找到更好的方法的同时让它运行。
mwfearnley

请参阅下面的“更好方法”答案。注意:仅在随机数据中扫描此数字会发现每65536个扇区(32 MB)为假阳性。
mwfearnley

谢谢你 由于我花了第二读才注意到testdisk,所以我只需要添加tl;dr:标题的编辑
Jan-Stefan Janetzky

5

基于@derobert的答案,我编写了一个程序(gist),该程序将解析来自输入流的内容dd并扫描每个扇区以查找类似于ext分区开始的内容。

它的运行速度至少与dd从硬盘读取数据的速度一样快。删节版在下面。

最简单的用法是sudo dd if=/dev/xxx | ext2scan,尽管您可能希望修改dd命令以提高块大小或选择要搜索的区域。

#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main() {
  unsigned char const MAGIC[2] = {0x53, 0xef};
  unsigned char const ZEROS[512] = {0};

  long long int sector = 0;

  char buf[4][512];
  int empty1, empty2;

  while (read(STDIN_FILENO, buf[sector&3], 512) > 0) {
    if (!memcmp(buf[sector&3] + 0x38, MAGIC, 2)) {
      printf("Found a possible ext2 partition at sector %lld", sector-2);

      empty1 = !memcmp(buf[(sector-2)&3], ZEROS, 512);
      empty2 = !memcmp(buf[(sector-1)&3], ZEROS, 512);

      if (empty1 && empty2) printf(" (first two sectors are empty :)\n");
    }
    sector++;
  }
}

注意:它不仅会发现分区的开始,而且还会发现其中的超级块

无论哪种情况,我都建议使用dumpe2fs来分析结果。您可以将可疑超级块的开始转储到文件中(根据我的非正式测试,至少前六个扇区),如果是超级块,则将dumpe2fs(其中包括)告诉您其他超级块的相对位置。


2

猜测分区从何处开始并施加一些蛮力:

bsz=512 # or 1024, 2048, 4096 higher = faster

for i in {2..10000000}; do
    echo "--->$i<---"
    mount -o offset=$(($bsz*$i)) -t ext4 /dev/whatever /mnt/foo
    if [ $? == 0 ]; then # whahoo!
        echo Eureka
        break
    fi
done

我想这可能会花费一些时间,但是如果您已经在testdisk上花费了6个小时,也许值得尝试一下。


哈哈,那真是蛮力!
derobert 2013年

它可以工作,但是很慢。我在多分区图像上尝试了此操作,该图像的偏移量已知,因此可以将其启动得很近。正echo "--->$i<---"因为如此,否则无法进行评估。我认为您可以增加到bsz4096,这样可以加快处理速度。
goldilocks 2013年

如果您假设分区在“轨道”(或圆柱体)边界上开始的传统布局,则可以大大提高速度。
derobert 2013年

我的估计是可怜这个解决方案是可行的,但可以在其他环境下工作
欧内斯特一个

2

尝试其他选项(例如,使用debugfs和fsck.ext4):

debugfs:

您必须先安装debugfs(而不是发生故障的硬盘本身):

http://johnsofteng.wordpress.com/2013/11/20/sysfs-procfs-sysctl-debugfs-and-other-like-kernel-interfaces/

http://afzalkhanlinuxtalk.wordpress.com/2013/08/07/how-to-recover-deleted-file-in-linux/comment-page-1/#comment-8

http://blesseddlo.wordpress.com/2010/10/12/using-debugfs/

(本质上是在启用写功能的情况下使用“ debugfs -w”,然后使用“ lsdel”列出所有已删除的文件)。或者你可以使用

这是fsck.ext4:

http://linuxexpresso.wordpress.com/2010/03/31/repair-a-broken-ext4-superblock-in-ubuntu/

另一个是“ sleuthkit”(“ sudo apt-get install sleuthkit”),它具有“ istat”之类的命令,用于提供有关inode的块信息-您可以从中获取偏移量,从而轻松地阻塞数据内容。

https://www.ibm.com/developerworks/cn/linux/l-cn-ext4resize/

(顺便说一句,如果通过debugfs的“ show_super_stats”命令将块大小设置为1024,则可以看到块1与磁盘的起始位置之间的偏移量为1024个字节,并且每个块组也可以具有多个块。)


1

我有一个电子书固件映像,其中包括ext3fs分区映像,以便进行装载和编辑,我必须使用bgrep工具扫描映像以查找ext3fs幻数的所有位置,0x53EF然后尝试使用找到的偏移量进行装载。

这是执行安装的简化脚本:

#!/bin/sh
FW_IMAGE=$1
MOUNT_POINT=$2

FS_TYPE=ext3
EXTFS_MAGIC_NUM=53ef
MAGIC_OFFSET=1080

OFFSETS=`bgrep $EXTFS_MAGIC_NUM $FW_IMAGE | awk '{print toupper($NF)}'`
for OFFSET in $OFFSETS; do
  OFFSET=`echo "ibase=16; $OFFSET" | bc`
  OFFSET=`expr $OFFSET - $MAGIC_OFFSET`
  sudo mount -t $FS_TYPE -o loop,offset=$OFFSET $FW_IMAGE $MOUNT_POINT 2>/dev/null
  if [ $? -eq 0 ]; then
    echo "Success!  Offset is: $OFFSET."
    break
  fi
done

完整的脚本位于此处


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.