Jump to content

Detecting USB device connects & disconnects and log them to a file


Rumbles
 Share

Recommended Posts

Hello,

I have been looking at a way to do this for a while, and I've been looking at a lot of >examples which do >similar to what I was after, and while I understand some of what they are doing, I think my lack of programming/scripting experience lets me down in the end. I am unsure as to why some scipts I have seen call GUI objects, when to my mind this should be a service that the user shouldn't see (unless I choose to alert them), I am also concerned that a lot of the examples I have seen are from 5-7 years ago, since the code could have changed quite a lot in that time I expect that I would struggle to simply copy & paste other code, also I would rather not just copy other peoples work and try to glue it together, if I can understand the process I would be much happier!

The requirements I have for this script are:

  • It needs to detect a USB connect/disconnect event (all USB devices, including Keyboards and Hubs, not just USB Removable media)
  • It needs to log this information to a file, with a timestamp
  • Ideally it should be able to print some information which will help identify the device (e.g. dbcc info, or a serial number & friendly name)

 

So far I have got the following code together, from some examples I have seen:

#include <file.au3>

Local $sLogPath = "C:\Windows\Logs\usbconnections.log"

_FileWriteLog( $sLogPath, "Test" )

Dim $DBT_DEVICEARRIVAL = "0x00008000"
Dim $DBT_DEVICECOMPLETEREMOVAL = "0x00008004"
Dim $USB_ATTENTION = "0x00000007"
Dim $WM_DEVICECHANGE = 0x0219

I know I haven't got much down so far, but I have got the printing to a file with a timestamp part nailed!

The next bit I am less than certain with though, how do I detect a USB connect/disconnect event, I know the variables I have declared should be vital in seeing this process happen, but I am currently unsure about how next to proceed.

I want to be able to understand the script as well, I have looked at some other similar scripts (one in AHK which did a lot of this, but logged to a GUI) which I really couldn't get my head around it and I felt I would be better off starting from scratch if I wanted to udnerstand how this worked.

I'm quite happy read through docs, but at the moment I am at a loss as to where to go to next. Any tips on functions which I can use for this job, or other scripts which have explainations as to how they work would be appreciated.

Just to clarify why I am trying to do this, the end goal here is to have the log file collected by nxlog, nxlog will then encrypt the log file and ship that on to a centralised logging system (logstash), which will be able to parse the log and index it, as well as send an alert out if we need it to do so.

Link to comment
Share on other sites

Checkout RegisterDeviceNotifications in my sig.

 

