开发者社区> 科技小能手> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

监控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' ";            
  18.               //[Disk must have DiskDrive fuck ]     
  19.               //Event Watcher [Test Event and semd informatio to this message and create new informtion .]    
  20.               getEventWatcher = new ManagementEventWatcher(getEventQuery);    
  21.               getEventWatcher.EventArrived += new EventArrivedEventHandler(getEventWatcher_EventArrived);    
  22.               getEventWatcher.Start();//Start Watch Event     
  23.           }    
  24.           catch (Exception se)    
  25.           { }    
  26.           finally    
  27.           {    
  28.               // getEventWatcher.Stop();    
  29.           }    
  30.       } 

当发生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.     { }    

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事情处理函数:


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

这样来一来就可以清晰判定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);    
  9.            int idx = 0;    
  10.            ManagementObjectCollection drives = driveClass.GetInstances();    
  11.            string _s = string.Empty;    
  12.            List<string> harddisk = new List<string>();    
  13.     
  14.            foreach (ManagementObject drv in drives)    
  15.            {    
  16.                idx++;    
  17.                _s = string.Format(" USB Driver({0}) Properties ", idx);    
  18.                harddisk.Add(_s);    
  19.                foreach (string strProp in propNames)    
  20.                {    
  21.                    _s = string.Format("Property: {0}, Value: {1}", strProp, drv[strProp]);    
  22.                    harddisk.Add(_s);    
  23.                }    
  24.            }    
  25.            string[] _ss = harddisk.ToArray();    
  26.            return _ss;    
  27.        } 

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

Can考资料:

Device ManageMent Events

System.Form.control.WinProc[]Method

System.Form.Control.Message[]Method



本文转自chenkaiunion 51CTO博客,原文链接:http://blog.51cto.com/chenkai/763645

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
可编程USB 转串口适配器开发板的S2S功能
USB2S 支持基于 STC 单片机的二次开发,若有需要,可参照原理图和单片机型号手册自行开发具有特殊功能的固件程序。
0 0
可编程 USB 转串口适配器开发板 S2S 功能介绍
USB2S 支持基于 STC 单片机的二次开发,若有需要,可参照原理图和单片机型号手册自行开发具有特殊功能的固件程序。
0 0
USB及手机平板设备插拔响应解决方案
USB及手机平板设备插拔响应解决方案 (一)、基本原理:WM_DEVICECHANGE 消息响应 一般WM_DEVICECHANGE只发给顶层窗口。你可以自己创建一个隐藏的顶层窗口来接收这个消息。
639 0
D3D11中的设备介绍
 Device Context可以被用于任何线程中,但一次只能在一个线程中使用。 所有的ID3D11Device接口都是free-threaded(线程无关的)的,也就是说可以在多个线程中同时调用其接口函数。
737 0
32、即插即用
即插即用  1、即插即用(IRP_MJ_PNP)功能能够通过操作系统协调自动分配设备上的资源,如中断号,I/O地址,DMA资源,设备物理内存等。  WDM框架程序是分层驱动,WDM处于分层的高端,而总线驱动程序处于分层的低端。
904 0
USB设备的Bulk模式驱动程序设计
USB设备的Bulk模式驱动程序设计     引言   通用串行总线(USB)是一种串行接口,具有自动配置能力和良好的兼容性,从而简化了计算机与外设的连接,被计算机外设硬件制造商广泛采纳。
804 0
文章
问答
文章排行榜
最热
最新
相关电子书
更多
《虚拟配网调度员》
立即下载
《如何驱动一个传感器》
立即下载
《配网虚拟调度员的核心技术》
立即下载