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:
- nazwa pliku według szablonu filename(numer).txt,
- zawartość pliku to od 1 do 16 bloków po 512 bajtów,
- w każdym z tych bloków z prawdopodobieństwem 1/2 (dla ułatwienia - na jego początku) mógł znaleźć się tekst MAGICVALUE
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:
$STANDARD_INFORMATION (16) Size: 48-72 Flags: Resident
$ATTRIBUTE_LIST (32) Size: No Limit Flags: Non-resident
$FILE_NAME (48) Size: 68-578 Flags: Resident,Index
$OBJECT_ID (64) Size: 0-256 Flags: Resident
$SECURITY_DESCRIPTOR (80) Size: No Limit Flags: Non-resident
$VOLUME_NAME (96) Size: 2-256 Flags: Resident
$VOLUME_INFORMATION (112) Size: 12-12 Flags: Resident
$DATA (128) Size: No Limit Flags:
$INDEX_ROOT (144) Size: No Limit Flags: Resident
$INDEX_ALLOCATION (160) Size: No Limit Flags: Non-resident
$BITMAP (176) Size: No Limit Flags: Non-resident
$REPARSE_POINT (192) Size: 0-16384 Flags: Non-resident
$EA_INFORMATION (208) Size: 8-8 Flags: Resident
$EA (224) Size: 0-65536 Flags:
$LOGGED_UTILITY_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:
- usunięciu katalogu i zawartych w nim plików,
- uruchomienia narzędzia cipher,
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: $STANDARD_INFORMATION (16-0) Name: N/A Resident size: 72
Type: $FILE_NAME (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: $STANDARD_INFORMATION (16-0) Name: N/A Resident size: 72
Type: $FILE_NAME (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% 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: $STANDARD_INFORMATION (16-0) Name: N/A Resident size: 72
Type: $FILE_NAME (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: $STANDARD_INFORMATION (16-0) Name: N/A Resident size: 72
Type: $FILE_NAME (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: $STANDARD_INFORMATION (16-0) Name: N/A Resident size: 72
Type: $FILE_NAME (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 (C) 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...