UART-to-Root: The (Slightly) Harder Way

Quick Note: This post assumes some knowledge of UART and U-boot, and touches slightly on eMMC dumping.

Many familiar with hardware hacking know that UART can be a quick and easy way to find yourself with a shell on a target device. Often times, especially in older home routers and the like, you’ll be automatically logged in as root or be able to log in with an easily-guessed or default password.

In other circumstances, you may need to edit some boot arguments in the bootloader to trigger a shell (such as adding a 1 for single-user mode or adding init=/bin/sh). With this initial shell, you can dump and crack passwords or modify the firmware to grant access without the modified bootargs (change password).

Recently, I came head-to-head with a device that had a slightly more complicated boot process with many environment variables setting other environment variables that eventually called a boot script from an eMMC that did more of the same.

Some Background

My target device was being driven by a cl-som-imx6; an off-the-shelf, bolt-on System on Module from Compulab. My target version of the cl-som-imx6 utilized a 16 gig eMMC for firmware storage that had two partitions: a FAT boot partition (in addition to U-boot on an EEPROM) and an EXT4 Linux filesystem.

cl-som-imx6 with eMMC removed

My first goal for this device was to get an active shell on the device while it was fully booted. Since I had multiple copies of my target device, I went for a quick win and removed eMMC then dumped it’s contents with the hope of recovering and cracking password hashes. While I was able to get the hashes from /etc/shadow, I was disappointed to see they were hashed with sha512crypt ($6$) and have yet been unable to crack them.

Without valid credentials, my next goal was to modify boot args to bypass authentication and drop me directly into a root shell, with the hope of being able to change the password. The classic init=/bin/sh trick.

It’s important to note that when modifying the bootargs with init=/bin/sh, the device will not go through its standard boot process, therefore it will not kick off any scripts or applications that would normally fire on boot. So, while you may have a root shell, you will not be interacting with the device in its normal state. It is also temporary and will not persist after reboot.

The Problem

This is where it started getting a bit tricker. In my experience, U-boot usually has an environment variable called bootargs that passes necessary information to the kernel. In this case, there were several variables that set bootargs under different circumstances. I attempted to modify every instance where bootargs were getting set (to add init=/bin/sh) to no avail.

# binwalk part1.bin 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
28672         0x7000          Linux kernel ARM boot executable zImage (little-endian)
34516         0x86D4          LZO compressed data
34884         0x8844          LZO compressed data
35489         0x8AA1          device tree image (dtb)
1322131       0x142C93        SHA256 hash constants, little endian
3218379       0x311BCB        mcrypt 2.5 encrypted data, algorithm: "5o", keysize: 12292 bytes, mode: "A",
3982809       0x3CC5D9        device tree image (dtb)
4273569       0x4135A1        Unix path: /var/run/L
4932888       0x4B4518        xz compressed data
5359334       0x51C6E6        LZ4 compressed data, legacy
5513216       0x542000        uImage header, header size: 64 bytes, header CRC: 0x665C5745, created: 2018-09-26 16:36:26, image size: 2397 bytes, Data Address: 0x0, Entry Point: 0x0, data CRC: 0x9F621F80, OS: Linux, CPU: ARM, image type: Script file, compression type: none, image name: "boot script"
5517312       0x543000        device tree image (dtb)
...

During this time, I also discovered that there appeared to be some sort of watch-dog active that would completely reset the device after about 2 minutes of playing around in U-boot’s menu options.

As a note: I don’t believe this was an intended “Security” function but rather an unintended effect caused by the rest of the device (attached to the cl-som-imx6) after it failed to fully boot after X time.

After an hour or so reading the UART output during boot and attempting to understand the logic flow of the environment variables, I discovered that U-boot was calling a boot script before it touched any of my edited boot args. Luckily for me, this boot script was being called from the eMMC’s boot partition, which I had dumped previously.

Binwalk quickly identified the boot script’s location, but failed to extract it. Using the offset of the script as a starting point and the offset of the following signature as the end point, I used dd to extract the script. As luck would have it, the script was actually a script (plaintext) and not a binary.

# dd if=partition1.bin of=boot.script skip=5513216 count=4096 bs=1
4096+0 records in
4096+0 records out
4096 bytes (4.1 kB, 4.0 KiB) copied, 0.0173901 s, 236 kB/s

The script was exactly 80 lines and contained several if/else statements, but most importantly, it had only one line setting the bootargs. At this point, my theory was that the only environment variables that mattered were being set by this script. I needed to modify this script to add init=/bin/sh.

