O czyszczeniu NTFS raz jeszcze

Ostatnio na newsach (to takie coś, co było przed forami) pojawiło się pytanie czym wyczyścić dysk przed sprzedażą. Jedną z odpowiedzi było narzędzie cipher. Jak już miałem okazję się przekonać, nie działa ono zbyt skutecznie:

To skłoniło mnie do małego eksperymentu...

Przygotowanie

Najpierw przygotowałem sobie mały dysk o rozmiarze 4MiB sformatowany jako NTFS. Następnie napisałem skrypt, który zapełnił ten dysk plikami o następującej charakterystyce:

Sprawdzenie

Zrzuciłem zawartość dysku do pliku za pomocą polecenia dd if=\\.\x: of=master.dd bs=1024. Rezultat polecenia fsstat :

FILE SYSTEM INFORMATION —————————————————————— File System Type: NTFS Volume Serial Number: 8E180A36180A1E39 OEM Name: NTFS Version: Windows XP

METADATA INFORMATION —————————————————————— First Cluster of MFT: 2730 First Cluster of MFT Mirror: 6858 Size of MFT Entries: 1024 bytes Size of Index Records: 4096 bytes Range: 0 – 303 Root Directory: 5

CONTENT INFORMATION —————————————————————— Sector Size: 512 Cluster Size: 512 Total Cluster Range: 0 – 8189 Total Sector Range: 0 – 8189

$AttrDef Attribute Values: $STANDARDINFORMATION (16) Size: 48-72 Flags: Resident $ATTRIBUTELIST (32) Size: No Limit Flags: Non-resident $FILENAME (48) Size: 68-578 Flags: Resident,Index $OBJECTID (64) Size: 0-256 Flags: Resident $SECURITYDESCRIPTOR (80) Size: No Limit Flags: Non-resident $VOLUMENAME (96) Size: 2-256 Flags: Resident $VOLUMEINFORMATION (112) Size: 12-12 Flags: Resident $DATA (128) Size: No Limit Flags: $INDEXROOT (144) Size: No Limit Flags: Resident $INDEXALLOCATION (160) Size: No Limit Flags: Non-resident $BITMAP (176) Size: No Limit Flags: Non-resident $REPARSEPOINT (192) Size: 0-16384 Flags: Non-resident $EAINFORMATION (208) Size: 8-8 Flags: Resident $EA (224) Size: 0-65536 Flags: $LOGGEDUTILITY_STREAM (256) Size: 0-65536 Flags: Non-resident

W pliku tym (czyli na dysku) fragment MAGICVALUE występuje 1172 razy:

strings -o master.dd | grep -i magicvalue -c 1172

Test 1: cipher

Test ten składa się z dwóch części:

Po usunięciu plików i wykonaniu polecenia cipher ponownie zrzuciłem zawartość dysku do pliku: dd if=\\.\x: of=cipher.dd bs=1024. Czy dysk został skutecznie wyczyszczony? strings -o cipher.dd | grep -i magicvalue -c 7 Okazuje się, że nie, choć rezultat 7 pozostałych MAGICVALUE nie jest może zbyt przerażający. Fragmenty te pozostały w następujących miejscach:

strings -o cipher.dd | grep -i magicvalue 33064:MAGICVALUE 52520:MAGICVALUE 54568:MAGICVALUEs2^$P 93480:MAGICVALUE 141608:MAGICVALUE 192808:MAGICVALUE7q 240936:MAGICVALUEP

Po sprawdzeniu okazało się, że wszystkie te wystąpienia znajdują się w obrębie $Mft. A to dlatego, że $Mft nie jest czyszczone przez cipher. Z tego powodu okazuje się, że można uzyskać również (niemal kompletną) listę plików (fragment):

ifind -p 27 cipher.dd –/r * 29: fil56D.tmp –/r * 30: 14.E –/r * 31: 15.E –/r * 32: 16.E –/r * 33: 17.E –/r * 34: 18.E –/r * 35: 19.E –/r * 36: 13.E –/r * 37: filename8.txt –/r * 38: filename9.txt –/r * 39: filename10.txt –/r * 40: filename11.txt –/r * 41: filename12.txt –/r * 42: filename13.txt –/r * 43: filename14.txt –/r * 44: filename15.txt –/r * 45: filename16.txt –/r * 46: filename17.txt –/r * 47: filename18.txt –/r * 48: filename19.txt –/r * 49: filename20.txt –/r * 50: filename21.txt –/r * 51: filename22.txt –/r * 52: filename23.txt –/r * 53: filename24.txt

Można uzyskać również informację o poszczególnych już nieistniejących (choć jak pokazuje MAGICVALUE nie zawsze) plikach, na przykład:

istat cipher.dd 37 MFT Entry Header Values: Entry: 37 Sequence: 2 $LogFile Sequence Number: 1598212 Not Allocated File Links: 1

