zoukankan      html  css  js  c++  java
  • 监控USB设备插拔

    最近做了UKey加密中设计到USB设备. 因UKEy是用来加密和执行PC与项目间通信加密的介质.从作用范围来讲不是传统意义上U盘作为存储介质来使用.其实熟悉网银驱动DR应该了解.在网银系统安全上一个最基本需求就是动态即时监控通信PC驱动以及设备列表通信变化.当然包括我们加密存储介质在PC上USB插拔.

    思路一.在WinFrom中通过拦截Windows 消息机制来实现. 类似定义MEssageForm窗体. 假如用鼠标左击一下窗体, 系统会收到一条 WM_LBUTTONDOWN 消息;当鼠标抬起, 系统又会收到 WM_LBUTTONUP 消息.系统收到消息后, 会告诉窗体发生的事情, 然后窗体再做出反应; 当然窗体能否做出反应要看窗体是否有相应的响应代码. 同样也可以把USB设备插拔事件通过重写窗体WndProc(Ref Message m)方法拦截并处理.

    首先引入命名空间:

       1:  using System.Management;
       2:  using System.Threading;
       3:  using System.Security.Permissions;

    定义Device Management Event的枚举:

       1:    public enum DeviceEvent : int
       2:          {
       3:              DBT_CONFIGCHANGECANCELED = 0x0019,
       4:              DBT_CONFIGCHANGED=0x0018,
       5:              DBT_CUSTOMEVENT=0x8006,
       6:              DBT_DEVICEARRIVAL=0x8000,//USB Insert DEvice Statu
       7:              DBT_DEVICEQUERYREMOVE=0x8001,
       8:              DBT_DEVICEQUERYREMOVEFAILED=0x8002,
       9:              DBT_DEVICEREMOVEPENDING=0x8003,//USB Revoing.
      10:              DBT_DEVICEREMOVECOMPLETE=0x8004,//USB Remove Completed
      11:              DBT_DEVICETYPESPECIFIC=0x8005,
      12:              DBT_DEVNODES_CHANGED=0x0007,//Device List _Changed
      13:              DBT_QUERYCHANGECONFIG=0x0017,
      14:              DBT_USERDEFINED=0xFFFF
      15:          }

    其中涉及到USB设备插拔的是DEVICEREMOVEPENDING/DEVICEREMOVECOMPLETE[删除]  DEVICEARRIVAL[插入设备]  重写WinFProc实现窗体上对Windows MEssage进行拦截并重新处理:

       1:        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
       2:          protected override void WndProc(ref Message m)
       3:          {
       4:              base.WndProc(ref m);
       5:              DeviceEvent lEvent;
       6:      
       7:              lEvent = (DeviceEvent)m.WParam.ToInt32();
       8:              switch (lEvent)
       9:              {
      10:                  case DeviceEvent.DBT_DEVICEARRIVAL://[Insert]
      11:                      this.CheckDeviceStatus_Lable.BackColor = Color.Green;
      12:                      this.CheckDeviceStatus_Lable.Text = "----Connection Device!----";
      13:                      MessageBox.Show("Just Insert At Moment !", "Insert");
      14:                      break;
      15:                  case DeviceEvent.DBT_DEVICEREMOVECOMPLETE://[REmove]
      16:                      this.CheckDeviceStatus_Lable.BackColor = Color.Red;
      17:                      this.CheckDeviceStatus_Lable.Text = "------No Connection------";
      18:                      MessageBox.Show("Remove Complete At Moment!", "Remove");
      19:                      break;
      20:                  case DeviceEvent.DBT_DEVNODES_CHANGED://[Device List Have Changed]
      21:                      MessageBox.Show("Device List have been Changed!");
      22:                      break;
      23:                  default:
      24:                      break;
      25:              }
      26:          }

    首先USB在进行插拔即时如果没有存储介质即Disk或是无驱动的方式可能不能触发DeviceEvent.DBT_DEVICEREMOVECOMPLETE 和 DeviceEvent.DBT_DEVICEARRIVAL插把事件. 但是一点是可以确认的是.PC端只要接受USB设备.PC识别之后设备列表肯定会发生变化. 如果不是加密Key. u盘的 盘符方式存在Disk存储介质.则没有问题.

    当然需要移植这种基于From窗体系统Message拦截方法时发现这种可重用性就不高.换一种思路采用Windows底层方式WMI实现.

    WMI以CIMOM为基础,CIMOM即公共信息模型对象管理器[Common Information Model Object Manager],是一个描述操作系统构成单元的对象数据库,为MMC和脚本程序提供了一个访问操作系统构成单元的公共接口。有了WMI,工具软件和脚本程序访问操作系统的不同部分时不需要使用不同的API;相反,操作系统的不同部分都可以插入WMI,工具软件和WMI可以方便地读写WMI.

    WMI 可以产生的系统级事件的一些更有用。 每当创建 WMI 类的新实例 ; 例如对于激发称为 __instancecreationevent 事件__instancedeletionevent 时将触发一个实例将被删除.  当然USB插拔时同样获得这个系统事件:

       1:    public void ControlUSBConnectionStatu()
       2:          {
       3:              ManagementEventWatcher getEventWatcher = null;
       4:              WqlEventQuery getEventQuery = null;
       5:   
       6:              ManagementOperationObserver getObserver = new ManagementOperationObserver();
       7:   
       8:              //Bind to Loacl Machine and Watch the PortConnection
       9:              ManagementScope getScope = new ManagementScope("root\\CIMV2");
      10:              getScope.Options.EnablePrivileges = true;//set requeired
      11:   
      12:              try
      13:              {
      14:                  getEventQuery = new WqlEventQuery();
      15:                  getEventQuery.EventClassName = "__InstanceOperationEvent";
      16:                  getEventQuery.WithinInterval = new TimeSpan(0, 0, 0, 1);
      17:                  getEventQuery.Condition = @"TargetInstance ISA 'Win32_DiskDrive' ";
                           //[Disk must have DiskDrive fuck ]
     
      20:                  //Event Watcher [Test Event and semd informatio to this message and create new informtion .]
      21:                  getEventWatcher = new ManagementEventWatcher(getEventQuery);
      22:                  getEventWatcher.EventArrived += new EventArrivedEventHandler(getEventWatcher_EventArrived);
      23:                  getEventWatcher.Start();//Start Watch Event
     
      25:              }
      26:              catch (Exception se)
      27:              { }
      28:              finally
      29:              {
      30:                  // getEventWatcher.Stop();
      31:              }
      32:          }

    当发生USB插拔并成功监听到事件时处理方法:

       1:   void getEventWatcher_EventArrived(object sender, EventArrivedEventArgs e)
       2:          {
       3:              ManagementBaseObject getBaseObject = (ManagementBaseObject)e.NewEvent;
       4:              if ((getBaseObject.ClassPath.ClassName == "__InstanceCreationEvent"))
       5:              {
       6:                  //Usb Inserted
       7:                  MessageBox.Show("USB Disk Inserted!");
       8:              }
       9:              else
      10:              {
      11:                  //Usb Removed
      12:                  MessageBox.Show("USB Device Removed!");
      13:              }
      14:          }

    如上在定义时设置一个Condition[条件]:存在Disk Driver 磁盘驱动.如果类似某些UKey不存在磁盘驱动同时也无存储介质 经过测试你会发现.加密的UKey插入 如上的WMI监听事件并不能扑捉到USB插拔. 但是针对这种方式我们还有一种更为彻底的方式就是USB插拔唯一可以确定在PC识别必然变化的因素是系统设备列表发生更新.

    WMI处理监听:

       1:         /// <summary>
       2:          /// 监听USB Device设备插拔事件 完整操作.
       3:          /// WMI Handle Event Change Device List chenkai
       4:          /// </summary>
       5:          public void RegisterDeviceWMIEventStatu()
       6:          {
       7:              try 
       8:              {
       9:                  //Device List HAve Changed  And Send Message 
      10:                  WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent");
      11:                  ManagementEventWatcher watcher = new ManagementEventWatcher(query);
      12:                  watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
      13:                  watcher.Start();  // Start listening for events
      14:              }
      15:              catch (Exception se)
      16:              { }
      17:          }

    WMI监听处理函数:

       1:   void watcher_EventArrived(object sender, EventArrivedEventArgs e)
       2:          {
       3:              string geteventtype = e.NewEvent.GetPropertyValue("EventType").ToString();
       4:              ManagementBaseObject getEventObject = (ManagementBaseObject)e.NewEvent;
       5:   
       6:              if (getEventObject != null)
       7:              {
       8:                  //close Operator 
       9:                  this.CloseDeviceEqument();
      10:              }
      11:          }

    其实这依然还是一种折中办法.因为导致PC端设备列表发生变化的因素有很多.如何判定是USB口发生设备变化.WMI依然没有让我们失望:

       1:    //WMI Control The USB Device Change Statu And Send Message to When IT‘s Changed/
       2:          public void ControlUSBDeviceSTatu()
       3:          {
       4:              try
       5:              {
       6:                  WqlEventQuery query = new WqlEventQuery("select * from Win32_VolumeChangeEvent");
       7:                  ManagementEventWatcher getwatcher = new ManagementEventWatcher(query);
       8:                  getwatcher.EventArrived += new EventArrivedEventHandler(getwatcher_EventArrived);
       9:                  getwatcher.Start();
      10:              }
      11:              catch (Exception se)
      12:              { }
      13:          }

    WMI在USB事情处理函数:

       2:          void getwatcher_EventArrived(object sender, EventArrivedEventArgs e)
       3:          {
       4:              MessageBox.Show(e.NewEvent.GetText(TextFormat.Mof).ToString());
       5:          }

    这样来一来就可以清晰判定USB在插拔时所发生在系统PC端的变化通知给应用程序来进行处理.如何获得当前PC端 USB Driver列表.经过几番测试找到一种很好的方式获取全部的USB Driver信息:

       1:   //Get ALL USB DRiver And Driver Property Fuck this shit。chenkai
       2:          public static string[] AllInformation()
       3:          {
       4:              StringCollection propNames = new StringCollection();
       5:              ManagementClass driveClass = new ManagementClass("Win32_USBController");
       6:              PropertyDataCollection props = driveClass.Properties;
       7:              foreach (PropertyData driveProperty in props)
       8:                  propNames.Add(driveProperty.Name);
      12:              int idx = 0;
      13:              ManagementObjectCollection drives = driveClass.GetInstances();
      14:              string _s = string.Empty;
      15:              List<string> harddisk = new List<string>();
      16:   
      17:              foreach (ManagementObject drv in drives)
      18:              {
      19:                  idx++;
      20:                  _s = string.Format(" USB Driver({0}) Properties ", idx);
      21:                  harddisk.Add(_s);
      22:                  foreach (string strProp in propNames)
      23:                  {
      24:                      _s = string.Format("Property: {0}, Value: {1}", strProp, drv[strProp]);
      25:                      harddisk.Add(_s);
      26:                  }
      27:              }
      28:              string[] _ss = harddisk.ToArray();
      29:              return _ss;
      30:          }

    WMI的更多体现是对Windows 交互中进一步封装和管理.

    Can考资料:

    Device ManageMent Events

    System.Form.control.WinProc[]Method

    System.Form.Control.Message[]Method

  • 相关阅读:
    Android测试提升效率批处理脚本
    iOS系统设备网络抓包工具介绍:越狱和不越狱的办法
    用于管理Linux系统中的各种服务的命令service命令
    linux sort 命令详解
    在loadrunner操作中,所碰见问题及解决方法
    Unable to connect to the remote server 问题(已经解决)
    均值、中位数、众数
    修改Android 界面颜色
    设置Android程序图标和程序标题
    Android中的EditText默认时不弹出软键盘的方法
  • 原文地址:https://www.cnblogs.com/chenkai/p/2009192.html
Copyright © 2011-2022 走看看