 Anyway, this is Steve, Sam, and the door. Let's give him a big DEFCON welcome. Afternoon, everyone. Welcome. Thanks for having us here. You may not believe it, but not only was that our first shot at DEFCON, it was actually our first shot ever since we got away from breakfast this morning anyway. So, all right. Well, welcome, guys. Thanks for having us. We're here to talk about the conclusion of our research. Feels like it's been a long time into hacking and access control system. This is called perimeter breach. My name is Steve Pavone. I'm head of advanced threat research and principal engineer at Trellix, and my Twitter handle is here if you want to connect afterwards. Most of the team makes fun of me since I'm a manager. Usually they joke that I'm not allowed to do anything but excel spreadsheets, which I can write a mean function in. But when I'm doing technical stuff, I'm interested in vulnerability root cause analysis, reverse engineering, exploitation, and actually with this project got some experience for the first time with hardware hacking. My name is Sam Quinn. I'm a senior security researcher at Trellix. I could have summed all this up which is hacking. I really like all aspects of it, but some of my core technical interests are listed here. I like exploitation, hardware hacking, looking at bed and systems like IoT devices and things like that, as well as just OS fundamentals. Now, Sam and I have interests outside of just hacking and computers and we're both avid mountain bikers as well as you'll see when we're not in the lab finding crashes, we're somewhere out there and crashes managed to find us either way. This is real footage, by the way. We're not faking anything here. All right, let's get right to it. The target for today and what we chose is the HID Mercury access control panel, which is this beautiful bright red board that you see. We chose the Lanelle 4420, which is a partner of HID Mercury. And the reason we got interested in it, we're going to talk about the how, the what, the why's of this project. But we got interested in it because obviously access control is one of those areas of critical infrastructure and industrial control systems that is really prevalent in this increasingly targeted attack space and really has not been widely researched, especially over the past few years. So we got interested in it for that reason. Before we get into the why and the how we did this project, let's set the stage for how this is typically deployed. Well, you see this beautiful door on stage that we unceremoniously brought in halfway through the last person's presentation. This is actually the Lanelle card reader. Controller is plugged in behind there and we have managed to a badge reader. This is typically going to be deployed on a local network. It is possible to make this cloud-facing but highly non-recommended. The panel itself can manage up to 64 different devices. In this case, we're using a badge reader. And being on a local network, we use a local network manager or an LSM to actually manage the door operations. And for Lanelle, that's this server called On Guard. That's a server that's responsible for facilitating all of the user control, badges, access, all of that provisioning. And then the board itself is kind of a dumb control relay. It essentially just flipped electric relays and we'll talk about that quite a bit more. Well, one of the things that first caught our eyes when we were exploring this target, this 4400 panel, was some marketing material from Lanelle that had specified that this had been approved for use in government facilities following, quote, rigorous security, vulnerability, and interoperability testing. Well, obviously, this really kind of intrigued us. We found out through the research process that this as intended to specify physical security testing, but really let us down the track of saying how does this hold up from a cybersecurity perspective? And that's what led us to these findings. Now, we did originally disclose all of this just a couple months ago at Hardware I.O., where we spent a lot more time focusing on the hardware hacking process and getting to a root shell, which we'll show you is going to be our starting point for today. And so for the purposes of this talk, we're going to focus on just three of the eight CVEs. But we submitted and patched eight CVEs, four of which are zero-day, unauthenticated remote code execution vulnerabilities, or were at the time we disclosed them. These are now all fully patched. The who in this scenario is who was affected by this. And as you can see here, the 4420 panel was the one that we chose and ordered off of eBay for a few hundred bucks. But throughout the research process, we did find out that additional eight boards manufactured by HID were also vulnerable to these same issues. And so there was a much wider install base than we had originally thought. Furthermore, there's more than 20 partners of HID Mercury, including Lynel, the board that we looked at there, that use these boards and rely on them. And all of them were vulnerable to the same issues as well. So this represents millions of controllers at tens of thousands of sites worldwide, and really the vast majority of the Fortune 100 companies. So the install base is pretty simple. We chose to approach this project in what we call Choose Your Pone Adventure, a little spin on the classical phrase here. And what that means to us is we're going to explain the process we took at various iterations of the project and the decisions we made at those steps and why. Now again, I mentioned how we have already disclosed these issues at Hardware I.O. So for today, we're going to start assuming we have a root shell on the device, which we do. And we're going to actually live hack it in iterations on stage here throughout the process. So of course, what could go wrong? We're not doing just one demo, but like three live ones. So we're going to really tempt the demo gods. This is all a network vulnerability. So you have to be on the same network as the device, which many of you know is kind of the low bar of exploitation. But either way, these are unauthenticated RCEs. As far as standard operations for the panel, one of the first things we looked at was of course doing a network scan. And we used Nmap to find just these three open ports. I know with the lights, it might be kind of hard to read. So just like three or hand up if you can't see or interested in something. But the ports that showed up on the scan were port 80 and 443 for the embedded web server that runs. And a separate port 3001, which at the time we didn't know what it did and found out later, that was that management server, the on-guard management server. How it communicates to the panel directly. But because we bought it off eBay, we had kind of this half-baked solution and we didn't have the on-guard set up at this point. When you boot up the web server on the device, which comes on automatically and by default, you're greeted with a typical login screen, admin password. You'll see this in a moment. It does pretty standard session management, including cookies for the most part. A little preview of things to come there. It does it quite well. Configuration pages are primarily what you see inside of this web server. So if you look closely, there's almost nothing that's related to actual bad usage or anything related to doors. This web server is used to configure the panel. And then it becomes kind of useless from that point on where you'll take over with the on-guard server and do all of the door-specific functions. The network setup page really caught our attention. It has a number of inputs. We'll show you why it was really interesting in a moment here. For right now you can just see that it's managing the host name of the device and we'll come back to that. All right. So that brings us to Choose Your Point of Adventure number one, where in this project we were just trying to look for an RCE, our first zero-day, and hypothetically unauthenticated. Three different areas that we could have explored here, the first one being an operating system vulnerability. This would include things like the vendor and product-specific libraries and files, keys, creds, crypto, the typical stuff here, maybe configuration flaws. We chose to go with more of a combination of web-based and network vulnerability and we decided to look at things like command injection because we had a web server that took user input and directly contacted the board and worked with the board. So bypassing the network stack which would have really been looking for probably an end-day or maybe a really cool O-day in third-party libraries or networking stack itself. So the process we went about as we decided to look at the web form and of course we're shortening this a little bit, but one of the areas that was interesting was command injection and our injection candidate here was the device host name itself. If you look at one of the root processes that spun up when the board boots here, there's a DHCP call where it does all the network factoring and one of the parameters to that DHCP call is dash H or host name of the controller. In this case, it's controller one and we can see by catting out the host name file that it is coming from the controller one. So if we can control input through the web server and get it to actually execute commands as root, that's a pretty cool command injection. Now before we talk about that some more, let's look at what are the restrictions. Everybody has client side, JavaScript restrictions. This is no different. What you'll see here if you can't read it is this is a alphanumeric and period and hyphen are the only characters allowed on the client side. When we look at the actual JavaScript, it matches up very well to the string. It's only allowing alphanumeric and period and hyphen. On the server side, there's a function called XSS string test for cross-site scripting string test and that looks for some additional kind of funky characters here. Of course, tied to cross-site scripting and other injection attacks but for us the ones that were most harmful to work around were the forward slash, of course, if we wanted to do a path and a command injection, the ampersand and the semicolon character for delimiting commands. One final thing here was this parse forms data function and the thing to pay attention to here is this string tokenizer function which will split our host name every time it sees either an equals or space. The equals we probably don't care about but the space is a really useful character in command injection and so we had to find a way around that. Before we get into that, let's talk about authentication and how it's handled. For get and post, this is kind of funny here. So get request are handled exactly as you'd imagine. A session ID is created by calling get session ID and return and then as you'd expect that session ID is compared to the session ID that's taken from the cookie value. If it checks out, the page is authenticated. For post request, it's done slightly differently and pretty poorly here. So it calls get session ID from cookie so far so good but then it never compares that to anything. So we can use any arbitrary session cookie value. You'll see Sam use 1337, 1337 in a moment here and we can send any post data completely unauthenticated and it'll actually redirect to get request looking like it failed but it will actually send the data. Let's tempt the demo gods and Sam you want to take over and do a little dive demo for us. Thank you. So here we go. Let's get the correct window where it should be. It is over here. Let's see. I'm going to go a little bit bigger. Hopefully that's better. So didn't clear this from our test before but we're going to start a listening server. This is going to be kind of the command and control aspect of this. We'll kind of dive into this a little bit more in detail. However, we'll start that off and have that run in the background. When we now go to the, we'll actually bring up the web server. So this is actually the website that is running on the Linux system on the board itself and of course as you can see there is a login page normal and if we go ahead and log in it will indeed give us that cookie that Steve mentioned earlier. All right. So logging in and it might be hard to see but over here there are some session IDs getting appended to the get requests and if we looked into the post parameters there's also a cookie there as well but we'll go over to that network host name that we wanted to command eject into. And as you can see it is controller one at the moment and now if we go ahead and actually try to do our unauthentic command injection by running this command where it is, we saved it off CI1. So this is the command injection where it's now bypassing that JavaScript that Steve showed earlier where it's restricting characters and what not. We do have the cookie as just a bogus 1-3-3-7 super elite cookie there and then the host name has this command injection that we'll cover in more detail in just a second so hold on for that but as you can see there's really nothing here that should have allowed this to take place. So if we go ahead and run this it looks like it failed. That's because the post data actually did take effect but then when it tries to refresh the page the get request actually fails so that's why we see this timeout error here. But if we go back to the web page and actually refresh this by just clicking network again, you can see now the host name is that big long command injection that we actually sent. That was all unauthenticated. Anyone could have done that without knowing the password or anything. So now we'll go back into our slides and I'll kind of explain why we chose that set of command injection characters and what not. So as Steve mentioned this is not a space but it works just the same in Linux interpreters so that is actually a tab character and that was not bypassed or checked in that XSS string test function and as Steve also mentioned this is the function that we're trying to get into more importantly into the host name and because this is when you're injecting into a process it's a halting operation and it's kind of a hard place to halt when you don't even have internet yet so we wanted to actually reach out to that command and control server to download more commands not having to go through the host name with all those restrictions for forward slashes and things like that. So the way that we wanted to get this command to actually run where it's actually W getting more commands from that listener that we set up is to actually nest another DHCP call in here to actually have the network finish its upbringing and actually get a valid IP address so the desired command injection can take place and that worked actually pretty well and that's why we filed it as our first CVE unauthenticated command injection the only reason this is only rated as a CVSS 9.0 is because we can't trigger it on the like on command it had to actually be on a reboot call where that DHCP process pulls in our host name that we modified and that's kind of where our second Choose Your Pone adventure took place where we needed to find some sort of reboot primitive because a few ways that we went about looking at this the first was looking at the web server as we just found that command injection is there any valid ways to cause a reboot and the apply settings tab did indeed at the end reboot the device however it did check for cookies correctly so we couldn't use that for this unauthenticated command injection here. The next thing we could have looked at is looking for a system exhaustion where we're trying to trigger some of the watchdogs on the device to actually forcefully reboot the device or the controller and that did work it took about an hour to actually do and it was really noisy it was thousands and thousands of requests but it did actually trigger the watchdog so that was always a fallback but we didn't really like that we wanted to be a little bit more meticulous about it and actually try to find something better so what we ended up looking at was trying to find some sort of crash that would cause a segfault and then you know look for more memory corruption vulnerabilities where we can actually use that to actually reboot the device and the reason a segfault here would cause a reboot is when we started to look at that as an avenue all segmentation faults on the device called the custom cordon pandler and you can always check what cordon pandler is on your machine by cutting out this cord pattern file in your file system and as you can see here this one says custom MSC cordon pandler so that was kind of interesting and that is just a bash script that if you look at the very bottom it eventually does call reboot and this was perfect for us since all of the websites or web pages on the device are CGI bin compiled the files any of them if you can cause a memory corruption vulnerability will dump their core so that's where we started to look with our as much as possible and to do that we wanted to really kind of improve our odds with automation anytime I get a ready tool I get pretty happy so using item python here we started to look for some of these dangerous functions that you can most familiar kind of or most common ways to actually get memory corruption vulnerabilities so there's a list here I'm not going to go through them but looking for these and with the power of automation through item python we wanted to actually find where these were user input could actually hit these before any authentication took place so the python script would find where these were being ran before any sort of authentication or cookie check would take place and as you can see we did find a few however all of them were actually programmed perfectly fine with static size fields things like that not very helpful for us to find memory corruption vulnerabilities however on the next page here as the list continues the last one is an advanced network CGI which did have 8 stir copies that we could actually use for memory corruption vulnerabilities where the source and destination pointers were actually attack or control our user what we passed in as the user we could modify the way we wanted to test this because it's never good to test live on the only board that you bought off ebay is we actually set up an ARM QMU virtual machine to actually emulate these and the way that we emulate it is since we have that root access on the machine we actually dumped the whole MTD partitions of all of the you know like the file system the boot all of that and then actually CH rooted into it through this ARM VM and that means that all of the configuration files and all of the other files that it's looking for are actually in the right spot since now we're into the CH root environment and we can execute these binaries as usual so you can see this is kind of a joke but we're actually interacting with that advanced network CGI bin file that we identified statically could have these memory corruption vulnerabilities in by just echoing parameters into it so this is how the CGI bin files take those parameters and you can see right below there is the timeout window that we saw when we did the live demo earlier so it is working properly now we wanted to fuzz it so to do that we used radamsa it's a pretty really simple fuzzer that just mutates whatever you pass into the standard in and then on its standard out will have something modified so you see here there is this is a test passed directly into radamsa and then it gets mutated to something else they changed some bytes to non ASCII printables and to do this for the CGI bin files since they take the post parameters over standard in as well we can take a valid post parameter string just pulled right out of the web server and then pass it into radamsa and as you can see it flipped one of the last octets on this DNS server to negative one which pretty good test in my opinion so we didn't want to run this fully you know manual every single time that's not how fuzzing works so we set up this little fuzzer that's I think pretty cute it's like 13 lines of code or something but it is all written in shell and it uses the radamsa mutator so you pass in the normal post parameter files here to get mutated as soon as it gets mutated we actually pass that directly into whatever CGI bin file we want to look at and then of course if it crashes which means it returned a return code other than zero we rerun the whole test case with the mutated data inside a gdb and then call a backtrace on it so while it looks super simple it actually gives great results where this is a crash that we found from that so you can see that the account stir here has a much longer string than it usually has and that is what radamsa decided to mutate on this run and you can see that it crashed right below in stir copy right as we suspected from our static analysis which kind of goes to show that we spent all this time getting this emulator setup and what not and didn't actually found any more crashes than we did statically but it's still a kind of a fun learning experience and this is where we filed this as our second CVE for this talk here that it's an unauthenticated denial of service where it is just because it can cause a reboot on command that's why it's just a denial of service the crash in stir copy was actually just an out of bounds read so we couldn't use it to write anything but I'll let Steve cover how we used these together as a chain to kind of continue our exploitation okay so now we've got two vulnerabilities which work in concert we have a command injection which is triggered at reboot and we have a way to trigger reboot default so we have a way to get full unauthenticated code execution and that meant it was time to upgrade to the latest firmware and kind of bypass our ebay yolo route and see if we could make this a little bit more official so we actually called up we live in Portland we called up one of the actual legitimate third party installers for Linnel systems a company called convergent we put heavy air quotes around social engineering we're not like doing a ton of social engineering here but we may have done a little cloak and dagger when we described the project to them of what we wanted to build out this monstrosity that you see on stage here so they're like you want us to build what why okay you're paying us how much okay we're good alright so they came to the lab and actually built out this full system and they integrated in the on guard as a standalone server and you can kind of see some of the pictures here it was wired up with a controller and card reader so this is essentially an installation that mirrors a production building install minus the fact that we have no glass in there but we'll mime that and it actually works just like you would and and our controller is actually on the back on a panel where you can't see it above the door that would be in a server closet typically but we obviously don't have room for that so otherwise this is a production system they also gave us some training and hands on experience with how to provision doors and badges and users and all the fun stuff that came with the software that was good for us to learn but it paled in comparison to the usefulness of being able to finally download and push firmware to the device so we could test whether our vulnerabilities survived from an older version of firmware to the latest one just doing this and we also had a copy of a legitimate firmware on the file system despite being encrypted on the linel that we had or on the on guard system that we had alright so that brought us to a success and failure point here let's start with a failure and the before as you recall Sam saying there was a seg fault on every system binary meaning it would reboot the system well afterwards they had restricted this just to the two main linel system binary or mercury system binaries here and actually that meant that we had lost the seg fault that led to our reboot and we couldn't arbitrarily trigger our command injection anymore and those are the two I know you can't read it but those are the two files that are now in the new crash dump handling file however our command injection did survive and update to the latest firmware version and that was really the higher bar here we knew we could find some way to get this thing to crash or reboot and that was really the next step of this process choose your own adventure number three now we need an alternative method of getting that unauthenticated RCE back because all we had is code execution unauthenticated but not on demand so we could have looked for a new standalone vulnerability a zero or one click kind of do it all in one here we could have looked for a new reboot primitive or a crash to replace the one that we missed in this chain here that we lost in the upgrade process and I suppose we could have updated the we could have actually moved on and just on our malware or door exploit because at some point the board's going to go down or going to be rebooted for maintenance and it's going to trigger that command injection obviously we're way too lazy to do that so we went ahead looking for a new toy to play with now luckily with this upgrade came some new fun functionality here specifically the firmware upload option and what you'll see is this diagnostics page on the web server added the ability to upload firmware and it says specifically will reboot board it's almost like they were in our heads here this was exactly what we're looking for so we're going to go ahead and do another live demo here or attempt to kind of showing you how we managed to play with this a little bit cool so we're back at the web server here where is it to the left okay it has timed out so I'm going to try my best to log back in I can't see anything down there but am I on it anybody read it okay cool it made that really hard to see maybe I get over and I'll pull it back okay wrong address that's why okay so what I'm going to show you here is that we're going to log into the web server itself and we're going to basically try to show you two things the ability to arbitrarily reboot the board Sam runs everything in the Dvorak keyboard which is really fun to switch back and forth from English to Dvorak I knew this would bite me somewhere alright so we're going to show you basically trying to log into the device do a bypass of the login and actually show you what the session management looks like problem with that yeah it's 8 cool alright let me pull this back on screen so you can see it here okay so we're back at the login screen and I have the developer tools up so we can see session management a little bit here just like Sam showed I'm going to log in for the first time legitimately so we can get a valid session cookie then we're going to capture the get request log out and see if it handles it properly so if we go over to the diagnostics tab that was added here that's the one that I mentioned was added that has the firmware upload feature and you probably can't see this I'm going to highlight and developer tools there is a diagnostic CGI tab that was requested and the session ID is validly appended onto there so I'm going to right click and copy the essentially the get request so we can test that logged out as well before we do that if you look just a little bit further down here what you might see is there's a request to another CGI page called view firmware update that CGI and you may have sharp eyes and see that that does not have a session ID appended onto it so let's look at that a little bit closer we'll log out and we'll try this get request to diagnostics page and see if it fails which we expected to well yes the session cookie was not valid it handled that properly so it was unable to actually log in I've got to bring this back over and I'll pull it over in just a minute so you can see this alright so now I'm going to go directly to that CGI page that I showed you before that was loaded which is view firmware update directly and what you'll see is we can browse that page completely unauthenticated without logging in whatsoever and randomly upload files to it which could not believe thank you thank you yes alright thanks for bearing with me through that demo train wreck alright so now we can upload a file what I'm going to do is I'm going to choose a file from the file system here and this is actually going to be running in the background it'll cause the segfault which we're going to explain to you shortly here so you the people in the front row may actually hear it reboot the device as we load this is going to actually segfault and reboot and we'll talk about how and why this works in just a moment alright let's click load file installing and sometime in the next maybe 30 seconds we some of us will hear a little beep there alright let's go back to the slides now and continue on and explain what's happening in the background okay we have a file that we've now control the file input to there's a few areas of interest we could look at the file contents itself you might have just heard the board reboot or the controller reboot we could look at the file contents itself for some kind of an overflow the file name the characters that are input even the things like the file size and we started to play around with could we control one of these to get a crash the first thing that we did on this diagnostics page is upload an empty file called foobar.txt doesn't matter what it is didn't have any contents in it we're just trying to see what happens as it went ahead and tried to install that it eventually aired out of course it would be really awesome if it didn't but it aired out and it through this error invalid signature size so we knew that it was looking for some kind of a file signature and more so that it was somehow parsing a size maybe that was interesting to explore a little bit further so the next thing that we did we pulled up that actual valid firmware file from the from the on guard system and it's an encrypted file so for the most part it's uninteresting until you get to the end of the file and the last hex 158 bytes if you have sharp eyes are a base 64 encoded blob as you might have guessed this specifies the file signature and more so at the very end there are three ASCII bytes 158 that specify the size of that file signature so it's not doing it dynamically parsing in byte by byte and determining a size mathematically it's taking in this case what we call a user controlled value here because we can upload this file and it's using that to calculate the size of or to compare the size of the file signature so the next thing we did of course was going and look at the code responsible for parsing this firmware file signature size check so the first thing that happens is there's a malloc of static malloc of 190 hex bytes and of course then the file is opened and saved off using a file open command so far so good now this is going to be hard to read so I'll just dictate it as we go the next function here is an F seek or a file seek it will go to the end of the file minus three bytes of course to retrieve those last three ASCII bytes which are a size field and using F read will read those in as a size value now it will come take a string to long or stir to L and change that ASCII value to a long value and as you guessed it shortly later in the F read function that will be used as a parameter here to the size and of course if we have a static buffer and we have a dynamic size that we control that's prime for overflow and of course this is where a heap overflow does happen shortly later in the file close function is where we actually see the crash happen and we can start to leverage it and we're going to show you a little bit more detail on that alright our steps to overflow or to test this we created a fake file basically a copy of the firmware file and we filled it with a unique and predictable pattern just think of your metasploit pattern create that's what we're filling it with to see if we actually control any registers in here now because this is an encrypted file it needed needed the salted underscore underscore underscore file header so it does check that and we added that to the beginning of the file and then we changed the file size or file signature size here to 999 anything over what was it 190 the static buffer size will work they had used 158 we changed it to 999 and then finally we set a break point here in we'll talk about you know we're going really in the context of the emulator Sam was talking about earlier but we set a break point here before we thought we controlled execution in the file close function and if you can see what's highlighted is a branch instruction and unconditional branch and arm to R3 register well we know we're going to hit this and why is that important well if you look to the right side at the registers you can see R0 R1 R3 and R6 all have our pattern data so they've been fully crushed with the overflow and R4 has a pointer to the pattern data that we've overflowed as well and that's going to be important here now before we go into Rob and we're going to spend a few minutes talking about the Rob we did we actually managed to get this working really beautifully in Rob the next few slides will show you how that works when we try to transfer it back to the physical hardware we had all sorts of issues like we're just it was unbelievable we had heat confusion issues and process threading and just would not transfer back to physical hardware so you'll see what we ended up doing is we just used that file to cause a reboot and essentially trigger our command injection but we do have full code execution using the Rob gadget in the emulator one is all we needed just a single Rob gadget and what we have on screen here is two commands the first one or the top half is just a script using Robber to search for Rob gadgets in all the binaries and third party or imported libraries we did use that and then we put we pushed it into a regular expression to filter it down to a set of useful gadgets now even if you can read these closely you may not know why these are useful gadgets obviously we're going a little bit out of order here you'll see that in a moment the gadget we chose here is just these five instructions and we'll talk about why these are important here the approach that we took is we wanted to so there's an un-conditional branch to R3 as I talked about and that's where we get the start of control if we can get into R3 an address that points to the beginning of our gadget which of course we can because we control that register we can potentially call a system call here alright so the first step was getting an address of our gadget into R3 because it gets R0 is moved into R3 here so the first step here is we want to get R0 as an address to our system call it's moved into R3 and then five instructions later that un-conditional branch calls it directly so it'll be calling system however to get an argument for system in arm the argument has to be still an R0 well that's beautiful because the second instruction of this gadget is moving R4 into R0 and it's not mangled in between then so not only can we use R0 to get system but we can use R4 to get our parameter to the system or our river shell into R0 and it'll be called in the un-conditional branch to R3 okay so good things come in small packages here when we started to put these into the correct offsets in our pattern file you can see that we used a WGIT command Sam talked about this in the command injection earlier this is going to be our attempted river shell you can see the locations of where we have R4 and R0 only 28 contiguous bytes though for us to get execution before R0 is messed up now as we were executing this we thought it was working perfectly and we'd be able to get our reverse shell but for some reason four bytes of that reverse shell string get copied and basically pasted into eight bytes later mangling our IP address and so that caused an epic fail here however in the process of running that Sam just because he likes to yellow everything just like let's change it from I don't know like whatever it was IP address to AAAA like that'll make some difference and of course it did and it caused a similar crash but now a four or R4 was located way earlier in the pattern file so instead of having 28 contiguous bytes we had something like 400 plus contiguous bytes so if you can see the pattern here that R4 points to it says QKAA that's the ASCII part of the pattern and you'll see it here in our pattern file so the wrap gods kind of smiled on us so now R4 is way earlier and we don't even have to bother with this reverse shell that we essentially push commands to from our C2 server we can actually just call system with a direct reverse shell as the argument to it and if we go back that's the right side of the screen so where R4 is we just did a straight up so cat reverse shell and connected to that directly and that's what we'll show you in a minute here. Alright so let's summarize here we have a break point at the call to Rop which is our branch to R3 and R3 has to be the address of our gadget okay so we can see that that does match up the address of our gadget works I know we're moving quickly but you can go back and check some of these later I know it's hard to see there's our gadget once we get into executing that address we have just those five instructions and inside of it the last thing is another unconditional branch to R3 so our complete pattern file here looks like this R4 has our reverse shell in the very beginning some 400 bytes later we have a system address in R0 and our gadget address in R3 and that's really all it took and we'll see here from the complete Rop that we now have system execution with our arbitrary so cat as the parameter to it and you see that we're on the break point where it's about to get called and that of course does work beautifully in an emulator doesn't go back real well to the hardware we might go back and figure that out at some point either way all we cared about was kind of learning this process and getting the door to crash so we could pick up our command injection that was then filed as our highest CVSS score of 10.0 it is arbitrary unauthenticated code injection code execution excuse me and that was also patched so for the last part before I do our demo Sam's going to take us through exploitation of this we call it malware with heavy quotes obviously malware in fact we're not even really writing malware but we are trying to interact with the door directly and Sam's going to show you how that's done. Alright so we'll wrap this up here and then do the final demo so this kind of brought us to the choose your printer venture 4 where now we got back our on command command injection with that reboot and chaining the two together and we could have gone about creating our quote unquote malware in two different ways the people that were actually hacking this in their life would probably want to do some ransomware thing but that's I don't know that's not cool so we wanted to do the more James Bond goes in the shell type approach where we actually could gain like you know secret access into a facility bypassing all monitoring or what not so that's ended up what we went down that path but to do either of those we actually needed to figure out how the door locks even work I'm going to kind of go quickly through this section these are through the use of relays which are electrical switches you can see them there's four here right now and then the switch is hooked up each of the door locks are actually hooked up to these outputs to find out how the software actually controls those relays you can look in the binary that has all of its symbols for relays and you can see that there are one function for on and off for each of these and they're even more simple when you look at it there is a simple kernel module where you can interact with I octal give it the file descriptor for the GPIO and then the GPIO device and then a parameter and then a zero indexed array of which relay you want to actually control so to actually make this into our malware and to open the door whenever we want we cross compiled it for ARM with just copying that I octal call and ran it on the device however you can probably see that there is this while loop here and this was our brute force way to actually keep the door unlocked whenever we would trigger an unlock it would instantly relock so calling it every millisecond was the right way to get it to stay persistent which is kind of a fun hack right there but now we'll go on to the demo and I just want to summarize kind of what we've done up here on stage live this could have all been done with our single click exploit but we wanted to separate it a little bit and try to explain it a little bit more the first thing we did was that command injection through the host name unauthenticated we then uploaded a arbitrary file a firmware update file that we can control the signature size to which caused a seg fault initiating that reboot that we heard just a little bit ago at that point at the device startup it's getting an IP address and it's calling our command injection through that host name parameter and at this point it's actually downloading more scripts from this laptop up here to run the reverse shell and then that reverse shell gets opened and now we'll show you live connecting to that reverse shell and opening the command so here we go let's see if we can do it switch to the vorac let me clear this goons were joking that we could make this a lot easier and just save you guys 50 minutes by doing this but I think they were being smart assets so alright so here's the reverse shell connection we'll go ahead and connect it and you can see that we do have a shell and if I run who am I we are root and then into finalize it we'll run our super leap open door hack so here we go alright so that was everything we have today thank you guys so much for coming we're going to stick around for a couple minutes for questions want to thank Carrier as well who handled the disclosure process to Mercury they're here today thanks to that team thank you guys for attending if you want to connect with us on social media or just stop by for questions feel free thank you so much enjoy the rest of your DEF CON