2016年6月17日金曜日

cipherコマンドでドライブ内のデータを完全に削除する

ファイルやフォルダを削除しても運が良ければ復元できます。誤って削除してしまった場合には復元できた方が良いのですが、機密情報の入っているHDDを廃棄したい場合は復元できてしまっては困ります。HDDに入っていたものを復元できないようにするためにcipherというコマンドが利用できるのですが、これは使用する上で色々と注意が必要です。
今回はその注意点について解説します。(次の記事でそれを気にしなくて良いサンプルを公開します)
2016/06/17追記:ストレージの廃棄を目的としてcipherを実行する場合に必要な下準備からcipher実行までを自動化するサンプルを作成しました。
2016/07/04追記:記事末尾にも追記しましたが、cipherで処理したHDDからでも復元できるソフトがあるようです。。
2016/07/06追記:cipherに比べて非常に時間がかかりますが復元ソフトで元のファイルを取り出すことができない状態にすることができました。記事末尾に詳細を追記しました。
2016/07/07追記:アロケーションユニットサイズを大きくすることで、高速に埋め尽くすことが出来ることを確認しました。埋め尽くすためのプログラムを公開しました。
2016/07/13追記:埋め尽くす.htaのソースを修正しました。(処理中断ができるようにした。処理終了or中断時に、WSFファイルを削除するようにした。空き容量が0になったらHTA側も停止するようにした)


cipherコマンドはドライブの空き領域を埋め尽くすサイズのファイルを1つ作成します。(ファイルは作成後に削除されます。3種類のファイルを作っては削除するので、全体としては3つのファイルを作って消します)
ファイルサイズの上限よりもドライブの空き容量が大きい場合、ファイルサイズの上限までしかcipherコマンドは実行されません。
例えばファイルシステムがFAT32のドライブではファイルサイズの上限は4GBytesですので、空き容量が4GBytes以上ある場合はcipherコマンドの影響を受けない領域が生じます

空き領域ではない領域は、cipherコマンドによる影響を受けません。
上記理由により、ドライブ内のデータを全て削除したい場合は、cipherコマンドを利用する前に、DISKPARTコマンドで以下を実行すると目的の達成が確実になります。
  1. select vol 選択したドライブレター
  2. list partition ←でリストアップされるパーティションを全て「delete par * override」で削除する
  3. create partition primary ←サイズを指定しなければ現在の領域に未割り当て領域がなくなるまでパーティションが作成されます
  4. format fs=ntfs quick ※NTFSは10MB16E(エクサ)Bまで対応します
ディスクの初期化作業の頻度が低いと忘れてしまいそうです。
そしてcipherコマンドはどんな状況でも特にエラーメッセージを出さず、出来るところまでやったら黙って終了する感じなので不適切な状態で実行した場合は気が付きにくいので危険です。

安全に、確実にすべてを削除するために、確認から削除まで自動で実行してくれるサンプルを作りたいです。
目的はドライブ内のデータ削除ですので、ファイルシステムの変更が必要な場合でもユーザへの確認メッセージは表示せず自動で変更して処理を継続させたいです。


サンプルは以下。

StdOut.ReadLine()にかなり苦しめられました。
結局納得のいく形にはできませんでしたが、最低限必要な処理ができるようにはなりました。



初期化に成功したら、あとはcipherを実行するだけですが、cipherは特にログを出力しないので、動作中に容量をモニタしてちゃんと全容量を埋め尽くしたかどうか確認するスクリプトを作成すると安心です。

2016/06/17追記:よく考えたらcipherを使わなくてもWSHで0x00と0x11とランダムパターンのファイルをバイナリ形式で作成すれば状態も確認しやすいかと思いましたが、下準備がちゃんとできていればcipherが失敗することは無いので、シンプルにcipherを実行するだけにしました。


例えば「ディスクの管理」での表示が以下のようになっている場合



cmdで以下のように起動すると


まず「E」を含む「ディスク 2」内の全てのパーティションを削除して1つのパーティションに作り替えた後、NTFS形式にしてフォーマットされます。


あとは、cipherで空き領域を埋め尽くして、ドライブ内にあった情報の復元が不可能になります。


2016/07/04追記
この記事を作成した時は廃棄したいHDDがあったため、上記サンプルを作成してHDD内のデータを削除しました。
その後、今度は「間違って削除してしまったデータを復元して欲しい」というお話があり、復元ソフトを試すことになりました。

cipherコマンドで処理したHDDはまだ手元にあったので、試しにそちらも復元ソフトで処理してみました。


おう。。


見えてる見えてるー

cipherで一回処理したぐらいでは消しきれないのかも、と思ってもう一度上記サンプルを使ってcipherを実行しました。

そして再び復元ソフトでテスト。



・・・・・・一個減った。