$STANDARD_INFORMATION Attribute Values: Flags: Archive Owner ID: 0 Created: Wed Jun 04 18:04:42 2008 File Modified: Wed Jun 04 18:04:42 2008 MFT Modified: Wed Jun 04 18:04:42 2008 Accessed: Wed Jun 04 18:04:42 2008

$FILE_NAME Attribute Values: Flags: Archive Name: filename8.txt Parent MFT Entry: 27 Sequence: 1 Allocated Size: 0 Actual Size: 0 Created: Wed Jun 04 18:04:42 2008 File Modified: Wed Jun 04 18:04:42 2008 MFT Modified: Wed Jun 04 18:04:42 2008 Accessed: Wed Jun 04 18:04:42 2008

Attributes: Type: $STANDARDINFORMATION (16-0) Name: N/A Resident size: 72 Type: $FILENAME (48-2) Name: N/A Resident size: 92 Type: $DATA (128-3) Name: $Data Non-Resident size: 7704 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799

Wniosek: cipher na pewno nie czyści $Mft, co może skutkować pozostawieniem nietkniętych plików, które całe mieszczą się w $Mft, jak również pozostawieniem metadanych o plikach.

Test 2: sdelete

Scenariusz testu jest identyczny z poprzednim. Sdelete od cipher różni się głownie tym, że czyści również $Mft. Test przeprowadzany jest na identycznych danych jak test cipher. Ponownie wykonałem kopię dysku: dd if=\\.\x: of=sdelete.dd bs=1024. Czy sdelete poradził sobie lepiej?

strings -o sdelete.dd | grep -i magicvalue 52520:MAGICVALUE 54568:MAGICVALUEs2^$P 93480:MAGICVALUE 141608:MAGICVALUE 192808:MAGICVALUE7q 240936:MAGICVALUEP

...nieco... Ponownie wszystkie wystąpienia mają miejsce w $Mft. Jeszcze dla pewności:

ifind -p 27 sdelete.dd –/r * 53: filename24.txt –/r * 54: filename25.txt –/r * 55: filename26.txt –/r * 56: filename27.txt (...) –/r * 297: filename268.txt –/r * 298: filename269.txt

I coś takiego:

istat sdelete.dd 298 MFT Entry Header Values: Entry: 298 Sequence: 2 $LogFile Sequence Number: 1592807 Not Allocated File Links: 1

$STANDARD_INFORMATION Attribute Values: Flags: Archive Owner ID: 0 Created: Wed Jun 04 18:04:43 2008 File Modified: Wed Jun 04 18:04:43 2008 MFT Modified: Wed Jun 04 18:04:43 2008 Accessed: Wed Jun 04 18:04:43 2008

$FILE_NAME Attribute Values: Flags: Archive Name: filename269.txt Parent MFT Entry: 27 Sequence: 1 Allocated Size: 0 Actual Size: 0 Created: Wed Jun 04 18:04:43 2008 File Modified: Wed Jun 04 18:04:43 2008 MFT Modified: Wed Jun 04 18:04:43 2008 Accessed: Wed Jun 04 18:04:43 2008

Attributes: Type: $STANDARDINFORMATION (16-0) Name: N/A Resident size: 72 Type: $FILENAME (48-2) Name: N/A Resident size: 96 Type: $DATA (128-1) Name: $Data Resident size: 1

Jak widać sdelete również nie wyczyścił dysku w 100%25 skutecznie. I bynajmniej nie chodzi mi tu o jakieś zaawansowane techniki odzyskiwania danych... Po prostu nie da się skutecznie wyczyścić dysku w ten sposób.

Test 3: ponownie sdelete

Tym razem jedna drobna różnica. Zamiast usuwać pliki przy pomocy polecenia rmdir /s /q , usunę katalog wraz z zawartością za pomocą polecenia sdelete właśnie. Rezultat:

strings -o sdelete2.dd | grep -i magicvalue -c 1

Lepiej, ale dalej nie idealnie... Co więcej tym razem wartość ta ostała się poza $Mft:

ifind -d 4684 sdelete2.dd 2-128-1

istat sdelete2.dd 2-128-1 MFT Entry Header Values: Entry: 2 Sequence: 2 $LogFile Sequence Number: 1052610 Allocated File Links: 1

$STANDARD_INFORMATION Attribute Values: Flags: Hidden, System Owner ID: 0 Created: Wed Jun 04 17:59:58 2008 File Modified: Wed Jun 04 17:59:58 2008 MFT Modified: Wed Jun 04 17:59:58 2008 Accessed: Wed Jun 04 17:59:58 2008