# cat boot.script 
setenv loadaddr 0x10800000
setenv fdt_high 0xffffffff
setenv fdt_addr 0x15000000
setenv bootm_low 0x15000000
setenv kernel_file zImage
setenv vmalloc vmalloc=256M
setenv cma cma=384M
setenv dmfc dmfc=3
setenv console ttymxc3,115200
setenv env_addr 0x10500000
setenv env_file boot.env
setenv ext_env ext_env=empty
...
setenv setup_args 'setenv bootargs console=${console} root=${rootdev} rootfstype=ext4 rw rootwait ${ext}'
...

The next hurdle was that I didn’t have a direct way of modifying the contents of the eMMC without removing it and that’s the easy part. Getting it back on the SOM would have been tougher work than I was willing to tackle at the time.

The Solution

Without a simple way to modify the boot script, I decided to try to manually copy and paste each line of the script into the U-boot menu shell and, if necessary, remove all other environment variables.

I ran into two problems with this approach. First, any line over 34 characters that I tried to paste got truncated to 34. This was likely just caused by the ft232h buffer or something else with the serial connection. Second, and more annoying, was the watch-dog reset. There was simply no way I was going to paste in 80 lines (especially as many would require multiple c/p’s due to the 34 char limit). Even after removing as much as possible

My only answer was to automate the process. I had previously been playing around with the idea of bruteforcing simple 4 digit security codes, so I already had the outline of a script ready.

I modified the script to read lines from an input file and write them to the serial device, where any line over 32 (to be safe) characters would be chucked up. To ensure data was sent at the correct time, I put made sure the script waited for the shell prompt to return before sending the next line, with an additional .5 second sleep for good measure. Also, since the script would take over my ft232h, I needed to make sure it stopped autoboot at the correct time to enter the U-Boot shell.

This approach worked perfectly and I was dropped into a /bin/sh shell as root. I then took control of my ft232h again so I could interact manually. With a quick passwd, I changed the root password and rebooted. As the modified environment variables didn’t persist through reboot, the device booted as normal and presented me with a login prompt. I entered my newly set password and I was in.

Serial and script output ending in shell
Changing password

I’d post a screenshot of the final successful login after full boot, but I’d have to redact too much stuff that it doesn’t make any sense.

As a note: So I could keep an eye on everything, I used a second ft232h to watch the target’s TX pin and since it echoed everything back, I could also see my script’s input. Also, the watch-dog was still in effect since the device didn’t boot as it should have, therefore I had to be quick on the passwd.

The Script

Below is the script exactly as I used it. With a touch of modification to the until1 and until2 vars, it should be useable for other targets.

#!/usr/bin/env python
# By Mike Kelly
# exfil.co
# @lixmk

import serial
import sys
import argparse
import re
from time import sleep

# Key words 
until1 = "Hit any key to stop autoboot:"
until2 = "SOM-iMX6 #"

# Read from device until prompt identifier
# Not using resp in this, but you can 
def read_until(until):
    resp = ""
    while until not in resp:
        resp += dev.read(1)
    return resp

def serialprint():
    # Get to U-Boot Shell
    read_until(until1)
    dev.write("\n")
    
    # Wait for U-Boot Prompt
    read_until(until2)
    sleep(.5)
    dev.write("\n")
    with open(infile) as f:
        lines = f.readlines()
        for line in lines:
            # Lines < 32
            if len(line) < 32:
                read_until(until2)
                sleep(.5)
                print "Short Line: "+line.rstrip("\n")
                dev.write(line)
            # Break up longer lines
            else:
                read_until(until2)
                sleep(.5)
                for chunk in re.findall('.{1,32}', line):
                    print "Long Line: "+chunk.rstrip("\n")
                    dev.write(chunk)
                    sleep(.5)
                dev.write("\n")
        print "" 
        print "Done... Got root?"
        exit()

if __name__ == '__main__':
    # Argument parsing
    parser = argparse.ArgumentParser(usage='./setenv.py -d /dev/ttyUSB0 -b 115200 -f infile.txt')
    parser.add_argument('-d', '--device', required=True, help='Serial Device path ie: /dev/ttyUSB0')
    parser.add_argument('-b', '--baud', required=True, type=int, help='Serial Baud rate')
    parser.add_argument('-f', '--infile', type=str, help="Input file")
    args = parser.parse_args()
    device = args.device
    baud = args.baud
    infile = args.infile
    
    # Configuring device
    dev = serial.Serial(device, baud, timeout=5)
    # Executing
    serialprint()