これはちょっと他の方法を考えた方が良さそうです。
0x00、0x11、ランダムパターンを書いて「すぐに消す」のが良くないような気がします。
セクターにクセがつくまで時間を置く方が良いような……しかしそれではゴミがいつまで経っても捨てられませんし、ずっとPCでドライブレターを占有されるのも困ります。

物理的に破壊するのが良いのかもしれませんが、あんな金属の塊を再起不能にするような力をかけるのも大変ですし、バネやら何やらが飛散して周囲に危険が及びそうなのも怖いです。


2016/07/06追記
元のファイルを復元不可能にしたいドライブに対して、ドライブ全体を埋め尽くすようにファイルを作成しまくるプログラムを作って動作確認しました。

とりあえず結果から



上記のようになったのは、対象のドライブが以下のように空き容量がゼロになるまで



中身が「000000…」というテキストファイルを作成したからです。


ちなみに、このドライブは1998年製の容量3GBのHDDです。年代物です。



3GBの容量を埋め尽くすのにかかった時間はほぼ丸一日です。。
昔はこれが普通の速度だったのか、あるいは年数が経っていることによる劣化なのか確認する気力もありませんが……古いHDDを捨てるのは大変だということは分かりました orz

埋め尽くすプログラムは既に作成済みですが公開するなら少し修正したい箇所があるので修正して動作確認してから公開します。


2016/07/07追記
動作確認のために何度もファイルを作って消してを繰り返しているうちにHDDから異音が聞こえ始めました。それはさておき。
アロケーションユニットサイズを変更するとディスクアクセスが高速になります。

NTFSではアロケーションユニットサイズは最大64KBです。



HDDをファイルで埋め尽くすプログラムを作成しました。


起動して、実行した結果が以下です。



ファイルをバンバン作成する処理はWSFで実行していて、HTAは2分おきに空き容量を確認しています。HTAでファイルの作成もやってしまうと画面更新されなくなってフリーズしたようになってしまうので、そうしています。

17:19に開始して18:44には空き容量がゼロになっています。
18:54から空き容量が少し増えているのは謎ですが……システムファイル的なものが削除されたか退避されて空き容量が作られたのでしょうか?不明です。

とにかく、アロケーションユニットサイズを64KBにして、書き込むファイルのサイズもピッタリ65536バイトにしたら80分程度で埋め尽くすことに成功しました。

もちろん、その後ドライブをフォーマットして、復元も試してみました。



64KBの無意味なファイルをすばらしいコンディションで復元できるそうです。
それ以外の「64KBのファイルが作られる前にあったファイル」はリストに表示されていませんでした。
まったく、すばらしいですね。


ちなみに、本日SanDiskのウルトラ II SSD SDSSDHII-960G-J26を入手したので、それだとどれくらいの速度でやれるのか試してみました。



これだけだと速度がよく分からないので、空き容量が減った量を計算してHDDと比較してみました。
容量の単位はバイトです。
SSDやHDDの下に記載している「4KB」と「64KB」はアロケーションユニットサイズです。
経過時間[min] SSD
[64KB]
SSD
[4KB]
HDD
[64KB]
HDD
[4KB]
2 9,974,382,592 886,898,688 218,955,776 33,832,960
4 8,381,661,184 727,580,672 207,421,440 25,604,096
6 8,328,249,344 709,976,064 184,287,232 25,006,080
8 8,251,113,472 726,462,464 188,416,000 25,038,848
……桁が違います。色々。HDDとSSDはもちろん、アロケーションユニットサイズでも。
ちなみにSSD[64KB]で最高速度の「9,974,382,592」は664Mbpsという計算(容量/1000/1000/2分/60秒 * 8ビット)になります。
メーカーの製品情報ページに「シーケンシャル 書込み(最大)500MB/秒」って記載されているのに上回っちゃってる感じなんですが…
単位を「MB/秒」にするなら9,974,382,592は(容量/1000/1000/2分/60秒)の計算で83.1MB/秒でした。今度は逆にシーケンシャル書き込み(最大)500MB/秒に対して大幅に低い値になってしまいますが、そこはWSHでファイルをCreate、Write、Closeなどしているあたりがボトルネックになっているのではと思います。
HDD[64KB]の218,955,776も同様に計算すると1.8MB/秒ということになり、3GBのHDDを埋め尽くすのにかかる時間は27分という計算になりますが、上記の表にもある通り速度は一定ではなく徐々に下がっている(プラッタの外周から内周に向かって書き込んでいる?回転速度が一定の時、内側より外側の方が単位時間あたりの距離が長くなるので読み書きが高速になる)ので、低速領域まで書き込むと全体としては80分程度かかるということで正解のようです。


あと、ストレージ容量の増大によってJavaScriptの変数で扱える数値の大きさも問題になってくるかも…と思いましたが、整数として精度が保障されるのは2の53乗(9,007,199,254,740,992)だそうですので、まだまだ大丈夫なようです。

0 件のコメント:

コメントを投稿