Skip to content

Commit 6e39c5b

Browse files
committed
land rapid7#2134 psexec_command improvements
2 parents 0d449cb + 4dfbce4 commit 6e39c5b

File tree

1 file changed

+47
-3
lines changed

1 file changed

+47
-3
lines changed

modules/auxiliary/admin/smb/psexec_command.rb

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ def initialize(info = {})
5050

5151
register_advanced_options([
5252
OptString.new('FILEPREFIX', [false, 'Add a custom prefix to the temporary files','']),
53+
OptInt.new('DELAY', [true, 'Wait this many seconds before reading output and cleaning up', 0]),
54+
OptInt.new('RETRY', [true, 'Retry this many times to check if the process is complete', 0]),
5355
], self.class)
5456

5557
deregister_options('RHOST')
@@ -70,9 +72,21 @@ def run_host(ip)
7072
print_error("#{peer} - Unable to authenticate with given credentials: #{autherror}")
7173
return
7274
end
73-
if execute_command(text, bat)
75+
res = execute_command(text, bat)
76+
77+
if res
78+
for i in 0..(datastore['RETRY'])
79+
Rex.sleep(datastore['DELAY'])
80+
# if the output file is still locked then the program is still likely running
81+
if (exclusive_access(text))
82+
break
83+
elsif (i == datastore['RETRY'])
84+
print_error("Command seems to still be executing. Try increasing RETRY and DELAY")
85+
end
86+
end
7487
get_output(text)
7588
end
89+
7690
cleanup_after(text, bat)
7791
disconnect
7892
end
@@ -103,10 +117,40 @@ def get_output(file)
103117
print_status("#{peer} - Command finished with no output")
104118
return
105119
end
106-
print_good("#{peer} - Command completed successfuly! Output:")
107-
print_line("#{output}")
120+
121+
# Report output
122+
print_good("#{peer} - Command completed successfuly!")
123+
vprint_status("Output for \"#{datastore['COMMAND']}\":")
124+
vprint_line("#{output}")
125+
126+
report_note(
127+
:rhost => datastore['RHOSTS'],
128+
:rport => datastore['RPORT'],
129+
:type => "psexec_command",
130+
:name => datastore['COMMAND'],
131+
:data => output
132+
)
133+
134+
end
135+
136+
#check if our process is done using these files
137+
def exclusive_access(*files)
138+
simple.connect("\\\\#{@ip}\\#{@smbshare}")
139+
files.each do |file|
140+
begin
141+
print_status("checking if the file is unlocked")
142+
fd = smb_open(file, 'rwo')
143+
fd.close
144+
rescue Rex::Proto::SMB::Exceptions::ErrorCode => accesserror
145+
print_status("#{peer} - Unable to get handle: #{accesserror}")
146+
return false
147+
end
148+
simple.disconnect("\\\\#{@ip}\\#{@smbshare}")
149+
end
150+
return true
108151
end
109152

153+
110154
# Removes files created during execution.
111155
def cleanup_after(*files)
112156
simple.connect("\\\\#{@ip}\\#{@smbshare}")

0 commit comments

Comments
 (0)