Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
module Rex
module Parser
module WinSCP
PWDALG_SIMPLE_MAGIC = 0xA3
PWDALG_SIMPLE_FLAG = 0xFF
def read_and_parse_ini(filename)
file = File.read(filename)
return if file.to_s.empty?
parse_ini(file)
end
def parse_protocol(fsprotocol)
return 'Unknown' if fsprotocol.nil?
case fsprotocol
when 5 then 'FTP'
when 0 then 'SSH'
else
'Unknown'
end
end
def parse_ini(file)
results = []
raise RuntimeError, 'No data to parse' if file.nil? || file.empty?
ini = Rex::Parser::Ini.from_s(file)
if ini['Configuration\\Security']
# if a Master Password is in use we give up
if ini['Configuration\\Security']['UseMasterPassword'].to_i == 1
raise RuntimeError, 'Master Password Set, unable to recover saved passwords!'
end
end
# Runs through each group in the ini file looking for all of the Sessions
ini.each_key do |group|
if group.include?('Sessions') && ini[group].has_key?('Password')
# Decrypt our password, and report on results
encrypted_password = ini[group]['Password']
user = ini[group]['UserName']
host = ini[group]['HostName']
sname = parse_protocol(ini[group]['FSProtocol'].to_i)
plaintext = decrypt_password(encrypted_password, "#{user}#{host}")
results << {
hostname: host,
password: plaintext,
portnumber: ini[group]['PortNumber'] || 22,
username: user,
protocol: sname
}
end
end
results
end
# Decrypts the next character in the password sequence
def decrypt_next_char(pwd)
if pwd.nil? || pwd.length <= 0
return 0, pwd
end
# Takes the first char from the encrypted password and then left shifts the returned index by 4 bits
a = pwd[0].hex << 4
# Takes the second char from the encrypted password
b = pwd[1].hex
# Adds the two results, XORs against 0xA3, NOTs it and then ANDs it with 0xFF
result = ~((a + b) ^ PWDALG_SIMPLE_MAGIC) & PWDALG_SIMPLE_FLAG
# Strips the first two chars off and returns our result
return result, pwd[2..-1]
end
def decrypt_password(pwd, key)
flag, pwd = decrypt_next_char(pwd)
if flag == PWDALG_SIMPLE_FLAG
_, pwd = decrypt_next_char(pwd)
length, pwd = decrypt_next_char(pwd)
else
length = flag
end
del, pwd = decrypt_next_char(pwd)
pwd = pwd[del*2..-1]
result = ""
length.times do
r, pwd = decrypt_next_char(pwd)
result << r.chr
end
if flag == PWDALG_SIMPLE_FLAG
result = result[key.length..-1]
end
result
end
end
end
end