天天看點

監控USB裝置插拔

最近做了UKey加密中設計到USB裝置. 因UKEy是用來加密和執行PC與項目間通信加密的媒體.從作用範圍來講不是傳統意義上U盤作為存儲媒體來使用.其實熟悉網銀驅動DR應該了解.在網銀系統安全上一個最基本需求就是動态即時監控通信PC驅動以及裝置清單通信變化.當然包括我們加密存儲媒體在PC上USB插拔.

首先引入命名空間:

using System.Management;     

using System.Threading;     

using System.Security.Permissions; 

定義Device Management Event的枚舉:

public enum DeviceEvent : int     

      {     

          DBT_CONFIGCHANGECANCELED = 0x0019,     

          DBT_CONFIGCHANGED=0x0018,     

          DBT_CUSTOMEVENT=0x8006,     

          DBT_DEVICEARRIVAL=0x8000,//USB Insert DEvice Statu     

          DBT_DEVICEQUERYREMOVE=0x8001,     

          DBT_DEVICEQUERYREMOVEFAILED=0x8002,     

          DBT_DEVICEREMOVEPENDING=0x8003,//USB Revoing.    

          DBT_DEVICEREMOVECOMPLETE=0x8004,//USB Remove Completed    

          DBT_DEVICETYPESPECIFIC=0x8005,    

          DBT_DEVNODES_CHANGED=0x0007,//Device List _Changed    

          DBT_QUERYCHANGECONFIG=0x0017,    

          DBT_USERDEFINED=0xFFFF    

      } 

其中涉及到USB裝置插拔的是DEVICEREMOVEPENDING/DEVICEREMOVECOMPLETE[删除] DEVICEARRIVAL[插入裝置] 重寫WinFProc實作窗體上對Windows MEssage進行攔截并重新處理:

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]     

  protected override void WndProc(ref Message m)     

  {     

      base.WndProc(ref m);     

      DeviceEvent lEvent;     

      lEvent = (DeviceEvent)m.WParam.ToInt32();     

      switch (lEvent)     

      {    

           case DeviceEvent.DBT_DEVICEARRIVAL://[Insert]    

              this.CheckDeviceStatus_Lable.BackColor = Color.Green;    

              this.CheckDeviceStatus_Lable.Text = "----Connection Device!----";    

              MessageBox.Show("Just Insert At Moment !", "Insert");    

              break;    

          case DeviceEvent.DBT_DEVICEREMOVECOMPLETE://[REmove]    

              this.CheckDeviceStatus_Lable.BackColor = Color.Red;    

              this.CheckDeviceStatus_Lable.Text = "------No Connection------";    

              MessageBox.Show("Remove Complete At Moment!", "Remove");    

          case DeviceEvent.DBT_DEVNODES_CHANGED://[Device List Have Changed]    

              MessageBox.Show("Device List have been Changed!");    

          default:    

      }    

  } 

首先USB在進行插拔即時如果沒有存儲媒體即Disk或是無驅動的方式可能不能觸發DeviceEvent.DBT_DEVICEREMOVECOMPLETE 和 DeviceEvent.DBT_DEVICEARRIVAL插把事件. 但是一點是可以确認的是.PC端隻要接受USB裝置.PC識别之後裝置清單肯定會發生變化. 如果不是加密Key. u盤的 盤符方式存在Disk存儲媒體.則沒有問題.

當然需要移植這種基于From窗體系統Message攔截方法時發現這種可重用性就不高.換一種思路采用Windows底層方式WMI實作.

WMI 可以産生的系統級事件的一些更有用。 每當建立 WMI 類的新執行個體 ; 例如對于激發稱為 __instancecreationevent 事件__instancedeletionevent 時将觸發一個執行個體将被删除. 當然USB插拔時同樣獲得這個系統事件:

public void ControlUSBConnectionStatu()     

          ManagementEventWatcher getEventWatcher = null;     

          WqlEventQuery getEventQuery = null;     

          ManagementOperationObserver getObserver = new ManagementOperationObserver();     

          //Bind to Loacl Machine and Watch the PortConnection     

          ManagementScope getScope = new ManagementScope("root\\CIMV2");    

           getScope.Options.EnablePrivileges = true;//set requeired    

          try    

          {    

              getEventQuery = new WqlEventQuery();    

              getEventQuery.EventClassName = "__InstanceOperationEvent";    

              getEventQuery.WithinInterval = new TimeSpan(0, 0, 0, 1);    

              getEventQuery.Condition = @"TargetInstance ISA 'Win32_DiskDrive' ";            

              //[Disk must have DiskDrive fuck ]     

              //Event Watcher [Test Event and semd informatio to this message and create new informtion .]    

              getEventWatcher = new ManagementEventWatcher(getEventQuery);    

              getEventWatcher.EventArrived += new EventArrivedEventHandler(getEventWatcher_EventArrived);    

              getEventWatcher.Start();//Start Watch Event     

          }    

          catch (Exception se)    

          { }    

          finally    

              // getEventWatcher.Stop();    

