Thank you for being here. I know that the third day of DEF CON is hard to get up so early, so thank you for being here. So this is Cesare Pizzi, my name is Cesare Pizzi, and this is the ArduSploit presentation. So ArduSploit is a proof of concept of an Arduino code injection. So what I try to do is to inject some arbitrary code in a working sketch without knowing the source code, without knowing how it works, and so on. So I try to put some arbitrary code there. Okay, so let's start. So a few words about me before starting. Okay, my real job, let's say, I work as a security engineer in an Italian company. And then, okay, as a hobby I have everything more or less that is technologically related. I work on a lot of open source projects and so on. And so I work a lot also on hardware, on the hardware field. Starting from more or less 2009, working on the first Arduino version and so on. I also built a custom Arduino compatible board with a GPS tracker called Here You Are. You can find all the details here in the site. Okay, so let's jump immediately into the presentation. So the basic idea of the project was actually to... Put some code in a working sketch. So these will be probably the main steps we have to follow to do it. The first one is dump the flash content. So we have the content of the board. We have to get it in some ways. Then we have to modify it because we need to put our code there and leave the previous functionalities working. And then refresh the injected code back. Into the board. We will see together that there were more than one way to do this. This is the important part, inject the payload. I don't know if you are aware of how the Arduino board works. In any case, usually it has a main loop that is repeatedly executed. And one of the options was to put the code there. But it wasn't, I didn't go in that way. Because it was more difficult to have a control on how often this code will be executed, actually. And so I tried to follow a different path to do it and we will see it together. I would like to split the presentation in three parts mainly. One with an overview of the AVR architecture. AVR is the MCU on which the Arduino is based. So I would like to do this just to have the same common ground to start up. Then we will see how it works. How the script works. And then we will also have a live demo to see the script, how it works and how it can get the code executed. Just a very, very, very fast overview on the AVR architecture. Flash, EEPROM and RAM are all integrated on the same chip. So the AVR chip holds everything in one piece of hardware. No. You don't have to mess with other components there. So you can just go with the same chip. All the program instructions are stored into the flash. This is very important to remember because we are going to mess with this code. So we know that everything is there. So we can get it. There is also an EEPROM available for permanent data storing. This is accessible through usual macros and so on. Then we have to consider that all the MCU are 8-bit. But the instruction set is built on instructions that are built on one or two 16-bit words. That means that the opcodes will be 16 or 32-bit words. Or 32-bits. All the opcodes are very well documented in the AVR datasheets and sites. So you can get all the documentation there. It's very well done. It is very important if you are going to start to play with this. Because obviously we are working at assembly level at this point. So we are going to inject some assembly code directly into the working code. As the last part. All the instructions are one or two clock cycles. Except jump and call that requires three or four clock cycles. Consider also that jump and calls are the few instructions that are 32-bits. This is because they have to address this. The whole memory of the board. Of the board. Of the MCU. And so they rely on the 32-bits to be able to set the correct address to the jump. This is the absolute jump and absolute call. So there will be also the relative jumps available in the opcodes of the MCU. This is how the flash memory is organized. Very important. Because the flash memory will be our playground here. And we are going to make some modification there to put our injected code. Okay. This is the main format. We have the flash memory starting at address zero. There. Where we have immediately a jump to the program start. So the real application will start here. All the room granted by the first part of the memory is for the interrupt vector table. We will go into details about this after because it's very important. Then there is the application section. Here it's where the code of the user, that the user will write with the proper ID is placed. And then there is the bootloader section at the end. The bootloader section is especially important because it allows to, let's say, write and manage easily the content of the flash. Because as you probably know, but I'm not sure if everyone knows that, the AVR MCU can be programmed by using an external programmer. So you don't have the need of the bootloader in that case. Or you can just use the board itself. Because the bootloader in this case is able to get from, to understand if from the USB port something is coming and it's able to rewrite the complete content of the flash over. So this is what allows us, for example, to use Arduino or similar boards directly with USB connection to program them. If you remove in some way the bootloader, you will end up with a brick, let's say, board. This happens. If you will start to play with the flash. But it's also true that it's easy to fix because you can reload the bootloader very easily with an external hardware. That could be another Arduino board, for example. So it's very easy to fix in this case. Consider that the whole memory is not protected in any way. So there are no protection for system or other ways. So you can write everywhere if you want. That means also that you can also damage something if you are not paying attention to what you are writing. Because there are no protection at all on the flash. So for the chip itself, you can write everywhere what you want. It's easy for us so that we can inject our code without checking so much things. But it's also dangerous because it allows us to make damage to the memory itself. So another important thing to consider are the fuses. Fuses are set of bits used by the MCU to store the initial configuration. Like, for example, the clock speed, the watchdog timer, and the bootloader location. I underline this because this is important. We need to understand if there is a bootloader in the flash because we have to stay away from it when we are going to modify the code to inject our payload. We have to stay away because otherwise we are going to probably break the MCU. So the bootloader location is stored in these bits here in a way that it's documented in the datasheet. The AVR datasheet says how to set this bit and how to set the proper bit to give the proper address for the code itself. Or you can use, for example, an utility like this one, which is a server. This is the site that will be referenced in the presentation reference here. By using some pulldowns menu or some check, you can, for example, as you can see here, set the bootloader present and where it is placed. So in this address. You can choose this. If you press a button on the site, this will compute for you the values of the fuses bits that you have to set to get this. This value written on the board. Consider that the fuses bits can only be read, but to be written it requires a specific external programmer. So you can read them with the usual utilities. We will use the common AVR utilities to perform our job. So if you download the Arduino IDE, everything is already there. You have all the utilities you need to go ahead with what we are doing tonight, this evening. OK. The bootloader, it's just a section of code, like all the other sections of the Flash, but with specific behavior and duties. So when the AVR is power or reset, it starts the boot sequence. So depending on the fuses status, as we said, it starts from the address 0, where we have the jump to the program start, or it starts the bootloader. The bootloader has these functionalities, but they may have also others, like initializing the control peripheral, load selected user application, and upload new code, for example, by using the USB connection. So that's very important. And so what we need to do is to avoid to mess up with the bootloader code. You can also decide to get rid of the bootloader when you are programming on an Arduino AVR board, because mainly the main reason why you want to do it is to save space. When you have to deal with 32 kilobytes of RAM, of Flash, you have a situation where the additional two or four kilobytes used by the bootloader are very important. So you may want to not use it. So if you don't want to use it, you just have to set the free uses accordingly, and you can use the bootloader area without any damage. Consider that the ARDU-Sploit, which is the script that will automate this process, it's independent on the presence of the bootloader. So it will work with a dampened content. There is no problem if it has been obtained through the bootloader, through the AVR-DUDE, through an external program. It just works with the dampened Flash. So let's go a bit into the interrupt vector table. Because I said before, my main target was to inject the payload. I said before, OK, I can put it into the main loop, but I'd lose control on it. And so the other solution was to try to use interrupts on the board itself. What is an interrupt? It's a way MCU and CPUs use to execute asynchronous code. So when there is an asynchronous event on an MCU or on a CPU, usually it is handled by an interrupt because the program flow can be at this point interrupted by these calls coming from external events like a keyboard press or something like that. So probably you already know this. So as we said before, the interrupt vector table is at the beginning of the Flash. True for the Arduino device. AVR is also used by other devices, not only for Arduino. And so this could be also placed in other place. And this is defined by these values, which are the boot RST fuse bit, the IV cell bit in MCU control register. These are data coming from the AVR data sheet. So you can have a look to them. A very important thing to say is that AVR and HTML do really a very good job in providing the documentation of their MCU. So you can find everything very easily about how the MCU are working. So OK, this is the interrupt vector table. This is coming from, on the left side, you see the description coming from the data sheet. On the right side, you see the disassembly from a dump of the Flash ROM. As you can see, OK, this is the table. It describes the position and which kind of function is handled by this specific interrupt. In the reality, it's just a jump. So it's an absolute jump to a specific location. As you can see here, most of these jumps are pointing to the same location, which is in this case, it's 0xba, xhmlba. This means that it's not used. So the interrupt vector is not used because it's jumping. If you are going to check this address, it's just a jump back to the 0 location, so at the very beginning of the problem. So when you see something different like this one, that means that the interrupt vector is in use. And this is actually the address of the ISR, which is the interrupt service routing. So the specific code will be executed when a specific interrupt is triggered. This output is very important. It's coming out from a very neat utility in the AVR toolchain coming with the Arduino environment, which is the AVR object dump. This is the most useful utility you have to use if you want to start to play with assembly and architecture and AVR architecture. So it will be your friend. In these cases. Different MCU may have different behaviors because, for example, the position of the vector interrupt can be different. And it's important that these things are realized when I was working on this project. For some specific MCU, the intervector table is built in a different way. For example, for the ATmega2560, which is the biggest one in this family of the Atmel MCU, the developers choose a different way to organize the memory of the compiler program. Because consider that one important thing, the intervector table is built by the compiler. So when the compiler creates the content of the flash and it uploads it on the MCU, it will prepare also the intervector table depending on what it has been done in the sketch. The GCC developers choose to go for a different solution for the ATmega. And they use relative jumps with a 16-bit opcode instead of the absolute jump. I can guess the reason of this choice, because the ATmega has 256 cores. It's a kilobytes of RAM. It cannot be addressed by the absolute jump in any case. So probably they choose to using a paging management of the memory by using the relative jumps. And so probably that's why they choose this way to code their outings. But in any case, they are deployed. My script will take care of this. And depending on the MCU, we are going to inject the code. It will act. Accordingly. OK. The last important thing is the entry point of the sketch of the program we are going to modify. So we said that we are going to use an interrupt to inject our code. But that means that also these interrupts must be initialized somewhere. Because otherwise, if you just go to place some code and modify the jump we saw before at the beginning without saying anything else to the MCU, I will not get anything because the interrupt itself is not initialized. So I need to find the entry point of the sketch itself to initialize the interrupt vector I'm using and say, OK, execute this every now and then when I tell you. And go ahead with the code. This is a specific section got from the AVROBG dump I said before. Run with this syntax here. And this is more or less from 99% of the code I checked where the initialization of the code itself begins. So the compiler, after the jump of the location 0 and then it comes here, it executes these two jumps and then there is this closing jump to 0 again here. This is where the preamble routings of the compiler are handling over the control to the application, let's say. And so this is where we need to look for the proper entry point. Because if we put our initialization routing too early, it will be overwritten by the initial setup done by the compiler itself. So we need to find out the proper way to put the proper place to put our code here. And so this will be where we have to find out. My script will automate this process. And it has also some built-in addresses where I know for some program we can safely inject our code. This will not work for every single sketch. This requires a bit of manual processing in case. So you have to have a look around this address here or here, mainly here, to find the proper place if it is not working automatically as we expect. So this is the entry point where we need to do our job. As we said, we need to dump the content of the flash because we need to get that out. We need to get that out from the board itself, what is already running there. And OK, this is just the syntax of the well-known utility in order to just define which kind of process we are working on and the speed of the for the port and so on. And this is the important part. This is saying, OK, read the content of the flash and write it on the .hex file. This dot, comma, I here say specify the format of the output file, which will be, in this case, the hex file. You can also dump the content into binary files. In this case, we are going to use the hex file because it will be easier to manage through the script. The script itself will take care of everything so you don't have to mess up with the format. It will get this specific format and it will change everything to inject the payload. This is how exactly looks a .hex file dumped from an Arduino. The format, it's a standard one, so it's not nothing very custom or something. This is the description. So you have the line start with the column. The byte count for the line. The address where the byte code are written. Our record type, it's always zero for the dumped content of the .hex. And there is the data. This is actually assembly code. Consider that and keep into consideration that the .hex, .hex, .hex are a little Indian architecture. So the byte are swooped. So here you have to swoop the bytes to read the proper code of the assembly line. And then there is a checksum at the end for the line. The hard-to-sploit will modify everything and the checksum as well. So you don't have to take care of this. Okay. Let's prepare something to inject. This is the hello world for the hardware hacking, so a blinking LED. This is the assembly code to blink a LED on a specific board. This could be different depending on the board you are working with because, for example, we will see during the live demo, we will make an Arduino Uno blinking. The LED is on a specific line of the MCU in this case, and so it is defined here, which is the first instruction here. Obviously, if you are working, and we can see if you have time, with another board like the Arduino micro, for example, the LED is on another board. So we have to change this. But the script will provide some example payloads already done for different architecture. So also these things will be automated. This is just a bunch of assembly. Okay. As I said, we have most different of them for specific different boards. I prepared this in the script. The script itself, and then Python. I'm not a Python guru. You will see it. I choose Python because it was easy to understand and to write the script in, but there are a lot of room for improvements in my encoding there. So you can also help me in doing this because obviously this will be, everything will be open source, so everything will be available for modification. So let's go on. Okay. We said before that we may have, okay, we are going to use an interrupt, but the interrupt can be also already in use. We said that we are going to inject code in an unknown application. So if the interrupt itself is already used, we have to handle the situation. And the script itself, it's able to do it. Actually, it will check if the interrupt we choose is already in use, and it will prepend our code to the existing routing so that everything will be executed, and then there will be a jump to the original routing, leaving the original functionalities untouched. Important thing to say when you write your PyPayload here is that you need to leave everything untouched. So you have to push and pop every single variable you are going to use in your assembly language to the original value, because since you don't know when exactly your code will be executed, it can be executed in a time that you don't know, and you don't know the application where you are working on, it's very important that you don't touch anything on what is in the stack, and you leave it exactly as it was. Okay, so this is the push, that's why I told you that I'm not a Python programmer, so you will see that. Okay. It could be written probably better, where we can take care of the presence of the existing ISR, and the script itself is going to inject the code. Okay, we said that we are going to use an interrupt. Which one? We can choose, because the script itself it's not, it can be also modified, but for this presentation I tried to use the timer interrupt. There are different timer interrupts in the AVR architecture, some 8 bits, some 16 bits, different also depending on the boards. What is a timer interrupt? It's a specific interrupt that's called every now and then, so with a specific interval we decide. So we can say, okay, execute this interrupt every one second. Okay. And the number of bits of the interrupts are defining the value of this interval we can define. So the bigger, the greater delay we can have between the two executions. Timers are increased at each clock tick. In CTC mode, the interrupt is triggered when the timer reaches a specific value. And so this is what we have to do. So we have to write our initialization code in order to initialize the interrupt to be executed when we want. By choosing the matching value and speed, you can control the frequency. So we can control how often our code will be executed. Okay. So the timer speed, the MCU are working at 16 megahertz, so we have a tick every 0 comma, okay, some zero, then 63, which is every four milliseconds. But you can also control the speed with a press color, so you can slow down this counter. And so I have the execution not every four milliseconds, but maybe also with greater values. So, okay, the press color, okay, is the value that you can use to slow down this execution. And it's set through the specific register on the MCU itself, which is documented as well as all the other things in the data sheets. And so you can specify it by setting these bits here. And we will see that our initialization code is doing is actually set up all these bits to set up the interrupt timer to the proper values. Okay. This is a quick computation of how we can compute the frequency. So the interrupt is triggered when the ticks reach the value in the compare match register. And to compute the value, I have to do some math, like dividing 16 million by the press color value here and by the frequency we want. For example, if we want an execution of two per second, so every half a second, we have to set up the compare match register to this value. And this is what exactly we are doing here with this set of code. This is the macros used in the Arduino IDE. And this is the translation in assembly language. This will be the portion of code that I defined as initialization of the interrupt. So we have to put this at the beginning in some way of the sketch and then inject our code in the interrupt timer. So... Okay, we have to find free space obviously to do this because we need to add some code to the existing one. Okay, as we said at the beginning, we have to avoid the bootloader RF present because otherwise we are going to break up things. We have to look for unused space, which is usually marked as 0xff. And so the script itself tries to find the proper aligned space unused space. But... Okay, what if the space is not available? We may have to condition. You don't have space marked as 0xff because maybe a bigger program was loaded on the sketch on the MCU before and then replaced with something else. Or... Because it's actually everything it's used. If the second case you don't have any way to inject the code actually because, okay, you don't have free space on the flash run. But in the first one, yes, because you can in the script specify manually the address to put the code. Okay, and this is what then the script will do to prepare the... the code to be injected back. So it will take care of... all the alignment and so on and it will prepare the X file, as we said before, ready to be injected. Okay. You remember the last slide we saw at the beginning with the flash memory... structure. This is what we are going to modify actually. So... Intervector table, we will get the jump to the routing and we will modify it to... with a jump of our injected code here. And... and then we have to initialize the timer... here. We have to find the free space and allocate our... our code. So, as you can see, you need a bit of space to inject these two portions of codes here. Okay, what... what R-Disployed can do automatically? Because, okay, we now... spoke about what has... should be done, but, okay, what the script itself is doing? So, it gives you some example payloads ready to be modified. Okay, it's blinking light, but it could be also something different. It has a radiant usable interrupt initialization routing, which will be injected in the proper place. It finds free space in the flash to place the payload and the interrupt initialization routing. It plays the code and takes care of the replaced code because, obviously, we are going to modify the existing flash. So, everything that is already existing we are going to override and it needs to be executed again. So, we are going to do that again at the end of our code. So, it will take care of this and it will automatically manage also the presence of an existing interrupt service routing. Managing and placing all the needed opcodes. So, everything will be done automatically by the script. And then it generates an output which will be X file ready to be written back on the flash. As I said, it's independent on the way we are using. We can use a VRDU, we can use an external programmer or something like that. So, this is external to the script itself. So, this is what exactly what the script is doing. Okay, there are a few options available on the script. Okay, verbose out with dry run we will see maybe the live demo. The possibility to specify where to place the payload and the initialization payload. Otherwise, it will be automatically computed. And, okay, they specify the MCU to work with because every MCU has different behaviors. Okay, we can also automate the process. We will see it during the live demo with a $13 device which is LinkySmart or similar. The importance is to have the Python support. A hot plug to the script which is just a demo that recognizes that something has been plugged into the USB. They are displayed in 30 seconds. You can inject the code without tapping any command. We will see also this during the presentation. So, this is the hardware needed for, for example, doing this automatic injection. So, it's just okay, this is this board here. This is an unusual Arduino device. In the software, it's just a few configurations here just to recognize that an Arduino device has been put, has been plugged in with this one and then just the execution of the AVR display the script itself. So, this is what exactly doing the injection. Okay, so, the live demo. Okay, let me now have a look. Okay. So, you see, okay. Okay, so, let's move. Okay, this is in temporary directory and here. Okay. So, let's get our, our device here and let's try to load a standard sketch. Okay, I'm using here this analog serial sample. Okay, I'm uploading it on the board. Not really. Let me see. Okay. So, okay. Let's change the port. Okay. Okay. Okay. So, now we're uploading the code. This is just writing a value like a value of an analog port. So, you can see that just, okay, dumping these values here. Okay. So, now, let's go back and let's start to do the first thing we need to do is dumping the code from the AVR. So, okay. Okay. This is the syntax we need to use. We saw it So, let's go on. Okay. Now, let's go into the hard exploit directory here and let's copy the dumped content here. And then, let's run the hard exploit script specifying the hard exploit. So, you see that, okay, it is running for the 80 mega 328p, which is the MCU used by the Arduino Uno. And the insert flag is the position where he needs to put our initialization routing. Okay. It's finding the entry point. It says that the timer vector is not used. And so, it's inserting payload and saving the injected file. Consider that the script will not modify the original one. It will create a new file named .injected, which we are now going to copy back. So, let's copy the result in file here, which is this one. Okay, let's have a look at this one. Okay. This is the hex file rewritten by the program itself. Copy. So, flash text .injected in tmp. So, let's move the text. So, let's rename it. And then, I'm just running the same utility as before, but modifying the read to write Okay. The code is loading. And, okay, probably it's . You see that there is a blinking light now. Okay. Let's see if the original function are already there, because, okay, we just inserted the code, but we don't know if it's still working as before. So, let's go back here. Okay. And so, it looks like, yes, okay, it's still dumping the content of the analog port, but now it also has the blinking light. Okay. The blinking light here. So, we can do another quick example by using a sketch that is using the ISR. So, let me just open it. Okay. Yeah. Okay. So, let's upload this one. Okay. This is very easy program that just use an interrupt timer to print an A here. Okay. Not really a real example, but in case for the purpose of the test, it's enough. So, it's printing an A. So, let's go back and do the same things here. So, let's dump the content again by reading the flash. Okay. Let's copy again the slash TMP slash in. Okay. And let's run again the hard exploit. Okay. Consider exactly see, not this one. So, the realize that the timer vector is there. So, it tries to open. So, now, we have the injected code. Let's copy it back. And let's it works. Okay. So, you can see again the blinking light here. And let's see if it still runs the interrupt as before. Okay. Yep. So, also in working here. Okay. So, this is more or less I think that we also running out of time. Maybe I have still some minutes to do an additional test, which will be the automation of the process here. So, let me show you. So, this can be. Okay. So, this is a starting point, obviously. It will be interesting to also know your opinion about this and to also have your for developing and do additional things about this way, also changing maybe the way we are using to inject the code, actually. Because this is a solution I found. It's not the only one for sure. Okay. So, let me upload again the analog read. So, I'm going to get rid of the blinking light here. Okay. Uploading down. So, okay. As you can see, as I said, we can automate the process. This board here has a Python support with the script on board. So, if I'm going to plug the board now, we should wait 30 seconds and we should see the LED start blinking again. What it's doing right now is just automating the process we did just 10 minutes ago. So, now it's uploading the code again. And, okay. Okay. As you can see, there is the blinking LED. Okay. So, that's all. I hope, okay, everything will be available on GitHub in a few days, just after the conference. So, these are the references I use to write everything. If you have any comment or something, I'm here to speak with you. And also, I would like to know if you do additional things on that. Okay. Thank you very much for being here. Thank you so much.