 First of all allow me to introduce myself because you probably don't know me work as a security engineer for over eight years Currently I'm working in Accenture embedded system security team. That's based in Prague Czech Republic That's also where I come from and I'm a big open source enthusiast So the tools that I'll be showing you here today are already published on github and could be used by anyone Let's have a look at what's ahead of us. We will start with the description of the canvas We're right next to the car hacking village. So 90% people there actually know that better than I do, but also try We will use this knowledge to define the problem that I'd like to talk about and Then I'll go into the demo section, which will be quite long because I have two of the demos first demo will you be using development board and access to the source code debugger and We will basically have a white box approach and we will see how this vulnerability works and Then we will continue in the second demonstration and I'd like to approach this one as a simulated security assessment here on stage of a real-life ECU So I brought an ECU from a vehicle and I'll be doing security assessment of that. This demo is quite packed We will be using JTAG debugger. We will be analyzing firmware. We will be using oscilloscopes so there's a lot to see and Then we will just wrap up the talk with just a couple points about who could be affected by it and Some general takeaways at the end. I hope there will be still some time left for question and answers So without further ado Let's jump into the first slide and that's the description of the CAN bus So most of you probably know but CAN bus or controller area network bus is a standard That was originally aimed at the vehicles to allow multiple ECUs to communicate with each other reliably in the noisy environments such as the car To achieve this there are two wires used for this Which are carrying a differential signal differential signal means that the data being transmitted over these two lines is basically identical It's just the polarity is inverted and each of these buses is terminated by 120 ohm resistor Typical vehicle probably contains multiple of these buses which are usually connected by something that's called security gateway If I'm to use analogy to AP networks, that would be like a router that decides which message can pass where Thanks to these properties like robustness. It's found its way into the address these as well That's why the talk is this described as embedded devices Because you can find CAN bus in a heavy industry equipment You can find CAN bus in medical devices and on a lot of other places, too It's also important to mention that there are multiple versions of the CAN bus as it evolved over the time It started with an 11-bit identifier CAN bus that carried just eight bytes of data These have been deemed insufficient. So an extended can ID came which has increased ID portion to 29 bits, but it kept the eight bytes of the data Then further CAN bus versions have been introduced such as can FD with 64 bytes of data But with the talk that I have I'm having today is only applicable to the Standard can ID frame an extended can ID frame will discuss briefly can FD and can Excel But only at the end of this talk This slide shows the message the frame and its individual fields In the green part, there is the most important field that's can ID. Obviously you need that then in yellow You can see field called DLC or data length code This tells us how many bytes of data actually follow that could be between 0 to 8 So there is a perfect valid message in CAN bus that has a zero bytes of data The meaning could be carried just inside the ID But you can have anywhere up to eight bytes of data Then in the blue field you can see the CRC, but that's not really irrelevant for this talk So I'm going to just skip the remaining fields for The picture at the bottom that's a capture from an oscilloscope It shows you how it works on the physical layer and you can see the differential signaling where The red line is can hide the blue line is can low and as you can see the data is basically identical It's just a mirror image between those two We'll be playing a bit with the oscilloscope later on in the demo But for now, this is just for me to show you how it works on the physical layer It's not really that it's actually relevant to what I'm going to talk about if we dive a bit into the specification of the CAN bus and We look at the description of the data length code field We will find that it has to have values between zero and eight To express eight in binary you need four bits because that's one followed by three zeros and therefore I Got an idea like what would happen if I'm going to just send DLC field with all four ones First disclaimer, you can never send more than eight bytes of data in those CAN frames those Packets would be just malformed never really received so you can you'll never send more than eight bytes of data however, what I found is that none of the hardware and Most of the software actually cares about the DLC field value So you can send whatever you want there and it's still valid and it will still be passed all the way to the developer And then it's up to the firmware development team how they work with this value on the slide you can see a hypothetical mem copy situation and Because the developers that are working with CAN bus probably know that they can never receive more than eight bytes The destination buffer would be allocated to eight bytes because why waste memory? Then the source of the operation as a second parameter would be can data because that's what we want to copy But since you're not always receiving eight bytes, but sometimes you receive four three or any other value You can use this convenient DLC field which the frameworks you're using is giving you to actually specify how many bytes should be copied and That's exactly where the problem comes now. I'm going to do the funny thing of readjusting the microphone I'm sorry if I drop it Because I want to sit for the demo Sorry for that delay. I mean just that Well, basically jump into our first demonstration But before that I'd like to introduce you the hardware that I brought with me It's in this yellow suitcase that you can see on the stage And as you can see it contains a lot of PCBs wires some displays LEDs And I hope you like it at least as much as people at the airport security did it Because I had to explain to like three people what it is. I had to take it apart and They basically swiped the hell out of it with those anti-explosive detective papers. So it's kind of a miracle It still works, but it does In this case I have a red Board here the red one in the corner that will be victim for our first demo. It's an NXP board Where I'll have source code running and everything The guy in the corner here the simple Arduino That's the attacker. It has a little button here that you can't really see but whenever I press it A malicious message will be sent. I'm going to ignore the middle Arduino for now And this is just a power source so that it actually works. So that's not really important now if I Like to show you actually how the source code looks like for these boards I'll start with the attacker one. So the Arduino in the setup function I'll just set up can bus serial and the button. That's not really interesting Then I set up the message. I'll start by setting a can ID 600 a you'll find out in the second demo Y But the most important thing I'll send to the DLC field value to F Then I need to send some dummy payload in this case would be a BCDF GH in Capital ASCII so that we can actually see it and refer to it while we're debugging and Inside the loop it just waits for the button press and whenever that happens. We're going to send the message with this function When I switch to the victim so the red board code, which we will be debugging There is a main function. We just have two variables one is obviously called override buffer because we're gonna overwrite it And we start by setting it to value one two three four five six seven again So that we have something easy to refer to Then there is not really interesting can bus setup, which I'll just skip and in here I'll be waiting for a message to arrive and when it does There is the mem copy function, which is pretty basically identical to the one from the previous slide Where you we're copying into the buffer frame DSR is how MCU express so chose to call the data field I'm not to blame for that and frame DLR is the DLC field value. That's how it's called in MCU express So again, I in every framework it will be called differently Since I have the board in the case I can just hit debug and this should run it learn the code and we should stop on our first breakpoint if I step over this I Can just investigate that the override buffer is now set to values one two three four five six seven and ask it Terminated by an albite, which is exactly as expected And if I run the code nothing really happens because we're now in this endless loop and we're waiting for can messages to arrive to do so I need to press this almost invisible button and Hopefully you see a notification pop up here on my screen that tells me that the breakpoint was hit at this mem copy function and In the data that I'm being as a sort using as a source for the mem copy You can see the ABCDFGH, which we've set in the Arduino and in the DLR We can see value 15, which is the DLC field value, which we've set I'm just gonna step over this so that the mem copy finishes what it did and now inside the buffer I should have these ABCD each ABCD string But more importantly, let's have a look at on what is in the override buffer. I'm just Going to scroll over it the very first value Hope it's readable a bit as value 15, which is suspicious because 15 is the DLC field we've sent But the remaining values I don't really recognize because there is null byte then 1 3 7 so 1 7 2 then repeat it then another null byte The final final null byte hasn't been overwritten because we're overwriting just with seven bytes So the not far enough bite is from the original buffer But now it would be good to see what we are actually whether we have some control over the data That we're overwriting with to do that. We have to investigate a Structure called MS scan frame again, this is specific to MCU express of framework in other frameworks you'll find something completely different and We'll see that the value of DSR, which is the data where we started the copy operation is actually a member of a union So that you can access the data as data words or data bytes But right after that, there is the DLR value, which is the DLC This confirms our suspicion that we are overwriting with this structure But the remaining values such as Buffer priority type format and sometimes stems and those aren't really in control of the attackers So we have very limited control of what we overwrite with But nevertheless, we can actually use this for some other impact than just denial of service That's in the title of this talk. I can imagine situations where you overwrite local and global variables In a way that you change their values from a zero to something else Why this is important? And that's because in when you program in C There's quite a common practice of doing canal checks and I'll check is for example is Authenticated if it is a variable then if it is zero you're not authenticated and anything else would mean you are and This way you could theoretically bypass some of the controls Although in the real-life examples this always resulted just in the denial of service Usually for various reasons, but mainly by overwriting pointers to something that makes absolutely no sense and then crashing the firmware With that I'd like to transition into the second demonstration where I'll be using an ECU from a Tesla Model 3 vehicle And it's the security controller that sits between the seats where you tap your NFC card when you want to drive it's responsible for example for unlocking the door and This decision whether you can drive or not. This is done together with the body control module and if we do a typical assessment We first unpack the ECU and see what the PCB has to offer in this case We found that on the bottom of the PCB. There is an SPC560B64 microcontroller from SD micro and Literally right next to it are pads which are labeled STJ tag The jackpot in this case was that this was actually working JTAG interface So we were able to dump the firmware image and proceed with the assessment And this is exactly what I'd like to do here and we will start by dumping the image Then we will analyze the firmware find the vulnerability exploit it and Then play with the oscilloscope and have some fun So let me just show you the unobfuscated view on the suit case You can see the ECU obviously the big green thing with the Tesla logo The Arduino in the middle serves only one purpose and that is to simulate the rest of the car So in fact this suitcase is the smallest Tesla car that you have probably seen I'll have this again a little black button whenever I press it I simulate the rest of the car so that the ECU works as if it is in if I don't do that I can't really work with this ECU and show you it live I talked about the debugger. So I have just the jailing. I hope it's readable In this suitcase, there are actually multiple layers. One of the layers contains a jailing debugger and I can connect with it And just type connect. I have pre-selected the correct MCU. So SPC 560 B64 So I'll just leave everything default because I like defaults and The CPU is now halted and I'm connected to it. This is a good time to dump the firmware image I can use save bit save bin command for that and as a destination. I'll choose file tmpfw.bin For example, and now I have to specify the memory range, which I want to dump So it will be from address 0 to address 1 7 ff ff This memory range I've read it from the datasheet, but I consider it kind of boring to open a datasheet here So I'm just gonna cheat and skip on that But this will save the binary from that section You can find it in a memory map. There's actually no science around this Now we have a firmware dumped and I'm going to open IDA and Analyze the binary. I made all fonts ridiculously large. So I hope you can read it for me It's quite painful to work like this, but It's for the audience's sake I'm going to choose powerPC because as I said I was reading the datasheet So I know that it's a powerPC and from now on I'll use my beloved defaults everywhere and This should load me a binary in an IDA But as you can see nothing really happened because we're working with a just binary blob and I that doesn't really know Is it the code? Is it data? Is it mix of both? There are no entry points. What should I do? Since this is a situation that we faced quite often Working with like extracted firmware image from a microcontroller We made a little plug-in for IDA Pro, which is called firm loader and here I just have to select the brand the line of the MCU and the correct MCU and This will start the auto analysis It will also create memory sections such as RAM peripherals And it will mark the code flash as executable and trigger the auto analysis If I'm to do a real assessment, this is a starting point not of complete analysis I have to do a bit more manual work to make it ideal, but we don't have time and We have to cheat a bit. So I'm going to be fine with the analysis that it did Mainly because it already found 1700 or so functions so I would be we have the binary loaded and we can start working with it Now I'd like to show you two different ways on how to approaching firmware analysis of an MCU The first approach is identifying standard functions Standard functions are things like memcopy, malloc, free, all of those libc Functions that developers use everywhere. It's good to find them because then it's a bit easier to uncover the custom logic in the firmware You can use IDA Lumina if you have IDA for that It's a great tool, but I'm going to do it manually and not because I just want to scare you with the assembly But I just actually want to show you that it's not that hard Let me just adjust the view of IDA a little bit so that we have more comfortable view and Also going to need to set the compiler. Sorry for that delay and This function is actually memcopy. I'm just going to walk you through very quickly on why it is a memcopy Again, I had to read about PowerPC to figure out that first three arguments to a function are passed in registers R3, R4 and R5 Therefore, if I look at the memcopy Parameters, I know that the first one is the destination The second one is source and the third one is how many bytes should be copied So the third parameter R5 is here first incremented and then it's set into something called counter register again Had to read about PowerPC unfortunately Then this counter register is Decremented every time we execute this function in this instruction and if it reaches zero We go here to end the function, but as long as it's not zero we will be executing this code block in a loop So we already know that whatever this function does it will do it for how many times we tell it in a third argument Which is already a good definition of a memcopy But inside the body of the loop we can see that it takes second argument So register R4 indexed by R0 and stores that value into R7 Then instruction after that takes that value from R7 and stores it in the first argument Which is R3 again indexed by R0 Then the index is just incremented and this repeats for however many times we specified This is how you find a standard function. Sometimes it's a bit more complicated I admit this was one of the very easiest examples I'm also going to set the type of the function because I would like to show you some automation later and for that This is necessary Now if I'm doing a security analysis of a firmware I can hit X on the keyboard and I should now theoretically go through all of these memcopy Crosser Francis and see if they are vulnerable or not. I'm lazy and I don't have time so I'm not gonna do that Second approach that I'd like to show you is a combination of static and dynamic analysis During the dynamic analysis, I know what the ECU sends on a canvas. I know what it receives on the canvas so it's actually very simple to just use search for immediate values and Find the can idea I'm interested in This isn't exactly working every time but in this case it does So the second hit is especially interesting because it's in compare instruction and It's comparing register R3 So first argument to the function to the value that I know I saw on the canvas And if I look around I actually see a lot of the values that I've seen on the canvas this one this one This one. So this is good enough assumption for me to just rename this to can handler Because it appears to be handling incoming can messages And now I'll end the torture and switch to the decompiler because we need to speed up a bit and We said that the first one is can DLC. So I'm just can ID. Sorry. I'm going to rename it to that With a bit of analysis that I'm not gonna show you here that we would figure out this is can data and We would actually figure out this is can DLC and Now we basically went from a black box assessment where we took an ECU from a vehicle to a crappy source code review And again, as you can see there are many can bus IDs being handled by this function And in theory I should go through all of them and identify whether any of these are vulnerable to some issues Again, I'm lazy. I don't have time. So I'm not gonna do that Instead I'm going to skip over And if you remember the attacking board sends can ID 600 a so I'm going to just look at the handler for can ID 600 a I'm gonna rename it to that because I don't want to lose track And this function gets can data and can DLC as parameters. So let's just open it and do the renaming again and now This mem copy here screams at us and vulnerable basically Because as you can see this link specifier here is can DLC The source is can data And as a destination there is this weird memory address Weird memory addresses in MCU firmware are usually global variables They're just static places in memory which are then used to access the variable values If I look at it, I can find that there is between 1af 0 and 1af 7 I have preallocated 8 bytes for this variable And right after it there is variable called 1af 8 And if I look at the cross references, I can see that it is being used somewhere So if I overflow this variable, I may adjust Something in the firmware and cause some undesired behavior I'm just going to synchronize the view because that's going to be useful if my right click would have worked sorry for that pseudocode And Now when we saw the can handler, there were many many many functions that were handling can messages I said I'm lazy, so I'm not going to do that But because I'm lazy all the time, but I don't have time just right now We created a plugin That automates a bit a search for cross references This plugin is called wolfie And to work with it I wonder why my touchpad doesn't work things You just have to add certain functions. I'm sorry. I don't know how to enlarge this text. So I'll just describe it We first select some name for the rule that actually doesn't matter at all And then we have to use a filter to somehow filter out all the memcopy functions We're not interested in or to just filter those that we are interested in To find this vulnerability. There is one precondition The memcopy function must not have static third parameter If there is a static value like two three eight in a third parameter this vulnerability will not work So I'll start by saying that the not param two dot is constant I'm sorry for the syntax. It's just python code that gets evaluated And if this condition is fulfilled I can also say that I'm actually only interested in the functions that are core from the can handler So I can just say function If I'm be able to type function call dot reachable from can handler And this query will now take a look at all 100 plus cross references to a memcopy function And it will only filter out those that match the criteria I've specified As you can see the very first one is the one we found manually in can handler 68 But there are five others. I'd like to specifically look at the one at 6f 1ba Which is right here The main reason I want to look at it is if I look at the cross references of this function We can see it's being called at the can handler 68 here And it's right here as you can see again. It gets can data can dlc as a parameters So rename again And now we can see that right in the middle of the function. There is a memcopy function It's uses as a source can data as a count of bytes. This is this time It's v4, but v4 is here. It's just can dlc. So it's just can dlc through a proxy. Let's say The destination in this time is variable v7, which is a local variable. It has an 8 byte array So we can cheer again. We will be overflowing But we will be overflowing into something called variable v8 And if you look at what it is, it actually is set to some constant value here from a global variable at the beginning of the function And then it's compared to it at the end of the function. This is a thing called stack canaries And it is used to protect the values on the stack against buffer overflows such as this one So in this case, we know that when we send this scan message, we would actually cause this stack canary to get triggered But we should have a look at what's going to happen and that's in this function We will actually play a bit with peripherals But more importantly, there is this endless while loop endless while loops are the best indicators for fold handlers in microcontrollers Because while in endless while loop the device cannot cause any harm by just Doing weird things with its peripherals. It's just executing the same instruction over and over again Therefore we will cause a crash of this microcontroller. That's why denial of service But unfortunately it would be true and anti-climatic overwrite of a stack canary We have access to the debugger So it would be quite nice to actually see this in action and see if we actually overwrite with the same values as we have seen in the previous demo So to do that, I decided to torture myself further and show you the access in the debugger Where I can set breakpoints First one would be at before memcopy function The second one will be right after it And I'll check if the cpu is all that it is. I'll let it go Now uh These you wouldn't actually react to any can messages because it's sleeping state. So I have to press this button This will turn on one of the leds that were so loved at the airport And once it turns off, I know that the car is properly simulated and I can start working with the ECU The cpu still shouldn't be halted But this would change after I sent the attacker message And as you can see it did now we're right before the memcopy function and we can investigate the registers And from the beginning of the demo we can actually know that The register r3 is the one that holds the destination Location so I can use mem32 function Command to dump that part of the memory I'm also terrible. Sorry to anyone who knows how to work with jailing and these kind of commands. I'm not really good with that But here these eight bytes are the legitimate v7 buffer This is what should be overwritten with the canned data This is stack canary, which is interestingly said to all zeros And this is the value that should be protected by this stack canary And now uh comes the part where I'm not really good with jailing because this is how I step over breakpoints As I said, I'm sorry to anyone who knows how to do that And if I repeat the command now Uh, we can see that these 41 42. This is basically the abcd fgh string This is the stack canary, which has been overwritten with the canid So we can cheer up a bit because we are controlling Quite a lot of bytes that we're overflowing But we can't really because if we change the canid this overflow would never happen So again, we can't really change what we overflow with in this case Then this is probably can dlc based on the value here Then there are some null bytes for some flags Inside the canned structure and this d8 is from the original pointer. We haven't really overwritten that Now having access to the debugger is nice But sometimes you don't have that And let me just check that the cpu is not halted it is not And in this suite case, there is a third layer under meet the jailing layer and that contains an oscilloscope One of the oscilloscope probes is connected here to the canvas. The other oscilloscope probe is hidden under this To sense the nfc field So if I now press this simulation button I can go into the oscilloscope view and start tracking the red line is the nfc field the blue line is the canvas So when the ecu comes up, you can see nfc field is up and if I press the attacker button You'll first see that let me stop that first You'll see that the can messages have stopped being sent. That's the reset of the ecu And about a half a second after that the nfc field got killed as well This is how we initially found the vulnerability through fuzzing and using this side channel detection The delay between the crash of the mcu and the nfc field disappearing is caused by the fact that the nfc controller is actually a separate chip And there's a communication line between the main mcu and the nfc chip And that's why there's a bit of a half second delay before that shuts down I'll try to zoom into this but I have never found the way how to increase text here So you'll probably not be able to read that But the message before this drop ends before this drop happens the last message is the one we've sent so id 600a And the voltage drop is actually caused by the gpio pins being reset into their default state After that if I zoom out a bit There is a break in can messages being sent This is because the ecu is restarting and then it gets into the initial state where it again waits for it to be restarted This is just one of the side channel ways and when I was here I've been actually given this invitation to a high roller com And quite interestingly it actually works as an nfc field detector So if you don't want to use oscilloscope for whatever reason You can actually Use this invitation that you can get here at defcom If placed properly This will light up the led here whenever it sees the nfc field And then by just pressing this button You'll see that the nfc field will stop I'm not going to the high roller com by the way. I have other plans. So But anyway, thanks. I like this The other side channel possibilities are detecting power consumption that however requires soldering Which we have done here but You can also do it on the canvas There are usually messages that appear periodically so you can detect the time difference in between the periodic messages And the easiest way is when you find an ecu that actually sends a specific message on a reset That's the easiest way how to detect a reset There is a Fuzzer published for that as well It's actually not published yet because I haven't clicked the button to publish it, but it will be right after this call And now I'd like to discuss who's affected by this issue It could be basically anyone who just blindly accepts the value of this dlc field in some memory copy operations We also looked at the popular sdk sanart us's and found that armabatos stm32 cube sdk and nxp msu expresso sdk They don't really care and they will send you any value in the dlc field that you sent to it We reported this to all of them. So as of now, this should have been fixed But there are other frameworks some of them commercial. We haven't really looked at so those might be still vulnerable We looked also at the default linux kernel drivers, which are not Vulnerable so those will never ever pass you anything higher than eight in the dlc field if you're working with it And now is the good time to look at other canbus versions So can fd is not affected by the nature of it because The data payload was increased to 64 bytes But the dlc field stayed at four bits and there is a with weird translation table where you translate into those four bits How many bytes follow? Can excel is likely not affected I would like to wait with any judgments here because I haven't seen any real implementation of it anywhere But based on the specification it should not be Finally, I'd like to have some general takeaways from this So first of all, if you're a developer regardless of the protocol you work with You should consider the metadata of it to as untrusted not just the data it arrives over it It is also good to know how the libraries you're actually working with are handling values such as length of incoming data for that matter And if you're in the assessment side such as me, I would like to suggest that it's always worth looking one layer below the obvious Application data into the protocol world because there may be some interesting vulnerabilities in there as well With that, I'd like to thank you for your attention and ask if you have any questions I'll try to stand and adjust this microphone again The high roller invitation. Although. I'm not sure if it's invitation. I can give it to someone if they want I have enough things that the tech nfc field at home There is a microphone over there so that everyone can hear Have you tried to increase the f value to read more memory and see what happens or try to over I'm sorry. I haven't heard Could you come just here? This microphone seems to work a bit better You have a stage time So the question was whether I tried to increase the f value in the dlc Uh, I can't because there are just four bits And if I set all four bits to one it is up to f I'd love to have more than f but I can't actually in can excel the dlc field is 11 which can fit up to 2047 But then the specification says you can have up to 2048 bytes of data And I don't know how is that gonna work But I'll wait for the implementation and then I'll head crap out of it I guess that's all so thank you and have a nice day