In this post I'm going to run through a crash course about UART, and write up some personal notes I use to find them quickly and dump shells on embedded devices. So is going to be a little informal at times but the aim of the post is to get the tips and process across quickly so those who want to can get to dumping shells too! So this focused on supporting the activity of interacting with UART ports as they appear on an average IoT device.
|This is me dumping dump UART traffic from a device using the Adafruit R232-TTL FTDI cable.|
- UART exists, its stands for Universal Asynchronous Receiver-Transmitter
- It usually comes in at least 3/4 pins Ground (GND), Transmit (TX), Receive (RX), Power (Vcc)
- The pins on a board are usually close together and in line, grouped together (especially if the PCB factory uses automated testing on the ports)
- Its a serial protocol which means bits are signaled one after the other
- Generally used for debugging; implementations often grant root access.
- To drop a shell (sub-TL;DR):
- Hook up the UART signals to a USB friendly connector
- Open a serial console
What is UART?
Well lets start with the name Universal Asynchronous Receiver-Transmitter. The Asynchronous part means that the protocol doesn't explicitly define an external clock to synchronize communication to i.e. one bit transfer per clock edge or clock cycle or every 36000 clock cycles or any "computable" function f(clock_cycles) hehe.
A clock signal if you're not familiar is something that offers are regular fluctuation of signal (whatever your signal is made of, rats or electrostatic force). Why does this help computation? Why do you need a clock? Clocks are there for many reasons, most of the important one's being mathematical and theoretical (I erased my rant about successor functions and primitive recursion many times but you can check out more here https://plato.stanford.edu/entries/computability/ ).
Anyway; they allow us to distinguish somethings place in a "set" (whatever your set is made of, bits in a byte, memory addresses in a kernel pool, button presses in a time frame etc), or prove that something happened at a given time and synchronize actions between different modules or computing things. Clocks are pretty much always there, the only real difference is whether they are inferred from other aspects of the context; either through the rate at which data is flip flopped out of the chip (the maximum amount of times signal state is allowed to change); or by a literal externally supplied signal.
Anyway UART could be a bit of strange place to start if you're not used to the hardware stuff (which I'm not entirely used to yet either!) so i thought I'd come in on a bit of a softer landing and talk about communication protocols in general.
Communication can happen in some of the following ways :
- One a single wire one bit sequentially following the other - Serial
- Multiple wires each signalling a bit at the same time - Parallel
- Signalling based on the difference between signals - Differential
- more things exist probably...
UART is on the serial side of things ("I'm super serial you guys" - E. Cartman), each bit is physically signaled down one after the other. Its important to know this because it affects how you interact with the device and sample from it. This orientation of bit signalling will theme how you navigate the errors and pitfalls when interacting with it - this again because you need to line up the bits according to a clock to argue that they were received correctly. For instance if it were parallel, and you don't have all your signals hooked up you're gonna read garbage lol. Another example if you're reading serial stuff and you aren't making good contact ALL THE TIME or if your device doesn't sample fast enough; you might see a broken clock, and not be able to interpret data correctly. So knowing what the orientation of the bit stream is gonna be is pretty crucial. Anyway on with the UART!
UART comes in many variants there are modifications that cater to faster data transfer, error correction and parity bit states, etc etc. In this post I'm going to show what a stock standard UART looks like for a random embedded devices I've been torturing lately. Before we get into the pins and signals lets look at a simple state machine for the protocol (because after all, even if you're engineering hardware the computer scientists are still frigging amazing at math). The FSMs for UART I'm going to show are for the RX (Receive signal, which will accept data for the UART host; and the TX (Transmit signal, which will send data from the UART host).
State Machine for RX:
Just to provide some clarity on my weird notation the 1,0 - means that the state will loop 8 times gobbling up the bits (either 1 or 0). For the latest example the bits are being "gobbled" by being signaled out through RX. Also the "e" means that you don't need any input to transition to this state, some real implementations of UART have states like this; usually to reset the data buffers and counters so they can catch more data when its time.
The state machine for TX looks exactly the same! It just says "TX" instead of "RX" hehe. But anyway if you know how to implement state machines in verilog this helps a ton (there's an example shown later on). This is because when re-creating a lot of this knowledge during reverse engineering, you'd run across many different types of FSMs describing complex protocols, check out this example from Lattice ( https://www.latticesemi.com/-/media/LatticeSemi/Documents/ReferenceDesigns/SZ/UARTUniversalAsynchronousReceiverTransmitterDocumentation.ashx?document_id=3466 ):
Surprisingly simple no? This is a good place to start with wire/hardware protocols I think, as far as I've looked the other one's can be looked at as different modes and orientations of some of the tricks uart uses.
For instance you can add some states to the FSM; accept 8 bits for a state before going into TX and you have a whole bunch of different instructions or addresses to store stuff or do stuff, from this simple FSM you can build a JTAG, SPI etc etc by simply adding states and adding states is not a massive mental operation once you got the previous idea. These simple extension gives you a tone of computational Joo Joo!
An awesome example can be found here https://www.nandland.com/vhdl/modules/module-uart-serial-port-rs232.html - comes in vhdl and verilog!
Its just a simple case statement with extra steps, not that big a deal! The tricky part is finding the friggin ports on the board.
UART pinouts can be as bare necessity as they come, ground (obviously); one signal for receiving, one for transmitting and maybe one for the "power in" Vcc.
- RX - Receive State, each clock cycle a bit is gobbled up by the device (your "host" TX should be input to this port)
- TX - Transmit State, ecah clock cycle a bit is pushed out by the device through this port (your
host" RX should be connected to this port)
- Vcc - Power input, a power input, usually if your UART module is mounted to a board you probably don't want to feed this any input, you may overpower the device sometimes!
- GND - Ground, very important port, if you don't know where this one is don't connect anything to the port.
The most important signals of course are RX, TX and GND you can usually get by with these. So lets look at what some UART interfaces look like on real devices. Here's some examples of UART ports, so you have a few examples to work from:
Example of a UART port on a IP camera PCB
|Probing out the Ground pin on a PCB for an IP camera.|
Finding UART Ports
Hunting down UART ports is pretty easy usually. People tend to want them to be easily identifiable because either a machine on an assembly is supposed to find it; or a human - but either way their not going to have anyone play where's wally to find the debug port. UARTs are typically a straight line of 3 to 4 or more signals. Other typical behavior I've seen, that they can be either a very easy to see / reach place like on the edge of the board, near a SoC or other external connectors.
The process for identifying these ports is typically the following phases.
Methods for locating the ports/pinsFastest method is to use the data sheet (my RTFM moment is finally here) for your device or as a first step assume there's a data sheet for literally everything (avoid reverse engineering stuff you don't need to) - and once you are all Google'd out and there's no data sheet anywhere in the whole world wide weeb network, then start playing with the electronics lol.
Find the ground signal. If you don't have a ground signal identified (by strong I mean, is strongly probably the right definite ground plane lol ), interacting with the UART safely is usually very hard to do. I like identifying the ground first because it means I can hook up all my toys without having them explode!
- Continuity test between an obvious ground and suspected one (many PCBs have exposed metal around USB ports, power inlets etc etc that will usually be grounded). To double check that you have the right ground I suggest finding the ground of the power or other ports as well and checking that there is continuity between an obvious ground, and your UART ground.
If you have identified another SoC or chip on the board and you have the data sheet for it. See if you can find out whether:
- It has a TX or RX (or MOSI / MISO any serial ports would be huge clues!) on it, see if this might give you more context on the possible UART port you're looking for. Obviously sometimes the system on chip needs to dump its debug data so it should be talking to the UART some how right? Could mean there's continuity between some pins!
|Easy to see which one is ground. This is from a stock standard router I plucked off amazon. The two signals other than ground are as you guessed it RX and TX.|
Interacting with the ports (logic tracing)
Hook up a logic analyzer to it (you don't always need a Saleae or how ever you spell it, some cheapo $20 one's sometimes to the job just fine!). Make sure your logic analyzer is grounded of course! And that the ground is common to the supposed UART!
|Logic analyzing the UART on an IP Camera board. The logic analyzer I'm using a cheapo logic analyzer here, it bearly samples above 25MHZ hehe but it does the job sometimes!|
Power the device, try to capture what you think will be where most of the OS debug noise will happen - sometimes it never stops and just keeps going, but you can't capture for ever and you don't need a huge capture to confirm a UART either - so think a bit about the device life cycle!
Look for some signals that register the following characteristics:
- CLK - usually this is a very regular square have signal (check out some of the examples)
- GND - just kidding you shouldn't be seeing this in your logic analyzer! Stay woke people!
- RX - if you're taking about the RX from the boards perspective, this shouldn't be showing anything it should just be pulled high or stay constant at some level the whole time
- TX - this is where the action is, if you're looking at a common TX signal for a UART it should start showing some "OS boot-loadery" looking data, or just readable data of some kind. For a lot of embedded devices this results in a direct bootl0oader shell, so expect kernel, expect Linux, expect us we are anonym-lol jk.
Interacting with the ports (dumping a UART shell)
- Bus Pirate - I know its a essentially the script kiddie version of nmap for hardware hackers; but to be honest it gets the job done and its damn easy to use!
- FTDI Serial TTL-232 cable, hook your port up-to this and stick it straight into your machine; the FTDI chip on these gadgets takes care of all the gritty details involved in turning the RX / TX into something picocom can pick up on your device.
- FPGA - for the hardcore folks out there, you can probably hook the UART upto a FPGA and use to forward it over to your machine using the FPGAs UART.
- (serial programming in python!) https://elinux.org/Serial_port_programming
Anyway that's it for this post, I'll cover more hands on UART stuff soon! Stay tuned!
References and Reading: