 So, I'm going to be talking to you about, uh, Raid Air 2. It has a lot of pronunciations. Uh, people tell me that I'm probably saying it wrong. I'm just going to keep saying Raid Air 2. I'm sorry, that's what I'm going to do. It's going to be about 25 minutes. I'm talking about OpenXC, which is, uh, Ford's platform for moving canned messages over Bluetooth, uh, to like mobile apps, and it's kind of neat. Because OpenXC is open source, we can actually look at the firmware and kind of skip a lot of the discovery parts and just focus on reverse engineering with Raid Air. So it's really, it's going to be a whole bunch of command line stuff. The talk is kind of in the Gen 2 quadrant. There's going to be just a lot of commands and, you know, I'll have the slides up. You can refer to the commands later. I'll try to describe what I'm doing too, but it's, it's not going to be in Buntu style. It's going to be kind of like just fly, you know, go. So, we'll see. Well, first up, OpenXC, you know, uh, this is a cool platform that kind of takes canned messages and translates them into message pack format, which is like JSON, and it lets you build these mobile apps for iOS recently, for Android. It's actively developed. Um, it's, it's pretty fun. I recommend you go check it out. They give you hardware platforms and the software development. Uh, so you can do some cool stuff with it. Raid Air. So, uh, Raid Air 2 is like this reverse engineering suite of tools. There's a whole bunch of command line utilities you can use, like RA Band and RA Hash. I'm going to be talking almost exclusively about R2, which is like the reverse engineering part of it. So, I'll show you a little bit of Raid Air. Uh, I really wanted to do everything like command line style. Um, but this is actually my backup deck because the command line stuff just didn't work. But I'm going to do this style of like here's a fake command prompt and I'm going to kind of scroll down. So, a Raid Air session, you might open up a file. It's like an L file from binary samples. And then you want to analyze it. So, A, A. Every command in Raid Air starts with like hierarchical letters. So, A is for analysis commands and AA is just like do the basic analysis. Okay, it says great. I looked at all the flags and I found some stuff. Thanks. Uh, S is for seek. So, I'm going to like seek to the function called main. There I did it. And then more analysis commands, AX is for listing cross references. So, here I'm just listing all the cross references that happen to be referring to main and you can see that the analysis actually completed because of a whole bunch of cross references. This is great. And this is usually the experience you get with Raid Air, especially on like L files and PE files and stuff. It's really great at finding all that metadata in the symbol table and then helping you kind of walk your way through the binary. Now, when you're dealing with a raw firmware file, just like a bin file, you don't actually get all those nice symbol exports, right? So, you can open it up in Raid Air. You can ask it into the analysis. It'll say, great, I analyze zero things for you because I don't know where main is, right? There's nothing there. There's no metadata. So, you have to actually kind of teach Raid Air about where the file goes, do some searching for functions. And first Easter egg, Raid Air has Clippy. Clippy is installed. So, you can actually get Clippy to tell you things if you want a little bit of help. He likes to help. Raid Air also does really great control flow graph visualizations in the terminal. So, this is actually like text mode using UTF-8 lines and all the disassembly for every disassembly flavor that it supports, it'll do this kind of control flow layout which is gorgeous. It's VV to get there. I'm not going to be showing you disassembly because this talk is really about extracting data. So, we're going to be looking at how to pretty print canned signal information inside OpenXC. So, not disassembly, more like data stuff. But if you want to just have great control flow graphs for free, check out Raid Air. It's great. Okay. It's going to be a lot of commands. I put together this summary of all the commands that I'm going to use. I will also show this slide at the end. So, you know, you'll have lots of time to take pictures for it. It'll probably be in a PDF somewhere as well. You can see that the commands are all really hierarchical, right? All the analysis commands start with A. All the printing commands start with P. Information for the binary starts with I. And then there's two different things. And the most important one is really the question mark. You can use question mark as a post fix. And if you put it at the end of any letter, basically, it'll tell you what that letter is as a command. And the help in, the help information in the command line for Raid Air 2 is really great. So, if you know that to put question mark at the end, you can actually walk your way through Raid Air pretty well. The other thing is question mark first is more like an echo command. So, you can, question mark E will echo like actual echo command line, the normal stuff. Question mark V shows you like hexadecimal values. Question mark capital E shows you clippy. We saw that already. So, to recap, just to make sure we know what we're talking about, OpenXC takes these JSON files as part of its build and turns them into these CAN signal structures. Okay? And what we're going to do is go through the Raid Air commands necessary to actually go backwards and get the information out of the CAN signal structures that are in the firmware. They're going to kind of reverse that arrow. This is reverse engineering, right? Okay. This isn't the first time OpenXC has been reversed. I've given some talks about doing this with Ida Pro. Ida Pro is very expensive. And this is now free. I run the same time I did the SANS talk. Someone who had to handle BSMT put out a blog post detailing how to do the steps with some Ida Pro Python scripts. So, BSMT's blog has like a fully automated way to do this using Ida Pro, which is kind of cool. Also, you know, I'm not the person who invented firmware reverse engineering. I'm totally standing on the shoulders of giants. And there are many. I really appreciate the help of Craig Hefner and his blog post. I recommend all of his work. And then finally, I didn't invent Raid Air. You know, that's done by Trufey or Pancake, Pancake Knop Code. He actually has a talk here, this YouTube link, where he takes the MD380, the Titerra radios, and he reverses the arm firmware in the Titerra radio. It's a firmware blob. It's using a lot of the same techniques. So, I'm really building on all this previous work here, okay? We don't have a whole lot of time. So, I'm really just going to do the yellow stuff, right? I'm going to assume, okay, we already know that we've got the firmware in our hand. You know, that's always a hard step with the device you just got, maybe getting the firmware. We already know the architecture. We already know the load address. We're just going to assume that stuff. And we're going to go to this yellow stuff, load it into R2. We're going to assume that we figured out where the loader loop is, you know, where the C runtime stuff does the copying. And we'll just do a copy for ourselves. And then we'll do the pretty printing of the structures. Okay. So, first up, we want to load this thing. So, we already know because we're smart and we did some reverse engineering already that the thing can get loaded at hex 10,000. Alright? If you wanted to do this in a one-off R2 command, you can do that with the dash M, as I'm showing here, M for the mapped address, hex 10,000. The architecture, which is A dash A is arm. The size, like the bit width, is 16 for thumb. And this is a bit of a weird round hole, or a square peg and a round hole, because thumb isn't necessarily 60-bit addressing. And that'll actually bite us when we're doing data printing. But you have to say B16 to get it to disassemble the thumb. And then you just give it the file. And this is the file that I got from the open source build of a VI firmware from OpenXC. Okay? Now, we don't necessarily want to just do the command line version of this, because we're going to keep adding stuff in. It's kind of like when you build a Project NIDA Pro, you have like an IDB, right? Rather than work with an IDB, we're going to have this like config file for RAID Air, and we're going to keep building in little commands. So, instead of that one line command, we're going to start with like this R2 script file, and I'm going to set the architecture, it's ASM arc, ASM CPU, ASM bits. So, this E command is setting config values. And under the hood, when you do those command line switches for dash A and dash B, that's really what's happening is just setting these config values. Okay? So, then I'm going to say, okay, the bin address is hex 10,000. I'm going to call something flash, the F flash. So, F is the flag command. In RAID Air, you can name any address by just calling it a flag. So, F flash is hex 10,000. And then O is for open files. So, O-N, I'm mapping a new file, the VI firmware file, at the address flash, which I just called 10,000. Okay? And then I'm setting this thing VA. With RAID Air, it knows the difference between file addresses and virtual memory addresses. And now that I've mapped the file, we need to tell RAID Air to switch into that virtual address space because I've just mapped it. Right? So, now I'm going to start referring to things by hex 10,000 instead of zero. Zero would be the file offset. Hex 10,000 is the virtual offset. Right? So, I'm going to switch to VA. And then lastly, the capital S, I'm adding a section. So, I'm creating a section for the flash, giving it executable bits. And dollar S is the size of the file. And that's the kind of RAID Air magic that you just kind of get used to. And you write this once in the config file and then you just kind of move on. Right? Okay. So, what else we got to do? We know that there's a loader loop in this firmware. Loader loops are for C runtime. You know, it takes like your segment that's packed up into the binary file and puts it into the writable data segment, for example. That's what we're going to do here. We're going to emulate that. We know that it does a copy from 32EBC up to this million C8 hex address. And we know the length. So, we're going to define data as this million C8. And then we're going to go and make another section. And this time you'll notice that the offset is different, right? Because the sections when you make them, they refer to the file offset. So, I'm doing it, I'm making the section start from 22, not 32. But it'll be mapped at 32 because that's the map address. Right? And then the last command, now everything set up, we actually know enough to use radars like search for preludes. You know, like push, you know, every time you start a function, it's always the same little push and set up of the stack. And radar knows how to search for that. So, you can go AAP. It'll search through all the code sections that you define and it'll define functions that it recognizes as preludes. And that's a really great command for raw binaries. So, at this point we've mapped the code. And we have search for preludes. And PowerPoint crashed? I don't know. Let's try again. We might have to drink. Let's see. Okay. Can you see that? Oh, good. And it crashed again. This is great. I should have made backup backup strats. That's what I really needed. Okay. Right. So, we have everything kind of mapped I'm going to try to present. No, I'm not going to present this like it's just going to crash again. We have everything mapped. Okay. But you can see here when I'm showing you, when you just kind of dump the memory, you're not seeing, for instance, that there's a string defined here. Like if it found the string, it would say str.signal1. It had identified the string. Radar would have. And when you do the disassembly, like right here, instead of seeing disassembly of op codes, you actually see that it was data, right? Like if you use Ida Pro before, there's a difference between saying it's code or saying it's a quad D word, right? What we want to see here to actually look at the data structures is turn this stuff into data. So it's not enough that we've mapped it. We have to actually somehow massage the information to get it together. So in this slide, which I'm sure won't crash PowerPoint, good. I'm showing you that you can ask Radar what it knows about strings. So here I'm saying, hey, Radar, IZ, what strings do you know? And it says nothing, nothing at all. But you can ask Radar to search through the entire file and just do like a string match just like, you know, GNU strings does. And it says I know all these strings. But if you look at the addresses they're all in 22, right? They're not in the data segment that we created. They're in the wrong base offset. So the problem we have now is we have to actually take all those strings and map them where we want them to go. Probably with a patch to radar, you could fix this because IZ should do all data segments. But when you make a data segment, it doesn't recognize it. It only sees it when it comes from an L file. So this happens a lot when you're using radar. And this solution is always just script it, right? So I like Python. You could script it with Ruby. I know that there's like, you know, choices like VIE max Ruby Python. But R2 pipe lets you script radar. Very simple Python script. I'm looking at the output of IIZ. And then I'm just adding that hex 10,000 to the base so that I can redefine all the strings, right? So then when I'm done that they're all redefined. All right, we need to groom the data to you, right? Because we know that when we looked at that data section in memory, we saw disassembly. We didn't see quad words. Craig Heffner wrote a really nice script for Ida Pro called codatify. When you're looking at firmware files, it's really useful to use this because it just kind of like grooms the entire data segment and makes everything a quad word. So it's everything to an offset type. And then what you get is like nice aligned data that automatically has cross references. So when you just start looking at x refs and start looking at data segments, it just starts popping out at you. With radar, you don't get that automatically, but we can script it, right? And what we're doing here is just walking the entire area of that data segment we created defining everything as a quad word and then creating a data reference of the value of that quad word. So you might be left with a bunch of false positives, but it's better to have a bunch of false positives than have none of the cross references at all. Okay. So here's a look at what our like project file is now. You can see we have the data segment. All the stuff we did before is in gray and I'm highlighting in white how you actually execute those Python scripts. So radar has this weird has the shebang idiom, right? So you go hash bang or exclamation point Python to run my Python script and then I give it the two arguments. I'm just all I'm doing my project file now includes those two scripts that we defined. Now I know we look at a lot of strings and text and stuff so I just wanted to give you a funny picture. Take a break, but there will be more commands. Okay. More commands. So we're loading stage three. Everything is all set. We know from our previous research that can signals the whole array starts at this particular address. Just let's assume that you can figure it out by looking at the cross refs. If we go to that point and we say, hey, radar, what cross refs are there? It says, okay, good. Now we have cross refs. See code datify went, set everything as a quad word and made data cross refs. And there's the proof we actually have our data cross references. And if we disassemble that location, we don't see disassembly, we now see nice quad word statements, which is kind of like what you'd see in Ida Pro after you set everything to the data type, right? This helps us like inspect the data better. Lastly, there's this really nice command called PXR. It does telescoping. So if anyone uses like Ponebug or any of those GDB add-ons, telescoping is where you take like the value on your stack and you just keep treating it like a pointer until you can't treat it like a pointer anymore. So you get this view of memory as a telescopes, right? And PXR does that for you automatically. So you can see PXR is telling us, yep, this particular address is pointing to something in data and that's pointing to something in data. Good, that's all set. And we can see that we actually are referring to a string signal one. And it's actually starting to map to that structure really well, right? What we would really love to be able to do is say, okay, if this signal is called tire pressure, what can message is that in? Right? That's kind of like what we would like to know, right? If you had some vehicle and you wanted to figure out where's the tire pressure signal, that's what you'd like to know. And this kind of telescoping isn't telling us enough. We want to go backwards to get all that mapping information. Okay. What we really want is types, right? Radar actually knows how to parse header files and how to pretty print types. So we could eventually tell it, hey, you know, we know this is a printer, a pointer to can message. And we know that this is a pointer to a string. Can you just pretty print that for me so I can see the ID in the string right next to each other? The answer is, yes, you can. The first problem you run into is if you rent load a raw binary file, you don't get any basic types, right? So here I'm here I'm asking Radar, hey, I opened that raw binary file. What types do you know about? I'm saying T, enter says nothing. I don't know any types. Okay, so what if I ask you to give me the types in Radar commands because the star post fix turns any output from instead just printing like the information in human form to printing it in Radar command so you can just reuse it. It says, nope, sorry, I don't know any Radar commands for types either. The workaround is you just open any L file that's close to what you want to do and then use that T star command to tell that instance of Radar to dump all its type information to a file, which I'm doing with like a redirect here at the bottom, right? And then when I go to the other instance of Radar, I can load that up, see if the dot, I can load the types 32 file. So I got all the basic info and I'm like, great, I got the basic types. I'll just go and load the header file from open XC it'll be fine, right? No, it's not fine. Segfault, but we can fix that. You take the header file, you massage the header file a little bit. I won't bore you with that. You just kind of like, you know, fix the types and all of a sudden we have all the info. Okay, so here's our new project file. We made some more flags. See the F commands. We're saying these are addresses that have important names. I'm doing dot types 32 to load in that basic type information. And then I'm just loading a can util dot H file which I've massaged into something that doesn't make radar segfault, which is useful. Now I have to set the bit width back to 32. When you're doing disassembly, it needs to be 16 to recognize thumb. But when you're doing the data inspection, you want the pointers to all be 32 wide. And if you leave it as 16, it treats pointers as half words, right? And then you just don't even see the data. So we set it back to 32 to continue. All right, where are we at? We can go to that can signal starter, right? I can ask Ray Deyer, what type information do you know about this can signal type? And it prints back this PF thing. So what it's telling me is this is a PF, a print format command for dumping that can signal structure, right? Now it's quite a long string. You know, you have this kind of PZ, BB, FFF, and then a whole bunch of names, OK? If we just do that straight up, things don't really line up properly. And we don't get stuff like, instead of seeing the address of that can message, we really would just like to see the arbitration ID in that message, right? That's the mapping we want to go for. And then you notice that factor doesn't even make sense. You can't have a factor of zero because if you take a number and you multiply that by zero, you're not going to get that number back. It's a useless can signal. So something has gone wrong. There's a lot of format commands, like a lot of them. Each one of them does something subtly different. If you're going to start doing this kind of thing, I recommend starting with that header file because then at least you don't have to just like grok the entire format. You can tweak one format at a time. And what I did was pf question, question to get this list. OK? So we have that signal start. I'm going to first fix the can message type, which is the thing that the signal structure refers to, because what I want to see is the arbitration ID. And that's really the only thing I care about in this message structure. See, it's got it's got an arbitrary, a bus, an ID, a format, frequency and stuff. I don't care about the rest. I just want that ID. So I know that the print format statement as PDE and all that stuff, I'm going to ignore things. And you can ignore stuff with colons and dots. So I'm going to change it to, you know, colon X dot, colon, colon, that whole statement you see there with the pf and all of a sudden all I see is the ID. Great. That's all I want, right? So I'm going to make a format identifier, like a custom for an identifier. I'm going to call it just the can message arbitration ID, please. And it'll remember that. And I can use that command. So now what I said is print me the current thing as a pointer to the structure. And I got back exactly what I wanted. I got just the arbitration ID. So I'm sitting here at the top of the array, sitting on a pointer to the structure that has the arbitration ID. And I asked it to print me just the ID. We're good. So now we can build up the rest. Another break. I know I'm doing a lot of text. Here you go. Funny picture. OK. All right. So back to the can signal structure. That's a really, really big print format statement. And it misaligned. So you look at the one that I'm highlighting in blue. There was an alignment problem in the can signal structure. And I had to add those two dots between the N1 and the F. And I've told it now, OK, I got two pointers, two bytes, two things you should ignore, and then a whole bunch of floats. And the good news is, when you do that, it's exactly the info you want. So we have our bit position. We have our bit size. We have a factor that makes sense. We don't have like a pointer to the message with the arbitration ID yet. We need to get that to work. The problem is you can print either a pointer to a string in a format specifier or a pointer to a structure in a format specifier. But you cannot print both a pointer to a structure and a pointer to a string in a format specifier. It just doesn't work for some reason. So more workarounds. We'll just print twice, right? But this gives us a chance to talk about macros, right? So Radar has this idea of macros. See the little round brackets? So I define this thing called just print something. And it's doing one print command, comma, another print command. And then I can just call that macro by putting in a round brackets later. We're off to the races. OK, so we load this thing up. I can now say invoke that macro. See the round brackets on print signal. And then I'm using the iterate operator. So I'm telling Radar to run that command on every address between the steps. It's just like Python's range operator. This address to that address with this step. And that means I can actually print each thing in a row in that whole array and we get what we're looking for, right? So you got the message structure pointer, which is just showing you the arbitration ID right next to the bit position and the bit size and the factors and the min and max values. And that's all the really key information that you need it, right? If you compare what's in the JSON from the build to what you can now pretty print with Radar, all the info you want is right there, right? So we're good. Now, because I like pain and we're not over time, let's do a live demo. What do you think? Live demo? All right. Let's do this. So actually I'm in the right folder. This is good. All right. We're gonna invoke Radar. I have created the final stage, final boss, okay? We have our macro defined. I've also introduced a new command here with CF. CF lets you do like what you do in IDA where you set an address to be formatted a particular way. So you can tell it, here's that print format statement and just make it persistent on this address. So I can go through all of memory and make it formatted so that when I do the disassembly, I can actually see the arrays. Here we go. Final boss stage, like that. Good. We'll seek to can signals start. No, we won't. Why not? Come on, live demo. Ah, I did the wrong stage, guys. Here we go. Here we go. Final boss. Yep. All right. So we formatted memory. Sorry. For those of you who can't see my keyboard, I'm typing V and then I hit the letter P to go to the disassembly view. And when we're looking at disassembly, we see the D words and when we're properly aligned in every place, we see the nice structures and this is all the way through that array of can signals. So we did it. Are there any questions? I know that was really fast and a lot of commands. This is the reference for commands and we put it up again so you guys can take some pictures. I'll definitely get the slides out as well. Hey, thanks for your attention, guys. I'm gonna have another drink.