NonSoft

ファイルを復元出来ないように削除する
サンプル(VB.NET)


 サンプル(ソース/コード)
<このサンプルの概要>
ファイルをIO.File.Deleteで削除した直後にファイル復元ツールを使えばそのファイルを
復元出来る可能性が高いです。うっかり削除してしまった時にファイル復元ツールは便利
なのですが、誰にも見せたく無いファイルの場合は困ります。

さて、どうすれば復元出来ないように削除出来るのでしょうか?
そこで、復元出来ないように削除するツールが必要になります。
または、削除した後にWindousのコマンド[cipher /w:c:\]を実行します。

cipherはディスクの空き領域(削除されたデータが残っている領域)にデータを上書きして
復元出来ないようにします。cipherを実行すると、まずディスクの空き領域いっぱいに0
を上書き(大きなファイルを作る)します。次に、同様に1を上書きします。最後に乱数を
上書きします。このように3回書くところがミソのようです。
1回上書きしただけでほとんどデジタル的には復元不可能だと思いますが、アナログ的に
は復元出来る可能性が残るようです。

さて、復元出来ないように削除するツールがどのように処理しているかと言うと、
それは、関係の無いデータ(乱数が良いと思います)を上書きしてから削除しています。

このサイトのフリーソフトに「古いごみ削除ツール(NonRccDel)」というものがあります。
このツールはごみ箱に入れてから指定の日数が経過した古いファイルを自動的に削除する
ツールです。ごみ箱の中のファイル数が多くなるとパソコンが遅くなるので古いファイル
を削除するために作ったのですが、ファイルを削除する時に復元出来ないように削除して
欲しいという要望を頂きました。そこで、このサンプルのような処理を調査して実装して
います。

このサンプルはファイルを削除する際に乱数を上書きしてから削除しています。
このサンプルで苦労した点は、乱数を上書き後、ファイル削除すると、削除時点ではまだ
ディスクにデータが書き込まれていない(システム・キャッシュ)状態がある事です。
そこで、ファイル書込み時点ですぐにディスクに反映されるようにAPIを使っています。

クラス(Module1.vb)
Public Class Class1
    ' API用Enum(CreateFile)---------------------------------------------------
    Private Enum ACC_MODE
        ACC_READ = 0
        ACC_WRITE = 1
        ACC_READWRITE = 2
    End Enum

    ' API用Const(CreateFile)--------------------------------------------------
    Private Const GENERIC_WRITE = &H40000000
    Private Const GENERIC_READ = &H80000000
    Private Const FILE_SHARE_READ = &H1
    Private Const FILE_SHARE_WRITE = &H2
    Private Const CREATE_ALWAYS = 2
    Private Const OPEN_EXISTING = 3
    Private Const OPEN_ALWAYS = 4
    Private Const INVALID_HANDLE_VALUE = -1
    ' (重要)キャッシュに書かれた情報をすぐにディスクに書く--------------------
    Private Const FILE_FLAG_WRITE_THROUGH = &H80000000
    ' ------------------------------------------------------------------------

    ' API定義-----------------------------------------------------------------
    Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _
        ByVal lpFileName As String, _
        ByVal dwDesiredAccess As Integer, _
        ByVal dwShareMode As Integer, _
        ByVal lpSecurityAttributes As Integer, _
        ByVal dwCreationDisposition As Integer, _
        ByVal dwFlagsAndAttributes As Integer, _
        ByVal hTemplateFile As Integer) As Integer
    Private Declare Function CloseHandle Lib "kernel32" ( _
        ByVal hObject As Integer) As Integer
    Private Declare Function WriteFile Lib "kernel32" ( _
        ByVal hFile As Integer, _
        ByVal lpBuffer As Byte(), _
        ByVal nNumberOfBytesToWrite As Integer, _
        ByRef lpNumberOfBytesWritten As Integer, _
        ByVal lpOverlapped As Integer) As Integer

    ''' <summary>
    ''' 復元出来ないように削除
    ''' </summary>
    ''' <param name="fpath">ファイルのPATH</param>
    ''' <remarks>ファイルを削除する前に乱数を上書き</remarks>
    Public Shared Sub NonRecoveryDel(ByVal fpath As String)
        ' 乱数をファイルに上書
        WriteRandom(fpath)
        ' ファイル削除
        IO.File.Delete(fpath)
    End Sub

    ''' <summary>
    ''' 乱数をファイルに上書きする
    ''' </summary>
    ''' <param name="fpath">乱数を上書きするファイルのPATH</param>
    ''' <remarks></remarks>
    Private Shared Sub WriteRandom(ByVal fpath As String)
        Dim hFile = INVALID_HANDLE_VALUE
        Dim bw As System.IO.BinaryWriter = Nothing
        Try
            Dim rd As New System.Random(Environment.TickCount)
            Dim fi As New IO.FileInfo(fpath)
            Dim sz1 As Integer = fi.Length
            Dim sz2 As Integer

            ' 乱数書込み用バッファ
            Dim dat As Byte() = New Byte(1024 * 1024 - 1) {}

            ' ファイルオープン
            hFile = OpenFile(fpath)
            Do While (sz1 > 0)
                sz2 = sz1
                If sz2 > dat.Length Then sz2 = dat.Length
                ' 乱数生成
                For i As Integer = 0 To sz2 - 1
                    dat(i) = rd.Next(256)
                Next
                ' 乱数書込み
                WriteBytes(hFile, dat, sz2)
                sz1 -= sz2
            Loop
        Catch ex As Exception
            Throw ex
        Finally
            ' ファイルクローズ
            CloseFile(hFile)
        End Try
    End Sub

    ''' <summary>
    ''' ファイルオープン
    ''' </summary>
    ''' <param name="fpath">ファイルのPATH</param>
    ''' <returns>ファイルハンドル</returns>
    ''' <remarks></remarks>
    Private Shared Function OpenFile( _
        ByVal fpath As String) As Integer
        Dim AccessMode As Integer
        Dim ShareMode As Integer
        Dim CreationMode As Integer
        AccessMode = GENERIC_WRITE Or GENERIC_READ
        ShareMode = FILE_SHARE_READ Or FILE_SHARE_WRITE
        CreationMode = OPEN_ALWAYS
        OpenFile = CreateFile(fpath, AccessMode, ShareMode, _
                           0, CreationMode, FILE_FLAG_WRITE_THROUGH, 0)
    End Function

    ''' <summary>
    ''' ファイルクローズ
    ''' </summary>
    ''' <param name="hFile">ファイルハンドル</param>
    ''' <remarks></remarks>
    Private Shared Sub CloseFile( _
        ByRef hFile As Integer)
        If hFile <> INVALID_HANDLE_VALUE Then
            CloseHandle(hFile)
            hFile = INVALID_HANDLE_VALUE
        End If
    End Sub

    ''' <summary>
    ''' ファイル書込み
    ''' </summary>
    ''' <param name="hFile">ファイルハンドル</param>
    ''' <param name="data">書込みデータ</param>
    ''' <param name="count">書込みバイト数</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function WriteBytes( _
        ByVal hFile As Integer, ByVal data() As Byte, ByVal count As Integer) As Integer
        Dim BytesWritten As Integer
        BytesWritten = 0
        WriteFile(hFile, data, count, BytesWritten, 0)
        WriteBytes = BytesWritten
    End Function
End Class