6.7.08

Obnova ODT souborů ze souborového systému EXT3

Konečně se nemožné stalo skutečností: před pár měsíci (přesněji 25. dubna v 19:27:32, unixovým časem 1209144452) se mi podařilo omylem smazat všechny soubory na disku. Data jsem se snažil obnovit různými nástroji, které jsou na netu k dispozici, bohužel ani s jedním jsem neuspěl; psal jsem o tom zde. Naděje jsem vkládal do programu ext3grep, který mi sice hodně pomohl a nějaké soubory obnovit dokázal, bohužel ne ty, co jsem potřeboval nejvíce, konkrétně šlo o několik ODT souborů (textových dokumentů OpenOffice). S autory ext3grepu jsem řešil způsob, jak data ven dostat a podařilo se! Postupně data dostávám z poškozené partišny ven, sice už to dělám několik hodin, ale jde to! Třeba se tento poznatek bude někomu také hodit.
Následující rady platí pro obnovu ODT souborů, ale určitě se dají předělat pro použití vyhledávání jiných typů souborů.

V prvé řadě je třeba znát bloky na diskovém oddílu, kde se ODT soubory nacházejí. K tomu posloužil právě program ext3grep, který mi padal při obnovování dat, ale bloky nalézt dokázal. ODT soubor je v podstatě hromádka zazipovaných XML souborů. Signatura ODT je tedy stejná jako u zip souboru, podle souboru /usr/share/misc/file/magic:
# ZIP archives (Greg Roelofs, c/o zip-bugs@wkuvx1.wku.edu)
0 string PK\003\004
>4 byte 0x00 Zip archive data
>4 byte 0x09 Zip archive data, at least v0.9 to extract
>4 byte 0x0a Zip archive data, at least v1.0 to extract
>4 byte 0x0b Zip archive data, at least v1.1 to extract
>4 byte 0x14
>>30 ubelong !0x6d696d65 Zip archive data, at least v2.0 to extract
>0x161 string WINZIP Zip archive data, WinZIP self-extracting
Díval jsem se, jaké signatury vytváří ODT soubory a přišel jsem vskutku na posloupnost bytů 50 4b 03 04 14. Programem ext3grep jsem dal vyhledat všechny bloky, které na tuto posloupnost bytů začínají (připomínám, že je to celkem zdlouhavý proces, můj 107GB velký diskový oddíl to procházelo téměř 2 hodiny, počítač je tím navíc zcela zahlcený, že se nedá dělat téměř nic jiného):
ext3grep /dev/sda7 --unallocated --search-start `echo "0: 504b 0304 14" | xxd -r -`
Doporučuji tento výstup přesměrovat do nějakého souboru:
ext3grep /dev/sda7 --unallocated --search-start `echo "0: 504b 0304 14" | xxd -r -` |tee bloky_s_zacatky_odt_souboru.txt
Pozor, výsledné bloky nemusí nutně obsahovat ODT soubory! Jde o zip soubor, který má jako 5. byte hodnotu 0x14. Proto je vhodné prohlédnout všechny bloky a zkontrolovat, zda se na začátku (resp. od 50. bytu podle /usr/share/misc/file/magic) vyskytuje řetězec "vnd.oasis.opendocument.text". K tomu jsem si dopomohl následujícím skriptem (používám oddíl /dev/sda7 i dále v textu, změňte si jej dle potřeby):
#!/bin/sh
OUTPUT="odt_files.log"
rm -f $OUTPUT
while read offset;do
echo "Offset $offset"

echo "Offset $offset" >>$OUTPUT

hexdump -s `expr $offset \* 4096` -n 500 -C /dev/sda7 >>$OUTPUT

