1 00:00:02,750 --> 00:00:04,220 Hi everyone. 2 00:00:04,500 --> 00:00:11,760 Today I'd like to welcome you guys to Car Hacking Village of DEF CON 2020, Safe Mode. 3 00:00:11,960 --> 00:00:18,780 Today's presentation is going to be a throwback to the times before J1939. 4 00:00:18,920 --> 00:00:30,600 If you don't know what that is, that is a protocol that runs on top of CAN and is primarily used in heavy vehicle component communications. 5 00:00:30,600 --> 00:00:42,520 So we will be talking about how we came about the creation of a decoder slash parser for J1708 and J1587. 6 00:00:45,180 --> 00:00:49,680 So just a quick breakdown of how this presentation is going to pan out. 7 00:00:49,680 --> 00:00:53,440 First, we will let you know who we are. 8 00:00:53,740 --> 00:00:57,880 We're going to let you know how this project came about. 9 00:00:57,880 --> 00:01:04,280 And then we're going to give a brief recap of the protocols that are interesting to us. 10 00:01:05,900 --> 00:01:11,400 And you will then see how we came across these protocols. 11 00:01:12,660 --> 00:01:18,780 Afterward, we're going to talk about the decoder slash parser and we'll give you a quick demo. 12 00:01:19,560 --> 00:01:26,280 Last, we'll conclude this talk with the info you'll need to pick up where we are leaving off. 13 00:01:28,980 --> 00:01:32,280 Okay, so my name is Daniel Saloom. 14 00:01:32,760 --> 00:01:36,880 I'm a reverse engineer at Assured Information Security. 15 00:01:36,880 --> 00:01:39,200 We're based out of Rome, New York. 16 00:01:39,280 --> 00:01:44,600 I've been with them for a little over a year and a half at this point. 17 00:01:44,600 --> 00:01:55,160 And I spend my days analyzing the security of things, digging into protocols, and developing anything to support these efforts. 18 00:01:55,880 --> 00:02:00,800 You can see in the images, I'm on the right-hand side. 19 00:02:01,260 --> 00:02:04,240 And there's an image of Thomas on the left-hand side. 20 00:02:04,540 --> 00:02:08,040 So now you have proof that we actually work. 21 00:02:11,140 --> 00:02:13,960 Hi, so my name is Thomas Hayes. 22 00:02:13,960 --> 00:02:19,580 I'm a hardware engineer at Bendix Commercial Vehicle Systems based out of Elyria, Ohio. 23 00:02:19,580 --> 00:02:27,600 I spend most of my days designing hardware, so PCBs and digital and analog interfaces for brake control systems. 24 00:02:27,600 --> 00:02:30,620 And I've been there for almost five years now. 25 00:02:35,200 --> 00:02:38,980 Okay, so what are we doing here? 26 00:02:38,980 --> 00:02:50,040 Well, we discovered that there are more than just J1939 messages that cross the networks in heavy trucks. 27 00:02:50,040 --> 00:02:54,700 And within this traffic, there's some very interesting data. 28 00:02:54,940 --> 00:03:00,860 So we're here to show you how it came about, as we needed a simple way to see it. 29 00:03:00,900 --> 00:03:05,320 And I can imagine you guys want to see how the decoder works as well. 30 00:03:09,720 --> 00:03:11,520 So is there a backstory? 31 00:03:11,680 --> 00:03:12,920 We know trucks. 32 00:03:12,920 --> 00:03:14,520 I've been playing them for a while. 33 00:03:14,520 --> 00:03:23,760 This project started off in mid-2019, when we started to do some exploratory testing on heavy vehicle systems. 34 00:03:23,760 --> 00:03:28,980 We noticed multiple networks and interconnection between all of these modules. 35 00:03:29,000 --> 00:03:35,580 We started to explore some tools and decoders that are already out there, available for use for people in industry. 36 00:03:36,480 --> 00:03:49,960 These legacy protocols of J1708 and J1587 are still being sent across the bus, even though now the CAN J1939 is much more prevalent in newer vehicles. 37 00:03:50,140 --> 00:04:01,360 It looks like it could be very interesting, as it is a very important bus that happens on the vehicle, with a lot of useful information that we were interested in looking at. 38 00:04:03,720 --> 00:04:07,170 Okay, so how do we... 39 00:04:08,960 --> 00:04:13,040 I'm sorry, what do we need in order to get things rolling? 40 00:04:14,040 --> 00:04:17,440 First is an understanding of the protocols involved. 41 00:04:17,440 --> 00:04:21,720 In this case, we mentioned J1708 and J1587. 42 00:04:21,720 --> 00:04:23,600 They kind of work together. 43 00:04:23,640 --> 00:04:29,300 We also need a hassle-free way of analyzing the traffic that we see. 44 00:04:29,300 --> 00:04:34,300 And at that point, we can decide what may or may not be done with this data. 45 00:04:38,870 --> 00:04:43,310 So what are J1708 and J1587? 46 00:04:43,310 --> 00:04:50,790 So they are SAE, the Society for Automotive Engineers, standards for medium and heavy-duty vehicles post-1985. 47 00:04:51,350 --> 00:04:56,990 J1708 describes a physical layer and data links layer and defines a bidirectional serial vehicle network. 48 00:04:57,090 --> 00:05:01,910 J1708 defines how the messages are structured and how they're distributed over the network. 49 00:05:01,910 --> 00:05:07,410 And J1587 makes up a transport application layer and describes messages format and parameters. 50 00:05:07,410 --> 00:05:13,310 So that's almost a big dictionary for all the possible messages that can be sent over this communication protocol. 51 00:05:16,600 --> 00:05:22,360 So J1708 is almost always used in conjunction with the application layer protocol, J1587. 52 00:05:22,360 --> 00:05:25,000 It's based on an RS-45 bus. 53 00:05:25,180 --> 00:05:30,000 We can have a max of 20 nodes on a vehicle and it runs at 9600 baud. 54 00:05:30,000 --> 00:05:40,400 A message contains a 1-byte long MID, a message identifier, followed by some data related to that MID and a 1-byte checksum. 55 00:05:40,400 --> 00:05:42,900 The message can be up to 21 bytes long. 56 00:05:42,900 --> 00:05:49,720 However, if the vehicle is stopped and no movement is detected, the messages can be longer if required. 57 00:05:53,340 --> 00:06:01,300 So J1708 MIDs, we go up to 0 to 127, defined by J1708. 58 00:06:01,300 --> 00:06:04,720 And these are defined by SAE for important vehicle systems. 59 00:06:04,720 --> 00:06:10,840 And then from 128 to 255 are defined by J1587. 60 00:06:10,840 --> 00:06:16,260 And these are used a little bit more for maintenance and information on the vehicle, more for a diagnostic side. 61 00:06:16,680 --> 00:06:17,720 It's very cool. 62 00:06:17,720 --> 00:06:21,960 The MIDs also serve as an arbitration method for the communication. 63 00:06:21,960 --> 00:06:35,180 So the lower your MID number is, let's say 0 to 7 for engine, that means it's a very high important message and will be passed before perhaps the trip recorder message with MID at 56 and 61. 64 00:06:35,460 --> 00:06:37,500 The checksum is quite simple. 65 00:06:37,500 --> 00:06:39,880 It's a two's complement of the sum of the message. 66 00:06:39,920 --> 00:06:43,540 And the data content is defined by the application document given by the supplier. 67 00:06:43,540 --> 00:06:57,000 So you can send the messages defined by SAE or possibly something defined by you as a manufacturer if you need to send something specific or proprietary across the bus. 68 00:06:59,760 --> 00:07:04,360 So J1587 defines the PID, the parameter identifier. 69 00:07:04,360 --> 00:07:07,480 So that's a little bit of a complement to the MID. 70 00:07:07,660 --> 00:07:17,200 So if you have an MID for the engine, a PID can be related to your engine oil or a knock sensor or something in your camshaft. 71 00:07:17,200 --> 00:07:24,360 So it's a little bit more information for the PID for the system to recognize if there's a fault and direct where that fault can be. 72 00:07:24,980 --> 00:07:29,800 So it consists of one MID, one or more PIDs, and a checksum. 73 00:07:29,800 --> 00:07:35,160 The data length of 1587 messages is mostly limited to 21 bytes according to J1708. 74 00:07:35,280 --> 00:07:46,100 And if a message needs to be longer than 21 bytes, we can use the C-C-O-T-S, the TP4. 75 00:07:46,100 --> 00:07:50,000 So that can be used to segment and reassemble large messages if needed. 76 00:07:50,000 --> 00:07:52,380 And a lot of the PIDs are standard. 77 00:07:54,350 --> 00:08:02,810 The PIDs range from 0 to 4 bytes, and the units for elucidating the range will be defined in the spec or by whoever is sending them out. 78 00:08:02,810 --> 00:08:12,270 So if you're a one-engine manufacturer, you could say the PID for oil pressure is 1 psi per bit, or another one could say it's 5. 79 00:08:12,270 --> 00:08:14,990 So it just depends on the manufacturer for that PID. 80 00:08:15,470 --> 00:08:16,970 There's also SIDs. 81 00:08:16,970 --> 00:08:29,650 These are related to the MID, but these are more related to anything that can be used to identify a section that is not necessarily covered under a PID, but covered under a diagnostic MID. 82 00:08:29,670 --> 00:08:35,070 So the MIDs for using SIDs will begin at 128. 83 00:08:35,070 --> 00:08:37,370 That's defined by 1587. 84 00:08:37,370 --> 00:08:42,550 And these are really used for something that can be troubleshooted or replaced by a field technician if needed. 85 00:08:45,720 --> 00:08:47,380 So what's in the data? 86 00:08:47,380 --> 00:08:52,600 Now, a lot of our testing was in the communication between trucks and trailers. 87 00:08:52,600 --> 00:09:00,840 So the trailer has an ABS ECU, and the trailer also has an ABS ECU, and those two will talk to each other using this protocol. 88 00:09:01,640 --> 00:09:05,520 The trailer ABS can have all kinds of diagnostic messages. 89 00:09:05,520 --> 00:09:07,620 A trough test is a test of the system. 90 00:09:07,620 --> 00:09:12,860 It will modulate the air solenoids a little bit and dispense a bit of air. 91 00:09:12,860 --> 00:09:19,440 Like when you hear a truck brake, you hear a large air release sound, and that's kind of just making sure that your system is working properly. 92 00:09:19,440 --> 00:09:26,360 You can restart the ECU, you can check the status of the ECU, and most importantly, demonstrate an ABS fault. 93 00:09:26,460 --> 00:09:46,240 So as per SAE standard, the ABS fault, if the trailer has an issue, the trailer ECU has to communicate to the truck ECU and illuminate a light on the dash, as well as a light on the trailer itself, indicating that there is an issue with the ABS and it needs to be resolved. 94 00:09:47,340 --> 00:10:04,160 Diving a little bit deeper, there's also configuration options on the ECU, so wheel size, which then relates to the speed of the vehicle, as there's a tone ring that counts the amount of rotations done, and driver info, so where the trailer is going and what truck it is connected to at the lot, 95 00:10:04,160 --> 00:10:13,800 and sensor data, so the speed, mileage, odometer stored on the ABS, location, temperature, and many proprietary vendor messages. 96 00:10:15,600 --> 00:10:18,420 So who uses J1708 and J1587? 97 00:10:18,420 --> 00:10:28,220 So any kind of heavy vehicles that we all know, but also school buses with all that same platform, military vehicles, and we even found that yachts will be using the same communication platform. 98 00:10:29,900 --> 00:10:33,740 So our use case, we were observing exchanges between a tractor and a trailer. 99 00:10:33,740 --> 00:10:42,120 As we said, the brake controllers communicate over J1708 and J1587, and these messages actually pass over a power line, which is very cool. 100 00:10:42,120 --> 00:10:59,640 Trailer manufacturers did not want to add another wire or two needed for an ABS communication, so they superimposed a sinusoidal wave on the power line going from the trailer, which then gets filtered out on the trailer side and on the truck side, depending if it's using that communication. 101 00:10:59,640 --> 00:11:03,360 It's very cool, but Dan and I did not focus our time on this. 102 00:11:03,360 --> 00:11:07,540 We were working on the J1708 and J1587 protocol. 103 00:11:10,700 --> 00:11:17,520 Okay, so the question comes up now, how do we look at these messages? 104 00:11:17,940 --> 00:11:19,620 There's a couple of options. 105 00:11:19,620 --> 00:11:39,660 We can use tools that were developed for J1939 and are backward compatible with the other two protocols we mentioned, or we can get our hands on an RS-485 transceiver, some bubble gum, a paper clip, maybe a tinfoil hat and see what we can hack up. 106 00:11:40,940 --> 00:11:44,380 But what happens when our bus is a power line? 107 00:11:44,640 --> 00:11:48,380 In this case, you need a specialty diagnostic tool. 108 00:11:49,360 --> 00:11:54,760 Some of the larger companies like Nexic, Halidex, Digitech, they provide these. 109 00:11:55,200 --> 00:11:59,240 But the problem with this approach is it's going to cost you some moolah. 110 00:11:59,240 --> 00:12:12,100 And flow between programs is not really there, as software is kind of tied with the hardware and it's all proprietary, which means minimal flexibility. 111 00:12:13,940 --> 00:12:18,500 So our solution is pretty J1587. 112 00:12:18,800 --> 00:12:24,080 This is a decoder that helps with at least part of the problem. 113 00:12:25,260 --> 00:12:29,220 By default, this takes in hexadecimal bytes. 114 00:12:29,220 --> 00:12:35,420 Which are comma delimited, but really it can take in a stream of any bytes. 115 00:12:35,600 --> 00:12:44,620 And a user can define how to manipulate that data to be parsed correctly by the decoder. 116 00:12:45,220 --> 00:12:53,540 It also supports reading from standard in files or sockets, UDP or TCP. 117 00:12:53,660 --> 00:13:03,160 And what it does is it takes this information, these messages, and it will break them down into a human tolerable format. 118 00:13:03,160 --> 00:13:07,220 So they can be easily analyzed by an end user. 119 00:13:08,080 --> 00:13:19,980 So to start off, what happens is the parser will read the SAE documentation PDFs. 120 00:13:19,980 --> 00:13:28,950 Okay, and it will do this to set up a primary database, which is used for interpreting the data that's coming in. 121 00:13:29,410 --> 00:13:36,670 And this is needed because there's no simple database holding the data that we need in a convenient format. 122 00:13:36,670 --> 00:13:42,430 Okay, it's all in the specifications or proprietary by vendors. 123 00:13:42,830 --> 00:13:49,430 So there is an option for an end user to create custom messages with this tool. 124 00:13:49,430 --> 00:13:52,790 And this will be handy for working with proprietary data. 125 00:13:54,350 --> 00:14:05,870 The benefit of this, using this tool, is that it can be piped from or to other programs, as it's just a command line utility. 126 00:14:08,150 --> 00:14:10,710 So there are some requirements. 127 00:14:10,750 --> 00:14:12,690 What do we need to get this off the ground? 128 00:14:12,690 --> 00:14:19,750 Well, the first part is on you guys, you're going to need an interface to some bus to get the traffic. 129 00:14:20,750 --> 00:14:33,690 The next part is, it uses the program PDF2Text, which is contained within the popular udos package standard on most Linux distributions. 130 00:14:33,710 --> 00:14:48,050 Okay, and what happens with this is we use this tool to convert the SAE portable document format specifications into formatted text files. 131 00:14:48,050 --> 00:14:52,670 Okay, then you need Python 2. 132 00:14:52,670 --> 00:15:00,090 We are hoping to port this to Python 3, but it started as a spaghetti code project that we just needed up and running. 133 00:15:00,150 --> 00:15:02,390 And Python 2 was default here. 134 00:15:02,390 --> 00:15:07,950 And that's what we stuck with until now when we realized it's actually useful. 135 00:15:09,030 --> 00:15:11,950 There's still some minor issues with it. 136 00:15:11,950 --> 00:15:16,830 The spec obviously was not written with being parsed in mind. 137 00:15:16,830 --> 00:15:25,470 Okay , so there's a lot of regular expressions and things that parse this information out of these files. 138 00:15:27,650 --> 00:15:37,470 Okay, so I think at this point, I'm going to give you guys a quick demo about how this thing works. 139 00:15:38,650 --> 00:15:43,710 It's a repository, which will be made public after this talk. 140 00:15:43,710 --> 00:15:45,430 And you can just clone it. 141 00:15:45,430 --> 00:16:03,050 And at that point, you will set up the configuration file to point at the text files that you've created from using PDF2Text on the SAE J1587 and 1708 specifications. 142 00:16:03,050 --> 00:16:03,670 Okay. 143 00:16:03,670 --> 00:16:08,010 So the first thing that I'll mention is this repository. 144 00:16:08,130 --> 00:16:13,090 Within it, we have a tool called Fuzzy Messages, which I'll be using for the demo. 145 00:16:13,090 --> 00:16:21,530 All right, this program just creates random bytes, I believe 1 to 19 bytes in length. 146 00:16:21,590 --> 00:16:28,530 And this winds up working out as a nice test environment to create a robust program. 147 00:16:28,530 --> 00:16:32,830 That way, it's not just failing on any sort of messages. 148 00:16:32,830 --> 00:16:42,570 As you might see, when running different types of hardware, you'll get funky bytes that aren't actually part of the message at times. 149 00:16:42,570 --> 00:16:50,030 So we've decided to make this program a little bit robust, and that it won't just error out on an incorrect message. 150 00:16:50,030 --> 00:16:55,910 It might print a warning to standard out, and it'll keep chugging. 151 00:16:55,910 --> 00:17:12,210 Okay, so the first thing I'm going to do is I'm going to create a file with, let's say, 100 messages, and I'm going to write that to temp. 152 00:17:12,830 --> 00:17:15,570 Okay, let me just make sure that that worked. 153 00:17:16,690 --> 00:17:18,910 Yep, seems like I got messages in there. 154 00:17:18,910 --> 00:17:27,470 All right, so now to run the tool, I just point it at that file that I created with all the messages. 155 00:17:27,770 --> 00:17:32,390 I'm also going to give it a flag to print the limiters between the messages. 156 00:17:33,470 --> 00:17:41,490 So you can see, when there are errors, it gets printed to standard error. 157 00:17:41,530 --> 00:17:45,150 So these can be piped to DevMill if you're not interested. 158 00:17:45,150 --> 00:17:53,970 But you can also see here the original message MID in hexadecimal, and these also are accompanied by decimal forms. 159 00:17:53,970 --> 00:18:01,490 And then the PIDs and the meanings of the PIDs, along with the accompanying bytes. 160 00:18:01,490 --> 00:18:04,050 Okay, so that's pretty good. 161 00:18:04,050 --> 00:18:13,270 But if you want more information, you can give this program a little bit more verbosity, like so. 162 00:18:13,270 --> 00:18:15,650 And you'll get details. 163 00:18:15,650 --> 00:18:18,730 This is the same message here that we saw previously. 164 00:18:18,950 --> 00:18:26,730 But now you can see it's giving details about the individual bytes related to a PID. 165 00:18:27,050 --> 00:18:32,970 So here we can see there's one byte and this has to do with the extended range barometric pressure. 166 00:18:32,970 --> 00:18:35,350 Okay, and here are the units right here. 167 00:18:35,350 --> 00:18:38,030 I just want to mention one thing. 168 00:18:38,030 --> 00:18:41,530 We are using random bytes for this data. 169 00:18:41,530 --> 00:18:46,130 So this MID says idle adjust system. 170 00:18:46,310 --> 00:18:55,390 And it's not necessarily in a real world scenario, this PID is probably not going to be matched with this MID. 171 00:18:55,430 --> 00:18:56,350 Okay. 172 00:18:56,590 --> 00:19:00,810 But we don't error out, we just want to parse the data as it comes. 173 00:19:02,770 --> 00:19:06,270 There's a couple of other options I wanted to mention. 174 00:19:06,410 --> 00:19:10,090 So some people prefer JSON. 175 00:19:10,970 --> 00:19:13,570 We added a flag for JSON. 176 00:19:13,570 --> 00:19:19,490 I will disable the output that you just saw, which can be easily grepped. 177 00:19:19,490 --> 00:19:23,390 And I will print these messages in JSON format. 178 00:19:23,390 --> 00:19:29,850 And I'm also going to pipe the standard out to dev null. 179 00:19:30,370 --> 00:19:39,810 Okay, so you can see in here, same messages, but these are output as JSON formatted messages. 180 00:19:39,810 --> 00:19:47,470 This could be convenient if you use the JQ tool, and you want to filter these messages the way you'd wish. 181 00:19:47,470 --> 00:19:50,350 But there's another option for you. 182 00:19:50,350 --> 00:19:53,590 And that is, we have a whitelist here. 183 00:19:57,110 --> 00:20:10,350 So what we can do is specify specific PIDs, like if we are interested in certain PIDs within a message, we only want to print those messages, we use the whitelist option. 184 00:20:10,350 --> 00:20:13,130 So I will just grab one from here. 185 00:20:18,960 --> 00:20:24,860 And so you can see I printed out one message with that PID, 48. 186 00:20:25,760 --> 00:20:30,540 And that is in actually decimal form for that. 187 00:20:31,540 --> 00:20:34,900 Okay, so there's a couple other things that this can do. 188 00:20:35,500 --> 00:20:40,220 If you just give it the dash H, it'll give you some help. 189 00:20:40,720 --> 00:20:45,780 One of the options is for a custom database. 190 00:20:45,780 --> 00:21:03,480 Now this means if you want to define your own messages, and overwrite those that are provided by the spec, or let's say you're working with some proprietary messages, and you have a good idea what it means, you can define that. 191 00:21:03,480 --> 00:21:08,320 We provide a sample file in the repo. 192 00:21:08,400 --> 00:21:14,980 And you can see here that basically, this is the format, it's just JSON. 193 00:21:14,980 --> 00:21:20,900 And you just give it your definitions, you can use this file as a guide. 194 00:21:20,900 --> 00:21:23,660 Okay, there are still some issues. 195 00:21:23,660 --> 00:21:30,380 There are a few PIDs that are a little bit more tricky to work with. 196 00:21:30,380 --> 00:21:37,720 And those might not have their individual byte definitions overwritten, but it's a work in progress there. 197 00:21:37,720 --> 00:22:02,640 I wanted to mention that, okay, if you want to read from standard input, the way that you do it is you just pipe hexadecimal delimited bytes, as I mentioned, to this, and you will use this usual format for reading from standard input. 198 00:22:02,640 --> 00:22:09,220 Okay, I'll also use the... I'll use packet delimiters here. 199 00:22:09,220 --> 00:22:11,440 And you can see what the meaning is. 200 00:22:11,480 --> 00:22:29,780 But one of my colleagues came to me and he said, well, you know what, you know, we have an issue because the output that I'm getting from my program is not set up like that, it doesn't have the comma delimited values, it's all just a string of hexadecimal bytes. 201 00:22:29,780 --> 00:22:45,920 So what we did was we added the option here, if you look in this file called canon functions, an end user can define a function to be called on the command line that will manipulate this format. 202 00:22:45,920 --> 00:22:55,960 And the only requirement is that the output would be a Python list of bytes, okay, or a Python list of integers. 203 00:22:55,960 --> 00:23:06,120 So in this case, we can use the dash j option and say canon no delims, I believe I called it. 204 00:23:06,220 --> 00:23:12,800 And you can see that it will just parse the message in that format. 205 00:23:12,800 --> 00:23:15,260 Okay, so it doesn't really matter. 206 00:23:15,260 --> 00:23:23,880 All you need to do is know what your input looks like, and figure out how to get that into a Python list of integers. 207 00:23:27,600 --> 00:23:31,140 Let me see if there's anything else I want to mention. 208 00:23:32,020 --> 00:23:33,380 I think that's it for now. 209 00:23:33,380 --> 00:23:38,760 I'll let you guys play with the rest of those options as you see fit. 210 00:23:43,830 --> 00:23:49,690 So getting back, what are the benefits of using this decoder? 211 00:23:49,690 --> 00:23:57,030 Well, there's no real software investment, other than getting your hands on the SAE specs. 212 00:23:57,030 --> 00:24:01,150 Okay, I'm sorry, we can't just provide them for free. 213 00:24:01,430 --> 00:24:05,630 But SSA, sorry, SAE would not be happy with us. 214 00:24:05,630 --> 00:24:09,410 And they take the intellectual property very seriously. 215 00:24:09,410 --> 00:24:11,090 So I'm sorry about that. 216 00:24:11,090 --> 00:24:12,990 You can handle it, I'm sure. 217 00:24:14,070 --> 00:24:21,610 The other benefit is that you can work with anything that outputs 1708, 1587 messages. 218 00:24:24,270 --> 00:24:26,030 So where can you get it? 219 00:24:26,030 --> 00:24:30,490 If you want to get your hands on this tool, you'll go to this URL. 220 00:24:30,790 --> 00:24:35,050 After the talk, we will make this a public repo. 221 00:24:35,270 --> 00:24:42,430 We're rolling with an MIT license, so don't forget where it came from, and feel free to make money on it. 222 00:24:42,430 --> 00:24:45,990 But remember that there are a few dependencies. 223 00:24:45,990 --> 00:24:52,330 So you need the specs, you need PDF to text tool, and Python 2 at the moment. 224 00:24:54,830 --> 00:25:07,150 We wanted to give a special thank you to NMFTA for giving us the opportunity to do this work, and our friendly motor freight carriers for allowing us to play with their trucks. 225 00:25:07,150 --> 00:25:17,690 Also the Hilton Executive Lounge for hosting a nice, hectic atmosphere by letting this group meet and set up mobile test benches. 226 00:25:18,350 --> 00:25:23,190 We only left a few solder burns under nice wood grain tables. 227 00:25:26,290 --> 00:25:31,390 We just want to thank you for joining us, and enjoy the rest of your DEF CON talks.