Zápisník · 23. dubna 2023

Jak obnovit smazané soubory pomocí metody file carving

Praktický pokus o obnovu videí z naformátované SD karty pomocí Scalpelu, signatur MP4 a ručního hledání atomu moov.

Porovnání začátků dvou MP4 souborů v terminálu.

Úvod

Začnu životní příhodou. Jeden krásný týden jsem byl se skauty na puťáku,
měli jsme půjčenou GOPRO kameru, abychom něco natočili. Prvních pár dní
jsme natáčeli jako diví, takže nám brzo došla kapacita SD karty. Bylo z
ní potřeba data přesunout na cloud. Bohužel, jelikož po vložení do
mobilu OS Android nabídl velkou nabídku na formátování. Kamarád se
překlikl a videa byla fuč. Abychom měli alepoň nějakou naději na
záchranu dat, tak jsme SD kartu ihned odstavili z provozu, aby se data
nestihla přepsat, a používali jsme jinou. Toto rozhodnutí bylo logické,
protože na paměťových médiích se nikdy hnedka nepřepisují bajty
smazaných souborů. Jen se označí, že jsou volné k zápisu. V případě
formátování se taky vše nepřepisuje.

Teorie

Takže teď přistupme k věci. Před veškerou manipulací s sd kartou
doporučuji pro jistotu vytvořit její obraz, třeba pomocí příkazu dd.
Potom lze buď pracovat se samotnou karktou, nebo právě s tím obrazem.
File carving funguje na úplně jednoduchém principu. Je to docela zřejmé
už z názvu (carving = vyřezávání), jelikož nenáme ze souborováho systému
žádné informace o souboru, co hledáme (jeho metadata neexistují, ale
data pořád někde jsou), tak se postupně procházejí po skupinách bajty a
zjišťuje se, jestli právě ty neznačí nějaký znamý začátek souboru (file
signature). Když se něco známého najde, tak se do paměti uloží, kolikátý
to je bajt a dále se hledá známý konec tohoto souboru. Když je nalezen,
tak se vytvoří soubor na disku a do něj se zkopírují všechna data mezi
začátkem a koncem. Pokud daný typ suboru žádný známý konec nemá, tak se
zkopíruje předem daný počet bajtů. Nějaký takový program bych sice mohl
napsat, ale jelikož by to trvalo dlouho a já jsem líný, tak jsem hledal
mezi existujícím softwarem něco vhodného.

Postup

Našel jsem prográmek Scalpel, který výše zmíněné zastává. Nyní popíšu,
jak s tím pracovat:

  • stáhneme jej
  • podíváme se do konfiguračního souboru
    /etc/scalpel/scalpel.conf“, jestli tam jsou typy souboru, které
    chceme obnovit. Většina je ve výchozím stavu zakomentovaná, tak je
    potřeba vše potřebné odkomentovat. Pokud tam náš typ souboru není,
    tak jej tam musíme dopsat.
  • v mém případě budu hledat soubory mp4, co generuje GOPRO. Tady je
    alo problém kvůli samotné skladbě mp4 souborů. Hledal jsem, co
    všechno tento typ obsahuje a našel jsem, že:
    • soubor se skládá z kousků, na jejich začátku jsou 4 bajty, které
      udávají jejich velikost (včetně těch 4 bajtů).
    • další 4 bajty po těch, co udávají velikost, obsahují informaci o
      typu toho kousku
    • počáteční kousek bývá typu ftyp (66 74 79 70) a tam můžeme podle
      následujících 4 bajtů zjistit podtyp souboru, v našem případě
      tam bude mmp4
    • polední blok bývá zpravidla typu moov a obsahuje všechna
      metadata videa s odkazy na mdat (v mdat jsou surová data)

https://www.file-recovery.com/mp4-signature-format.htm - tady jsem
našel hezký popis.

