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


9

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


1
testdiskと付随するphotorecを試してください。
jippie 2013

@jippieは、ディスク全体をスキャンするのにtestdiskに6時間かかり、最終的にはパーティションが見つかりませんでした。ファイルシステムの場所を直接見つけてマウントするのが最善の戦略だと思います。
アーネストA

photorecはおそらくファイルをディスクから取り出すことができますが、ファイル名とパス名は失われます。もちろん、ファイルシステムのマウントに成功したが、testdiskがそれを見つけられなかった場合は、ファイルシステムの先頭も破損している可能性があります。
jippie 2013

回答:


13

もちろん、標準のオフセット自体はありません。もちろん、どこからでもパーティションを開始できます。しかし、少しの間、最初のパーティションを探していて、それが多かれ少なかれデフォルトを受け入れて作成されたと仮定しましょう。次に、従来の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(コメントで推奨)の機能です。


2
成功!!!私は自分のスクリプトを書かなければなりませんでした。testdiskそれは見つかりません。助けてくれてありがとう。
アーネストA

これに基づいて、dd if=/dev/sda skip=$start_sector | xxd -a | grep '[02468]30: .... .... .... .... 53ef'いくつかの可能性のある一致を取得するようなものを使用できます。おそらくそれほど高速ではありませんが、より良い方法を見つけている間は実行できます。
mwfearnley 2017

「より良い方法」については、以下の私の回答をご覧ください。注:ランダムデータでこの数をスキャンするだけで、65536セクター(32 MB)ごとに誤検知が見つかります。
mwfearnley 2017

これをありがとう。気づくのに2回目の読み込みが必要だったという事実のtestdiskため、tl;dr:ヘッダーの編集を追加する必要がありました
Jan-Stefan Janetzky

5

に基づく @ derobertの答え、私はプログラム(書いた主旨からの入力ストリームを解析します)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して結果を分析することをお勧めします。疑わしいスーパーブロックの開始をファイル(私の非公式テストによると、少なくとも最初の6セクター)にダンプすることができ、それ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

動作しますが遅いです。オフセットがわかっているマルチパーティションイメージでこれを試したので、かなり近くで開始できました。で投げたecho "--->$i<---"ので、そうでなければ、それは進捗状況を測定することは不可能だとのライン。私はあなたがbsz4096に増やすことができると思います、それは物事をスピードアップします。
goldilocks 2013

パーティションが「トラック」(またはシリンダーか)境界で始まる従来のレイアウトを想定すると、速度を大幅に向上させることができます。
derobert、2013

私の推定では、このソリューションが実用的であるためには不十分でしたが、他の状況でも機能する可能性があります
Ernest A

2

別のオプションを試してください(たとえば、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バイトのオフセットであり、各ブロックグループは複数のブロックを持つこともできます。)


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

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


0

これはテストされていませんが、このSU Q&Aで説明されている方法を使用できると思います

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


1
この方法でファイルシステムの開始場所を特定する方法がわかりません。
アーネストA
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.