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.
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.
Našel jsem prográmek Scalpel, který výše zmíněné zastává. Nyní popíšu, jak s tím pracovat:
/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.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
Teď už teda víme, jak soubor začíná, tak to zapíšeme do konfiguráku.
cp /etc/scalpel/scalpel.conf /někde/někde
nano /někde/někde
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ů:
scalpel -c /někde/scalpel.conf -o /cilova/slozka/ /dev/sdX
(nebo místo zařízení obraz)pokračování příště… No, tak alespoň dopovím, jak jsem chtěl po vytažení souborů pokračovat.
moov
grep -obarUP “moov” /cesta/k/souboru.mp4
moov
zjistíme samotnou délku atomu typu moov.dd skip=(OFFSET-4) count=4 if=soubor.mp4 bs=1|xxd
(bez té závorky)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í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.