久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    用 C# 編寫 USB 存儲設備使用痕跡檢測和刪除工具

     tianht 2015-10-30
    轉:http://blog.csdn.net/metaphysis/article/details/18504315

    編寫 USB 存儲設備使用痕跡檢測和刪除工具

    (C# Windows Form 編程練習)

    [版權所有 邱秋 2014 metaphysis@yeah.net, 轉載請注明出處]

    第一節 準備知識

    之前一直都是用 Visual Basic .Net 來寫 Windows Form 程序。這幾天,熟悉了一下 C# 語言的語法,想練習一下。以前使用過一些 USB 存儲設備使用痕跡檢測和刪除工具,于是想寫了一個小工具來模擬這些功能。

    USB 存儲設備在使用后會在注冊表留下一些記錄,一般是通過檢索相應的注冊表鍵值來檢查使用痕跡。這些鍵值包括:

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. HKEY_LOCAL_MACHINE\SYSTEM\ControlSetXXX(CurrentControSetXXX)\Enum\USB  
    2. HKEY_LOCAL_MACHINE\SYSTEM\ControlSetXXX(CurrentControSetXXX)\Enum\USBSTOR  
    3. HKEY_LOCAL_MACHINE\SYSTEM\ControlSetXXX(CurrentControSetXXX)\Control\DeviceClasses\{53f56307-b6bf-11d0-94f2-00a0c91efb8b}  
    4. HKEY_LOCAL_MACHINE\SYSTEM\ControlSetXXX(CurrentControSetXXX)\Control\DeviceClasses\{a5dcbf10-6530-11d2-901f-00c04fb951ed}  

    其中 ControlSetXXX 和 CurrentControlSetXXX 表示的是注冊表中的類似于 ControlSet001、ControlSet002、CurrentControlSet 這樣的子鍵(CurrentControlSet 子鍵一般只有一個,特殊情況下可能有 CurrentControlSet001 等多個,同樣的 ControlSet 一般只有 ControlSet001 和 ControlSet002 這兩個,特殊情況下可能會有多個),CurrentControlSet 保存的是系統的當前的一些配置信息,而 ControlSet001 等則是對當前配置信息的備份,一般注冊表都會有兩個以上的備份,有的時候可能會有更多。在 ControlSetXXX 中的信息和 CurrentControlSet 中的信息一般都是一樣的,所以在檢測和刪除 USB 存儲設備信息時,不僅要檢測 CurrentControlSet 子鍵,也要檢測 ControlSetXXX 子鍵。

    對于 Enum\USB 子鍵,其中存儲的是曾經連接到系統的 USB 設備的一些信息,包括 USB 鼠標、鍵盤、光驅、手機、移動硬盤、攝像頭、U 盤等,所以并不是所有的信息都是 USB 存儲設備信息,雖然把這些信息刪除并無大礙(因為刪除的只是這些設備的一些連接信息和相應的驅動信息,并不是刪除系統的實際驅動文件,所以系統會自動重新識別這些設備),但為了提高識別精確性,還是增加一些判斷來得好些。

    而對于 Enum\USBSTOR 子鍵來說,則相當于把 USB 存儲設備的信息單獨分離出來了,該子鍵下存儲的信息都是曾經連接到計算機的 USB 存儲設備的相關信息。這些信息詳細列出了該 USB 存儲設備的類型、硬件 ID、設備描述、友好名稱等信息。

    對于 Control\DeviceClasses 來說,該子鍵下存儲的是以 GUID 分類的設備信息,其中有幾個是和 USB 設備有關的(它們在微軟的 USB 和存儲設備輸入輸出控制頭文件 USBIODEF.H 和NTDDSTOR.H 中定義):

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. {A5DCBF10-6530-11D2-901F-00C04FB951ED} GUID_DEVINTERFACE_USB_DEVICE  
    2. {3ABF6F2D-71C4-462A-8A92-1E6861E6AF27} GUID_DEVINTERFACE_USB_HOST_CONTROLLER  
    3. {F18A0E88-C30C-11D0-8815-00A0C906BED8} GUID_DEVINTERFACE_USB_HUB  
    4. {53F56307-B6BF-11D0-94F2-00A0C91EFB8B} GUID_DEVINTERFACE_DISK  

    一般檢查 {53F56307-B6BF-11D0-94F2-00A0C91EFB8B} 和 {A5DCBF10-6530-11D2-901F-00C04FB951ED} 這兩個鍵值,其他兩個由于是和 USB 控制器有關,一般可不檢查。有的資料介紹說還要檢查 MountedDevices 子鍵,但是由于該子鍵和系統的分區信息有關,一般無絕對的把握,不必進行檢查和刪除,到時可能會造成不必要的麻煩。

    第二節 檢測 USB 存儲設備使用痕跡

    1、打開 Visual Studio 2010,新建一個空白方案,命名為 USBView。

    2、在解決方案下新建一個類型為“Windows 窗體應用程序”的項目,命名為 USBViewer。將主窗體命名為 MainForm。并添加一些圖標和 PNG 圖像資源,美化一下程序界面。

    資源文件包含了一個文本文件,名稱為 VendorIDs.txt,保存的是 USB 設備廠家的 ID 號及廠家名稱值對,用于顯示在注冊表中搜索到的 USB 設備的廠家名稱(該文件內容來源于微軟的 USBView 示例程序中的頭文件vndrlist.h,該示例程序使用 C++ 編碼,需要使用 Visual Studio 2013打開,并要求安裝 Windows Driver Kit (WDK)8.1,下載鏈接地址 http://code.msdn.microsoft.com/windowshardware/USBView-sample-application-e3241039)。

    在建立必要的按鈕后,開始編寫檢測代碼。因為要讀取注冊表,有必要使用 .Net 框架提供的 RegistryKey 類。這需要引用 Microsoft.Win32 命名空間,注冊表類都在該命名空間中。

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. using Microsoft.Win32;  

    之后便是獲取我們感興趣的注冊表的基項 HKEY_LOCAL_MACHINE,接著使用RegistryKey 類的 OpenSubKey 方法以只讀方式打開 SYSTEM 子鍵。

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. RegistryKey hklm = Registry.LocalMachine;  
    2. RegistryKey systemKey = hklm.OpenSubKey("SYSTEM");  

    這里順帶說一下,.Net 框架已經將注冊表中的數據封裝成了 Registry 類(注意 Registry 類和 RegistryKey 類是不一樣的),并公布了幾個只讀屬性,它們是:

    RegistryKey 類是用于在注冊表中檢索數據用的類。以下是本文中用到的 RegistryKey 類的幾個屬性和方法:

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. SubKeyCount                     // 檢索當前項的子項數目。  
    2. OpenSubKey(string)              // 以只讀方式檢索 string 標識的子項。  
    3. OpenSubKey(stringbool)        // 以 bool 指定的方式檢索 string 標識的子項,若 bool 值為 true,表示以可讀寫方式打開,否則為只讀方式。  
    4. DeleteSubKeyTree(string)        // 遞歸刪除 string 標識的子項和任何子級子項。  
    5. GetValue(string)                // 檢索 string 標識的名稱所關聯的值,若該標識的名稱不存在,則返回 null。  
    6. GetSubKeyNames()                // 返回一個包含所有子項名稱的字符串數組。  
    7. Close()                         // 關閉該鍵,如果有更改,則將更改刷新到磁盤上。  

    需要注意的是若想用可寫方式打開某個子項進行刪除或寫入操作,一定要具有相應的權限,否則會拋出 SecurityException 異常。在檢測階段,由于只需要只讀權限,可以使用方法 OpenSubKey(string)。在打開了 Local_Machine\SYSTEM 子鍵后,開始檢索該鍵下類似于 ControlSetXXX 和 CurrentControlSetXXX 的鍵。

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. if (!sysKey.ToUpper().StartsWith("CONTROLSET") &&  
    2.     !sysKey.ToUpper().StartsWith("CURRENTCONTROLSET"))  
    3.     continue;  

    找到這樣的子鍵后,就在其中檢索 Enum\USB、Enum\USBSTOR、Control\DeviceClasses 等子鍵。由于 Enum\USB 子鍵中的信息并不都是 USB 存儲設備的信息,所以要加以判斷。觀察一下 Enum\USB 子鍵下的項:

    除了 ROOT_HUB20 外,其他鍵值都是以 VID_ 開始,后面跟著一個 4 位的16 進制數,這就是廠商的 ID 號,其后的 PID_XXXX 則是廠家的產品號。進一步打開這些 VID_ 打頭的子鍵鍵值,可以看到更多的信息:

    例如 Service 表示的是該 USB 設備是由系統服務 HidUSB 進行處理的,而系統服務 HidUSB 表示的是使用 USB 協議的人體工程學輸入設備,只要有 USB 類的鼠標、鍵盤、攝像頭等設備連接到計算機,就會觸發一個特定于 HID 設備的事件,HidUSB 服務會處理該事件,可以看到有 ClassGUID 這個鍵值,它的值 {745a17a0-74d3-11d0-b6fe-00a0c90f57da} 就是表示 Class 是 HIDClass 這樣的設備。同樣的,對于 USB 存儲設備,在接入時同樣會由一個服務予以處理,這個服務就是 USBSTOR 系統服務。以下列出了在 Enum\USB 下和 USB 設備有關的服務名稱(還有其他的相關服務,這里列出的是我的系統上有的):

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. Usbccgp:       USB 設備控制器服務。  
    2. HidUsb:        USB 人體學工程輸入設備服務。  
    3. USBSTOR:       USB 存儲設備服務。  
    4. Usbhub:        USB 設備接口服務。  
    5. WUDFRd:        用戶模式驅動框架反射器相關的服務,當連接只能手機等設備時,該服務會進行處理。  
    6. VboxUsb:       安裝 Oracle 的 VM VirtualBox 虛擬機軟件后會出現該服務,用于處理連接到虛擬機的 USB 設備。  

    在本文中,只檢測了 USBSTOR、WUDFRd、VboxUsb服務所處理的 USB 設備。對于 Enum\USBSTOR 子鍵的鍵值,其結構和 Enum\USB 下的鍵值結構類似。在 USB、USBSTOR 的子鍵鍵值中有FriendlyName 這個鍵值,它表示的是設備的友好名稱,可以作為 USB 的設備名稱來顯示。

    第三節 刪除 USB 存儲設備使用痕跡

    檢測到之后便是刪除這些痕跡的問題。由于注冊表的某些鍵值權限是 SYSTEM 賬戶的,一般的管理員賬號權限無法刪除,如果要想通過代碼來刪除,必須取得 SYSTEM 權限,一個方法是將執行刪除的代碼做成程序后安裝為系統服務(Sysinterals 的工具 PsExec 也是利用了系統服務可以使用 SYSTEM 權限的特性,使得啟動的進程繼承了 SYSTEM 權限),系統服務是可以運行于 SYSTEM 權限的,這樣對注冊表就有了完全的控制權,可自由進行刪改(但是同時一定要注意不要刪除其他的注冊表項,以避免麻煩)。如何使用 Visual Studio 制作系統服務呢,Step by Step。

    1、右鍵單擊解決方案 USBView,選擇“添加”-“新建項目”,項目類型選擇“Windows 服務”,項目名稱命名為 USBCleaner,隨后在 IDE 自動生成的代碼中會出現以下方法:

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. protected override void OnStart(string[] args)  
    2. protected override void OnStop()  

    分別表示服務啟動和停止時的事件處理過程。在這兩個事件處理過程中寫入刪除注冊表鍵值的代碼,邏輯和檢測時的一樣。在刪除過程中,我添加了一個日志功能,記錄在執行刪除過程中成功和錯誤的信息。為了在程序運行目錄下生成日志文件,需要在系統服務的運行過程中得到其所在路徑,網上查閱了一些資料,有許多獲取路徑的方法,自己實際用注冊服務的方式做了一下實驗,結果如下:

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. Assembly.GetExecutingAssembly().Location  
    2. D:\DATA\USBViewer\bin\Release\USBCleaner.exe  
    3.   
    4. this.GetType( ).Assembly.Location  
    5. D:\DATA\USBViewer\bin\Release\USBCleaner.exe  
    6.   
    7. Process.GetCurrentProcess().MainModule.FileName  
    8. D:\DATA\USBViewer\bin\Release\USBCleaner.exe  
    9.   
    10. System.Environment.CurrentDirectory  
    11. C:\Windows\system32  
    12.   
    13. System.AppDomain.CurrentDomain.BaseDirectory  
    14. D:\DATA\USBViewer\bin\Release\  
    15.   
    16. System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase  
    17. D:\DATA\USBViewer\bin\Release\  
    18.   
    19. System.IO.Directory.GetCurrentDirectory()  
    20. C:\Windows\system32  

    最后決定用 Assembly.GetExecutingAssembly().Location 這個方法,在 Windows 7 和 Windows XP 及 Windows Server 2003 上運行都能得到正確的結果。

    在所有刪除代碼都編寫完畢后,就是給服務添加安裝程序了。雙擊打開 USBCleaner.cs,此時會顯示設計界面,在設計界面上單擊右鍵,選擇“添加安裝程序”,會為該服務項目添加用于服務安裝時的支持,這樣就可以通過代碼來直接安裝和卸載服務了。

    “添加安裝程序”這一步會在項目中自動添加兩個組件,一個是服務進程安裝類組件,另外一個是服務安裝類組件:

    服務進程安裝類組件具有以下的屬性:

    其中的“Account”屬性即是服務所運行的權限級別,選擇“LocalSystem”,即可以使用 SYSTEM 權限。另外一個是服務安裝類組件,屬性如下:

    其中的幾個關鍵屬性:

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. Description 用于該服務的簡短描述。  
    2. DisplayName 顯示在服務列表中的顯示名稱。  
    3. ServiceName 服務的名稱,系統使用該名稱唯一標識該服務,不能和已有的服務沖突。  
    4. StartType   表示服務的啟動方式,可以是自動、手動、禁用。  

    設置完畢后,生成 USBCleaner,得到一個 EXE 文件:

    接下來就是在項目 USBViewer 中對 USBCleaner.exe 進行安裝調用了。

    如果是手動進行安裝,可以使用 .Net 框架提供的工具:InstallUtil.exe 程序,對于 .Net Framework 4.0 來說,它一般位于:

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. SystemRoot%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe  

    使用 /u 或 /uninstall 來卸載服務,不加參數則是安裝服務。但是要在程序中自動執行安裝和卸載服務,就需要使用 .Net 框架提供的 TransactedInstaller 類,它提供了的作用就是InstallUtil.exe 服務安裝工具所提供的功能。

    為了代碼更好的組織,我將檢測服務運行和安裝的代碼統一放在 USBViewer 項目的 ServiceHelper.cs 文件中。代碼首先添加對以下兩個命名空間的引用:

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. using System.Configuration.Install;  
    2. using System.ServiceProcess;  

    引用 System.Configuration.Install 的目的是使用 TransactedInstaller 類,該類的作用是以事務的方式對服務進行安裝或卸載,要么安裝或卸載成功,要么回到安裝前的狀態。在進行操作前常規對服務進行一下檢測,看服務是否已經存在,這里使用了 ServiceController 類對服務名進行輪詢,只要查找到具有指定名稱的服務,就可以知道服務已經存在了。

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. /// <summary>  
    2. /// 檢測服務是否安裝。  
    3. /// </summary>  
    4. /// <param name="serviceName">要查詢的服務名。  
    5. /// <returns></returns>  
    6. private static bool IsWindowsServiceInstalled(string serviceName)  
    7. {  
    8.   ServiceController[] services = ServiceController.GetServices();  
    9.   foreach (ServiceController service in services)  
    10.   {  
    11.     if (service.ServiceName == serviceName)  
    12.     return true;  
    13.   }  
    14.   return false;  
    15. }  

    安裝服務則按以下方式調用 TransactedInstaller 類:

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. string[] cmdline = {};  
    2. TransactedInstaller transactedInstaller = new TransactedInstaller();  
    3. AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);  
    4. transactedInstaller.Installers.Add(assemblyInstaller);  
    5. transactedInstaller.Install(new System.Collections.Hashtable());  

    注意 Install 方法需要一個 IDictionary 接口類型的變量來保存安裝狀態,這里使用了哈希表。卸載服務和安裝服務時類似,不過是調用 Uninstall 方法,而且可以不用提供保存狀態的變量。

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. transactedInstaller.Uninstall(null);  

    在安裝和卸載前,不要忘記對要安裝和卸載的服務文件進行檢測,確保該文件確實存在。

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. // 檢測相應的服務文件是否存在。  
    2. string serviceFileName = Path.Combine(Application.StartupPath, "USBCleaner.exe");  
    3. if (File.Exists(serviceFileName) == false)  
    4.   return false;  

    第四節 運行測試

    對項目 USBViewer 進行編譯,得到一個 EXE 文件:

    因為在刪除過程中要安裝系統服務,運行本程序,需要系統管理員權限,這在 Windows XP 和 Windows Server 2003 等操作系統上,需要以管理員賬戶登錄系統后使用。在 Windows Vista 或 Windows 7 以上的操作系統,由于 UAC (用戶賬戶控制)的問題,可能程序無法運行,畢竟Windows Vista 以上的系統對系統安全性做了進一步增加,對注冊表等敏感數據的操作做了進一步的限制,要使得程序能夠正常運行,一個方法可以通過右鍵單擊程序,在“兼容性”選項卡,選擇“以管理員身份運行本程序”。

    或者在每次運行程序時,單擊右鍵選擇“以管理員身份運行”。

    另外一種方法是使用 app.manifest 文件的方式,把程序運行所需要的權限事先聲明,這樣就可以避免 Windows UAC 的控制阻攔問題了。具體方法是:在項目 USBViewer 右鍵單擊,選擇“屬性”-“安全性”,勾選“啟用 ClickOnce 安全設置”,

    這時會自動為項目添加一個 app.manifest 文件(在項目的 Property 文件夾下),打開該文件,找到

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. <requestedexecutionlevel uiaccess="false" level="asInvoker"></requestedexecutionlevel>  

    將其中的 asInvoker 替換為 requireAdministrator,

    [csharp] view plaincopy在CODE上查看代碼片派生到我的代碼片
    1. <requestedexecutionlevel uiaccess="false" level="requireAdministrator"></requestedexecutionlevel>  

    保存編譯項目。注意在保存編譯項目前,注意要取消勾選項目安全性中的“啟用 ClickOnce 安全設置”,否則編譯會出錯(取消勾選并不會刪除已經生成的 app.manifest 文件)。這樣程序就會自動以管理員權限運行了。

    解決了權限的問題后,將刪除 USB 存儲設備使用痕跡的服務程序 USBCleaner.exe 復制到 USBViewer.exe 所在文件夾下,運行 USBViewer.exe,結果如下:

    執行刪除操作,可以看到系統服務列表里出現了顯示名稱為 USB Cleaner 的服務:

    查看其屬性,確實是執行注冊表刪除操作的服務。

    點擊“退出”按鈕,稍等程序對服務進行卸載,然后再次查看一下系統服務列表,發現 USB Cleaner 服務被卸載了。檢查 USBViewer.exe 文件所在文件夾,會發現多了兩個文件,一個是 USBCleanerLog.txt,它是執行刪除操作的日志文件:

    而另外一個文件 USBCleaner.InstallLog 則是在執行安裝和卸載服務時產生的日志文件,可打開查看其中的內容。

    第五節 小結

    通過此次 C# WindowsForm編程練習,進一步熟練了C#的使用,對注冊表的操作和 Windows服務的安裝及卸載有了進一步的了解,同時對相關的知識做了一番梳理,有利于自己編程水平的提高(本文所涉及的解決方案文件已壓縮為 RAR格式的壓縮文件以供下載,下載鏈接:http://download.csdn.net/detail/metaphysis/6864213)

      本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發現有害或侵權內容,請點擊一鍵舉報。
      轉藏 分享 獻花(0

      0條評論

      發表

      請遵守用戶 評論公約

      類似文章 更多

      主站蜘蛛池模板: 国产精品亚洲二区在线看| 亚洲AV日韩AV不卡在线观看 | 国产欧美在线一区二区三| 婷婷综合久久中文字幕| 精品国产成人A区在线观看| 日本高清一区免费中文视频| 国精品无码一区二区三区在线蜜臀| 中文有无人妻vs无码人妻激烈| 四虎国产精品免费久久久| 51精品免费视频国产专区| 国产精品自在拍首页视频| 精品无人区无码乱码毛片国产 | 国产果冻豆传媒麻婆精东| 亚洲一区二区偷拍精品| 亚洲AV日韩AV永久无码电影| 中文字幕日韩有码av| 亚洲一区二区三区影院| 亚洲成人资源在线观看| 丝袜美腿一区二区三区| 精品免费看国产一区二区| 亚洲国产成人久久一区久久| 成人无码特黄特黄AV片在线| 亚洲AV无码之国产精品网址| 国产萌白酱喷水视频在线观看| 国产精品一区中文字幕| 欧美成人精品一区二区综合| 69天堂人成无码免费视频| 日日摸夜夜添夜夜添高潮喷水 | 青青草原国产AV福利网站| 国产一区二区不卡在线| 体验区试看120秒啪啪免费| 无码AV无码免费一区二区| 国产欧美日韩精品丝袜高跟鞋| 亚洲男女内射在线播放| 一区二区三区鲁丝不卡| 无码人妻少妇久久中文字幕蜜桃| 老色鬼永久精品网站| 免费无码成人AV片在线 | 国产黑色丝袜在线观看下| 国产精品久久中文字幕| 无码AV免费永久免费永久专区|