Problém vidím už na začátku, protože velikost prvního kousku (někde se
říká atomu) může být variabilní. Můžeme sice hledat až těch dalších 8
bajtů, co udává typ atomu ftyp a za ním je, že ftyp=mmp4, ale to bychom
potom zpětně museli ty první 4 bajty doplnit. Je to sice jednoduché, ale
opruz. Lepší je využít toho, že soubory ze stejného zařízení budou mít
pravděpodobné stejnou velikost prvního atomu. Jelikož mám dostupné jinší
videa ze stejné kamery, tak je zkusím porovnt a zjistím, co mají na
začátku stejného. To se dá provést pomocí příkazu diff (nebo
colordiff) a hexdump (nebo xxd). Příkaz bude vypadat tak, že do
(color)diff nalijeme výstupy z hexdump(xxd) z obou souborů k porovnání:

colordiff -y <(xxd -l 900 SOUBOR1) <(xxd -l 900 SOUBOR2)

Je dobré k xxd použít argument -l, který vezme ze souboru jen prvních
X bajtů.

Vidíme, že soubory mají společný začátek:

00 00 00 14 66 74 79 70 6d 70 34 31 20 13 10 18 6d 70 34 31

Pozn.: Podle internetu by měl být file signature takovýto: (s offsetem 4
bajty - hvězdičky)

\** ** ** ** 66 74 79 70 4D 53 4E 56
\** ** ** ** 66 74 79 70 69 73 6F 6D

Příklady signatur souborů

Teď už teda víme, jak soubor začíná, tak to zapíšeme do konfiguráku.

  • napřed si config zkopírujeme jinam, abychom o něj náhodou nepřišli:
    cp /etc/scalpel/scalpel.conf /někde/někde

Takto nějak konfigurák vypadá

  • upravíme kopii: nano /někde/někde

  • přidáme řádek s našimi informacemi (odděleno tabulátorem):

    ‚‚mp4 y 100000000 \x00\x00\x00\x14\x66\x74\x79\x70\x6d\x70\x34\x31\x20\x13\x10\x18\x6d\x70\x34\x31‘‘

udává nám to, že to má uložit prvních 100000000 bajtů (100 mb) po
nalezení bajtů
00 00 00 14 66 74 79 70 6d 70 34 31 20 13 10 18 6d 70 34 31 do souboru
s příponou mp4. Bohužel neznáme, jak soubor končí, tak to potom budeme
muset oříznout manuálně.

Tady přikládám diff konců souborů:

  • uložíme, spustíme program a budeme se modlit, aby to něco našlo:
    scalpel -c /někde/scalpel.conf -o /cilova/slozka/ /dev/sdX (nebo
    místo zařízení obraz)
  • pokud je médium velké, tak budeme čekat klidně několik hodin
  • pokud to napíše, že nemáte oprábnění, budete muset program spustit
    jako root
  • takto vypadá program při své práci, ta je rozdělena do dvou fází -
    v první hledá, ve druhé „rozřezává“

  • hmm, nic mi to nenašlo, pokračovat budu tím pádem asi někdy jindy.
    Ne vždy se podaří, šance na obnovu hlavně výrazně klesá, když se
    vytvoří nové soubory. To se právě kvůli Androidu stalo, bohužel…

pokračování příště… No, tak alespoň dopovím, jak jsem chtěl po
vytažení souborů pokračovat.

  • vylezlo by několik stejně velkých souborů a jelikož nelze podle
    určitého ocásku v souboru určit konec, tak by se na to muselo
    složitěji
  • musíme napřed zjistit velikost souboru a potom takto velký soubor
    zkopírovat z původního
  • využijeme toho, že poslední atom bývá typu moov
  • zkusíme najít v souboru právě tyto 4 bajty a zjistíme offset, kde
    jsou: grep -obarUP "moov" /cesta/k/souboru.mp4

  • pomocí 4 bajtů, které jsou před moov zjistíme samotnou délku atomu
    typu moov.
  • Tu zjistíme pomocí:
    dd skip=(OFFSET-4) count=4 if=soubor.mp4 bs=1|xxd (bez té závorky)

  • výslednou délku spočítáme: offset-4+délka moov (z offsetu musíme
    odečíst 4, protože před ním jsou ty 4 bajty délky, které se do té
    samé délky započítávají
  • nyní známe vše potřebné, stačí už jen zkopírovat vypočítanou délku
    do nového souboru
  • to uděláme opět pomocí dd:
    dd count=vypocitana_delka if=puvodni.mp4 of=vystup.mp4 bs=1

No a to je vše, teď by mělo video s trochou štěstí fungovat.

Další zápisy