111 lines
3.9 KiB
Ruby
111 lines
3.9 KiB
Ruby
|
|
module Rex
|
|
module Parser
|
|
module NetSarang
|
|
# @author Kali-Team
|
|
class NetSarangCrypto
|
|
attr_accessor :version
|
|
attr_accessor :username
|
|
attr_accessor :sid
|
|
attr_accessor :master_password
|
|
attr_accessor :key
|
|
|
|
# This class implements encryption and decryption of NetSarang
|
|
#
|
|
# @param type [String] only Xshell or Xftp.
|
|
# @param version [String] Specify version of session file. e.g.:5.3
|
|
# @param username [String] Specify username. This parameter will be used if version > 5.2.
|
|
# @param sid [String] Specify SID. This parameter will be used if version >= 5.1.
|
|
# @option master_password [String] Specify user's master password.
|
|
#
|
|
# @return [Rex::Parser::NetSarang::NetSarangCrypto] The NetSarangCrypto object
|
|
def initialize(type, version, username, sid, master_password = nil)
|
|
self.version = version.to_f
|
|
self.username = username
|
|
self.sid = sid
|
|
self.master_password = master_password
|
|
md5 = OpenSSL::Digest.new('MD5')
|
|
sha256 = OpenSSL::Digest.new('SHA256')
|
|
if (self.version > 0) && (self.version < 5.1)
|
|
self.key = (type == 'Xshell') ? md5.digest('!X@s#h$e%l^l&') : md5.digest('!X@s#c$e%l^l&')
|
|
elsif (self.version >= 5.1) && (self.version <= 5.2)
|
|
self.key = sha256.digest(self.sid)
|
|
elsif (self.version > 5.2)
|
|
if self.master_password.nil?
|
|
self.key = sha256.digest(self.username + self.sid)
|
|
else
|
|
self.key = sha256.digest(self.master_password)
|
|
end
|
|
else
|
|
raise 'Invalid argument: version'
|
|
end
|
|
end
|
|
|
|
# Encrypt
|
|
#
|
|
# @param string [String]
|
|
# @return [String] ciphertext
|
|
def encrypt_string(string)
|
|
cipher = Rex::Crypto.rc4(key, string)
|
|
if (version < 5.1)
|
|
return Rex::Text.encode_base64(cipher)
|
|
else
|
|
sha256 = OpenSSL::Digest.new('SHA256')
|
|
checksum = sha256.digest(string)
|
|
ciphertext = cipher
|
|
return Rex::Text.encode_base64(ciphertext + checksum)
|
|
end
|
|
end
|
|
|
|
# Decrypt
|
|
#
|
|
# @param string [String]
|
|
# @return [String] plaintext failed return nil
|
|
def decrypt_string(string)
|
|
if (version < 5.1)
|
|
return Rex::Crypto.rc4(key, Rex::Text.decode_base64(string))
|
|
else
|
|
data = Rex::Text.decode_base64(string)
|
|
ciphertext = data[0, data.length - 0x20]
|
|
plaintext = Rex::Crypto.rc4(key, ciphertext)
|
|
if plaintext.is_utf8?
|
|
return plaintext
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
# Parse xsh session file provided as a string.
|
|
#
|
|
# @param input [String] XSH Session file as a string
|
|
# @return [Array] An array containing the version, host,
|
|
# port, username, and password obtained from the XSH session file.
|
|
def parser_xsh(input)
|
|
ini = Rex::Parser::Ini.from_s(input)
|
|
version = ini['SessionInfo']['Version']
|
|
port = ini['CONNECTION']['Port']
|
|
host = ini['CONNECTION']['Host']
|
|
username = ini['CONNECTION:AUTHENTICATION']['UserName']
|
|
password = ini['CONNECTION:AUTHENTICATION']['Password'] || nil
|
|
[version, host, port, username, password]
|
|
end
|
|
|
|
# parser xfp session file
|
|
#
|
|
# @param ini [String]
|
|
# @return [version, host, port, username, password]
|
|
def parser_xfp(file)
|
|
ini = Rex::Parser::Ini.from_s(file)
|
|
version = ini['SessionInfo']['Version']
|
|
port = ini['Connection']['Port']
|
|
host = ini['Connection']['Host']
|
|
username = ini['Connection']['UserName']
|
|
password = ini['Connection']['Password']
|
|
[version, host, port, username, password]
|
|
end
|
|
end
|
|
end
|
|
end
|