@@ -53,6 +53,9 @@ def initialize(info = {})
53
53
54
54
register_advanced_options ( [
55
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' , '' ] ) ,
56
59
] , self . class )
57
60
58
61
deregister_options ( 'RHOST' )
@@ -77,9 +80,21 @@ def run_host(ip)
77
80
print_error ( "#{ peer } - Unable to authenticate with given credentials: #{ autherror } " )
78
81
return
79
82
end
80
- if execute_command ( text , bat )
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
81
95
get_output ( text )
82
96
end
97
+
83
98
cleanup_after ( text , bat )
84
99
disconnect
85
100
end
@@ -110,10 +125,47 @@ def get_output(file)
110
125
print_status ( "#{ peer } - Command finished with no output" )
111
126
return
112
127
end
113
- print_good ( "#{ peer } - Command completed successfuly! Output:" )
114
- print_line ( "#{ output } " )
128
+
129
+ # Define log filename
130
+ timestamp = ::Time . now . strftime ( '%Y%m%d:%H%M%S' )
131
+ filename = "#{ datastore [ 'RHOSTS' ] } _#{ timestamp } "
132
+ if ( datastore [ 'LOGDIR' ] . nil? )
133
+ log_file = ::File . join ( log_dir , "#{ filename } .txt" )
134
+ else
135
+ log_file = ::File . join ( datastore [ 'LOGDIR' ] , "#{ filename } .txt" )
136
+ end
137
+
138
+ print_good ( "#{ peer } - Command completed successfuly!" )
139
+ print_status ( "Logging output to #{ log_file } ." )
140
+ output = "# CMD: #{ datastore [ 'COMMAND' ] } " + output
141
+
142
+ fd = ::File . new ( log_file , 'w+' )
143
+ fd . write ( output )
144
+ fd . close ( )
145
+
146
+ if datastore [ "VERBOSE" ]
147
+ print_status ( "Output:" )
148
+ print_line ( "#{ output } " )
149
+ end
115
150
end
116
151
152
+ #check if our process is done using these files
153
+ def exclusive_access ( *files )
154
+ simple . connect ( "\\ \\ #{ @ip } \\ #{ @smbshare } " )
155
+ files . each do |file |
156
+ begin
157
+ print_status ( "checking if the file is unlocked" )
158
+ fd = smb_open ( file , 'rwo' )
159
+ fd . close
160
+ rescue Rex ::Proto ::SMB ::Exceptions ::ErrorCode => accesserror
161
+ print_status ( "#{ peer } - Unable to get handle: #{ accesserror } " )
162
+ return false
163
+ end
164
+ end
165
+ return true
166
+ end
167
+
168
+
117
169
# Removes files created during execution.
118
170
def cleanup_after ( *files )
119
171
simple . connect ( "\\ \\ #{ @ip } \\ #{ @smbshare } " )
0 commit comments