Odzyskiwanie kontenera TrueCrypt II

Dość dawno temu popełniłem kilka wpisów dotyczących TrueCrypt, między innymi wpis W poszukiwaniu kontenera TrueCrypt. Pokazałem w nim, że teoretycznie istnieje możliwość znalezienia kontenera TrueCrypt nawet wówczas, gdy informacja o jego lokalizacji została utracona. Szansa powodzenia jest dość duża w przypadku, gdy plik (kontener) znajduje się w jednym kawałku. Problem zaczyna się wówczas, gdy plik jest sfragmentowany. Dziś chciałem pokazać nieco inny scenariusz odzyskiwania kontenera, tym razem z wykorzystaniem pozostałości $Mft.

Do tematu wracam, bo w ciągu kilku ostatnich dni pojawiły się dwa pytania o możliwość odzyskania utraconego kontenera TrueCrypt, jedno z nich w komentarzu do starszego wpisu, drugie – mailem.

O co chodzi

Problem z odzyskiwaniem kontenerów TrueCrypt polega przede wszystkim na:

We wspominanym wpisie pokazywałem co prawda, że pliki TC mają jednak jedną cechę charakterystyczną – wysoką entropię. Można próbować wykorzystać to do wytypowania miejsc na dysku, w których fragmenty kontenera są zapisane. Można próbować, ale skuteczność takich poszukiwań może być mizerna. Wiele innych plików, lub ich fragmentów, może charakteryzować się dużą entropią. Ciężko jest odróżnić, czy w danym klastrze zapisany jest fragment kontenera TrueCrypt, czy może fragment jakiegoś skompresowanego pliku.

Nawet jeśli takie typowanie miejsc, w których znajdują się fragmenty kontenera, odbyło by się ze 100%25 skutecznością, to dopiero połowa problemu. Druga kwestia – fragmenty pliku trzeba ułożyć we właściwej kolejności. Oczywiście, może zdarzyć się tak, że cały kontener zapisany jest w jednym ciągłym kawałku, jednak bardzo prawdopodobne jest to, że kawałków będzie kilka. I wcale nie jest powiedziane, że każdy kolejny fragment pliku będzie zapisany na dysku po kawałku poprzednim.

Oczywiście, można próbować ułożyć wszystkie możliwe układy, jest ich (n-1)! ponieważ pierwszy fragment pliku (ten z nagłówkiem) możemy zidentyfikować dość skutecznie. Stąd właśnie n – 1 , pierwszy kawałek zawsze jest pierwszy, a pozostałe kawałki (czyli właśnie n-1) układamy we wszystkie możliwe permutacje. Im więcej kawałków, tym liczba możliwych układów jest większa, silnia pod tym względem jest dość paskudna. Do tego trzeba dodać problem choćby z przygotowaniem warunku sukcesu - jak sprawdzić, że wszystkie kawałki zostały ułożone we właściwej kolejności?