2 Mics: An over-engineered solution

Background:

My wife is the Assistant Director at Cottonwood Center for the Arts, a local non-profit art center here in Colorado Springs. As a small non-profit, everybody has many different responsibilities. One of her’s is marketing and social media. A project she has been interested in piloting is a podcast and/or video series to help introduce the public to the many things that happen at Cottonwood.

As the former producer for the Exoticliability (RIP) podcast, I figured I could help her with the technical aspects of setting up equipment and recording. As a non-profit, budget is tight especially for a pilot project, but her MBP already has Garageband and we were able to find a couple cheap USB Mics that came with stands. That should be everything she needs to get started.

The Problem:

As we were getting everything hooked up, we discovered a problem. OS X seemed to recognize both USB mics, but would only use the most recent one plugged in. After much googling and almost finding an answer, it was determined that the problem stemmed from the fact that both Mics had identical USB descriptors, including serial number.

(the following screenshot only shows one mic because I “fixed” the first one already)

The simple solution was to buy a new USB microphone from a different brand. We would pay for the new one and I’d keep one of the originals. But, where’s the fun in that?

Can I Fix it?

If I’m gonna buy a new mic, I might as well check this one out in depth. I took the microphone apart to find a pretty small little board. The mic really only had two things of interest, an SOC and an EEPROM.

The SOC was a CM6327A (datasheet), an apparently common SOC for USB mics, and the EEPROM was labeled MX24C02.

The first page of the datasheet immediately tells us that:

Serial EEPROM programming interface supports customized
VID/PID/Product string/Manufacture string for device
name changed and configuration

This led me to believe that all I should need to do is change the data stored on the EEPROM and that should be enough for OS X to recognize it as a separate device.

Yes I can.

I removed the EEPROM from the board, soldered it to a breakout board from adafruit, and placed the breakout in the Mini Pro universal programmer.

The Mini Pro software did not have an option for an “MX24C02” but it did have an “M24C02”. Figuring that EEPROMs are all pretty much the same, I went with that option. Luckily there was no read protection set so I was able to view the data with no problems.

As you can see in the screenshot above, the data on the EEPROM matches the USB descriptors as reported by OS X. All that’s needed is to change some data and it should be good. I probably only needed to change the serial number (201505), but just incase, I changed all the ASCII data, but made sure the lengths never changes.

I programmed  the changes…

and returned the EEPROM to it’s original location on the USB mic’s board. I plugged the mic back into the MBP and checked the descriptors.

And there we have it, a brand new CAD LOL1337USB Licrophone. While I don’t have a screenshot of it, I can confirm that OS X now recognizes both microphones separately and they can both be used in Garageband at the same time (after some aggregate device stuff you have to do, which is required for multiple simultaneous inputs no matter what).

In the end, this solution saved me about $50, since I had all the tools necessary already, and I got a quick blog post out of it. But I am left with a little curiosity about what I could put in all the unused space of the EEPROM and what OS X might think of it. There’s also a ton of space inside the microphone. Could probably fit a small USB hub and a rubber ducky, but that’s a post for another day.

Badge Hackers Kit

As a fledgling hardware hacker, one of my favorite things about conferences is hacking on electronic badges. I’m not much of a CTF player and rarely do I care about the flags intentionally placed in a badge. I am, however, interested in the hardware itself and attempting to find unintentional method of accessing firmware or making potential modifications.

For the last two years or so, I’ve been packing up random tools from my bench and tossing them in my luggage. I got tired of sorting through all my tools before leaving and upon my return home, so I decided to build out a small dedicated travel kit for badge hacking. Probably important to note that I usually check my luggage. If you don’t check, you might want to put a bit more thought into what TSA would allow. I think the only tool over the size limit is the soldering iron, which might be fine with the tip removed, but don’t take my word for it.

I decided to share my load out to help those who may be new to hardware or interested in building something similar. Also, since I’m still relatively new to it, I’d love any feedback from others. I’ve built out 2 BOM’s, one contains the items I consider “must haves” and the second containing the optional items that most likely won’t be required but can be pretty nice.

Check out the BOM here: https://docs.google.com/spreadsheets/d/13yUsgbyqdR-uTF4VaN706SWAdZshy3CyjNz7YjBWk0U/

If you’re looking for a little more reading, continue on for my justification on some items and some additional things that I include in my personal kit that aren’t priced out in the BOMs.

