web-dev-qa-db-ja.com

ext4ファイルシステムのオフセットを見つけるにはどうすればよいですか?

ディスクの最初のセクターを読み書きできない、故障したハードドライブがあります。 I/Oエラーが発生するだけです。ディスク上には(ほとんど)正常に見える他の領域があります。パーティション(ext4)をマウントして、回復したいファイルにアクセスできるかどうかを確認しています。 mountコマンドはoffsetオプションをサポートしているので、パーティションテーブルが読み取り不可で書き込み不可であっても、ファイルシステムをマウントできるはずです。問題は、オフセットを見つける方法です。 ext4ツールのどれも、この特定の機能を備えていないようです。

9
Ernest A

もちろん、標準のオフセット自体はありません。もちろん、どこからでもパーティションを開始できます。しかし、少しの間、最初のパーティションを探していて、それが多かれ少なかれデフォルトを受け入れて作成されたと仮定しましょう。次に、従来のDOSパーティションテーブルを使用していたとすると、2つの場所が見つかる可能性があります。

  1. (512バイト)セクター63から。これは非常に長い間伝統であり、誰かが4Kディスクを思いつくまでは機能していました...
  2. (512バイト)セクター2048から。これは、4Kディスクに対応するための新しい伝統です。
  3. ボーナスオプション!セクター56でのサーティング。これは、誰かが63開始パーティションを4Kセクターと整列させるために移動した場合に起こります。

ここで、次に進むには、お気に入りの16進ダンプツールを選択して、 ext4ディスクレイアウト について少し学びます。特に、これは1024バイトのパディングで始まり、ext4では無視されます。次はスーパーブロックです。オフセット0x38(スーパーブロックの先頭から、またはパーティションの先頭から0x438、または10進数では1080)でマジック番号0xEF53をチェックすることにより、スーパーブロックを認識できます。マジック番号はリトルエンディアンです。 。したがって、実際には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..........

マウントするオフセット(またはlosetup)を指定するときは、スーパーブロックではなく、パディングの開始位置にオフセットを指定する必要があることに注意してください。

さて、それが最初のパーティションではない場合、または予想される2つ(3つ)のスポットのいずれにもない場合は、基本的にマジック番号0xEF53を検索します。これはtestdisk(コメントで推奨)が行うことです。

13
derobert

@ derobertの回答 に基づいて、ddからの入力ストリームを解析し、各セクターをスキャンして次のようなものを探すプログラム( Gist )を作成しました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++;
  }
}

注:パーティションの開始だけでなく、その中に superblocks も見つかります。

どちらの場合でも、 dumpe2fs 結果を分析します。疑わしいスーパーブロックの先頭をファイル(私の非公式のテストによると、少なくとも最初の6セクター)にダンプできます。それがスーパーブロックである場合は、dumpe2fsは、他のスーパーブロックの相対的な位置を(特に)教えてくれます。

5
mwfearnley

別のオプションを試してください(たとえば、debugfsやfsck.ext4を使用)。

debugfs:

最初にdebugfsをマウントする必要があります(障害のあるハードディスク自体ではありません)。

http://johnsofteng.wordpress.com/2013/11/20/sysfs-procfs-sysctl-debugfs-and-other-similar-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/

もう1つは「sleuthkit」(「Sudo apt-get install sleuthkit」)です。これには、iノードに関するブロック情報を提供する「istat」のようなコマンドがあり、オフセットを取得してデータコンテンツを簡単にブロックできます。

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

(ところで、ブロックサイズが1024の場合、debugfsの「show_super_stats」コマンドから、ブロック1はディスクの先頭から1024バイトのオフセットになり、各ブロックグループは複数のブロックを持つこともできます。)

2
Peter Teoh

パーティションの開始位置を推測し、ブルートフォースを適用します。

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時間を費やしている場合は、試してみる価値があるかもしれません。

2
goldilocks

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

ここにある完全なスクリプト

1
taro

これはテストされていませんが、このSU Q&Aで説明されている方法を使用できると思います: Linuxおよびext3/4のrawデバイスのオフセットからのiノード/ファイルの逆ルックアップ?

ファイルのiノード+ディスクオフセット+ブロックサイズを使用してファイルのオフセットを決定できるようです。

0
slm