As a reminder, Lesson 1 was a primer on electronics and setting up your lab, and Lesson 2 was an introduction to classical hardware hacking. To get started with security-focused hardware hacking, let’s look at a pretty simple example: getting a root shell by breaking into U-Boot via a serial console. Basically, we’re just going to connect to a serial port, change a boot flag, and get a shell. Sounds simple, right? To some extent, it is! The only real hard parts are finding the serial port, determining the pinout, and determining the timing. No problem, right? By the end of this lesson, you’ll be abusing UART with the best of them.
The unassuming target of this lesson is a Synology RT2600ac wireless router. This is one of the devices that the ISE Labs team assessed as part of our SOHO 2.0 project, but we had a bit of a problem. We had used the device but failed to record the credentials. And the reset button? Broken. This is where getting a hardware shell came in handy. By using a UART to get a shell, I was able to reset the password and get the assessment back on track. Hardware shells allow you to do so much more though, both in the context of repair and in the context of security. It’s a root shell, you can usually do whatever you like.
A Note on Safety
Now that we’re working with something that plugs into the wall, we need to have a serious talk about safety. Like I said in the first part of this series, electricity can be deadly. The fact of the matter is that electricity doesn’t give a damn about your spouse and children. It will kill you without hesitation, should you give it a chance. Now, the voltages we’re working with are usually safe to handle. 12 volts generally isn’t going to overcome a human body’s internal resistance enough to cause damage. However, the only thing between that safe-ish 12v and deadly mains voltage is a cheap wall plug.
Do you really want to trust a random 12v power supply with your life? Admittedly, I did just that. Over the years, I managed to fall into the trap of thinking, “It’s just 12v, it’s safe.” That changed while I was writing this article. I touched a grounded part of the device, while it was switched off but still plugged in. To my surprise, I heard a rather loud 60Hz hum in my headphones. As it turns out, the ground on this device floats at about 60v A/C relative to earth ground, and it will gladly dump over 2 amps to earth ground. That hum was my headphones picking up the 60v A/C signal flowing through my body. 60v is a bit more substantial than 12v; it can overcome the internal resistance of a human body enough to cause damage or, given the right conditions, death. Had I been in contact with something connected to earth ground when I touched the router, this article may have never been written.
That said, it truly isn’t hard to stay safe while hacking away on a device. If you have any kind of tech related background, you’re probably familiar with the saying “trust but verify.” It’s extremely important to trust but verify when working with electricity. Just because something should be at a safe voltage doesn’t mean it is at a safe voltage. So, take a few seconds to measure the voltage and verify that it’s actually safe. And, in general, don’t touch anything until you know for a fact that it is safe to handle. Hackaday has a nice two-part series on safely dealing with mains voltage, and I highly recommend reading through it. It’s extremely rare to encounter a deadly malfunctioning 12v power supply, but it can happen. So take precautions.
Now that the safety rant is out of the way, let’s get back to getting root on this router!
When attacking IoT devices, especially devices that need to stay intact, disassembly can be half the battle. Sometimes disassembly is super easy, but other times it’s downright infuriating. However, there are a few common construction techniques and, subsequently, deconstruction techniques. There are two main types of hardware holding these devices together: screws and clips. I’m sure everyone is familiar with screws, and they’re usually the least annoying of the two. It’s quite common for screws to be hidden by other parts though. Common hiding places are under adhesive feet and under stickers. Finding hidden screws under stickers can be a bit tricky, but they’re usually pretty easy to feel if you rub the sticker with the side of your fingernail. Our Synology RT2600ac has 6 screws, 3 of which are hidden – 2 under adhesive feet and 1 under the label.
On the other side of the annoyance spectrum are clips. These are retention clips designed into the device’s case that snap together when the device is assembled. Undoing clips without causing damage usually requires a bit of mechanical persuasion (that’s an engineer’s gentle way of saying elbow grease). In general, one half of the case will have clips on it and the other half will have recesses for the clips to grab on to. When undoing these clips, we want to push the part with the clip inward and upward to unhook the clip from the other part of the case. Doing so will usually cause a satisfying/terrifying click sound as the two parts of the case separate slightly. Repeat this process for the rest of the clips but be careful not to let the opened clips snap back together. I like to start at a corner, insert a spudger between the two parts, pop the first clip open, and then slowly work the spudger along that side of the device. Multiple spudgers may be needed to keep opened clips from snapping shut again.
Now that we have the case apart, we can access the PCB… sort of.
As you can see, most of the board is covered by a massive heatsink. This restricts our access to most of the important components. but, thankfully, there happens to be a 6-pin header in one corner.
At this point, we don’t know what this header is. We just know that the manufacturer decided it was necessary to include it. There are a few likely suspects though. Two of the most common relevant interfaces are UART and JTAG. JTAG (Joint Test Action Group) is immensely powerful, usually providing flashing, debugging, and boundary scanning capabilities. However, it’s a bit less common, usually uses a lot of pins, and can be rather difficult to use. UART (Universal Asynchronous Receiver-Transmitter), on the other hand, is much less powerful but much easier to work with, and usually only uses 2-3 pins. In the context of IoT devices, an exposed UART interface is almost always used by the bootloader and OS for a hardware console.
Since UART interfaces are quite common and one could easily fit in our 6 mystery pins, I’m going to guess that there’s a UART in there somewhere. Now it’s just a matter of finding it. To do this, let’s first think about why UARTs are used and how they operate. As far as we’re concerned, a UART is more-or-less a two-wire serial connection with a few notable properties:
- One wire is used for transmitting to the device while the other is used for receiving from it.
- The transmit pin is pulled high when not transmitting.
- Data will be transmitted at a certain speed known as the baud rate. If the baud rates are mismatched, any data will be terribly mangled.
- Data will be transmitted with a certain number of data bits, an optional parity bit, and a certain number of stop bits. Again, mismatching will cause corruption. These are almost always 8N1 (8 data bits, no parity, 1 stop bit).
As for why these UARTs are included in so many devices, the main reason is to help with setup and debugging tasks. By exposing the device’s bootloader and OS via a serial console, developers and manufacturers can easily interact with low level functions of the device – something that as hackers we would quite like to do as well.
Now that we know a bit more about what we’re working with, let’s attempt to make sense of our mystery header. To do this, I usually start by identifying ground pins with a multimeter in continuity mode. After connecting one probe to a known ground, such as a USB port housing, we can simply touch the other probe to each unknown pin and test for continuity. We can then write down each pin with continuity as a ground pin and exclude them from future tests. Since pin 2 has continuity, we can note it down as a ground pin.
Next, we’ll want to check the voltage on each pin. After powering on the device, waiting a few minutes for it to finish booting, and then checking voltage between ground and each pin, I found the following:
- Pin 1: 3.28v
- Pin 2: 0.00v (ground)
- Pin 3: 1.80v
- Pin 4: 3.28v
- Pin 5: 0.00v
- Pin 6: 0.89v
A few voltages stand out. There’s pins 1, 3, and 4 which all have voltages close to common supply voltages (3.3v and 1.8v). Remember how the transmit pin of a UART is held high? If there is a UART on this pin header, the transmit pin is probably either pin 1 or pin 4. Another interesting voltage is the somewhat strange 0.89v on pin 6. If there is a UART on this pin header, there’s a good chance that this is the receive pin. This is somewhat counterintuitive, but often times the receive pin will float at a few hundred millivolts. It won’t always float at a low voltage though, so we shouldn’t rule out pin 5 as an input just yet.
With these baseline voltages, we can move on to identifying the transmit pin. Since UARTs usually print output from the device’s bootloader and OS, we should be able to generate data by rebooting the device. Doing so will cause the text from boot messages to flow through the transmit pin, generating a measurable change in voltage. What you use to detect this voltage will depend on the tools available, but the general idea is the same. If all you have is a multimeter, you can measure voltage on each suspected transmit pin as the device boots. If the voltage reading continuously fluctuates between 0v and VCC, then that pin is likely transmit. Using this method, I determined that pin 4 is likely the transmit pin.
Interfacing with the board via UART
Now that we have a signal to work with, we’ll need some sort of UART adapter to interface with it. Some people like to use expensive name-brand adapters, but I prefer the cheapest ones I can get. That way, when I inevitably fry one, I’m only out a dollar or two. However, the ability to use nearly any UART adapter is somewhat of a luxury limited to Linux-based operating systems. If you’re using Windows, or especially Mac, your best option is probably an FTDI or FTDI-compatible adapter.
Connecting the adapter to the target device is usually pretty simple. We need to make 3 connections:
- Adapter ground to board ground.
- Adapter receive to board transmit.
- Adapter transmit to board receive.
We don’t know which pin is receive on the target device, so we’ll skip that for now. Here’s how I connected my adapter to the target device:
Now comes one of the more annoying parts. Remember how UARTs operate at a specific baud rate with a specific number of bits, parity, etc.? We need to determine those settings before we can communicate with the target device. Without specialized hardware, it can be quite hard to calculate these settings. However, there are a few very common settings, so it’s usually trivial to guess a correct combination. The data bits, parity, and stop bits are almost always 8N1 (8 data bits, no parity, and 1 stop bit). For the baud rate, some of the most common settings that I’ve seen are:
- 4800 – Very rare.
- 9600 – Probably the most common option. Try this first.
- 19200 – Somewhat rare.
- 38400 – Rare.
- 57600 – Common on Realtek devices. Not a good sign.
- 115200 – Common on newer, high-end devices.
An oscilloscope or logic analyzer can usually be used to determine the baud rate by measuring the length of the start bit in Hertz and choosing a common baud rate closest to that number. If you don’t have an o-scope or logic analyzer, your best option is to just try different baud rates until something works. Reboot the device to generate messages, try a baud rate, and repeat if needed. If you get no output, the baud rate is probably way off. If you get a lot of garbled characters, you’re close but not close enough – try another common baud rate adjacent to the current one. Once you see comprehensible text, you’ve found the correct baud rate.
How you go about connecting to the UART adapter will depend on your operating system. *nix-based (including Mac) should be able to use the ‘screen’ command, while Windows will require a handful of Powershell commands or a 3rd-party utility. For more information, check out this handy introductory article on Sparkfun, Serial Terminal Basics.
My first attempt was 9600 baud.
The data was quite thoroughly corrupted, so I moved on to another baud rate. Since this device is a fairly new design, I chose 115200 baud.
Much better! Now we know the baud rate – 115200. There’s just one problem, we can’t send anything yet. However, now that we know the baud rate, we can try connecting to suspected receive pins and checking for a response. Remember how pin 6 was floating at a weird voltage, indicating that it may be a receive pin? Let’s give it a shot.
With the suspected receive pin on the target device connected to the transmit pin on the adapter, we can try interacting with the device. Once it has finished booting, hitting enter will usually produce a login prompt or a shell.
Great! It received our enter key and responded. We clearly guessed correctly on the pin and everything is connected properly. Except we don’t have any creds… Time for Plan B (for boot, U-Boot to be exact).
Getting friendly with U-Boot
If we reboot the device, there’s a good chance it will display a message regarding entering the bootloader or aborting the boot process. The Synology router did just that, and dumped me into a U-Boot shell when I hit ^C.
U-Boot lets us do something quite helpful: modify boot arguments (AKA kernel parameters). If you’ve ever used single-user mode or modified init to recover a trashed *nix box, you’re probably already familiar with how powerful these arguments can be. If not, think of them as configuration parameters that determine how the operating system boots. These parameters can change a ton of stuff, including how the device connects to the console and what it runs during startup. It’s also worth noting that these parameters are applicable to much more than IoT devices. The Arch Linux wiki has a nice article on the subject of kernel parameters.
In the context of U-Boot, we can view the current arguments via ‘printenv’.
This particular device has some relatively complex boot arguments, but we’re only interested in one thing: init. If we can change the value for init, we can tell the device to give us a shell before fully initializing. Looking in “syno_bootargs”, “init=/sbin/init” seems pretty promising, so let’s modify that. We want to change it to “init=/bin/sh” so that the device will drop us to a root shell instead of running init. To do this, we’ll need to use the ‘setenv’ command. Normally I would copy the entire environment variable, make the change, and then paste the entire thing back, but this environment variable was large enough to make U-Boot angry. So, I resorted to copying the parts that seemed most important and hoped for the best.
From there, it’s just a matter of running the command ‘run bootcmd’, crossing your fingers, and hoping for a root shell.
Looks like we got lucky! The device dropped us into a root shell! The system hasn’t fully initialized, since we quite literally told it to give us a shell instead of initializing, but we can deal with that. Enough of the filesystem has mounted that we can do pretty much anything we like. Since I was originally trying to reset the device and regain access, my first task was to change the admin password. Like most IoT devices, this router just relies on Linux’s user management facilities. So, using the ‘passwd’ command was all I needed to gain access to the administrative web application and reset the device.
Since most of my recent hardware hacking activities have been for ISE Labs, my next steps are usually to dump the filesystem for static analysis and set up a persistence mechanism. There are often other ways of doing this, but the wonderful thing about a hardware shell is that it drops you right in the middle of whatever walled-garden the manufacturer has built. Unsurprisingly, it tends to be much easier to find vulnerabilities in a device when you can start as the most privileged user in the system.
In general, UARTs are your friend when working with embedded devices. More often than not, there will be a UART in the device somewhere, and it can be your gateway to the bootloader and operating system. Sometimes it takes a bit of work to properly interface with it, but the rewards are usually worth the effort.
With the conclusion of Lesson 3, we now, as the saying goes, know enough to be dangerous. But these are just the basics along with some easy examples. We clearly haven’t seen every device or every scenario. And as hackers, we want to dive much deeper. We need more! So more you shall have. In the coming months we’ll present several more hacks of both the classical and security-focused varieties of hardware hacking, with each one getting more complex. We’ll take a break during the summer to throw in a sneak preview of the IoT Village at DEF CON 27!
Feedback on Abusing UART and HH101
Now that the basics have been covered, what do you think so far? What have you done with this newfound knowledge? What did you mod? You shouldn’t have much difficulty in finding a device laying around your own home that has a UART. Did you have any trouble taking it apart? Did you connect successfully? What did you find? Did this spark something inside of you that you didn’t know existed before now?
We truly want to know. So please leave your questions at the bottom of each article in the Comments Section. You can also share your stories, experiences or resources / tutorials you found helpful right here or in the Hardware Hacking Group on EH-Net.
See you next time!
Ian Sindermann is an Associate Security Analyst at Independent Security Evaluators (ISE), a firm of security specialists that provide a wide range of services including custom security assessments and software development. He is also a researcher for ISE’s newly formed research division, ISE Labs. ISE also runs IoT Village, which hosts talks by expert security researchers who dissect real-world exploits and hacking contests consisting of off-the-shelf IoT devices. Ian’s day-to-day duties include conducting rigorous security assessments on a wide variety of web applications, researching the security posture of various IoT devices, and sharing knowledge whenever possible. His background is somewhat varied, with a primarily self-taught education, prior experience as a wannabe Linux admin, and a childhood spent as a traveling performer. Interests include hardware hacking, legacy systems, mainframes, and whatever tech obscurities he can get his hands on.diy electronics hacking hardware highlight iot lesson sindermann stem uart