$FILE_NAME Attribute Values: Flags: Hidden, System Name: $LogFile Parent MFT Entry: 5 Sequence: 5 Allocated Size: 2097152 Actual Size: 2097152 Created: Wed Jun 04 17:59:58 2008 File Modified: Wed Jun 04 17:59:58 2008 MFT Modified: Wed Jun 04 17:59:58 2008 Accessed: Wed Jun 04 17:59:58 2008

Attributes: Type: $STANDARDINFORMATION (16-0) Name: N/A Resident size: 72 Type: $FILENAME (48-2) Name: N/A Resident size: 82 Type: $DATA (128-1) Name: $Data Non-Resident size: 2097152 (...)

Lepiej natomiast wygląda lista plików:

ifind -p 27 sdelete2.dd –/r * 29: ZZZZZZZZZ.ZZZ –/r * 30: ZZZZZZZZZ.ZZZ –/r * 31: ZZZZZZZZZ.ZZZ (...) –/r * 296: ZZZZZZZZZZZ.ZZZ –/r * 297: ZZZZZZZZZZZ.ZZZ –/r * 298: ZZZZZZZZZZZ.ZZZ

Również ich metadane:

istat sdelete2.dd 296 MFT Entry Header Values: Entry: 296 Sequence: 2 $LogFile Sequence Number: 3753819 Not Allocated File Links: 1

$STANDARD_INFORMATION Attribute Values: Flags: Archive Owner ID: 0 Created: Wed Jun 04 18:04:43 2008 File Modified: Wed Jun 04 18:43:32 2008 MFT Modified: Wed Jun 04 18:43:32 2008 Accessed: Wed Jun 04 18:43:32 2008

$FILE_NAME Attribute Values: Flags: Archive Name: ZZZZZZZZZZZ.ZZZ Parent MFT Entry: 27 Sequence: 1 Allocated Size: 4096 Actual Size: 3590 Created: Wed Jun 04 18:04:43 2008 File Modified: Wed Jun 04 18:43:32 2008 MFT Modified: Wed Jun 04 18:43:32 2008 Accessed: Wed Jun 04 18:43:32 2008

Attributes: Type: $STANDARDINFORMATION (16-0) Name: N/A Resident size: 72 Type: $FILENAME (48-29) Name: N/A Resident size: 96 Type: $DATA (128-3) Name: $Data Non-Resident size: 3590 8169 1626 1617 1608 1419 1396 1313 1296

...choć i tak można się dowiedzieć, kiedy plik został stworzony: Created: Wed Jun 04 18:04:43 2008. Dla porównania rekord z oryginalnego dysku:

istat master.dd 296 MFT Entry Header Values: Entry: 296 Sequence: 1 $LogFile Sequence Number: 1213705 Allocated File Links: 1

$STANDARD_INFORMATION Attribute Values: Flags: Archive Owner ID: 0 Created: Wed Jun 04 18:04:43 2008 File Modified: Wed Jun 04 18:04:43 2008 MFT Modified: Wed Jun 04 18:04:43 2008 Accessed: Wed Jun 04 18:04:43 2008

$FILE_NAME Attribute Values: Flags: Archive Name: filename267.txt Parent MFT Entry: 27 Sequence: 1 Allocated Size: 0 Actual Size: 0 Created: Wed Jun 04 18:04:43 2008 File Modified: Wed Jun 04 18:04:43 2008 MFT Modified: Wed Jun 04 18:04:43 2008 Accessed: Wed Jun 04 18:04:43 2008

Attributes: Type: $STANDARDINFORMATION (16-0) Name: N/A Resident size: 72 Type: $FILENAME (48-2) Name: N/A Resident size: 96 Type: $DATA (128-3) Name: $Data Non-Resident size: 3590 8169 1626 1617 1608 1419 1396 1313 1296

Test 4: wipe

Wipe jest elementem pakietu FAU (Forensic Acquisition Utilities). Jego działanie można porównać do dd if=/dev/zero of=/dev/hda. Po wyczyszczeniu: wipe \\.\x: klasyczne skopiowanie dysku do pliku: dd if=\\.\x: of=wipe.dd bs=1024. Czy jakieś MAGICVALUE ocalało?

strings -o wipe.dd | grep -i magicvalue -c 0

W zasadzie NIC nie ocalało:

strings -o wipe.dd Strings v2.4 Copyright © 1999-2007 Mark Russinovich Sysinternals – www.sysinternals.com No strings found.

Dysk jest idealnie czysty.

Dobra rada

Jeśli z jakichś powodów trzeba oddać dysk (na przykład sprzedać), należy go wyczyścić. Nie koniecznie musi to polegać na nadpisaniu jego zawartości 35 razy, ale choćby takie narzędzie: Darik's Boot and Nuke, czy zwykłe LiveCD z pierwszym lepszym linuksem...

Oryginał tego wpisu dostępny jest pod adresem O czyszczeniu NTFS raz jeszcze

Autor: Paweł Goleń