Robert does not need an introduction, but he wants me to give you one because he loves to hear other people talk about him. So, Robert taught me how to hack a Cadillac CTS back in the day. I think, what was it? Or you showed me how to allow the DVD to show video while you're driving. Yeah, while in motion. You need to. Yes, that is very important. And that was a very big learning curve for me. Of course, I was a big dummy, so I forgot the termination and on and on. Everything. So, Robert is going to give his wonderful talk. CMAP. Yes, that's right. CMAP on your... and you've got a repo for this, which we'll put... I know you've already posted it, but I will... We'll link it to things. Yeah, we'll put it into the... and this is track one, correct? Yes. So, any Q&A, normally we've been answering that in the track in text, but this one, we'll try to monitor track one text and we will get those questions to Robert at the end, okay? It's all you, man. Thank you. There we go. Welcome back. Do you want to kill that music? In the stream? It's coming from the Discord channel. Thank you, Discord. Thank you. There. There it goes. We got this. You can see why we didn't do any of the live talks. For this exact reason. All right. Hello, everyone. My name is Robert Leally, also known as Carfucker. And I would like to talk a little bit about a tool that will help you analyze or check what services are available on a particular vehicle. So, I'm currently connected to a vehicle. Specifically, we have a truck over here. It's the same truck that we're using for the challenges inside of the DEF CON CHV truck. So, after I'm done with this, you guys can go get the repo right from GitHub. So, just go to GitHub.com canbushack and you'll find CMAP there. Canbushack is one word. C-A-N-B-U-S-H-A-C-K. And you'll find the CMAP repo that lives there. The concept is pretty simple, but kind of basic as well. So, I'm going to take you through sort of a very deep dive into CMAP, how it works. Again, this is live. So, if it fails, sorry. I'll sort of talk about the concepts. I don't have any slides. Like I said, pretty lazy. But the concepts are really simple. So, you're just going to go in. You run this thing. Connect it to a CAN bus. Right now, I'm currently using a Raspberry Pi. Maybe I'll take a second to break out and show you what the Raspberry Pi looks like. Do like a live feed over there. It's connected to a Raspberry Pi, which has got a device that essentially enumerates a CAN0 network. So, CAN0 is socket CAN. On this one, actually, we are on CAN2. We're going to be on CAN2, not CAN0. So, let me just break this real quick. If I can. If not, I'll get another terminal window open. I might just have to grab another terminal window. Because, you know. Bad idea. Okay. Now my whole screen is frozen. Nothing wrong with that. Sorry, guys. This is why we do it. So, my computer is not happy with this scenario. Real quick. Oh, my goodness. This is why we didn't do any live talks, by the way. I apologize. I cannot get my computer to close this window. It's completely frozen, my computer. So, just one second. Now you guys are missing the real DEF CON experience. It was working great, just two seconds ago. So, how's your guys' day so far? Everything's going well? Alright, good. I'm going to take a picture of these screens so everybody can kind of see what's happening over here. I don't know if you guys got a chance to see this. But it's pretty crazy. I'll show you. Wow, my computer is totally stuck. This is awesome. This is what's happening over there. It's pretty exciting. Right now, my computer is totally frozen. So, I've got nothing. Quite literally. It's done. I can't even terminate a window right now. This is insane. I've never seen this before. This is the first time. I just posted a link to your repo on this holiday. Yeah, no. You know what? We might just try it again in a second. Because everybody... It's quite literally just absolutely frozen. Even my task manager is locked out. This is why we didn't do any logins. So, anybody have any questions about how this works? I'll give it another couple minutes before we bomb out completely. Are you done? I'm better. I need to plug that in anyways. Oh, in the office. It's just next to where I was sitting. It's just a battery charger. Battery charger, okay. I'll be back. Alright, looks like we're back. And I will just close these windows down. I apologize for that. And it's locked. Okay, so. Alright, so I'm going to restart. So, hello everyone. My name is Robert Ali. We're going to edit that out, I'm sure, later. So, if you guys are just joining us, I just had some computer problems. I'm going to go ahead and talk about CMAP, my new car mapping tool. And I'm just going to kind of give you a deep dive of how it works. What we're doing with it. What the goal of it is, as well. So, I guess this is PyCharm. I have PyCharm loaded. And actually, I have the actual code itself. So, if you're going to use this for the first time, there's some configurations that need to happen. I've documented it a little bit on how it works. But ultimately, the concept is pretty simple. We're just going to send CAN bus messages out to different controllers to see if they're there. Just kind of like a ping. So, this is like a ping. Also, with a service mapping tool, as well. So, the first thing that we're going to do. So, I'm going to go ahead and go online. And in debug mode. And you'll notice, as soon as it does that, it kind of goes into debug mode. I'll show you the console. And here we are. The first thing we're going to do is we're going to create a CAN bus object. So, this CAN bus object essentially tells me what CAN bus I want to connect to. So, I can give it different object instantiations. Maybe I'm not going to be working with CAN0. But maybe I'm going to be working with other ones. Sorry, I've got to plug my laptop in. I can plug it in for you while you're talking. I appreciate that. Thank you. So, after you connect to CAN bus and it gets onto the network using CAN0 or whatever CAN interface you are going to want to search. Maybe you can enumerate through multiple searches. That's kind of up to you. So, this first program here is called scan with class. So, we're going to scan the network. But this particular file is meant as an example for you to sort of create your own applications in Python using this program. So, first thing we do, we create a CAN0. And now CAN0 can do a lot of things. So, CAN0 is essentially a network using the network CAN bus class. And that particular class has a method called scan for IDs. So, scan for IDs takes a few arguments. And so, we'll go through those different arguments here. One is the actual service identifier that we want to use to do our scan. On a lot of different vehicles, you might have more success with different service IDs. I have defaulted it to service 3E, which is something called tester present. In theory, tester present shouldn't do any effects. It shouldn't have any effects on the vehicle. It shouldn't start the vehicle. It shouldn't turn on lights. It shouldn't do anything weird on the particular vehicle itself. But sometimes certain controllers don't respond to it. So, you might want to use a different service ID. Maybe service 10 for initiate diagnostics or something like that. So, there's a lot of different services you could use. You could just use 0. Whatever you like. Maybe try different services to see what service IDs work better. It's a single byte identifier. If you put something larger than a single byte, it'll just bring it back down to a single byte. So, just put in a single byte. The next thing we have is the arbitration ID. So, this is the actual identifier, 11-bit identifier that we're going to start at. Since it's 11 bits, we can put any number between 0 and 7FF here. Since this is a start one, we probably want to start it with a low number. But you can start it with a high number and put a low number before. It doesn't matter. It'll just go in the order that you decide to. So, if you put a number like 7FF and you put 0 as the end address, then it'll just decrement as opposed to increment. And I'll show you that later. So, you can go in whatever order you like. Sometimes, when I do my scans, I often do decrement because you'll find more things in the top area, like 700s, 600s, as opposed to the bottom area. So, you're probably going to have more success decrementing. But it's up to you, whatever order you want to go in. So, there's the start arbitration ID and the end arbitration ID. I just accidentally skipped over one. It's called try twice. I'm going to get into what try twice is in a little bit. And then, we'll also prompt wait time. I'll get into some of these other parameters in a little bit when we hit them. So, let's go ahead. So, now we're in that particular method, specifically scan for IDs. So, we just passed it a bunch of variables. There are some others that we didn't pass that are just leaving as the default. And I'll talk about those when we hit them. So, as we go through, we're going to import the CAN bus Python. So, these are some of the prerequisites you'll see when you get to the GitHub. One is CAN. Logging is something that's usually included. And time is something that's usually included. But you do need something called Python-CAN in order for you to... you do a pip install in order for you to run this. So, that's important as well. Oops, what just happened? You know, always something. Isn't it? Frozen bootstrap, I'm not sure. Oops, I hit the wrong button. Hopefully. Of course. Let me just restart the debugger real quick. Sitting too long on something. I think it probably crashed. Okay. So, here we are. So, now here's our input timeout that we're going to use a little bit later. I'm going to initialize something called common pairs. I won't get into too much. I'm just going to go through the more interesting things such as this. So, the first thing I'll do with CMAP is I'll listen to the bus. The reason why I do that, there's two reasons. One, if you have a non-active bus that maybe you have a misconfiguration with how you connect it to the vehicle network, I want you to at least be aware of it. Maybe there's no traffic on it. In fact, that's what we're going to see here on our particular vehicle is there's no traffic on that particular bus. But it's not because the vehicle's off or there's no traffic. There's just no traffic normally. The reason why is we have a gateway. A lot of these vehicles nowadays, especially if we're connecting to the OBD2 port, have a gateway. And this particular vehicle does. But don't let that discourage you. We're using diagnostics and these diagnostic ports are intended for that. So all of this stuff will still pass quite nicely through a diagnostic connector. So even if there is a gateway, it shouldn't matter. Now, it might matter a little bit. Some gateways do filter some information as it's going across the back. So you might want to try it on the other side of a gateway too. But I just want to give you guys an example of, yeah, you can actually do this on what's called the dirty side of a gateway if you want to. So I'm going to initiate a time thing. And then essentially what this will do is it'll sit there and listen to the bus. And if there is no traffic, it'll just warn you, hey, do you really want to continue or not? And if there is traffic, it'll create a list of IDs for later. The reason why we want to know those IDs of what is on the bus is because we want to essentially avoid those identifiers later when we're actually transmitting requests. To scan the bus because those identifiers are not the identifiers we want. You can almost say that any traffic that's normally on the bus is not something you want to transmit on. In fact, if we do transmit on it, that can cause problems. You get lights and other things coming up on your dash. That's something we're going to try to avoid. So just be aware that we do intentionally filter out normal traffic. If you don't want to do that, you can modify this particular class to skip this step if you'd like to. You don't have to do this particular thing. But I think it saves a lot of time and it avoids a lot of accidentally overriding messages that we know are not part of our scan. So that's what I'm going to do here. And after about two seconds or so, I have this sort of timeout after two seconds. It says, hey, I wasn't able to... you'll see that my normal message length is actually going to be at zero. So this is going to say, okay, for sure we need to just sort of warn the user. And that's what we're going to see here, that there was a problem. I'm going to go ahead and just jump past that. So to warn the user, would you like to continue? I gave a little command prompt and I have a timeout in there. It's about two seconds or so. Okay, cool. Let's move on. So what's our message length? Here we have a message length and just some other initialization that's happening of our payload that we're going to send out, etc. I won't get in too much, but here we'll go down to the pairs list. And we initialize everything. And then, of course, if the bus is quiet, one of the challenges with the Python CAN interface is if we're going to listen to the bus and it was quiet, it doesn't let us just sort of timeout. It's got a kind of a weird bug. So in order to get around that bug, I actually do create some noise on the network just to... I have to create some CAN messages just to allow me to receive CAN messages. It's kind of a weird bug that I found. I haven't found a way around. So if anybody knows a way around it, I'd like to hear it. I create some noise here on the CAN bus just so we can get around that. Let's just take a look at the CAN bus real quick here. Go into the device. And so we should be able to do a CAN dump on CAN 0. And there's our noise that's going across real quick. Essentially I'm sending 7FF with a very specific payload that I've initialized earlier. So there's our noise. I just want you to know it's there. I'm actually going to get rid of the noise when we do monitor this CAN bus later. I don't want to see it, so I'll actually just tell it to remove the noise. And you can do that by just creating a negative filter or a not filter. Just a comma 7FF tilde 7FF. And now anything that has the identifier 7FF will be gone. So there we have... Now if I was monitoring the CAN bus, we shouldn't see anything. Now it looks like some people are doing some scans. Again, this is a live network right now. So if anybody's on the network, they will actually be able to see it because people are currently hacking this bus as we speak. So it's kind of cool to see other people working on it as we are as well. And they're going to love us in a little bit. So what I'm going to do is I'm going to send a bunch of CAN IDs. So I have essentially our low range, our low number, our high number, and the direction that we're going to scan. So plus 1, negative 1. Essentially I can skip over IDs if I would like to here, but it's kind of up to me. So here we're going to go and we're going to set this up. All right, here's our arbitration ID. Is it part of our normal messages that we had before? In other words, do I need to skip this ID or not? Because if we were monitoring the CAN bus earlier and we noticed, hey, ID 222 is on the bus and I'm about to send 222, I'll skip over that one. That way we don't have to collide with those particular messages. So it's sort of an anti-collision way of doing it. Now since we didn't have any normal messages on the bus, our normal mode message is gone. It's empty, which is cool. So we'll move on to the next step. In this case, we're going to set up our CAN frame, initialize some things, and then we'll do this thing where we check how many tries or set the amount of tries that we want each time to run. So I'll take a look. Let's take a look real quick at what that means. One of the challenges, especially if we're doing this on a busy and active bus, we're going to send out a command and then we're going to listen for some period of time for responses. Now what is a response? It's just another message. So all of these messages that might be going on on the bus at that particular time could all be replies. So how do we differentiate them? Well, number one, we have this normal message list that we listen to and we can say, hey, is this in the message list or not? The other thing we can do is we can try it multiple times. And if we get the same ID two times, the probability is much greater that this is actually a reply to our message. So I have this ability. I built in this thing so you can actually have it either send it one time or two times. Since this is a quiet bus, we really don't need to do that. Send multiple tries. And again, if you send multiple tries, you're going to send it twice, which means it's going to take twice as long to do a scan. So if you can limit the amount of tries, that's good. So here we are. We set our tries to one, so it's only going to try it one time. I have some logging here. Here we are recreating our CAN bus. And I have a time here. So I want to sort of stop here because this is super time dependent and just go over what I'm about to do. What I'm going to do here at this particular step is I'm going to send this message that I created earlier. If you want to take a look, this message is pretty simple. It's got the identifier 442, so that's where we start. It's got the data bytes 023E, and then the rest are zero. The reason why we're sending zeros is because we need to make sure we pad this data. So essentially, remember I said service 3E is the thing that I'm going to send out? That's in the data bytes themselves. You see it's the second data byte there. So there we are. We're going to send 023E out onto the bus. And if I bring this over, eventually we'll see that come across. So I'm going to do that in just a second. And then what we're going to do is we're going to say, all right, I sent out a request. Then we're going to wait on that particular bus. We're going to wait for a receive message. And that's the reason why I have some noise there, because we have to generate some messages so that our clock or our timing essentially works. So we're going to wait for a receive message, and then we're going to take a look and inspect that receive message. We're going to filter it out. A few things. Is that a receive message that we've already seen before? All right. Well, I don't want to see that anymore. That's not the message that I was looking for. I'm looking for new identifiers, not old identifiers. So in other words, I'm sending out a request. I should not see this identifier or should not have seen it in the past before. So I'm looking for new IDs. Is this ID the same ID that I just sent out? Maybe I just was listening to my own data bus, and I saw an ID that I just sent out. So I don't know. That's not what I want. If I'm sending noise, is this the noise identifier payload that I just sent out? If it is, ignore that as well. Or is this ID got a DLC that's... One of the challenges with SocketCAN is that the way it displays error frames is using ID 000 with a DLC of 4, which is just kind of a dead giveaway that this is an error frame. It's really the only way to know if it's an error frame. So is this also an error frame? Is this an error noise on the bus as well? So I'm filtering out all those other things. And then what we're left with should be, if it passes all of those because they're not true, then we should say, OK, that is indeed a successful arbitration ID. And so we will append our list right here. So let me go ahead and just run this real quick. And then I'll show you what it kind of looks like on the bus as we're going across. So there it is running. Oops. We caught our first one. That's not a coincidence. It started there. So we caught our first identifier right there. Just a second. Oops. Try a second. How do I get rid of that one? No, we haven't caught one yet, but we'll catch one real soon. Let me get rid of some of these breakpoints so we can just see it run. And there it goes. It's running. It's running. It's running. And then pretty soon we're going to get a message. Cool. So we got our first message. Actually, here, let me... Oops. Messed up over here. Let me... Zoom in here. So let me just sort of emphasize what just happened here. So here I sent out this CAN message, 47D. Didn't see anything come across. And the same for all these other ones before. But then I sent out CAN message 47E. Sent out the same message. And then what happened was I got a response. How do I know it was a response? Well, first of all, I've never seen this ID before. That was one reason. I didn't transmit this ID. This wasn't something that I transmitted. I know it's the next number here in this list. But also it's interesting to look at the data bytes. It's a little bit different. It's not a 3E here. It's a 7E. Now, I don't really care what the data bytes are. I could do some more data byte inspection. But for the most part, you don't really have to. You just need to see an identifier that you didn't send on the bus. If you did send it, then, well, you can ignore it. But if you didn't send it, in this case, I didn't send this. It's just something that I received. Oh, good. This is called a pair. So we add this to our pairs list. Now, I have two pairs lists. If I'm trying twice, I'll compare the two pairs lists. In this case, we're not trying twice. We just get the one pair list. So a pair is essentially these two identifiers. A pair is the identifier 47E and 47F. Those pairs are essentially how we can communicate directly with the controller. If we send the ID 47E, we'll get a response back on 47F. So this is kind of the channel, if you will. This is an RF thing. I kind of think about these as the same thing. This is the channel that we send out on, and it's a different channel that we receive on. It's the best way to look at that. And then the data bytes are right here. So anytime I send out a message on 47E, 47F will respond to me. So let's keep going. Let's keep going. Let's just do this. And I don't really care about hitting more pairs. I'm just going to let it go until we get a response. It should be going. Sorry. Okay. So it's going, and it's going to catch a few more. As you'll see. I just realized I need to open up another window. One second. So I'm just going to let it keep running. It'll eventually catch a few more. It's loading up our list, and I'm just letting it run. So just give me one second while I find something. Yeah. One part of debugging is there's no way to hit the escape or whatever. So I've got to do it kind of programmatically. It's an interesting problem that I have to do. So... Boo, boo, boo. Okay. All right. So we finished our scan. And what do we got here? So let's take a look at what happened. So what returns is our pairs list. So let me just open up our debugger. And we'll actually take a look at... We'll watch some of this data. So just one second while I scroll over. Take a look at my watch list. I'll have it open. Just one second while I move this around. Where are you variables? I had them open just two seconds ago. And I lost them. All right. Well, anyways, here's the pairs list. I was going to just open it up for you. But the easiest way to just... So here's the pairs list. Now, what we'll see here is actually... It's hard to tell. But these are all in decimal right now. But if we wanted to, we could see in hex. Sort of. Here's a pair. That's our first one that we grabbed. 47E, 47F. So there we have a pair. And then we have a few more here as well. And then you have one that actually has a bunch of different pairs in it. And the reason why we see something like this is you'll look that all of the different IDs are the same values across all of them. And the reason why is this is called... This particular identifier... So I'll show you here. 7DF has multiple different controllers that respond to it. It's called a functional request. So every time we send that particular type of request out, we get multiple responses back. So that's good to know about the functional request. So the functional request will have... The pair itself will be just a list of pairs, essentially. So that's why you'll notice that these lists are actually lists of lists. And most of the time, there's just a single pair inside of there. But in this case, there's multiple pairs. So now we've got a list of pairs. That's great. Now we can do something with that. We have a list. Basically, you do a ping. You check out and see all the different IP addresses that you've got on the network. Same thing. That's exactly what we just did. A scan is kind of a ping. We get a ping for all the different identifiers. And now we've got a list that we can do something with. So inside of this CAN0 has nodes. And those nodes are essentially the pair list that we had before. So now what we can do is just pull out the pairs inside of the pair node. So here we're going to go ahead and take apart that particular one. We're just going to grab the first pair. If it's a list of multiple pairs like we had that I just showed you, I'm just going to kind of ignore that. If you have a script and you want to do a little bit more with that, feel free to do that. And then I'll just go ahead and print it out so we can kind of see. Here it is, our 47E, 47F. Just let us know, hey, we're going to do some work with that particular pair. So let's take a look and see what we're doing next. So we're going to do another thing. Actually, I'm going to skip over the initiation of that particular one. And then go right to the actual method that is interesting for me. And that's the findServices method. Now we have the identifiers. Now what services can we do? So we've done the ping. Now let's do a port scan. That's kind of the best way to describe this. So findServices is going to do a port scan. It's going to see what services or functions the particular controller supports. So let's go ahead and run into that. And the first thing we're going to do is initialize a list of known services in case we want to filter on just known services. And that's kind of what I want to do in a little bit. So we have a few different options here. We can actually filter our list just to try to do a sweep of every single possible service identifier. Which is only 256 possible service identifiers. Or we can just skip service identifiers that are potentially valid. So half of the service identifiers are reserved for response only, not for transmit. So if you're going to get data back from the controller, half of them are reserved for that function as well. So we can say, hey, I just want to work on ones that are valid. Essentially skip the response-only service identifiers. Or we can skip and just scan the ones that are known. So we're just scanning known service identifiers as opposed to unknown ones. And so that's what I've initialized as true here. So we're going to use this list that we have right here. And that's the list of identifiers that we want to go over. Now depending on what type of service scan you want to do, maybe you want to do a more inclusive one. So you'll scan everything. Maybe you want to do a non-inclusive one like this where we just scan the UDS ID. So I give you like three different options. You can scan everything, a little bit of everything, or like half of everything, or just a small amount of everything. So it's just the amount of time you want to spend on doing that. It's kind of the trade-off. So if we've already done the scan once, hey, let's not do it again. Let's just return the container that we store all of the services that that particular node supports. In this case, we haven't done it yet, so that's good. So the other thing that we require is something called ISOTP. I think it's called CAN-ISOTP, if that's the module name. So we're going to have to use that one as well. So go ahead and take a look, try to find CAN-ISOTP on the internets so that you can use this as well. And I'll just keep going. ISOTP is great. ISOTP is essentially the diagnostic layer 2, if you will, the transport layer for CAN bus diagnostics. And it's awesome because there's already a thing for it. So let's go ahead and create the socket, set the padding options so that we can fill in the data bytes, bind that socket, and then we can say, all right, if the service ID is sort of like limit the service ID, so I'm going to skip over some of this stuff. It's pretty self-explanatory. Let's go right into the meat of the actual script. What is it actually doing? So we're going to create a range. So inside of this range, we have two service IDs that we set. One is the start service ID. Where do you want to begin? One is the end service ID. Where do you want to end? Again, if we apply some filters, it's going to skip over that. So typically what I'll say is if you want to grab a small amount, turn on a filter. But if you know there's just a service ID, maybe you want to target one or two service IDs, then you can limit your range to what service IDs you're going to go after. Again, service IDs are only one byte, so really there's only going to be 256 options here. So let's go ahead and see what we want to do. We just grabbed an identifier and a range. And we want to... so I'll look at zero. Hey, do I want to scan this zero ID or not? Since I have a filter turned on, scan only service IDs, I say yes. It's only going to scan a service ID that's in my list. In this case, zero isn't in my list. So it's just going to skip right over it. It's going to continue saying, no, I don't want to do that. So let's go to one where there actually is a service ID I'm interested in. So in this case, the service ID, the first one is going to be ID 16 decimal or 10 in hexadecimal. So service ID 10 is the first service of UDS, which is the session control service. So let's take a look and go through here. And we're going to add to it payload length, do some fun math here. And then we're going to go down to the actual loop. So we send our ID out. Let's see if I already sent it. I did. So here we go. We sent out a request. 10-0-0-0-3-10-0-0. And look, we got a response back. 0-3-7-F-10-12. So don't worry about what that means. I'll do all the parsing for you. Well, displaying for you. And I'll just sort of say, all right, since this is a 10-12, 12 is what's called the negative response code. This is an error frame. This is like error. Hey, you have a problem with your request. And here's the response. And 12 is the negative response code. And what it's trying to tell you is, hey, we have an issue with that request. And the particular issue in this case, 12, means that the sub-function, 0-0 in this case, is not supported. What we're trying to do with the service scan is not see if the sub-function is supported or not. We want to see if the service is supported. Because we're going to probe to see if the service is supported. So ultimately, 12 is a good thing. So we're going to go down here. And I'm going to go run. And we're going to take a look at how that logic works. Hey, we received something. We got an ID. We got a negative response code, which is 7F, which we saw here. And the service identifier here, 7F. I see negative response code. We're going to pull that out and say, hey, negative response code came back as 12 hex or 18 decimal. Is that equal to 11? Why 11? Well, 11 is actually the negative response code for a service not supported. That's specifically what it means. So since this is a service that is supported, I don't really want to have that in my supported... I don't want to have this in my not supported list. I want to have that in my supported list. So I'm going to create two lists here. Or two sets, I should say. Two sets that we can sort of just... Hey, there's our service ID. I'm going to add this supported one to it. Even though I got a negative response, that's not terminal. It just means that the sub-function that I request isn't supported. But the service itself is actually supported. So there we go. Our service is supported. And I added that to my list. I'm just going to go through all of them real quick. It doesn't take very long. And we're going to take a look and see what that kind of looks like here. So I'm going to get rid of some of these breakpoints. And there we go. We kind of got the entire list. That was really fast. So it doesn't take very long to go through that list. Maybe we already did it. Yeah, it went really fast. Sorry, you guys might not have caught it. But it didn't take very long. It went through the entire list really quickly. And we got a list of all of the services that were particularly supported on that particular one controller. Now we just went through one controller. And that's what we're going to do at a time. Single controller. And we're going to try... Now that we have that list, we're going to print it out and see what happens. So what are we going to do? We're going to print out a list of all of the different services that are supported. In this case, 22, 85, 27, 28, 2E, 10, 11, 14, 36, 34, 37, 19, 3E. Those are all the services that are supported. Now if you want a good list of what these functions mean, I actually have that as a enumerated... I have created an enumerated list for all the particular services and what they mean inside of this. So you can actually reference it. I forgot where I put it. So give me a second here while I dig it up. I think I called it... Yeah, it's under service. Makes sense. Good spot for it. And I collapsed it here. But yeah, I have a service description that you can run. And there's a method called update service description. And there's a property of every service. So if you want to, you can enumerate a list. And just read out the service description from each of these services as well. There's also a list inside of here which I've collapsed because it's so big. I don't know where I put it. But I won't go into too much detail. But it's in there in the code itself. Feel free to take a look if you want to see what those service identifiers mean. But we can take a look. And there's just a handful that are really unique and interesting that we'll probably want to scan later. So we'll go ahead and take one of the services. I think the first one we're going to take is actually service 22. Because that's our first on the list. Which is kind of a bummer because that's the biggest of all the services. But let's go ahead and take a look at what it is we're actually doing here. So I'm going to create a little report for you after it's done. A list of all of the different service functions that are there. And I just want to kind of send out the service and see what's happening. So give me a second while I run it. So the next method we're going to do is now we have a list of all the services that are supported. Let's enumerate all of the particular service sub-functions that are also in there. So the first thing we did was ping all of them. Next we did was check the services that are supported. Now we're going to actually ask it to say, hey, what sub-functions are actually supported? I'm going to run that real quick here. Just one second. I don't want to get in too much right now because we're running out of time. But this one's pretty cool. So let's take a look and see what it is it's doing here. So what it's doing is it's sending out a request. 0322 0091 0092 0093. You get the idea. It's just enumerating all possible identifiers or sub-functions for this particular service. In this case, this is a two bytes service, so it does it for you automatically. You don't have to tell it. That's part of the specification, how many bytes each particular service supports. So we're just going to enumerate through a list of all possible sub-functions that are supported. And eventually, when we're done, we're going to get a good list of all of the IDs that come through. Now, I did have a plan here on canceling this scan midway through so that we could get a list, but unfortunately, this particular service doesn't allow us to do that. So what I'm going to do is I'm going to go to a diff. I'm going to figure out how to exclude. Let me just think about how I can exclude a particular service ID. Maybe I can't. What I really want to do is, let me just look it up real quick while we hang it out. I'm going to check out the scan real quick. And I'm going to see what this particular... I need to issue a keyboard halt error. And that will break out of it. So, just one second, I'm going to... So there's a really cool utility called... Oops, sorry. Called psutil. So I opened up another Python window. We use psutil, which allows me to send a SIGINT to a process. So we need to do a SIGINT and then it's called process. And then the process ID, which is pit equals 9971.signal.signal. I think it's two. Network. Oops. Send signal, sorry. And what that did is, it did a keyboard halt. So it's a good way to do debugging. It's just essentially, I'd have a try, catch, try, not catch, but try command. So here it is. It tried to... It actually ended that particular scan. So that, just for demonstration purposes, I wanted to show you what kind of report we were able to get out of that. And there you can kind of see, here's a list of all the identifiers. This is service 22 on this particular node, 747F. I don't know what node that is in the vehicle yet. Maybe I can get that from doing my service scan. But here it is. We have a list of parameter IDs. So this is sort of a matrix of 00, 010, etc. And so as we scroll down, you can kind of see, hey, this is a service that has a negative response code of 31. So 31 means that the request that I sent is out of range. So I sent an ID 0000 to it, and it says it doesn't support that. But where it shines is we can actually see what is supported. In this case, 0108 is supported. So if I scroll down and keep scrolling, you'll eventually see that some of these services are indeed supported. So we create a cool map of the services that are actually supported. And here we have a longer list. We can kind of get an idea. And not only that, we see the services that are supported, but I also, after I'm done printing the report, I'll also print the actual data bytes that I received from the service itself. So in the case of 0001, I got these data bytes. This is a byte string that returned back to me. So I can get a byte string of the actual data itself. Maybe there's some interesting information that's stored inside of the byte string. What I can do later with this list is I can say, OK, now that I have a list, I can go back and just kind of recapture the data over and over and over again. And so that's the idea. That's what CMAV does. It gives you kind of a cool list. I'm going to keep it running. Oops. Keep it running so we can actually get some other sub-functions or services that might come up. Some of the other services are much faster, so I'll let them run real quick. Here's another one. And pretty quickly get rid of all our debug information. And I'll scroll down. Here's service 85 and all the different sub-functions it responded back to. So it might not be that interesting. Maybe we'll get a 12, which means sub-function not supported. But in some cases, we don't get a 12. We get a 7F, which is incorrect. We can do this function or the sub-function, but not in this particular service or session. So we have to change our session. And what sessions are available? Well, there's another report that's going to come up later on what sessions are supported. So we can keep scrolling through. And as we're running through all of these things, we can kind of say, hey, look, service 28, what's unique about all of them? Or what's not unique about them? So here we are. We're continuing to run. We're on service 2E right now. Same with service 22. 2E is a very long one, so I'll issue another reset command as well. So we'll kind of speed this up a little bit, but you don't have to reset every time. Here we are. Oh, sometimes it'll get a little stopped up here. This is kind of a bug that I know I'm going to try to fix in the next revision. But if I don't get a response back from a particular controller, it sits there and waits for this 5 or 10 second timeout. And I really should just limit the timeout. I thought I was doing it, but it's not working right now. So this is something that is a known bug, but sometimes we'll get these no responses. And this is actually a correct no response. It shouldn't respond back to us. That particular one doesn't. So we'll wait for it. There it is. There's our service 10. It responds back that it supports these particular sub-functions. So I was just talking about modes before. There are actually three modes that it supports. 10.01, 10.02, and 10.03. It supports all three of them. You'll notice that this is negative response code 12, which means it doesn't support it. But in this case, it does support. Service 10.01 is supported. 10.02 is also supported, but it has a negative response code of 33, which means that you need security access first in order to do this one. So as a security researcher, you may be really interested, why do I need security access to do a 10.02? If you do a little bit more digging on this particular service or sub-function, this is the reprogramming mode. So it wants you to do security access in order to reflash the controller. This is actually very unusual. Most cars don't require this. But it's something that's new for these particular vehicles. Service 11 is an ECU reset service. If this had succeeded, we would have had some issues probably through here. The controller would have reset and taken a very long time. Don't know why these all fail. Maybe it doesn't have a sub-function, and that might be why. Service 14, similarly, quite interesting. Service 34, all of these need to be in a different sub-function. So we get a lot of really cool information just from the get-go of what may or may not be supported on these particular controllers. Including what is supported and what gives us a little bit of an empty spot. It means I didn't get a response back, so I don't know what to tell you. It's empty. So you get a lot of really cool information. If you run these for a very long time across all the different controllers, you're going to get a ton of information from the particular vehicle. And then maybe you can save it and do something. So I finished with one controller, and now I would move to the next one. So that's essentially what this is telling me it wants to do, is go to the next controller, etc., etc., and find all the services and sub-functions on that. So I'm going to do that real quick. We're kind of running out of time, but I'd like to try to see what else we can get out of it. There it is, trying to get data from these controllers. Scroll down... it's really quite interesting. Now it's scanning this ID 620, and it has a response of 504. 19, 22, and 3E are all supported. So this one only has three functions that are supported. Again, I'm running through a gateway. My thought process here is maybe if I get past the gateway, I'll actually have some more information that's available on the other side of the gateway, which I do have this connected, I just haven't done that yet. We have five minutes left, or ten minutes left, because I can't count. I think this is a good time to stop. I think I am giving you guys the information, but hopefully it's enough for you guys to go. Again, let me just type in the web page right here. www.github.com I'm typing in something else. Canvas at... There it is. It opened an edge. You're welcome. I'll fix it. You get the idea. It's awesome. Thanks, Microsoft. That's what I want. And then CMAP is right here. So CMAP, essentially, you can go ahead and get this code that I just showed you guys today. I'm sure I'll be pushing some updates. Give me my first pull request. Somebody, right now, first pull request gets free CMAP. And if you guys have any other questions, I'll be around all day. Just hit me up on the Twitter at C-A-R-F-U-C-A-R. If you want to do your own Canvas hacking or anything like that, I highly encourage you to get to the virtual.carhackingvillage.com. This car that I just showed you, it is on there. Everything I've just shown you is on there. You can put CMAP on there if you'd like to right now and run these right now on the same vehicle that I just ran this on. And if you have some questions, regardless of that, we'll be available to give you some hands. Alright, if there's anything else, any questions from the field? I've not seen anything. Maybe there wasn't anybody because of the initial start that we had. Yeah, this is horrible. For some reason, I was... A lot? Like two? Or three? Thirty! Hey, you over there. Yeah, you. How come you're not asking me a question? No, that. Over there. Yeah, you. Alright, maybe they don't have any questions. Yeah, I've seen no questions in the chat. That's fine. I guess I'm just that good at presenting. Or the opposite. Linted is telling me. Hey, Linted. Oh no, not Linted. Linted wants to know. He's got a technical question. Robert, what's wrong with the cars right now? Talk about... Talk about hardware checkout. Alright. I think you have to... Is Discord stream muted or is that just me? That's his question. So... You gotta go on Twitch, man. That's all there is to it. Alright, cool. Thank you.