Hardware Modification:

Travel Soldering Iron:
Hakko FX-901 Soldering Iron or Sainsmart Pro32.

Access to a soldering iron may be the most important thing for diving into the hardware of an electronic badge. Many cons have a hardware hacking village, but irons are usually in high demand. Currently my travel kit uses the Hakko FX-901 which is battery powered (using rechargeable AA’s). Being battery powered is nice because you don’t need to find an outlet if you’re hacking about con. The down-side to this iron is it’s weight. It takes 4 AA’s, causing the iron to be not only heavy but unbalanced.

I was introduced to the Sainsmart Pro32 (AKA TS100) just last weekend and it’s currently on it’s way to me. The Pro32 is powered using a 12-24 power supply, has adjustable temperature, and is just about as small and light as you could possibly make a soldering iron. While more expensive, it has more features than the FX-901. I haven’t personally tested this iron yet, but the largest draw-back appears to be the need for an outlet. I expect this will become my iron moving forward, and will update after some testing. The Sainsmart will be listed in the BOM, subject to change after testing. If you go with the FX-901, be sure to add batteries and a charger.

4″ x 6″ PCB:
This might seem like a weird item to add, but it serves it’s purpose. I have 2 of these in my kit to serve as heat resistance surfaces to do my soldering or removal. They also serve as a spot to set the soldering iron down while your working without needing to shut it off.

Compressed Sponges:
Also might seem odd, but I like working with a clean soldering iron. These compressed sponges are very compressed but expand to 3/8″ when wet. The 12 pack measures to roughly 1/2″ while compressed, meaning you’ll have more then enough sponge to keep your iron clean for a while.

Chipquik SMD removal kit:
This is something I’d definitely consider an optional kit component, but at it’s price I had to include it in mine. Chip removal can be very beneficial in PCB reversing or investigating the chips itself (dumping contents or programming). Chipquik’s SMD removal kit’s specially designed alloy lowers the melting temperature of the solder already on board making removal significantly easier.

56 piece driver set:
Another completely optional item. It’s fairly unlikely that you’ll run into an electronic badge that you’ll need a screwdriver set to hack. That said, you might find yourself hacking something other than a badge. I put one of these in my kit because I’ll often end up picking up some random IoT product or electronic kids toy just to hack on with friends while at con.

Small Adjustable Power Supply:
This is optional. You will almost never require it for badge hacking, but if you want your kit to work with other targets, then this becomes a lot more beneficial to have.

Various breakouts, headers, wires, and grabbers:
I carry a pretty diverse list of header pins with different pitches and layouts. Various different types of jumpers (m-m, m-f, f-f, etc), and a bunch of different sized wire grabbers. I could list each individual item out, but honestly, I’m too lazy to look up the links. The BOM will only contain basic jumper wires which should serve the majority of needs. Check out adafruit for various breakout boards. I’ve found they come in pretty handy, and not always for what you expect.

Additional tools:

  • 20-30 awg wire stripper
  • Small pliers
  • Wire snips
  • Solder sucker
  • Solder wick
  • Solder
  • Flux pen
  • Electrical tape

Signals and Firmware:

Buspirate and FT232H:
The buspirate and FT232H are both multi-purpose tools that can speak multiple different protocol. Each have their advantages and disadvantages over the other. Being that both are fairly inexpensive (for hardware tools), I decided to include both in this kit.

Logic Analyzer:
There are tons of options available for logic analyzers. You can roll your own using an Arduino or RPi, or you can buy something. In my kit, I’m using a Saleae Logic 8 primarily because I already had a spare one. Saleae recently discontinued the 4 channel, and increased their prices, but ~50% discounts are available for non-commercial use with little more than an email.

Multimeter:
If you search amazon for “pocket multimeter” you’ll get a ton of results. I picked up the Victor VC921 cause it was cheap and available for prime shipping (at the time). For badge hacking, you don’t really need something super special. Primarily just checking basic voltages, continuity, and resistance. Anything with decent review should be fine.

JTAGulator:
The JTAGulator is an optional tool as you can usually manually trace out pins to identify JTAG and you can easily use a logic analyzer to identified active UART pins. That said, the JTAGulator makes this process much easier, especially if the badge designer left lots of headers accessible. Also, it’s quite sexy with its hot pink solder mask and large metal-inspired logo.

Various USB cables:
Between all the different tools listed above and many badges now having some USB interfacing, you gotta have cables.