ฉันจะค้นหาออฟเซ็ตของระบบไฟล์ ext4 ได้อย่างไร


9

ฉันมีฮาร์ดไดรฟ์ที่ล้มเหลวซึ่งไม่สามารถเขียนหรืออ่านส่วนแรกของดิสก์ได้ มันแค่ให้ข้อผิดพลาด I / O และนั่นคือทั้งหมดที่มี มีพื้นที่อื่น ๆ บนดิสก์ที่ดูเหมือน (ส่วนใหญ่) ปรับ ฉันกำลังพยายามเมาต์พาร์ติชัน (ext4) และดูว่าฉันสามารถเข้าถึงไฟล์บางไฟล์ที่ฉันต้องการกู้คืนหรือไม่ เนื่องจากmountคำสั่งรองรับoffsetตัวเลือกฉันควรจะสามารถเมาท์ระบบไฟล์ได้แม้ว่าตารางพาร์ติชั่นจะไม่สามารถอ่านและเขียนไม่ได้ ปัญหาคือวิธีการหาค่าชดเชย ดูเหมือนว่าไม่มีเครื่องมือ ext4 ใด ๆ ที่มีคุณสมบัติพิเศษนี้


1
ลองtestdiskและ photorec ที่มาพร้อมกัน
jippie

@jippie ใช้เวลา testdisk 6 ชั่วโมงในการสแกนดิสก์ทั้งหมดและในที่สุดก็ไม่พบพาร์ติชันใด ๆ ฉันคิดว่ากลยุทธ์ที่ดีที่สุดคือพยายามค้นหาตำแหน่งของระบบไฟล์โดยตรงและติดตั้ง
เออร์เนสต์

photorec อาจจะสามารถนำไฟล์ของคุณออกจากดิสก์ได้ แต่ชื่อไฟล์และชื่อพา ธ จะหายไป หากคุณจัดการติดตั้งระบบไฟล์ซึ่งเป็นตัวเลือกที่ดีกว่าของคุณ แต่ถ้า testdisk ไม่พบสิ่งใดโอกาสที่ระบบไฟล์เริ่มต้นก็เสียหายเช่นกัน
jippie

คำตอบ:


13

ไม่มีออฟเซ็ตมาตรฐานต่อการใช้งานแน่นอนคุณสามารถเริ่มพาร์ติชันได้ทุกที่ที่คุณต้องการ แต่ลองสมมติว่าคุณกำลังมองหาพาร์ติชั่นแรกและสร้างค่าเริ่มต้นที่ยอมรับได้มากหรือน้อย มีสองที่ที่คุณอาจพบมันสมมติว่าคุณใช้ตารางพาร์ทิชันแบบดั้งเดิมของ DOS:

  1. เริ่มที่เซกเตอร์ (512- ไบต์) 63 นี่เป็นประเพณีมาเป็นเวลานานและทำงานจนกระทั่งมีคนมากับดิสก์ 4K ...
  2. เริ่มต้นที่ (512- ไบต์) ภาค 2048 นี่คือประเพณีใหม่เพื่อรองรับดิสก์ 4K
  3. ตัวเลือกโบนัส! Sarting ที่เซกเตอร์ 56 นี่คือสิ่งที่จะเกิดขึ้นถ้ามีคนย้ายพาร์ติชัน 63-start เพื่อให้สอดคล้องกับเซ็กเตอร์ 4K

ตอนนี้เพื่อดำเนินการต่อคุณจะต้องเลือกเครื่องมือ hex-dump ที่คุณชื่นชอบและเรียนรู้เกี่ยวกับext4 Disk Layoutเล็กน้อย โดยเฉพาะอย่างยิ่งมันเริ่มต้นด้วย 1024 padding ซึ่ง ext4 ละเว้น ถัดไปเป็น superblock คุณสามารถรับรู้ซุปเปอร์บล็อกโดยการตรวจสอบหมายเลขเวทย์มนตร์ 0xEF53 ที่ออฟเซ็ต 0x38 (จากการเริ่มซูเปอร์บล็อกหรือ 0x438 จากการเริ่มพาร์ติชั่นหรือ 1080 เป็นทศนิยม) เลขเวทย์มนตร์เป็นเลขน้อย ดังนั้นมันจึงถูกเก็บไว้ในดิสก์เป็น 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) คุณต้องกำหนดออฟเซ็ตให้ตรงกับตำแหน่งที่ padding เริ่มไม่ใช่ superblock

ทีนี้ถ้าไม่ใช่พาร์ติชั่นแรกหรือไม่อยู่ในหนึ่งในสอง (สาม) สปอตที่คาดไว้โดยทั่วไปคุณจะต้องค้นหาเลขเวทย์มนตร์ 0xEF53 นี่คือสิ่งที่testdisk(แนะนำในความคิดเห็น) สำหรับคุณ


