监控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

相关文章
|
3月前
|
JavaScript
亚丁号云控之云控设备
亚丁号云控之云控设备
13 0
|
9月前
|
Linux 测试技术 Windows
可编程 USB 转串口适配器开发板应用于电子设备开发测试
可编程 USB 转串口适配器开发板应用于电子设备开发测试
可编程 USB 转串口适配器开发板应用于电子设备开发测试
|
10月前
|
算法 编译器 C语言
达夫设备简单介绍
达夫设备简单介绍
107 1
|
11月前
|
Linux API 芯片
USB2S可编程USB转串口适配器开发原理的通讯协议
USB2S可编程USB转串口适配器基于FTDI FT2232H芯片设计,对多种通讯协议的支持,包括UART,I2C,SMBus,1-Wire,SPI,CAN和PWM等。
USB2S可编程USB转串口适配器开发原理的通讯协议
|
11月前
|
Web App开发 芯片
USB2S可编程USB转串口适配器的开发原理
USB2S可编程USB转串口适配器的开发原理主要涉及USB接口协议、USB控制器芯片以及串口通信协议等方面。
USB2S可编程USB转串口适配器的开发原理
|
11月前
|
XML 传感器 数据格式
可编程 USB 转串口适配器开发板主要开发测试作用
上面写的东西不少,其实这个模块用法特别简单,拿到套件和专门的工具软件后一分钟都不需要就完全明白了,如果想编写自己的xml驱动,随便打开一个照葫芦画瓢,然后另存就行。
RK3399平台开发系列讲解(高速设备驱动篇)6.61、USB如何模拟HID设备
RK3399平台开发系列讲解(高速设备驱动篇)6.61、USB如何模拟HID设备
119 0
RK3399平台开发系列讲解(高速设备驱动篇)6.61、USB如何模拟HID设备
|
Linux API 数据处理
USB协议架构分析
USB协议架构分析
|
C#
C# 获得设备usb信息
原文:C# 获得设备usb信息 本文告诉大家如何获得设备的usb来进行判断是否有哪些usb和找不到usb可能是什么。 需要在项目右击引用,点击程序集,搜索 System.
1578 0

热门文章

最新文章