Dot-Net

用於防止文件刪除的簡單 API Hook?

  • November 26, 2018

我想在使用者刪除任何目錄上的文件時攔截,方法是將所需的 API 函式與在消息框“ Really Would you like to Delete this file?”中詢問簡單布爾問題的可用性掛鉤,這個問題是表達我想的一個例子控製文件,刪除它或防止刪除。

我的作業系統是Windows 8 x64,但我想為其他 Windows 作業系統及其架構中的通用用法編寫一種方法(如果這不認為更難做到的話)。

在這個 SO question 中,我讀到最好的選擇是掛鉤NtSetFileInformation函式Intercept FIleSytemCall 進行刪除,因為我看到存在一個名為 WinAPI 的函式DeleteFile以及介面ICopyHook,但我不知道它們之間的區別,但是無論如何我真的不知道如何開始這樣做……

我想澄清一下,我正在尋找一個 VBNET 解決方案,我很頭疼,因為這些 API-Hooking 庫通過 Google 沒有任何 VBNET 程式碼範例,並且當複雜的程式碼是涉及。

***編輯:***我找到了一個EasyHook庫範例,NtSetFileInformation它似乎非常適合我的需求,但它是 C# 程式碼,我試圖翻譯它但沒有成功: Hooking NtCreateFile API from ntdll.dll with EasyHook (c#)

所以,我已經用圖書館 2.6 試過這個Deviare,但什麼也沒做:

Public Class Form1

   Private _mgr As Deviare2.NktSpyMgr = Nothing
   Private WithEvents _hook As Deviare2.NktHook = Nothing
   Private _proc As Deviare2.INktProcess = Nothing

   Private Shadows Sub Shown() Handles MyBase.Shown

       _mgr = New Deviare2.NktSpyMgr()
       _hook = _mgr.CreateHook("ntdll.dll!NtSetFileInformation", Nothing)
       _hook.Hook()

   End Sub

   Private Sub OnFunctionCalled(ByVal proc As Deviare2.INktProcess,
                                ByVal callInfo As Deviare2.INktHookCallInfo,
                                ByVal rCall As Deviare.IRemoteCall) Handles _hook.OnFunctionCalled

       MsgBox("Caught function call in " & proc.Name)

   End Sub

End Class

@mazoula基本上上面的程式碼與這裡回答的相同,在 vb.net 中掛鉤另一個程序對 winapi 函式的呼叫,他說該程式碼對他有用,但我已經按原樣嘗試過(沒有進行上面的修改)並向我扔了一個_hook.Attach(_mgr.Processes)指令中的異常。

我也試過這個庫EasyHook但是當我從 Explorer.exe 或 CMD 中刪除一個文件時再次沒有做任何事情,程式碼是這個 C# 程式碼的翻譯http://www.codeproject.com/Questions/528094/DeleteFileplushookingpluswithplusEasyHookplussucce

Imports System.Runtime.InteropServices
Imports EasyHook

Public Class Form1

   <DllImport("kernel32.dll", CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.StdCall)>
   Private Shared Function DeleteFile(filename As String) As Integer
   End Function

   <UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet:=CharSet.Unicode)>
   Private Delegate Function DeleteFileHandler(filename As String) As Integer

   Private Shared deleted As Boolean = False

   public Function DeleteFileHookInstance(filename As String) As Integer
       MsgBox("works?")
       If deleted Then
           deleted = False
           Return 1
       End If
       If MessageBox.Show((Convert.ToString("Do you really want to delete file ") & filename) + "?", "Confirm delete file", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then
           deleted = True
           Return DeleteFile(filename)
       Else
           Return 1
       End If
       'Assume the call is successfull
   End Function

   Public Sub Run()

       Dim hook As EasyHook.LocalHook

       Try
           MsgBox("Creating...")
           hook = LocalHook.Create(LocalHook.GetProcAddress("kernel32.dll", "DeleteFileW"), New DeleteFileHandler(AddressOf DeleteFileHookInstance), Me)
           'It stops here, the main interface receives the reported status 'Creating...' seemly forever, I understand that is for the unexpected restarting of explorer.exe
           MsgBox("Completing...")
           hook.ThreadACL.SetExclusiveACL(New Integer() {0})
           RemoteHooking.WakeUpProcess()
           MsgBox("OK")
       Catch ex As Exception
           MsgBox("CreateHook failed: " + ex.Message)
           System.Diagnostics.Process.GetCurrentProcess().Kill()
       End Try
       While True
           Application.DoEvents()
       End While
   End Sub

   Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
       Run()
   End Sub

End Class

幾天前我寫了這個方法來臨時解決問題,但我不是 100% 確保該方法在所有場景中都能正常工作(例如,使用者可以按ctrl+z恢復文件刪除和我的方法邏輯使用文件的 datetime 屬性來嘗試選擇我不是 100% 安全的最後刪除的文件),這現在有效,但我想學習如何使用 API 掛鉤而不是這樣做。

同樣顯然這不適用於永久文件刪除。

Imports System.IO
Imports Shell32

Public Class Test

   Private SH As New Shell
   Private RecycleBin As Folder = SH.NameSpace(ShellSpecialFolderConstants.ssfBITBUCKET)
   Private WithEvents FSW As New FileSystemWatcher

   Private Shadows Sub Load() _
   Handles MyBase.Load

       With FSW
           .Path = "C:\Test"
           .IncludeSubdirectories = True
           .Filter = "*"
           .NotifyFilter = NotifyFilters.FileName Or NotifyFilters.DirectoryName
           .EnableRaisingEvents = True
       End With

   End Sub

   Private Sub OnItemDeleted(sender As FileSystemWatcher, e As FileSystemEventArgs) _
   Handles FSW.Deleted

       Dim DeletedItems As IEnumerable(Of FolderItem) =
           RecycleBin.Items.Cast(Of FolderItem).
                            Where(Function(Item) Item.Name = e.Name).
                            OrderBy(Function(Item) Item.ModifyDate)

       Dim LastDeletedItem As Shell32.FolderItem = DeletedItems.LastOrDefault

       If LastDeletedItem IsNot Nothing Then

           If (LastDeletedItem.IsFolder AndAlso Directory.Exists(e.FullPath)) _
              OrElse (Not LastDeletedItem.IsFolder AndAlso File.Exists(e.FullPath)) Then

               Throw New Exception(String.Format("¿ Item has been restored ?: {0}", e.FullPath))
               Exit Sub

           End If

           LastDeletedItem.InvokeVerb("undelete")

       End If

   End Sub

End Class

如果是我,我會重新審視我的架構,看看我是否真的需要防止任何和所有文件刪除。可能您只需要防止刪除一些敏感目錄(可能只是這些目錄中的一些敏感文件)。這應該可以減少煩人的 UI。

引用自:https://stackoverflow.com/questions/20815333