Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/rex/parser/winscp.rb
Views: 11778
1module Rex2module Parser3module WinSCP4PWDALG_SIMPLE_MAGIC = 0xA35PWDALG_SIMPLE_FLAG = 0xFF67def read_and_parse_ini(filename)8file = File.read(filename)9return if file.to_s.empty?10parse_ini(file)11end1213def parse_protocol(fsprotocol)14return 'Unknown' if fsprotocol.nil?1516case fsprotocol17when 5 then 'FTP'18when 0 then 'SSH'19else20'Unknown'21end22end2324def parse_ini(file)25results = []26raise RuntimeError, 'No data to parse' if file.nil? || file.empty?2728ini = Rex::Parser::Ini.from_s(file)2930if ini['Configuration\\Security']31# if a Master Password is in use we give up32if ini['Configuration\\Security']['UseMasterPassword'].to_i == 133raise RuntimeError, 'Master Password Set, unable to recover saved passwords!'34end35end3637# Runs through each group in the ini file looking for all of the Sessions38ini.each_key do |group|39if group.include?('Sessions') && ini[group].has_key?('Password')40# Decrypt our password, and report on results41encrypted_password = ini[group]['Password']42user = ini[group]['UserName']43host = ini[group]['HostName']44sname = parse_protocol(ini[group]['FSProtocol'].to_i)45plaintext = decrypt_password(encrypted_password, "#{user}#{host}")4647results << {48hostname: host,49password: plaintext,50portnumber: ini[group]['PortNumber'] || 22,51username: user,52protocol: sname53}54end55end5657results58end5960# Decrypts the next character in the password sequence61def decrypt_next_char(pwd)62if pwd.nil? || pwd.length <= 063return 0, pwd64end6566# Takes the first char from the encrypted password and then left shifts the returned index by 4 bits67a = pwd[0].hex << 46869# Takes the second char from the encrypted password70b = pwd[1].hex7172# Adds the two results, XORs against 0xA3, NOTs it and then ANDs it with 0xFF73result = ~((a + b) ^ PWDALG_SIMPLE_MAGIC) & PWDALG_SIMPLE_FLAG7475# Strips the first two chars off and returns our result76return result, pwd[2..-1]77end7879def decrypt_password(pwd, key)80flag, pwd = decrypt_next_char(pwd)8182if flag == PWDALG_SIMPLE_FLAG83_, pwd = decrypt_next_char(pwd)84length, pwd = decrypt_next_char(pwd)85else86length = flag87end8889del, pwd = decrypt_next_char(pwd)90pwd = pwd[del*2..-1]9192result = ""93length.times do94r, pwd = decrypt_next_char(pwd)95result << r.chr96end9798if flag == PWDALG_SIMPLE_FLAG99result = result[key.length..-1]100end101102result103end104end105end106end107108109