Hi there. I hope everyone is joining DEF CON Safe Mode. This should be one of the talks near the end of the conference. I'm pretty sure it's the last one for the Car Hacking Village. So I hope everyone's done well and survived this long. We don't certainly have to worry about some of the main hazards that you would normally have to worry about during a DEF CON because everyone's remote. The concepts I'm going to present in this were originally intended to be part of the main Tesla reverse engineering talk that I've done. But when everything was shortened due to going remote, I decided to actually split these individual topics off and do them as a separate talk. The things I'm going to cover here don't require that you actually have listened to the main talk. However, it certainly wouldn't help if you've actually already seen that or go back and watch it if some of the concepts are on here. They're all really just going to build on some of the stuff I've already talked about, but they're also going to cover DVC and ODX and some of the firmware stuff that would really stand on its own as well. So a little bit about me. My name is Patrick Kiley. I'm a Principal Security Consultant at Rapid7. I've been with them for quite a bit of time. I started with them in 2013. I've been working more recently in subjects such as avionics security. I did some research that I released last year on CAN bus and avionics, and I've actually done quite a bit of other poking around with avionics systems as an item that I've focused on. And of course, researching the Tesla, I'm interested in Internet connected transportation platforms, hardware hacking, IoT, done quite a bit of that, and of course, autonomous vehicles and CAN bus. Tesla not being one of the autonomous vehicles I've looked at, just autonomous vehicles in general, it's a subject that I'm interested in. So topics we're going to cover here. First, we're going to go over the Model S architecture just briefly again. From there, again, I cover a little bit about the Tesla BMS, and then we're going to go into CAN bus DVC files and some of the information that we can get from that if we actually have a DVC file on your reverse engineering vehicle. The screen that you see here is actually from Kvaser's database editor. That's a free tool that you can use to basically edit and create your own DVC files. It's very helpful because you don't actually have to see the signal on the bus to go in and modify it, and you can actually trim it down. I use this to actually trim down the amount of signals that were present on a mobile app for a little wireless dongle called a Panda that was connected to the BMS, the powertrain CAN bus on the Tesla, and then actually just listen to some individual signals. Trying to put this entire DVC file on there would just basically crash the mobile app. It can't handle that much. However, trimming it down to just the signals I was interested in is really useful using this tool for that. So I'd encourage anyone who's interested in messing around with DVC to check this one out because it is free. From there, we're going to cover UDS and some of the routines that you're able to extract from the Tesla firmware and from the Tesla toolbox firmware and some of the useful things that you can actually do with them. I'm going to show security access and shunt calibration, the ones I actually use for this research because they're the ones I did the most work with, and I've got a couple of interactive demos for that. And then from there, we're actually going to go into a BMS firmware. We're going to talk about the things that I learned from trying to reverse the firmware itself, the nature of the firmware, the type of the way it's stored, and then some information on the TMS320, which is the primary CPU used in the battery management system. It's also used, on the Model S and other Tesla models. So just a quick overview, the Tesla Model S, the main screen that you see to the right of the driver is actually, on the older vehicles, it's NVIDIA Tegra based, newer ones, it's Intel Atom. And then the instrument cluster is actually NVIDIA Tegra based as well. And it connects to the CID, the central display, over an Ethernet connector. That Ethernet connection actually connects to a service port, but it also connects to the security gateway. The security gateway is basically like a vehicle firewall. It acts as a filtering mechanism between the various CAN buses and the CID itself, the Ethernet. And then all the stuff that we're going to see today is actually on a powertrain CAN bus. A powertrain CAN bus contains the drive units, also charging, thermal control, and any other powertrain-related controllers all exist on that CAN bus. That CAN bus runs at 500 kilobits a second. Other than that, it's like any other vehicle CAN bus that you've seen, 11-bit arbitration IDs, sports UDS. And then the other CAN buses, there are like six or seven, but the other big ones are chassis and body. Chassis runs at 500 kilobit, body runs at 125. So the BMS itself, it's the TI-TMS320C2809. That is a DSP microprocessor. It takes all the various signals coming from voltage from the individual battery packs, from the voltage sense, from the temperature sensors, and then also talks CAN bus out on the chassis itself. There's a hardware backup to that. That's the Altera CPLD. In all the research I did, that CPLD wasn't really messed with at all, except for having a signal bypass, so it wasn't actually sent to the CPLD. But basically, it's a hardware backup to the TMS320. And for some reason, there's a software fault, the CPLD will still allow the battery to function while I assume the vehicle shuts down and safely disconnects the conductors. I've never actually seen the fault condition. I've just talked to some people and learned that that's really its mission in life, is to act as a hardware backup. There's also a few other devices. I'm going to just skip to the next slide to talk about those. There's a current shunt. For those of you who aren't familiar with what a shunt is, a shunt is a way of measuring current by measuring a voltage drop across a known resistance value. This one actually measures quite a bit of current. It's a pretty ingenious device, but every device actually has its own low level of resistance that's calibrated onto the shunt itself. The shunt runs STM8. There's also a pre-charge resistor. So the way the vehicle actually engages the contactors, it will engage one side of the contactors. I believe it's negative, please don't quote me on that. And then it goes through the standard low voltage cabling to slowly bring the vehicle up slowly, as a matter of milliseconds or microseconds, as opposed to instantaneously. But basically it brings the rest of the vehicle up to the same voltage as the battery before it engages the other contactor. And it uses the pre-charge resistor for that. Then the contactors themselves, in Ludicrous they are actually replaced with higher current models. This is a different set of contactors that I picked up off the secondary market so I can do my research. I also have a single BMB board on this. There are 16 of those in the model S85 and each of them has like six different channels that talk to the six different modules of series batteries on there. It also contains bleed resistors for a battery balancing, voltage measurement, temperature measurement, etc. And then the voltage sense wires, the ones you see on the far right, those four wires actually connect to the four sides of the contactors so they can detect if a contactor is fused. So it's basically if it welds itself closed, the voltage sense can detect that but it also can be used to just detect battery voltage overall. So a little bit about CAN-DBC. The CAN-DBC files I was able to extract from both Toolbox and the vehicle firmware. Here's what it looks like within Vehicle Spy after it's been imported. And you can actually see DI means Drive Inverter, DIS means the Front Drive Inverter. So DI is the Rear Drive Inverter, DIS is the Front Drive Inverter. You can actually see some different values being broadcast onto the CAN bus from this capture. And it's an interesting way of actually extracting the signals from this. You can actually see everything. I'm not even quite sure where this image came from, if it was from a running unit or just from a unit sitting idle, but this one actually shows the two drive inverters so I wanted to share it. This set of images actually shows the BMS after it was upgraded to Ludicrous. So it has different signals for current and power. Current is a hard limit. Once the pack has been upgraded to support Ludicrous, it goes from 1305 to 1516. You can see that in here is the max discharge current of 1516. However, the drive power max, the value you see down here is 297 kilowatts, is a variable value. It varies based on the state of charge of the battery, the temperature of the battery, and how much power was used recently. So the warmer the battery gets up to a point, that drive power max will actually increase. But then if the car has been stomped on for a little while, it will actually decrease. There's a whole leaky bucket thing that's mentioned in some of the Tesla engineering docs that talks about how it'll limit the amount of power if the power has been used recently. So it's got to wait for it to basically recharge, regenerate, and I assume cool off again before it brings it back. So one of the things I found that was interesting was that as soon as max battery power was selected, so for those of you who haven't actually been into a Model S, there's chill, sport, ludicrous, and then ludicrous plus. And if you don't have ludicrous, you have insane mode. And what I actually found right away is by monitoring the CAN bus, is after putting in the setting to enable ludicrous plus, the available power went up right away. So even though the battery had not heated up anymore from the 22 degrees Celsius value, instantly more power is available. It went from 439 to 452 kilowatts. All right, here's a screenshot from a P90DL that someone actually gave me access. Let me plug into the CAN bus and capture some messages as the battery was heated a little bit. And you can see that from this, even though the state of charge went down, it went from 93 to 91 percent, the amount of power went up. So it really seemed like pack temperature is the most dependent value. So it went from 22 to 31 and went from 454 kilowatts of power available to 480 kilowatts. You can also see region change went from 63 to 90. 90 appeared to be a top end static value. So a little bit about ODX. ODX is an ISO standard for diagnostic communication and ECUs. The way a lot of other vehicles, not Tesla's, work is you can have ECUs from like several different manufacturers and they all need to be able to communicate together within a different vehicle. So you might have some Bosch units or Mitsubishi units or some other different ECUs, but they all still need to be able to communicate with one another on the CAN bus. ODX is a standard that kind of aids in that. It's a standard for diagnostic communication so that a specific message start always means generally the same thing. And this image that you see in the screenshot is actually the XML file from ODX file that I actually extracted from a toolbox from the main talk if you follow my values that we got from there. So here is one of the most interesting ODX routines if you're going to start hacking on Tesla. Tesla's use a static key and C for security access. Not the best security practice, but it's the way they decide to implement it. And every single time you actually request security access, you can see the 2705, that's security access. It says, okay, give me the seed. The seed is 010203 all the way up through 0F. And the response is always the same thing. So you can actually configure your CAN bus tool to send the same response every single time. And that's the 353437 value C is the key. The seed can be whatever it wants, but all the ones that I've tested and all the modules that I've tested on this one, they all require the same key. And here I have a little demo actually showing how I set this up in Vehicle Spy. So you just send routine 27 level 5, level 5 security being the security access level. And then you reply with this static key as the response. There's a quick demo of it. Okay. Here we have a quick demonstration of security access. We have both routines configured within Vehicle Spy. The first thing we want to do is we want to request the seed. It's a very quick routine. And then from there, we actually request the key and we can see we can get a quick positive response. It's a very simple routine. Do it one more time. Request the seed. You can see the seed 1, 2, 3, 4, 5, 6, 7, 8, 9, A through F. And then, oh, didn't do it fast enough. One more time. Request the seed. Send the key. We got a positive response. A positive response shows the static value actually configured within Vehicle Spy. And just 303332, same things shown in the slides. And it's a very trivial thing to set up within Vehicle Spy. This is actually connected to a BMS system that's a test bench. Okay. So thank you for watching that one. I hope you enjoyed it. So the next one I'm going to kind of talk about is the shunt calibration. Shunt calibration over UDS was a separate routine. Those require basically you read the data from the shunt and you actually have to load special firmware onto the BMS to do this. The shunt calibration was a critical part of that, the ludicrous upgrade for the PD5D. But all you have to do is after you load the special firmware for the BMS is run routine22id401 and you actually get these values back. Those actually show the current value, but all you really need is the serial number. The serial number is then looked up in a Python pickle file for the values that you're going to recalibrate the shunt for. And you re-change CGI1, CIU1, and the CRC value to the new values. Even though you're reading it, the way it actually shows the write success, this is just a read screenshot. But once you actually get that back, there's a separate routine to write it. So for writing the shunt value, there's actually a write data by nanofire and there's actually ones for the shunt, but that's not the actual value one. The one that was supposed to be used to calibrate the shunt was 31 routine control. So for this particular example, if you go back, you can see that the old values were 41478. I'm actually going to try and change these and actually write them out separately. So you can see in the routine control, the value is set here for CGI1, CIU1, 65286. Instead of 65287, you're going to see a different value written and then see it actually read back in as the newer value. Okay, so there are several other routines that are actually included in the ODX files. If you actually look at this, there are ridiculous ones just even for the battery management system. All sorts of different ones for looking at different calibration data, looking at the RAM, reading that out, controlling the contactors, very dangerous to do if you're working on a vehicle that's actually powered on right now, because if you open the contactors at the wrong time, you can have some current transient issues. However, so just be careful with any of these, but it just found it interesting to see all the ones that were included in that. And then just the number of routines that were available in all the other modules were interesting to read out of the ODX files as well. So, next thing we're going to talk about is the firmware. So, all the UDS firmware updates, when they are passed on to the vehicle, when the car updates, they're all in Intel HEX format. They're stored on the firmware itself, at least on the Tegra under deploy seat artifacts v2, and then the module and the ID. So, they'll include all the firmware for all the various possibilities for that particular vehicle. And then what it does is it uses the file version underscore map 2.tsv to help the car identify the firmware file individually that it needs for the configuration that the car actually has. So, here's a little overview on how the Intel HEX format works. The first value, it always starts with a colon, and then the first value C20 is 32 bytes for HEX. And then we have an address of where that particular piece of firmware goes. And then 00, the next two values of the type of record, you'll see a 01 for EOF, and you'll see two other values for extended values or anything like that. And then you actually have data. And then the final value is a checksum. I added these spaces in for clarity. I tried to directly import the HEX files into IDA, but it has a problem reading HEX files with values this great. So, what I actually had to do is convert it to a TI.out format, which has the similar information on the location, but then it actually imported better. So, this shows the actual data sheet for the TI-TMS320-2809. It actually shows the memory map. And the really important thing that we need from this memory map, other than knowing where the different sections of memory are, the sections that are reserved because it is dual mapped, we're knowing where the code entry point is. So, you can actually see it. 3F7FF6 is actually where the initial, basically, boot-to-flash entry point. So, that basically tells us where the code entry point is for IDA. So, from that, we can actually import the data and actually go to this location. So, 7FF6 on the firmware that I'm looking at here points to 699B, and you can actually see the code starting. It's still not terribly helpful unless you're really, really good at reading assembly for the TMS320. However, it is there. It is interesting to actually see it, to see the code jump around, to see it all broken down into the various subroutines. And the thing that I did find very useful was actually doing some differential analysis. So, taking the different types of firmware and doing diffing on it. So, again, the assigned metadata map file tells us where the BMS firmware is for each config. This example, so, rear drive type one, four-wheel drive one, 4WD1 is P85D. Rear drive type zero and 4WD1 is an 85D. So, here we're comparing the performance rear motor to the standard rear motor. And you can see in this firmware, there's not really a whole lot of differences. If you look, the last line is just the CRC value. There are some single bit changes at three lines in the file. And then there's this other small little section, the 935F00 that you see in the actual major change in that. And the single motor version of the firmware is the same. It was just that single line that's changed. So, what I did is actually wanted to see if I could find this code in IDA and see where it was mapped to. And I was able to find it pretty easily. So, you can see within the hex, the 935F007A. This might have something to do with the power available. I don't know yet. I haven't changed it yet. Like I said, it's an ongoing project. But my goal is to actually find where the variables are that control the max power, the max power map, and just see if I can change them a little bit. See where I can actually take it. Don't think I'll ever actually do anything on a live vehicle just because it's too dangerous. I just want to see if I can figure this out. It's a challenge to me. But you can see it's actually mapped into this variable. The 935F actually comes out to 7A 935F. Right here, IDA was able to disassemble it. You can see where it is in code. The other values, you can actually find they're right around there. You can see it in a couple of the locations as well. So, again, like I said, the next step is to modify the firmware on a bench BMS and see where it takes us. There's also... I want to look for some other interesting changes with the other PAC ID codes. See if I can actually narrow it down to some variables being located in other locations. And then I'm also actually taking a really close look at the hardware. Code Composer Studio is not the most user-friendly program unless you're really used to working with it. But I do have it working somewhat with a BMS. It does have JTAG exposed and available on it. That's some other stuff that I'm working on. But obviously somebody has figured it out because they're selling it as an aftermarket tuner kit for the Model 3, the all-wheel drive Model 3. Again, I'm just doing this because I want to explore it. I don't want to make money on this. I just want to figure it out. And thank you for listening to my talk. I think we're going to move into Q&A next.