Thanks for the response, it looks like a great little script. But as far as I can tell this script detects changes to USB Removable storage devices (It doesn't detect my keyboard/hub being dis/connected), do you think the same method you use in this script could be applied to detect all USB device connections & disconnections? Or is that outside of the scope of the methods used here?

Thanks for the help, I appreciate it!

Link to comment
Share on other sites

Windows has this feature built in, perhaps you could just use AutoIt to automate the activation of the USB trace event logging in Windows, then forward the logs.

http://msdn.microsoft.com/en-us/library/windows/hardware/jj151573(v=vs.85).aspx

If @error Then
    MsgBox(262192, "", @ComputerName & " slaps " & @UserName & " around a bit with a large trout!")
EndIf

"Yeah yeah yeah patience, how long will that take?"  -Ed Gruberman

REAL search results  |  SciTE4AutoIt3 Editor Full Version

Link to comment
Share on other sites

alienclone thanks for the info, I will look in to that further. Do you know if it's possible to use this functionality with AutoIT at all? andrewz thanks for the link to the script, but this is a script which looks for USB removable storage, not something which looks for all USB connect & disconnect events as far as I can see
Link to comment
Share on other sites

http://azjio.narod.ru/autoit3_docs/userfunctions/WM_DEVICECHANGE.htm

$DBT_DEVNODES_CHANGED = 0x0007

        $DBT_DEVTYP_OEM = 0x00000000 ; oem-defined device type
        $DBT_DEVTYP_DEVNODE = 0x00000001 ; devnode number
        $DBT_DEVTYP_VOLUME = 0x00000002; logical partition
        $DBT_DEVTYP_PORT = 0x00000003 ; serial, parallel
        $DBT_DEVTYP_NET = 0x00000004 ; network resource

Make experiments

Link to comment
Share on other sites

http://azjio.narod.ru/autoit3_docs/userfunctions/WM_DEVICECHANGE.htm

$DBT_DEVNODES_CHANGED = 0x0007

        $DBT_DEVTYP_OEM = 0x00000000 ; oem-defined device type
        $DBT_DEVTYP_DEVNODE = 0x00000001 ; devnode number
        $DBT_DEVTYP_VOLUME = 0x00000002; logical partition
        $DBT_DEVTYP_PORT = 0x00000003 ; serial, parallel
        $DBT_DEVTYP_NET = 0x00000004 ; network resource

Make experiments

 

Thanks, I've copied the example script from that site, and I can get this to work:

#include <GUIConstantsEx.au3>

Global Const $WM_DEVICECHANGE = 0x0219
Global Const $DBT_DEVICEARRIVAL = 0x8000 ; Found New Hardware
Global Const $DBT_DEVICEREMOVECOMPLETE = 0x8004 ; The device is disconnected

Global Const $DBT_DEVNODES_CHANGED = 0x0007
Global Const $DBT_DEVTYP_OEM = 0x00000000 ; oem-defined device type
Global Const $DBT_DEVTYP_DEVNODE = 0x00000001 ; devnode number
Global Const $DBT_DEVTYP_VOLUME = 0x00000002; logical partition
Global Const $DBT_DEVTYP_PORT = 0x00000003 ; serial, parallel
Global Const $DBT_DEVTYP_NET = 0x00000004 ; network resource

Global $k = 0

$Gui = GUICreate("WM_DEVICECHANGE", 370, 140)
GUICtrlCreateLabel('WM_DEVICECHANGE function is performed when connecting or disconnecting devices to the system. Try inserting the stick', 5, 5, 360, 70)

GUISetState()
GUIRegisterMsg($WM_DEVICECHANGE, "WM_DEVICECHANGE")

Do
Until GUIGetMsg() = -3

Func WM_DEVICECHANGE($hWnd, $Msg, $wParam, $lParam)
    $k += 1
    WinSetTitle($Gui, '', 'Connection ' & $k)

    If ($wParam = $DBT_DEVICEARRIVAL) Or ($wParam = $DBT_DEVICEREMOVECOMPLETE) Then
        Local $DEV_BROADCAST_VOLUME = DllStructCreate("int dbcvsize;int dbcvdevicetype;int dbcvreserved;int dbcvunitmask;" & _
                "ushort dbcvflags", $lParam)
        Local $iDriveType = DllStructGetData($DEV_BROADCAST_VOLUME, "dbcvdevicetype")
    Else
        Return $GUI_RUNDEFMSG
    EndIf

    ; If the device is not a logical drive, the output of the function
    If $iDriveType <> $DBT_DEVTYP_VOLUME Then Return $GUI_RUNDEFMSG

    Local $iMask = DllStructGetData($DEV_BROADCAST_VOLUME, "dbcvunitmask")
    $iMask = Log($iMask) / Log(2)

    Local $iDrive = Chr(65 + $iMask) & ":"

    Switch $wParam
        Case $DBT_DEVICEARRIVAL ; detection device
            TrayTip("WM_DEVICECHANGE", "device connected", 5, 1)

        Case $DBT_DEVICEREMOVECOMPLETE ; Disconnecting
            TrayTip("WM_DEVICECHANGE", "device disconnected", 5, 2)
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc

This updates the tray message when a device is connected & disconnected.

But when I try using the extra functions you have mentioned I don't get anywhere... :

#include <GUIConstantsEx.au3>

Global Const $WM_DEVICECHANGE = 0x0219
Global Const $DBT_DEVICEARRIVAL = 0x8000 ; Found New Hardware
Global Const $DBT_DEVICEREMOVECOMPLETE = 0x8004 ; The device is disconnected

Global Const $DBT_DEVNODES_CHANGED = 0x0007
Global Const $DBT_DEVTYP_OEM = 0x00000000 ; oem-defined device type
Global Const $DBT_DEVTYP_DEVNODE = 0x00000001 ; devnode number
Global Const $DBT_DEVTYP_VOLUME = 0x00000002; logical partition
Global Const $DBT_DEVTYP_PORT = 0x00000003 ; serial, parallel
Global Const $DBT_DEVTYP_NET = 0x00000004 ; network resource

Global $k = 0

$Gui = GUICreate("WM_DEVICECHANGE", 370, 140)
GUICtrlCreateLabel('WM_DEVICECHANGE function is performed when connecting or disconnecting devices to the system. Try inserting the stick', 5, 5, 360, 70)

GUISetState()
GUIRegisterMsg($WM_DEVICECHANGE, "WM_DEVICECHANGE")

Do
Until GUIGetMsg() = -3

Func WM_DEVICECHANGE($hWnd, $Msg, $wParam, $lParam)
    $k += 1
    WinSetTitle($Gui, '', 'Connection ' & $k)

    If ($lParam = $DBT_DEVNODES_CHANGED) Then
        Local $DEV_BROADCAST_VOLUME = DllStructCreate("int dbcvsize;int dbcvdevicetype;int dbcvreserved;int dbcvunitmask;" & _
                "ushort dbcvflags", $lParam)
        Local $iDriveType = DllStructGetData($DEV_BROADCAST_VOLUME, "dbcvdevicetype")
    Else
        Return $GUI_RUNDEFMSG
    EndIf

    ; If the device is not a logical drive, the output of the function
    If $iDriveType <> $DBT_DEVTYP_VOLUME Then Return $GUI_RUNDEFMSG

    Local $iMask = DllStructGetData($DEV_BROADCAST_VOLUME, "dbcvunitmask")
    $iMask = Log($iMask) / Log(2)

    Local $iDrive = Chr(65 + $iMask) & ":"

    Switch $lParam
        Case $DBT_DEVNODES_CHANGED ; detection device
            TrayTip("WM_DEVICECHANGE", "device connected", 5, 1)

        ;Case $DBT_DEVICEREMOVECOMPLETE ; Disconnecting
        ;    TrayTip("WM_DEVICECHANGE", "device disconnected", 5, 2)
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc

For example here I have replaced some wParam objects with lParam objects and I am trying to trigger off $DBT_DEVNODES_CHANGED but nothing hapens when I connect/disconnect the device.... I'm not really sure what I am doing wrong here....

I was also looking at how you might run something like this as a service, and I found this >page which might be a good way to get the functions to run in the background. Would you say this is a good way to go? It seems pretty complicated, and since I'm confused with what I have so far, I am not sure how well I will get on with this other script :)

Thanks for the help so far!

Link to comment
Share on other sites

  • 9 years later...

This reply may be ten years late but I hope it will be helpful to future learners.

 

How to use :

1.Run this code 

2.Plugin or Unplug usb device

3.It is will pop-up message

 


 

#include <WinAPI.au3>
#include <Array.au3>
#include <WinAPIDiag.au3>

HotKeySet("{ESC}", "_exit")


Global Const $WM_DEVICECHANGE = 537


Global Const $DBT_CONFIGCHANGECANCELED = 0x0019
Global Const $DBT_CONFIGCHANGED = 0x0018
Global Const $DBT_CUSTOMEVENT = 0x8006
Global Const $DBT_DEVICEARRIVAL = 0x8000
Global Const $DBT_DEVICEQUERYREMOVE = 0x8001
Global Const $DBT_DEVICEQUERYREMOVEFAILED = 0x8002
Global Const $DBT_DEVICEREMOVEPENDING = 0x8003
Global Const $DBT_DEVICEREMOVECOMPLETE = 0x8004
Global Const $DBT_DEVICETYPESPECIFIC = 0x8005
Global Const $DBT_DEVNODES_CHANGED = 0x0007
Global Const $DBT_QUERYCHANGECONFIG = 0x0017
Global Const $DBT_USERDEFINED = 0xFFFF
Global Const $DBT_DEVTYP_OEM = 0x00000000
Global Const $DBT_DEVTYP_DEVNODE = 0x00000001
Global Const $DBT_DEVTYP_VOLUME = 0x00000002
Global Const $DBT_DEVTYP_PORT = 0x00000003
Global Const $DBT_DEVTYP_NET = 0x00000004
Global Const $DBT_DEVTYP_DEVICEINTERFACE = 0x00000005
Global Const $DBT_DEVTYP_HANDLE = 0x00000006
Global Const $DBT_DEVTYP_DEVINST = 0x00000007
Global Const $DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000
Global Const $DEVICE_NOTIFY_SERVICE_HANDLE = 0x00000001
Global Const $DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 0x00000004
Global $RegisterDeviceInterface_Handle[0][2]
Global $GUI_hwnd = GUICreate("Detect device change")
Global Const $tagPack = "align 1;"
Global Const $tagDEV_BROADCAST_HDR = _
                "dword size;" & _
                "dword devicetype;" & _
                "dword reserved;"
Global $DEV_BROADCAST_HDR = DllStructCreate($tagDEV_BROADCAST_HDR)
Global Const $tagDEV_BROADCAST_USERDEFINED = _
                $tagDEV_BROADCAST_HDR & _
                "char szName[1];"
Global $DEV_BROADCAST_USERDEFINED = DllStructCreate($tagDEV_BROADCAST_USERDEFINED)
Global Const $tagDEV_BROADCAST_HANDLE = _
                $tagDEV_BROADCAST_HDR & _
                "handle handle;" & _
                "ptr hdevnotify;" & _
                $tagGUID & ";" & _
                "long nameoffset;" & _
                "byte data[1];"
Global $DEV_BROADCAST_HANDLE = DllStructCreate($tagDEV_BROADCAST_HANDLE)
Global Const $tagDEV_BROADCAST_DEVICEINTERFACE = _
                $tagDEV_BROADCAST_HDR & _
                $tagGUID & ";" & _
                "WCHAR name[256];"
Global $DEV_BROADCAST_DEVICEINTERFACE = DllStructCreate($tagDEV_BROADCAST_DEVICEINTERFACE)
Global Const $tagDEV_BROADCAST_OEM = _
                $tagDEV_BROADCAST_HDR & _
                "dword identifier;" & _
                "dword suppfunc"
Global $DEV_BROADCAST_OEM = DllStructCreate($tagDEV_BROADCAST_OEM)
Global Const $tagDEV_BROADCAST_PORT = _
                $tagDEV_BROADCAST_HDR & _
                "WCHAR name[256];"
Global $DEV_BROADCAST_PORT = DllStructCreate($tagDEV_BROADCAST_PORT)
Global Const $tagDEV_BROADCAST_VOLUME = _
                $tagDEV_BROADCAST_HDR & _
                "dword unitmask;" & _
                "word flags;"
Global $DEV_BROADCAST_VOLUME = DllStructCreate($tagDEV_BROADCAST_VOLUME)
Local $Flags = $DEVICE_NOTIFY_WINDOW_HANDLE
DoRegisterDeviceInterface($GUI_hwnd, "{A5DCBF10-6530-11D2-901F-00C04FB951ED}", $Flags) 
DoRegisterDeviceInterface($GUI_hwnd, "{f18a0e88-c30c-11d0-8815-00a0c906bed8}", $Flags)
;_ArrayDisplay($RegisterDeviceInterface_Handle)


;UnregisterDeviceNotification($RegisterDeviceInterface_Handle[1][1])
;UnregisterDeviceNotification($RegisterDeviceInterface_Handle[0][1])
;UnregisterDeviceNotification("{A5DCBF10-6530-11D2-901F-00C04FB951ED}")
;_ArrayDisplay($RegisterDeviceInterface_Handle)

GUIRegisterMsg($WM_DEVICECHANGE, 'Detect_device')

Do
Until GUIGetMsg() = -3

Func Detect_device($hWnd, $Msg, $wParam, $lParam)

    Local $DEV_BROADCAST_GetDeviceType = DllStructCreate($tagDEV_BROADCAST_HDR, $lParam)
    Local $DeviceType = DllStructGetData($DEV_BROADCAST_GetDeviceType, "devicetype")

    Switch $wParam
        Case $DBT_DEVICEARRIVAL

            if $DeviceType = 5 Then
            $dddd = DllStructCreate($tagDEV_BROADCAST_DEVICEINTERFACE,$lParam)
            msgbox(0,"",'Detect device - ' & DEVTYP($DeviceType)&$dddd.name)
            ConsoleWrite('Detect device - ' & DEVTYP($DeviceType)&$dddd.name&@CRLF)
            EndIf

        Case $DBT_DEVICEQUERYREMOVE

        Case $DBT_DEVICEQUERYREMOVEFAILED

        Case $DBT_DEVICEREMOVEPENDING

        Case $DBT_DEVICEREMOVECOMPLETE
            if $DeviceType = 5 Then
            $dddd = DllStructCreate($tagDEV_BROADCAST_DEVICEINTERFACE,$lParam)
            msgbox(0,"",'Detect device remove - ' & DEVTYP($DeviceType)&$dddd.name)
            ConsoleWrite('Detect device remove - ' & DEVTYP($DeviceType)&$dddd.name&@CRLF)
            EndIf

        Case $DBT_DEVICETYPESPECIFIC

        Case $DBT_DEVNODES_CHANGED

        Case $DBT_CONFIGCHANGECANCELED

        Case $DBT_CONFIGCHANGED

        Case $DBT_CUSTOMEVENT

        Case $DBT_QUERYCHANGECONFIG

        Case $DBT_USERDEFINED

    EndSwitch
    Return 'GUI_RUNDEFMSG'
EndFunc


Func DEVTYP($lParam)
    Switch $lParam
        Case $DBT_DEVTYP_OEM
            Return "Type ( OEM ) "

        Case $DBT_DEVTYP_DEVNODE
            Return "Type ( DEVNODE ) "

        Case $DBT_DEVTYP_VOLUME
            Return "Type ( VOLUME ) "

        Case $DBT_DEVTYP_PORT
            Return "Type ( PORT ) "

        Case $DBT_DEVTYP_NET
            Return "Type ( NET ) "

        Case $DBT_DEVTYP_HANDLE
            Return "Type ( HANDLE ) "

        Case $DBT_DEVTYP_DEVICEINTERFACE
            Return "Type ( DEVICEINTERFACE ) "

        Case $DBT_DEVTYP_DEVINST
            Return "Type ( DEVINST ) "
    EndSwitch
EndFunc

Func DoRegisterDeviceInterface($hGUI, $Device_Class_GUID, $flags )
    Local $ptrDEV_BROADCAST_DEVICEINTERFACE  = DllStructGetPtr($DEV_BROADCAST_DEVICEINTERFACE)
    Local $Size = DllStructGetSize($DEV_BROADCAST_DEVICEINTERFACE)

    DllStructSetData($DEV_BROADCAST_DEVICEINTERFACE, "size", $Size)
    DllStructSetData($DEV_BROADCAST_DEVICEINTERFACE, "devicetype", $DBT_DEVTYP_DEVICEINTERFACE)
    Local $CameraGUID =_WinAPI_GUIDFromString($Device_Class_GUID)
    DllStructSetData($DEV_BROADCAST_DEVICEINTERFACE, "Data1", $CameraGUID.Data1)
    DllStructSetData($DEV_BROADCAST_DEVICEINTERFACE, "Data2", $CameraGUID.Data2)
    DllStructSetData($DEV_BROADCAST_DEVICEINTERFACE, "Data3", $CameraGUID.Data3)
    DllStructSetData($DEV_BROADCAST_DEVICEINTERFACE, "Data4", $CameraGUID.Data4)

    Local $RDNhandle = DllCall("User32.dll", "handle", "RegisterDeviceNotification", "hwnd", $hGUI, "ptr", $ptrDEV_BROADCAST_DEVICEINTERFACE, "long", $flags)
    _ArrayAdd($RegisterDeviceInterface_Handle, $RDNhandle[0]&"|"&StringUpper($Device_Class_GUID))

EndFunc

Func UnregisterDeviceNotification($GUID)
    Local $delete_number = _ArraySearch($RegisterDeviceInterface_Handle,$GUID, 0, 0, 0, 0, 1, 2)
    Local $check = DllCall("User32.dll", "UINT", "UnregisterDeviceNotification", "handle", $RegisterDeviceInterface_Handle[$delete_number][0])
    _ArrayDelete($RegisterDeviceInterface_Handle,$delete_number)
EndFunc


Func _exit()
    Exit
EndFunc

 

Edited by konya
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...