當發生USB插拔并成功監聽到事件時處理方法:

void getEventWatcher_EventArrived(object sender, EventArrivedEventArgs e)     

       {     

           ManagementBaseObject getBaseObject = (ManagementBaseObject)e.NewEvent;     

           if ((getBaseObject.ClassPath.ClassName == "__InstanceCreationEvent"))     

           {     

               //Usb Inserted     

               MessageBox.Show("USB Disk Inserted!");     

           }     

           else    

           {    

               //Usb Removed    

               MessageBox.Show("USB Device Removed!");    

           }    

       } 

如上在定義時設定一個Condition[條件]:存在Disk Driver 磁盤驅動.如果類似某些UKey不存在磁盤驅動同時也無存儲媒體 經過測試你會發現.加密的UKey插入 如上的WMI監聽事件并不能撲捉到USB插拔. 但是針對這種方式我們還有一種更為徹底的方式就是USB插拔唯一可以确定在PC識别必然變化的因素是系統裝置清單發生更新.

WMI處理監聽:

/// <summary>     

/// 監聽USB Device裝置插拔事件 完整操作.     

/// WMI Handle Event Change Device List chenkai     

/// </summary>     

public void RegisterDeviceWMIEventStatu()     

{     

    try      

    {     

        //Device List HAve Changed  And Send Message     

        WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent");    

        ManagementEventWatcher watcher = new ManagementEventWatcher(query);    

        watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);    

        watcher.Start();  // Start listening for events    

    }    

    catch (Exception se)    

    { }    

WMI監聽處理函數:

void watcher_EventArrived(object sender, EventArrivedEventArgs e)     

           string geteventtype = e.NewEvent.GetPropertyValue("EventType").ToString();     

           ManagementBaseObject getEventObject = (ManagementBaseObject)e.NewEvent;     

           if (getEventObject != null)     

               //close Operator      

               this.CloseDeviceEqument();    

其實這依然還是一種折中辦法.因為導緻PC端裝置清單發生變化的因素有很多.如何判定是USB口發生裝置變化.WMI依然沒有讓我們失望:

//WMI Control The USB Device Change Statu And Send Message to When IT‘s Changed/     

      public void ControlUSBDeviceSTatu()     

          try     

          {     

              WqlEventQuery query = new WqlEventQuery("select * from Win32_VolumeChangeEvent");     

              ManagementEventWatcher getwatcher = new ManagementEventWatcher(query);     

              getwatcher.EventArrived += new EventArrivedEventHandler(getwatcher_EventArrived);     

              getwatcher.Start();    

WMI在USB事情處理函數:

void getwatcher_EventArrived(object sender, EventArrivedEventArgs e)     

MessageBox.Show(e.NewEvent.GetText(TextFormat.Mof).ToString());     

這樣來一來就可以清晰判定USB在插拔時所發生在系統PC端的變化通知給應用程式來進行處理.如何獲得目前PC端 USB Driver清單.經過幾番測試找到一種很好的方式擷取全部的USB Driver資訊:

//Get ALL USB DRiver And Driver Property Fuck this shit。chenkai     

       public static string[] AllInformation()     

           StringCollection propNames = new StringCollection();     

           ManagementClass driveClass = new ManagementClass("Win32_USBController");     

           PropertyDataCollection props = driveClass.Properties;     

           foreach (PropertyData driveProperty in props)     

               propNames.Add(driveProperty.Name);    

           int idx = 0;    

           ManagementObjectCollection drives = driveClass.GetInstances();    

           string _s = string.Empty;    

           List<string> harddisk = new List<string>();    

           foreach (ManagementObject drv in drives)    

               idx++;    

               _s = string.Format(" USB Driver({0}) Properties ", idx);    

               harddisk.Add(_s);    

               foreach (string strProp in propNames)    

               {    

                   _s = string.Format("Property: {0}, Value: {1}", strProp, drv[strProp]);    

                   harddisk.Add(_s);    

               }    

           string[] _ss = harddisk.ToArray();    

           return _ss;    

WMI的更多展現是對Windows 互動中進一步封裝和管理.

Can考資料:

<a target="_blank" href="http://msdn.microsoft.com/en-us/library/aa363232(v=vs.85).aspx">Device ManageMent Events</a>

<a target="_blank" href="http://msdn.microsoft.com/zh-cn/library/system.windows.forms.control.wndproc(v=VS.100).aspx">System.Form.control.WinProc[]Method</a>

<a target="_blank" href="http://msdn.microsoft.com/zh-cn/library/system.windows.forms.message.aspx">System.Form.Control.Message[]Method</a>

本文轉自chenkaiunion 51CTO部落格,原文連結:http://blog.51cto.com/chenkai/763645

繼續閱讀