usbsacn实现了监控设备是否有非法接入,如果有usb设备非法接入,则会报警,向目标账户发送邮件,并且在log中记录日志。
利用usb设备的一些固定信息,比如PID,VID检测指定USB设备或者所有USB设备的插入与拔出状态。同时加入消息提醒和日志功能,做了一个简易的Windows版的usbscan。
代码实现:
VC提供了WM_DEVICECHANGE消息,但还需要RegisterDeviceNotification()注册要检测的“Device Interface Class GUID”才能获取到有用信息。
设备相关的GUID有 Device Class GUID、Device Interface Class GUID、 Interface GUID。
·Device Class GUID 是INF文件中Verison Section中指名的设备类GUID,它标志着此设备图标,此设备出现在哪一栏,电压电流等各种信息。
·Interface GUID是指驱动程序中的GUID,用于使用API打开此设备进行一系列读写操作。
·Device Interface Class GUID是Microsoft定义用来调用RegisterDeviceNotification()时所使用的一类GUID。
本次要使用的是GUID_DEVINTERFACE_USB_DEVICE,GUID(A5DCBF10-6530-11D2-901F-00C04FB951ED)写成代码为static const GUID x_guid = { 0xA5DCBF10, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED }。
窗口初始化函数为:
外联设备检测和目标信息读取:
消息通知函数:
效果展示:
在插入u盘设备之后,我的邮箱会受到一封提示信息,提示查看日志信息。
# -*- coding: utf-8 -*- """ Created on Mon Feb 14 14:55:58 2022 @author: wangzhaolin """ import sys from PyQt5.QtWidgets import QMainWindow, QApplication from ctypes.wintypes import MSG import time import ctypes from ctypes.wintypes import MSG import ctypes.wintypes as wintypes import smtplib from email.mime.text import MIMEText def send_mail(Alert): msg = MIMEText(Alert,'plain','utf-8') sender = '' password = '' receiver = '' mailto_list=[''] smtp_server = 'smtp.qq.com' msg['From'] = '' msg['To'] = msg['Subject'] = 'security information' server = smtplib.SMTP(smtp_server,25) server.login(sender, password) server.set_debuglevel(1) server.sendmail(sender, receiver, msg.as_string()) server.quit() NULL = 0 INVALID_HANDLE_VALUE = -1 DBT_DEVTYP_DEVICEINTERFACE = 5 DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000 DBT_DEVICEREMOVECOMPLETE = 0x8004 DBT_DEVICEARRIVAL = 0x8000 WM_DEVICECHANGE = 0x0219 WM_KEYDOWN = 0x0100 user32 = ctypes.windll.user32 RegisterDeviceNotification = user32.RegisterDeviceNotificationW UnregisterDeviceNotification = user32.UnregisterDeviceNotification class GUID(ctypes.Structure): _pack_ = 1 _fields_ = [("Data1", ctypes.c_ulong), ("Data2", ctypes.c_ushort), ("Data3", ctypes.c_ushort), ("Data4", ctypes.c_ubyte * 8)] class DEV_BROADCAST_DEVICEINTERFACE(ctypes.Structure): _pack_ = 1 _fields_ = [("dbcc_size", wintypes.DWORD), ("dbcc_devicetype", wintypes.DWORD), ("dbcc_reserved", wintypes.DWORD), ("dbcc_classguid", GUID), ("dbcc_name", ctypes.c_wchar * 260)] class DEV_BROADCAST_HDR(ctypes.Structure): _fields_ = [("dbch_size", wintypes.DWORD), ("dbch_devicetype", wintypes.DWORD), ("dbch_reserved", wintypes.DWORD)] GUID_DEVCLASS_PORTS = GUID(0x4D36E978, 0xE325, 0x11CE, (ctypes.c_ubyte * 8)(0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18)) GUID_DEVINTERFACE_USB_DEVICE = GUID(0xA5DCBF10, 0x6530, 0x11D2, (ctypes.c_ubyte * 8)(0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED)) class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.setupNotification()#注册usb插拔通知 def setupNotification(self): dbh = DEV_BROADCAST_DEVICEINTERFACE() dbh.dbcc_size = ctypes.sizeof(DEV_BROADCAST_DEVICEINTERFACE) dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE dbh.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE # GUID_DEVCLASS_PORTS self.hNofity = RegisterDeviceNotification(int(self.winId()), ctypes.byref(dbh), DEVICE_NOTIFY_WINDOW_HANDLE) if self.hNofity == NULL: print(ctypes.FormatError(), int(self.winId())) print("RegisterDeviceNotification failed") else: print("RegisterDeviceNotification success") def nativeEvent(self, eventType, msg): message = MSG.from_address(int(msg)) #message = ctypes.wintypes.MSG.from_address(msg.__int__()) if message.message == WM_DEVICECHANGE: # 设备消息来了 dev_name = '' #设备的名称 if DBT_DEVICEARRIVAL == message.wParam or DBT_DEVICEREMOVECOMPLETE == message.wParam: dbh = DEV_BROADCAST_HDR.from_address(message.lParam) if dbh.dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE: dbd = DEV_BROADCAST_DEVICEINTERFACE.from_address(message.lParam) dev_name = dbd.dbcc_name if message.wParam == DBT_DEVICEARRIVAL: # 有设备接入 print("device in:",dev_name) send_mail("设备插入,请查看日志信息") fo = open("log.txt","a") localtime = time.asctime( time.localtime(time.time()) ) fo.write(localtime) fo.write("device in :") fo.write(dev_name) fo.write('\n') fo.close() elif message.wParam == DBT_DEVICEREMOVECOMPLETE: # 有设备拔出 send_mail("设备拔出,请查看日志信息") fo = open("log.txt","a") localtime = time.asctime( time.localtime(time.time()) ) fo.write(localtime) fo.write("device out :") fo.write(dev_name) fo.write('\n') fo.close() return True, id(message) if message.message == WM_KEYDOWN:#按键消息来了 print('有按键被按下了,key:',hex(message.wParam),message.wParam) return True, id(message) return False, id(message) app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())