@@ -13,6 +13,12 @@ class Console::CommandDispatcher::Automotive
13
13
include Console ::CommandDispatcher
14
14
include Msf ::Auxiliary ::Report
15
15
16
+ def initialize ( shell )
17
+ super
18
+ self . tpjobs = [ ]
19
+ self . tpjob_id = 0
20
+ end
21
+
16
22
#
17
23
# List of supported commands.
18
24
#
@@ -21,14 +27,17 @@ def commands
21
27
'supported_buses' => 'Get supported buses' ,
22
28
'busconfig' => 'Get baud configs' ,
23
29
'connect' => 'Get HW supported methods for a bus' ,
24
- 'cansend' => 'Send a CAN packet'
30
+ 'cansend' => 'Send a CAN packet' ,
31
+ 'isotpsend' => 'Send an ISO-TP Packet and get a response' ,
32
+ 'testerpresent' => 'Sends TesterPresent Pulses to the bus'
25
33
}
26
34
27
35
reqs = {
28
36
'supported_buses' => [ 'get_supported_buses' ] ,
29
37
'busconfig' => [ 'get_bus_config' ] ,
30
38
'connect' => [ 'get_supported_methods' ] ,
31
- 'cansend' => [ 'cansend' ]
39
+ 'cansend' => [ 'cansend' ] ,
40
+ 'testerpresent' => [ 'testpresent' ]
32
41
}
33
42
34
43
# Ensure any requirements of the command are met
@@ -106,9 +115,10 @@ def cmd_connect(*args)
106
115
end
107
116
unless client . automotive . is_valid_bus? bus
108
117
print_error ( "You must specify a valid bus via -b" )
118
+ print_line ( "Current active bus: #{ self . active_bus } " ) if self . active_bus
109
119
return
110
120
end
111
- active_bus = bus
121
+ self . active_bus = bus
112
122
client . automotive . set_active_bus ( bus )
113
123
hw_methods = client . automotive . get_supported_methods ( bus )
114
124
hw_methods
@@ -141,7 +151,7 @@ def cmd_cansend(*args)
141
151
data = val
142
152
end
143
153
end
144
- bus = active_bus if bus . blank? && !active_bus . nil?
154
+ bus = self . active_bus if bus . blank? && !self . active_bus . nil?
145
155
unless client . automotive . is_valid_bus? bus
146
156
print_error ( "You must specify a valid bus via -b" )
147
157
return
@@ -154,17 +164,167 @@ def cmd_cansend(*args)
154
164
success
155
165
end
156
166
167
+ #
168
+ # Generic ISO-TP CAN send packet command
169
+ #
170
+ def cmd_isotpsend ( *args )
171
+ bus = ''
172
+ id = ''
173
+ ret = ''
174
+ data = ''
175
+ timeout = nil
176
+ maxpackets = nil
177
+ cansend_opts = Rex ::Parser ::Arguments . new (
178
+ '-h' => [ false , 'Help Banner' ] ,
179
+ '-b' => [ true , 'Target bus' ] ,
180
+ '-I' => [ true , 'CAN ID' ] ,
181
+ '-R' => [ true , 'Return ID' ] ,
182
+ '-D' => [ true , 'Data packet in Hex (Do not include ISOTP command size)' ] ,
183
+ '-t' => [ true , 'Timeout value' ] ,
184
+ '-m' => [ true , 'Max packets to receive' ]
185
+ )
186
+ cansend_opts . parse ( args ) do |opt , _idx , val |
187
+ case opt
188
+ when '-h'
189
+ print_line ( "Usage: isotpsend -I <ID> -D <data>\n " )
190
+ print_line ( cansend_opts . usage )
191
+ return
192
+ when '-b'
193
+ bus = val
194
+ when '-I'
195
+ id = val
196
+ when '-R'
197
+ ret = val
198
+ when '-D'
199
+ data = val
200
+ when '-t'
201
+ timeout = val . to_i
202
+ when '-m'
203
+ maxpackets = val . to_i
204
+ end
205
+ end
206
+ bus = self . active_bus if bus . blank? && !self . active_bus . nil?
207
+ unless client . automotive . is_valid_bus? bus
208
+ print_error ( "You must specify a valid bus via -b" )
209
+ return
210
+ end
211
+ if id . blank? || data . blank?
212
+ print_error ( "You must specify a CAN ID (-I) and the data packets (-D)" )
213
+ return
214
+ end
215
+ if ret . blank?
216
+ ret = ( id . hex + 8 ) . to_s ( 16 )
217
+ print_line ( "Default return set to #{ ret } " )
218
+ end
219
+ bytes = data . scan ( /../ ) # Break up data string into 2 char (byte) chunks
220
+ if bytes . size > 8
221
+ print_error ( "Data section can only contain a max of 8 bytes (for now)" )
222
+ return
223
+ end
224
+ opt = { }
225
+ opt [ 'TIMEOUT' ] = timeout unless timeout . nil?
226
+ opt [ 'MAXPKTS' ] = maxpackets unless maxpackets . nil?
227
+ result = client . automotive . send_isotp_and_wait_for_response ( bus , id , ret , bytes , opt )
228
+ if result . key? 'Packets'
229
+ result [ 'Packets' ] . each do |pkt |
230
+ print_line pkt . inspect
231
+ end
232
+ end
233
+ print_line ( result [ 'error' ] . inspect ) if result . key? 'error'
234
+ result
235
+ end
236
+
237
+ #
238
+ # Sends TesterPresent packets as a background job
239
+ #
240
+ def cmd_testerpresent ( *args )
241
+ bus = ''
242
+ id = ''
243
+ stop = false
244
+ stopid = 0
245
+ tp_opts = Rex ::Parser ::Arguments . new (
246
+ '-h' => [ false , 'Help Banner' ] ,
247
+ '-b' => [ true , 'Target bus' ] ,
248
+ '-I' => [ true , 'CAN ID' ] ,
249
+ '-x' => [ true , 'Stop TesterPresent JobID' ]
250
+ )
251
+ tp_opts . parse ( args ) do |opt , _idx , val |
252
+ case opt
253
+ when '-h'
254
+ print_line ( "Usage: testerpresent -I <ID>\n " )
255
+ print_line ( tp_opts . usage )
256
+ return
257
+ when '-b'
258
+ bus = val
259
+ when '-I'
260
+ id = val
261
+ when '-x'
262
+ stop = true
263
+ stopid = val . to_i
264
+ end
265
+ end
266
+ bus = self . active_bus if bus . blank? && !self . active_bus . nil?
267
+ unless client . automotive . is_valid_bus? bus
268
+ print_error ( "You must specify a valid bus via -b" )
269
+ return
270
+ end
271
+ if id . blank? && !stop
272
+ if self . tpjobs . size . positive?
273
+ print_line ( "TesterPresent is currently active" )
274
+ self . tpjobs . each_index do |jid |
275
+ if self . tpjobs [ jid ]
276
+ print_status ( "TesterPresent Job #{ jid } : #{ self . tpjobs [ jid ] [ :args ] . inspect } " )
277
+ end
278
+ end
279
+ else
280
+ print_line ( "TesterPreset is not active. Use -I to start" )
281
+ end
282
+ return
283
+ end
284
+ if stop
285
+ if self . tpjobs [ stopid ]
286
+ self . tpjobs [ stopid ] . kill
287
+ self . tpjobs [ stopid ] = nil
288
+ print_status ( "Stopped TesterPresent #{ stopid } " )
289
+ else
290
+ print_error ( "TesterPresent #{ stopid } was not running" )
291
+ end
292
+ else
293
+ jid = self . tpjob_id
294
+ print_status ( "Starting TesterPresent sender (#{ self . tpjob_id } )" )
295
+ self . tpjob_id += 1
296
+ self . tpjobs [ jid ] = Rex ::ThreadFactory . spawn ( "TesterPresent(#{ id } )-#{ jid } " , false , jid , args ) do |myjid , xargs |
297
+ ::Thread . current [ :args ] = xargs . dup
298
+ begin
299
+ loop do
300
+ client . automotive . cansend ( bus , id , "023E00" )
301
+ sleep ( 2 )
302
+ end
303
+ rescue ::Exception
304
+ print_error ( "Error in TesterPResent: #{ $!. class } #{ $!} " )
305
+ elog ( "Error in TesterPreset: #{ $!. class } #{ $!} " )
306
+ dlog ( "Callstack: #{ $@. join ( "\n " ) } " )
307
+ end
308
+ self . tpjobs [ myjid ] = nil
309
+ print_status ( "TesterPreset #{ myjid } has stopped (#{ ::Thread . current [ :args ] . inspect } )" )
310
+ end
311
+ end
312
+ end
313
+
157
314
#
158
315
# Name for this dispatcher
159
316
#
160
317
def name
161
318
'Automotive'
162
319
end
163
320
164
- private
165
-
166
321
attr_accessor :active_bus
167
322
323
+ protected
324
+
325
+ attr_accessor :tpjobs , :tpjob_id # :nodoc:
326
+
327
+
168
328
end
169
329
170
330
end
0 commit comments