Ich Fall, dass Inodes weg sind und wir nur noch auf vorhandene Daten (Inhalte) zugreifen können, kann noch immer der Ansatz verfolgt werden, mal für jeden Block herauszufinden, welche Art Daten da drin sind. Das sollte eigentlich mit jedem Filesystem funktionieren.
Nebenbei: Dateien werden blockweise geschrieben, weshalb pro Block nur zu einer Datei zugehören kann.
`dd` und `file` helfen uns dabei. Also per `dd` jeden Block extrahieren, `file` zur Auswertung übergeben und das Ergebnis in ein Logfile speichern:
#!/bin/bash
bs=4096
length=`ls -l disk.img | awk '{print $5}'`
echo -n > filetypes.log
for (( i=0 ; $i<$length ; i=$i+$bs )); do
dd if=disk.img bs=$bs count=1 skip=$i status=noxfer
| file -b -
| egrep -v ": data$"
| sed "s/$/ ($i)/"
>> filetypes.log
done
Problem: Das dauert bei 250 GB etwa 7 Tage! Ich konnte es etwa um den Faktor 7 beschleunigen, indem ich eine 25 MB grosse RAM-Disk schuf, jeweils ca 20 MB der Disk auf diese extrahierte und diese per split teilte. Danach kann man file diese Blockdateien als Parameter übergeben:
#!/bin/bash
mount -o size=25M -t tmpfs tmpfs /mnt
count=5000
bs=4096
length=`ls -l disk.img | awk '{print $5}'`
echo -n > filetypes.log
for (( i=0 ; $i<$length ; i=$i+$bs*$count )); do
dd if=disk.img bs=$bs count=5k skip=$i status=noxfer
| split -b $bs -a 5 -d - /mnt/ file /mnt/*
| egrep -v ": data$"
| sed "s/^\/mnt\//$i+/"
>> filetypes.log
rm /mnt/*
done
umount /mnt
Warum ist das viel schneller?
- file muss bei jedem Aufruf seine magic-Datei einlesen und verarbeiten. Wenn ich mehrere Dateien in einen Aufruf packen kann, kann ich mir diesen Vorgang sparen.
- Dann fand ich heraus, dass mit dd einzelne Blocks zu bilden schnell viel Zeit beansprucht. Der Split-Befehl macht das im Nu.
- Grundsätzlich auf einer RAM-Disk zu arbeiten, heisst eine um 1 Mio mal schnellere Zugriffszeit nutzen zu können (Harddisks arbeiten im ms-, RAM im ns-Bereich: 1 ns ist 106 mal kürzer als eine ms).
Was können wir nun mit dem Ergebnis anfangen?
`grep jpeg filetypes` ergibt uns eine Liste von Blocks, wo jpeg-Daten gespeichert sind. Wir können mit `dd` diese Blocks auslesen und in eine neue Datei abspeichern – und hoffen, dass die Daten nicht all zu oft fragmentiert abgelegt wurden!
Bei Text-Daten ist das Prinzip wohl einfacher nachvollziehbar.
Weitere Links zum Thema
http://www.noah.org/wiki/Forensics,_Undelete,_and_Data_Recovery
http://oss.sgi.com/LDP/HOWTO/Ext2fs-Undeletion-Dir-Struct/index.html
http://oss.sgi.com/LDP/HOWTO/Ext2fs-Undeletion-Dir-Struct/index.html