2
ความสำเร็จ !!! ฉันต้องเขียนสคริปต์ของตัวเอง testdiskจะไม่พบมัน ขอบคุณทุกท่านสำหรับความช่วยเหลือ
เออร์เนสต์

จากนี้คุณสามารถใช้สิ่งที่ต้องการ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ฉันได้เขียนโปรแกรม ( ส่วนสำคัญ ) ที่จะแยกการสตรีมอินพุตจากddและสแกนแต่ละเซกเตอร์เพื่อหาสิ่งที่ดูเหมือนจุดเริ่มต้นของพาร์ติชันเสริม

มันจะทำงานได้อย่างน้อยเร็วเท่าที่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++;
  }
}

หมายเหตุ: มันจะค้นหาไม่เพียงแค่จุดเริ่มต้นของพาร์ติชัน แต่ยังมีsuperblockภายใน

ไม่ว่าในกรณีใดฉันจะแนะนำให้ใช้dumpe2fsในการวิเคราะห์ผลลัพธ์ คุณสามารถถ่ายโอนจุดเริ่มต้นของ superblock ที่น่าสงสัยไปยังไฟล์ (อย่างน้อยหกภาคแรกตามการทดสอบอย่างไม่เป็นทางการของฉัน) และถ้ามันเป็น superblock นั้นdumpe2fsจะเป็นการบอกตำแหน่งที่เกี่ยวข้องของ superblock อื่น ๆ .


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

ฉันคิดว่านี่อาจใช้เวลาสักครู่ แต่ถ้าคุณใช้เวลา 6 ชั่วโมงกับ testdisk อาจจะคุ้มค่าที่จะลอง


ฮะนั่นมันแรงดุร้ายมาก!
Derobert

มันใช้งานได้ แต่มันช้า; ฉันลองทำสิ่งนี้ในอิมเมจหลายพาร์ติชั่นที่ฉันรู้ว่าออฟเซ็ตดังนั้นฉันจึงสามารถเริ่มต้นได้อย่างใกล้ชิด โยนเข้าecho "--->$i<---"แถวเพราะอย่างนั้นมันเป็นไปไม่ได้ที่จะวัดความก้าวหน้า ฉันคิดว่าคุณสามารถเพิ่มbszเป็น 4096 ซึ่งจะเร่งสิ่งต่าง ๆ
goldilocks

คุณสามารถเร่งความเร็วได้มากขึ้นถ้าคุณคิดว่าเลย์เอาต์แบบดั้งเดิมที่พาร์ทิชันเริ่มต้นที่ขอบเขต "แทร็ก" (หรือเป็นทรงกระบอก?)
Derobert

ประมาณการของฉันคือยากจนสำหรับวิธีแก้ปัญหานี้ในทางปฏิบัติ แต่สามารถทำงานในสถานการณ์อื่น
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/

อีกอย่างคือ "sleuthkit" ("sudo apt-get install sleuthkit") ซึ่งมีคำสั่งเช่น "istat" สำหรับการจัดเตรียมข้อมูลบล็อกเกี่ยวกับ inodes - ซึ่งคุณจะได้รับการชดเชยและบล็อกเนื้อหาข้อมูลได้อย่างง่ายดาย

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

(BTW หากขนาดบล็อกเท่ากับ 1024 จากคำสั่ง "show_super_stats" ของ debugfs จะตามมาว่าบล็อก 1 คือ 1024 ไบต์ชดเชยจากจุดเริ่มต้นของดิสก์และแต่ละกลุ่มบล็อกสามารถมีหลายบล็อกได้เช่นกัน)


1

ฉันมีภาพเฟิร์มแวร์ e-book ซึ่งรวมถึงอิมเมจพาร์ติชัน ext3fs เพื่อที่จะเมานต์และแก้ไขที่ฉันต้องสแกนภาพโดยใช้เครื่องมือ bgrepเพื่อค้นหาตำแหน่งทั้งหมดของหมายเลขเวทมนตร์ ext3fs 0x53EFและลองติดตั้งโดยใช้ offsets พบ

นี่เป็นสคริปต์ย่อที่ทำการติดตั้ง:

#!/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 นี้ได้: การค้นหา inode / file จาก offset ในอุปกรณ์ดิบบน linux และ ext3 / 4? .

ดูเหมือนว่าคุณสามารถใช้ inode ของไฟล์ + ขนาด offset ของดิสก์ + block เพื่อกำหนดออฟเซ็ตของไฟล์


1
ฉันไม่เห็นว่าวิธีการนี้จะช่วยให้ฉันทราบว่าระบบไฟล์เริ่มต้นจากที่ใด
เออร์เนสต์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.