done
Skriptu je předat čísla bloků, které jste získali programem ext3grep (uvedeno výše), oddělené znakem nového řádku. Skript dělá to, že vypíše prvních 500 bytů od určitého bloku na disku, vše zapisuje do souboru. Hodnota 4096 je použita jako klasická velikost bloku na EXT3, pokud používáte jinou, ve skriptu ji změňte (viz tune2fs -l /dev/sda7 |grep "Block size"). Z tohoto souboru můžete snadno zjistit, které bloky obsahují skutečný ODT soubor - hledejte právě řetězec "vnd.oasis.opendocument.text".
Na obrázku (vygenerovaném programem hexedit, velmi užitečném nástroji, který se vám bude hodit, podobně jako výše použitý program hexdump) lze vidět v invertovaných částech začátek bloku, obsahujícího ODT soubor. Signatura 50 4b 03 04 14 značí zip soubor, byty řetězce "vnd.oasis.opendocument.text" zajišťují, že jde o ODT soubor.
Nyní tedy máme skutečné začátky bloků, kde se jistě vyskytuje nějaký ODT soubor. Přejděme k části, která je zdlouhavá, ale měla by přinést ovoce. Dodávám, že následující postup je odzkoušený pro kratší soubory o velikosti několika desítek kB - u větších souborů s největší pravděpodobností dojde k nějaké fragmentaci a data nebudou spojitě na disku. Tak bohužel. :-/ Budu předvádět na datech z obrázku výše.
  1. Spusťte hexedit /dev/sda7. Najděte si začátek bloku - číslo bloku * velikost bloku je vaše číslo. V mém případě 15974435 * 4096 = 65431285760 = 0xf3c023000 (hexadecimálně). Stiskněte Enter a zadejte hexadecimální hodnotu. Měli byste vidět začátek ODT souboru.
  2. Další krok je spíš věc štěstí a intuice. Scrollujte v hexeditu dolů, měli byste vidět nějaký ten binární odpad - není to moc čitelné, jde o komprimovaný soubor. Nicméně někde "dole" objevíte řetězec, který v ASCII části hexeditu vypadá zhruba takto: "META-INF/manifest.xmlPK..........(.........", podstatná je ta část META-INF/manifest.xmlPK.
  3. Posuňte se za řetězcem "nifest.xmlPK" na první tečku a posuňte se o 20 dalších znaků doprava. Dostanete se na adresu, která je konečnou adresou tohoto ODT souboru. V mém případě je to 0xf3c02b3ca, tedy 65431319498 decimálně.
  4. Rozdíl koncové a počáteční adresy vám dá velikost souboru: 65431319498 - 65431285760 = 33738 bytů.
  5. Vydělte tuto velikost velikostí bloku EXT3 (4096) a zaokrouhlete nahoru. Dostanete počet bloků, přes které soubor přesahuje.
    Zde se právě projevuje slabina tohoto řešení u větších souborů - soubory mohou být fragmentovány a může na ně být odkazováno přes nepřímé bloky.
    V mém případě 33738 / 4096 = 8,2 -> 9.
  6. Zkopírujte syrová data z disku z daných bloků do souboru, použijte jako počáteční blok číslo bloku z bodu 1.
    # dd if=/dev/sda7 bs=4096 of=block count=9 skip=15974435
    9+0 vstoupivších záznamů
    9+0 vystoupivších záznamů
    36 864 bajtů (37 kB) zkopírováno, 0,000116287 s, 317 MB/s
  7. Nyní je třeba ověřit, zda soubor block obsahuje celý odt soubor, otevřete jej v hexeditu, zascrollujte až dolů a musí obsahovat řetězec "META-INF/manifest.xmlPK..........(.........". Dojděte opět na konec ODT souboru (za PK a 20x šipka doprava) a zjistěte skutečnou adresu konce souboru - tato adresa zároveň určuje velikost souboru, opět jej překopírujte.V mém případě je velikost souboru 0x83ca = 33738 bytů, což správně odpovídá velikosti vypočtené v bodě 5.
    Kopírování je následující:
    #dd if=block bs=1 of=file.odt count=33738
    33738+0 vstoupivších záznamů
    33738+0 vystoupivších záznamů
    33 738 bajtů (34 kB) zkopírováno, 0,0752972 s, 448 kB/s
Soubor file.odt lze nyní otevřít v OpenOffice. Data jsou zachráněna!!
Občas se může stát, že dojde k nějaké fragmentaci a data tímto způsobem zachránit nelze. Občas si také OpenOffice postěžuje, že je soubor poškozen, dokument ale dokáže dobře obnovit. Osobně jsem měl s tímto postupem více než 90%-ní úspěšnost obnovy dat.
Snad to někomu pomůže... a rada na závěr: zálohovat, zálohovat, zálohovat! :-)

2 komentáře:

Anonymní řekl(a)...

Zdravím,
chcem sa opýtať, či je možné obnoviť data prepisane ufs suborovym systemom

m1c4a1 řekl(a)...

Hmm, tak tím způsobem, kterým jsem to dělal já, jen asi za předpokladu, že nebyl přepsán superblok, který odkazuje na další bloky filesystému. Protože bývá imho nejčastěji na začátku disku (oddílu), je šance přepsání asi dost vysoká.
Můžeš zkusit ten ext3grep, pokud ti najde superblok, nějaká šance snad ještě existuje.
Pokud je to na disku fyzicky přepsané, tak tam se šance rapidně snižuje; jde prý nějak zjistit původní hodnoty v sektorech, ale to už souvisí ne tak se softwarovou, jako spíše hardwarovou stránkou věci, do toho bohužel vůbec nevidím.