Czy można zadanie odzyskania pliku/kontenera TrueCrypt zrealizować inaczej? Tak i metoda ta nie ogranicza się do tego typu plików. Po prostu można próbować odnaleźć na dysku rekord, który utracony/zagubiony plik opisuje. W przypadku systemu NTFS takie informacje zapisane są w $Mft. Tu z góry uprzedzam, że nie będę opisywał dokładnie struktury NTFS. Jeśli ktoś jest zainteresowany tym tematem, to dobrym źródłem informacji jest opracowanie NTFS Documentation , trzeba szukać pliku ntfsdoc.pdf , bo “oryginalny” link (http://data.linux-ntfs.org/ntfsdoc.pdf) nie działa.

Eksperyment

By pokazać jak można ustalić położenie fragmentów pliku na dysku, przeprowadzę mały eksperyment. Utworzę specjalnie sfragmentowany kontener TrueCrypt, następnie znajdę odpowiadający mu rekord MFT i odczytam z niego informacje o ilości fragmentów, w których plik jest zapisany i ich rozmieszczeniu na dysku.

Przygotowanie materiału

Do stworzenia “środowiska testowego” wykorzystam niewielki “dysk” o rozmiarze 1GiB. Został on sformatowany jako NTFS. Ponieważ zależy mi na tym, by kontener TrueCrypt był sfragmentowany, najpierw utworzyłem na tym testowym dysku kilka plików:

E:>dir Volume in drive E has no label. Volume Serial Number is 2C93-FE01

Directory of E:

2011-02-02 19:21 134 217 728 test1.dat 2011-02-02 19:21 134 217 728 test2.dat 2011-02-02 19:21 134 217 728 test3.dat 2011-02-02 19:21 134 217 728 test4.dat 2011-02-02 19:21 134 217 728 test5.dat 2011-02-02 19:21 134 217 728 test6.dat 2011-02-02 19:21 134 217 728 test7.dat 7 File(s) 939 524 096 bytes 0 Dir(s) 126 145 536 bytes free

A następnie usunąłem część z nich:

E:>dir Volume in drive E has no label. Volume Serial Number is 2C93-FE01

Directory of E:

2011-02-02 19:21 134 217 728 test1.dat 2011-02-02 19:21 134 217 728 test3.dat 2011-02-02 19:21 134 217 728 test5.dat 2011-02-02 19:21 134 217 728 test7.dat 4 File(s) 536 870 912 bytes 0 Dir(s) 528 798 720 bytes free

Dzięki tym zabiegom stworzony później kontener TrueCrypt był przyzwoicie sfragmentowany:

E:>contig -a kontener.tc

Contig v1.55 – Makes files contiguous Copyright © 1998-2007 Mark Russinovich Sysinternals – www.sysinternals.com

E:\kontener.tc is in 8 fragments

Summary: Number of files processed : 1 Average fragmentation : 8 frags/file

W zasadzie w tej chwili powinienem jeszcze “uszkodzić” system plików na tym “dysku”, ale do pokazania tego, co chcę pokazać nie jest to konieczne.

Wyszukanie rekordu pliku

Plik $Mft zawiera rekordy, które opisują umiejscowienie każdego pliku i katalogu na dysku. W szczególności zapisane są w nim informacje o tym, gdzie fragmenty pliku są fizycznie zapisane na dysku.

Każdy rekord MFT zaczyna się od charakterystycznego znacznika: FILE0. Nazwa pliku jest natomiast zapisana w kodowaniu UNICODE. Wystarczy więc znaleźć odpowiedni rekord MFT (jeśli taki na dysku ocalał) i... Dalszą część pokażę z użyciem narzędzia FTK Imager, choć równie dobrze można to samo osiągnąć z użyciem dowolnego edytora HEX.

Najpierw wyszukując po nazwie pliku (kontener.tc) znajduję rekord (albo to, co z niego zostało) MFT. Wyszukiwać będę po nazwie pliku, przy czym trzeba pamiętać, że nazwa ta zapisana jest w Unicode. Większość narzędzi pozwala na określenie encodingu wyszukiwanego stringa, trzeba więc pamiętać by wybrać właściwe kodowanie. Znaleziony rekord wygląda następująco:

Na zrzucie zaznaczyłem znacznik początku rekordu (FILE0) oraz nazwę pliku. Warto zwrócić uwagę gdzie występuje znacznik. Wielkość rekordu MFT jest stała i wynosi 1024 bity, siłą rzeczy więc znacznik rekordu nie może wystąpić w dowolnym miejscu. Tak jak zapowiadałem, nie będę się zagłębiał w dokładny opis struktury rekordu MFT.

Interpretacja atrybutu DATA

Po znalezieniu rekordu szukamy w nim atrybutu $DATA (0x80). Może być ich więcej niż jeden (alternate data stream), w tym przypadku jest tylko jeden atrybut tego typu. Dla małych plików atrybut ten zawiera również treść pliku, w przypadku większych – informacje gdzie dane są zapisane. Właśnie ta informacja będzie potrzebna do odzyskania fragmentów kontenera (lub dowolnego innego pliku).

Atrybut $DATA można znaleźć po jego identyfikatorze, tu (prawie) cały atrybut zaznaczony na zrzucie:

Na poniższym zrzucie zaznaczone są istotne elementy atrybutu DATA, w kolejności:

To właśnie run list jest tym, czego szukaliśmy i co pozwoli poskładać fragmenty pliku rozsiane po całym dysku w całość. Jedyny problem to prawidłowa interpretacja run list (data runs).

Jeśli kogoś interesuje skąd poszczególne wartości się wzięły, dobry opis znajduje się na przykład tu: FAQ NTFS. Opis pracy i odzyskiwania danych z partycji NTFS.

Interpretacja data runs

33 F8 03 02 08 00 02 33 00 00 02 28 01 08 33 CF FE 01 00 00 04 33 9E A9 00 31 55 F9 22 4D 25 B2 D9 31 24 F0 CF 00 31 04 4D 55 FD 13 26 FE 00 35 00 00 00 00 00 00 00 00

Data runs to sekwencja elementów, każdy element można w uproszczeniu przedstawić jako FLAB, gdzie:

Dla oszczędności miejsca pola A i B mają rozmiar zależny od potrzeb (opisany w F i L). Trzeba pamiętać, że offset zapisany jest jako signed integer i może mieć wartość ujemną. Pierwszy element data run informuje o pierwszym klastrze pierwszego fragmentu pliku. Informacja o kolejnych fragmentach zapisana jest już jako offset do poprzedniego fragmentu, więc w szczególności może to być liczba ujemna, jeśli kolejny fragment znajduje się na dysku “przed” fragmentem go poprzedzającym (w pliku).

Pierwszy bajt znalezionego data run ma wartość 0x33 co oznacza, że zarówno offset jak i długość fragmentu pliku zapisana jest na trzech bajtach. Są to odpowiednio:

F8 03 02 08 00 02

Dowiadujemy się z tego, że pierwszy fragment pliku ma długość 132 088 klastrów:

Pierwszy klaster tego fragmentu pliku to 131 080:

Dla pewności numer pierwszego klastra sprawdźmy w inny sposób:

Kolejne fragmenty mają następujące parametry (długość, offset):

W takim układzie pierwsze klastry fragmentów pliku to:

Zgodnie z oczekiwaniami fragmentów jest osiem. Przy okazji plik sfragmentował się na tyle sympatycznie, że fragmenty pliku “przeplatają się”. Próbując otworzyć plik ze zidentyfikowanych fragmentów o dużej entropii i nawet zakładając, że fragmenty te zostały zidentyfikowane prawidłowo, trzeba sprawdzić 7! ułożeń, czyli, bagatela, 5040 możliwych permutacji. Oczywiście – w najgorszym przypadku. Nie jest to liczba prób niemożliwa do wykonania. Cały czas podkreślam, że większym problemem będzie właściwe i precyzyjne zidentyfikowanie fragmentów kontenera.

Jak odzyskać fragmenty pliku

Jak odzyskać fragmenty pliku? Wystarczy znaleźć miejsce, gdzie dany fragment się zaczyna i skopiować określony fragment danych o określonym rozmiarze. W tym miejscu kluczowe jest ustalenie rozmiaru klastra. Można tu posłużyć się dokumentem Default cluster size for NTFS, FAT, and exFAT . Jest tylko jeden mały problem – ta informacja może nie być zgodna z rzeczywistością.

Druga istotna informacja – gdzie właściwie zaczyna się partycja? Jest to istotne, ponieważ w końcu trzeba wiedzieć od którego miejsca (fizycznie) na dysku trzeba liczyć te klastry.

Obu potrzebnych informacji dostarczyć może nam $Boot, a właściwie jego atrybut $DATA. Jest on zawsze na początku partycji (jest jeszcze jego kopia), więc dzięki temu można ustalić gdzie się ona zaczyna. Dodatkowo zapisana jest w nim między innymi informacja o ilości bajtów na sektor i ilości sektorów na klaster. Ponownie obrazek poglądowy:

Na powyższym zrzucie zaznaczone są w kolejności:

Wiemy w takim razie, że rozmiar klastra to 1024 bajty, wiemy również skąd powinniśmy zacząć liczyć. Tak się składa, że tym razem początek partycji zbiega się z początkiem dysku i jest to 0x00. Jest to dość niezwykła sytuacja i wynika ze sposobu przygotowania dysku/obrazu do tego przykładu. Zwykle partycja zaczyna się z pewnym offsetem od początku dysku (np. gdzieś musi się zmieścić informacja o partycjach na dysku. Na typowym dysku gdzie są założone partycje układ może wyglądać następująco (przykład mojego laptopa, mmls to narzędzie ze sleuthkit):

mmls \.\PHYSICALDRIVE0

DOS Partition Table Offset Sector: 0 Units are in 512-byte sectors

Slot Start End Length Description 00: Meta 0000000000 0000000000 0000000001 Primary Table (#0) 01: ——– 0000000000 0000000062 0000000063 Unallocated 02: 00:00 0000000063 0000160649 0000160587 Dell Utilities FAT (0xde) 03: 00:01 0000160650 0625137344 0624976695 NTFS (0x07)

Rzeczywiście, jeśli wyszukamy “NTFS “, to znajdziemy wartość tę dalej na dysku:

Offset 0004e71400 to nic innego jak 160650 pomnożone przez 512 (rozmiar sektora), co daje 82252800 (czyli właśnie 4E71400).

W tej chwili mamy w zasadzie wszystkie dane potrzebne do odzyskania fragmentów pliku i poskładania ich w odpowiedniej kolejności:

Pozostaje tylko skopiować fragmenty pliku i ułożyć je w kolejności zapisanej w data runs. Do tego zadania wystarczy nawet dd.

Można jeszcze inaczej

Odzyskiwanie plików można przeprowadzić jeszcze inaczej. Tu po raz kolejny polecę narzędzia PhotoRec i TestDisk. Co prawda carving w przypadku kontenerów TrueCrypt nie zadziała (powtarzam – brak cech charakterystycznych), to przy pomocy TestDisk można (przynajmniej próbować):

Dzięki temu być może “utracone” pliki znowu staną się normalnie widoczne. Bardzo miłą cechą tych narzędzi jest również możliwość pracy na obrazie dysku zapisanym do pliku. Taką kopię dobrze wykonać jak najszybciej po przypadkowym usunięciu lub innej awarii, która doprowadziła do “zniknięcia” istotnych danych. Im szybciej, tym lepiej. Każda operacja zapisu zwiększa prawdopodobieństwo, że zagubione dane zostaną uszkodzone, lub uszkodzona zostanie informacja dająca szansę na ich odzyskanie. Oryginał można spokojnie “zabezpieczyć”, a wszystkie eksperymenty przeprowadzać na jego kopii. Nawet jeśli coś nie wyjdzie, zawsze można zacząć próbować od początku.

Choć “typowy” carver nie zadziała, to można próbować narzędzia nieco inne. Takie, które robią właściwie to, co opisałem wcześniej, ale robią to automatycznie. Tu polecam wyszukiwarkę i słowa kluczowe typu: MFT carver albo MFT carving.

Oryginał tego wpisu dostępny jest pod adresem Odzyskiwanie kontenera TrueCrypt II

Autor: Paweł Goleń