173 lines
7.8 KiB
Ruby
173 lines
7.8 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Post
|
|
include Msf::Post::Android::Priv
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Multiplatform Installed Software Version Enumerator',
|
|
'Description' => %q{
|
|
This module, when run against a compromised machine, will gather details on all installed software,
|
|
including their versions and if available, when they were installed, and will save it into a loot file for later use.
|
|
Users can then use this loot file to determine what additional vulnerabilites may affect the target machine.
|
|
|
|
Note that for Linux systems, software enumeration is done via package managers. As a result the results may
|
|
not reflect all of the available software on the system simply because users may have installed additional
|
|
software from alternative sources such as source code that these package managers are not aware of.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' => [ 'gwillcox-r7' ],
|
|
'Platform' => %w[win linux osx bsd solaris android],
|
|
'SessionTypes' => [ 'meterpreter', 'shell' ],
|
|
'Notes' => {
|
|
'Stability' => [CRASH_SAFE],
|
|
'SideEffects' => [IOC_IN_LOGS],
|
|
'Reliability' => []
|
|
}
|
|
)
|
|
)
|
|
end
|
|
|
|
def store_linux_loot(listing)
|
|
file = store_loot('host.linux.software.versions', 'text/plain', session, listing, 'installed_software.txt', 'Installed Software and Versions')
|
|
print_good("Stored information about the installed products to the loot file at #{file}")
|
|
end
|
|
|
|
def enumerate_android_packages
|
|
if command_exists?('pm') == false
|
|
print_error("The command 'pm' does not exist on the host")
|
|
return nil
|
|
end
|
|
listing = cmd_exec('pm list packages -f').to_s
|
|
if listing.empty?
|
|
print_error('No results were returned when trying to get software installed on the Linux host. An error likely occured.')
|
|
return nil
|
|
end
|
|
listing
|
|
end
|
|
|
|
# Run Method for when run command is issued
|
|
def run
|
|
case session.platform
|
|
when 'windows'
|
|
if command_exists?('wmic') == false
|
|
print_error("The 'wmic' command doesn't exist on this host!") # wmic is technically marked as depreciated so this command could very well be removed in future releases.
|
|
return
|
|
end
|
|
listing = cmd_exec('wmic product get Name, Description, Version, InstallDate', nil, 6000).to_s
|
|
unless listing.include?('Description')
|
|
print_error('Was unable to get a listing of installed products...')
|
|
return
|
|
end
|
|
file = store_loot('host.windows.software.versions', 'text/plain', session, listing, 'installed_software.txt', 'Installed Software and Versions')
|
|
print_good("Stored information about the installed products to the loot file at #{file}")
|
|
when 'linux'
|
|
# All of the following options were taken from https://distrowatch.com/dwres.php?resource=package-management
|
|
# and further verified against VMs that were set up in testing labs.
|
|
if command_exists?('apt') # Debian, Ubuntu, and Debian derived distros.
|
|
cmd = %w[apt list --installed]
|
|
elsif command_exists?('dpkg') # Alternative for Debian based systems
|
|
cmd = %w[dpkg -l]
|
|
elsif command_exists?('pacman') # Arch and Manjaro are two popular examples
|
|
cmd = %w[pacman -Q]
|
|
elsif command_exists?('zypper') # OpenSUSE is a popular example
|
|
cmd = %w[zypper search -is]
|
|
elsif command_exists?('rpm') # Fedora, Centos, RHEL
|
|
cmd = %w[rpm -qa]
|
|
elsif command_exists?('apk') # Apline
|
|
cmd = %w[apk info -v]
|
|
elsif command_exists?('qlist') # Gentoo
|
|
cmd = %w[qlist -Iv]
|
|
elsif command_exists?('pkg') # FreeBSD
|
|
cmd = %w[pkg info]
|
|
elsif command_exists?('equo') # Sabayon
|
|
cmd = %w[equo q list installed -v]
|
|
elsif command_exists?('nix-env')
|
|
cmd = %w[nix-env -q]
|
|
else
|
|
print_error("The target system either doesn't have a package manager system, or does not use a known package manager system!")
|
|
print_error('Unable to enumerate the software on the target system. Exiting...')
|
|
return nil
|
|
end
|
|
|
|
if command_exists?((cmd[0]).to_s) == false
|
|
print_error("The command #{cmd[0]} was not found on the target.")
|
|
return
|
|
else
|
|
listing = cmd_exec(cmd.join(' ')).to_s
|
|
if listing.empty?
|
|
print_error('No results were returned when trying to get software installed on the Linux host. An error likely occured.')
|
|
return
|
|
end
|
|
store_linux_loot(listing)
|
|
end
|
|
when 'bsd', 'solaris'
|
|
if command_exists?('pkg') == false
|
|
print_error("The command 'pkg' does not exist on the host")
|
|
return
|
|
end
|
|
listing = cmd_exec('pkg info').to_s
|
|
if listing.empty?
|
|
print_error('No results were returned when trying to get software installed on the BSD/Solaris host. An error likely occured.')
|
|
return
|
|
end
|
|
file = store_loot('host.bsd.solaris.software.versions', 'text/plain', session, listing, 'installed_software.txt', 'Installed Software and Versions')
|
|
print_good("Stored information about the installed products to the loot file at #{file}")
|
|
when 'osx'
|
|
listing = ''
|
|
if command_exists?('system_profiler') == false
|
|
print_error("The command 'system_profiler' does not exist on the host! Something is seriously wrong!")
|
|
return
|
|
end
|
|
command_result = cmd_exec('system_profiler SPApplicationsDataType').to_s
|
|
if command_result.empty?
|
|
print_error('No results were returned when trying to get software installed on the OSX host via system_profiler!')
|
|
return
|
|
end
|
|
listing += command_result
|
|
|
|
# Start enumerating other potential MacOS package managers now that
|
|
# the main system app manager has been enumerated.
|
|
if command_exists?('brew') # HomeBrew
|
|
listing += "\n\n----------------Brew Packages----------------\n"
|
|
listing += cmd_exec('brew list --versions')
|
|
end
|
|
|
|
if command_exists?('port') # MacPorts
|
|
listing += "\n\n----------------MacPorts Packages----------------\n"
|
|
listing += cmd_exec('port installed')
|
|
end
|
|
|
|
file = store_loot('host.osx.software.versions', 'text/plain', session, listing, 'installed_software.txt', 'Installed Software and Versions')
|
|
print_good("Stored information about the installed products to the loot file at #{file}")
|
|
when 'android'
|
|
if is_root?
|
|
if command_exists?('dumpsys') == false
|
|
print_error("Something is odd with this Android device. You are root but the dumpsys command doesn't exist. Perhaps the device is too old?")
|
|
return
|
|
end
|
|
listing = cmd_exec('dumpsys package packages').to_s
|
|
if listing.empty?
|
|
print_error('Something went wrong with the command and no output was returned!')
|
|
return
|
|
elsif listing =~ /android.permission.DUMP/
|
|
print_warning('You do not have the permissions needed to dump the versions of software installed. Reverting to just enumerating what software is installed.')
|
|
listing = enumerate_android_packages
|
|
return if listing.nil?
|
|
end
|
|
else
|
|
print_warning('You do not have the permissions needed to dump the versions of software installed. Reverting to just enumerating what software is installed.')
|
|
listing = enumerate_android_packages
|
|
return if listing.nil?
|
|
end
|
|
file = store_loot('host.android.software.versions', 'text/plain', session, listing, 'installed_software.txt', 'Installed Software and Versions')
|
|
print_good("Stored information about the installed products to the loot file at #{file}")
|
|
end
|
|
end
|
|
end
|