Many embedded Linux devices will have a serial port on them, which can allow us access at either the bootloader or operating system level. This can be a powerful tool to the reverse engineer, allowing recovery of firmware, dynamic analysis, and access to other hardware components.
Interacting with the USB serial adapter
I am using Ubuntu 18.04 LTS as my operating system. Ideally, we should be using 20.04, but some tools that are heavily used in hardware hacking (like Binwalk) do not currently work under 20.04. You can work inside a virtual machine.
Windows is a world of pain; it’s probably tolerable on a Mac but I have not tried.
Connect the USB serial adapter to the machine. In a terminal, run the command “dmesg”. This should show you if the device has been recognised. They mostly show up as /dev/ttyUSB0.
You now want to install minicom. This is a terminal emulator that we will use to connect to the DVR. There are alternatives, but I find minicom is the easiest.
sudo apt install minicom
Next up, we want to run minicom. We need to tell it which device we are interacting with. By default, you need to run minicom as root to access serial devices.
sudo minicom -D /dev/ttyUSB0
You should now get minicom running.
On the USB serial adapter, use a jumper wire to connect RX back onto TX. Why? You always need to test your tools and instruments are working before using them in anger. This should loopback what you send, demonstrating that the adapter can both send and receive.
Trying typing. Nothing will happen – our tools are not working! This is because hardware flow control is on, and we need to turn it off.
Press the following keys:
(as in Ctrl with A, let go, Z)
This shows you the different commands you can carry out. We want to cOnfigure Minicom – so press O.
Scroll down with the cursor keys to “Serial Port Setup”.
Press enter, then press F to turn OFF hardware flow control. Press enter to leave the menu.
Now scroll down to “Save setting as dfl” (default) – this saves the change so we don’t need to make it again.
Finally, scroll down to “Exit”.
You should now be able to type and see the characters come back! Try disconnecting the wire to confirm that it is being carried that way.
By default, minicom is at 115200bps. Nearly all DVRs seem to use this, but if you do need to change it, press
And then you can use A/B to shift up or down the common baud rates.
To exit minicom, do
Finding the Physical Serial Port
For this particular example, I am looking at a Zosi CCTV NVR/DVR. This has a labelled and obvious serial port on the board. In a previous post, we looked at identifying security-relevant parts of a DVR, including serial ports. In a later post, we will look at using a logic analyser to work out if something is a serial port.
The pitch of this connector is not the typical 2.54mm that we’d find. It’s 2mm. We want to connect to it – so how do we do it?
- Get hold of 2mm pitch pin-headers. I recommend that people have a stock of common pitches of pin headers at hand.
- Shoe-horn 2.54mm pin-headers onto the board. This sounds awful, but if you chop the plastic separator apart, they fit very well.
- Solder wires on. This is the best option, but I’m very lazy and would rather avoid it.
In this particular instance, I am not even going to solder the connections on. Push-fit is good enough for my needs today.
Silence is Golden
Nearly all DVRs have a buzzer on them. It gets annoying very quickly. Plug it with some Blu Tack to reduce the volume, or desolder it.
Even though we have a silkscreen showing one of the pins is ground, we should absolutely confirm this. Whilst it is unlikely to cause serious harm, connecting 12V on the DVR to ground on your laptop could have consequences.
To do this, we use a multimeter in continuity mode. This is normally indicated by the buzzer symbol and sometimes needs a button press from resistance (“SELECT” is common).
Never perform continuity tests on a powered board. The continuity test works by testing for resistance – the meter does this by applying a voltage to the board. It will get very confused if there is already voltage present.
Always confirm the meter is working by touching the probes together first.
Find a known ground. The following are good places to look.
USB connector shields – be warned you might need some pressure to break through oxides or coating/
The outer connection on the barrel jack power connector for most DVRs. This is normally on the side of the black plastic socket.
The middle two pins of a Molex power connector for the hard drives (not present on this DVR board).
The top (-) of the coin cell for the RTC backup battery.
The BNC video connection outers (not present on this DVR board as it uses WiFi cameras).
Screw mounts for the PCB to case often have a grounded ring around them.
Pushing needle probes through the solder mask into a ground pour.
Visual inspection can also show which pin is ground. As can be seen on this DVR, the pin marked UART_GND is connected to a large ground pour around it, whereas the UART_TXD and UART_RXD pins have thin signal traces.
Serial ports can work at different voltages. We need to make sure we are using an appropriate USB serial interface for the voltage. In order of descending popularity:
- 3.3V – this is typical for a DVR
- 5V – older DVRs may use this
- 12V – some DVRs use this for interacting with external devices
- 1.8V – some DVRs with newer chips may use this.
- RS232 – this is +/-25V – sticking this into a normal 3.3V USB serial adapter will not be good.
The best tool for checking this is an oscilloscope, but we don’t all have them. So let’s use a multimeter and acknowledge the limitations.
Power the DVR. Immediately measure the voltage between ground and TX and the voltage between ground and RX. Then wait a couple of minutes for it to boot, and measure again.
On this board, with this multimeter I see:
- Ground to TX -> 3.29V with some slight fluctuations
- Ground to RX – > 2.36V mostly constant
I can be fairly confident that this is 3.3V logic. Let’s talk through some of what we saw there:
The quiescent state for TX on nearly all serial ports is the high state. If we saw 0V most of the time, this assumption would be false.
The TX signal will have data on it as the device boots. It will fluctuate between 0V and 3.3V. A multimeter only shows an average value, and the mechanism by which it averages is fairly arbitrary. We measure the voltage right at the beginning (before serial output) and at the end (generally, the device will go quiet after a while) to avoid this issue.
We measure both TX and RX because we often don’t know which is which at this stage. They are also frequently labelled incorrectly – TX and RX flip depending on which perspective you are looking at it from!
Why is RX at this strange middle ground of 2.36V? It is highly likely that there is no pull-up or pull-down resistor on the board, leaving it “floating” when not connected.
An oscilloscope would let us observe the high and low voltage.
Connecting the USB serial adapter to the DVR
The device is working at 3.3V, so we can use one of the readily available 3.3V USB serial adapter. Any of these will do.
The USB serial adapter will have the pin-out labelled on it. We want GND, RX and TX.
With both the DVR and the USB serial adapter turned off, connect up the three wires. GND always goes to GND. RX on the adapter goes to TX on the DVR, and TX on the adapter goes to RX on the DVR.
I would recommend always using black for ground wires, just to keep things clear.
If you get RX and TX the wrong way round, nothing bad will happen. You just won’t get any output. If this happens, try swapping the wires around.
I used test clips for this particular situation as they were to hand.
Bringing it all together
Connect the USB serial adapter to your machine. Start minicom as we did earlier.
Turn the power onto the DVR. You should see text very quickly! You can capture this into a text file using:
Choose a file name. Press the same key combination to close the file. We’ll use this to recover the firmware in another post.
The first part is the bootloader – U-boot. Considering the DVR was bought in 2020, U-boot from 2010 might be considered out of date.
You can see that the SPI flash chip has been identified as an MX25L128XX. It’s 128Mbits or 16Mbytes in size.
You might then see a prompt saying that you can press a key to stop autoboot. This is a prompt to get into the U-boot console. You might have to hammer a key repeatedly to get into the console. This isn’t the operating system – this is the bootloader before that stage. You can still read and write the flash, which we will use in another post to recover the firmware.
If you don’t go into this console, the device will carry on booting.
Many DVRs stop immediately after U-boot, as the serial console is disabled in the kernel. Not this time. We see normal system logs fly past, and then what looks like logging from the DVR processes:
Don’t make the assumption that you don’t have control when you see this. A process might be outputting to the console, but that doesn’t mean you can’t provide input.
Yep, we are straight in as root, no password. The annoying DVR logging sticks about though – I think it’s actually partially built into the kernel, making it impossible to suppress.
And, with a bit of exploration, we quickly find a file called config.dat in /mnt/mtd/config/ that contains the admin password as plaintext.
Not great for a new DVR!
Hopefully, you have seen how easy it can be to get a serial console on a DVR. In this case, we have full OS-level access.
In the next post, we’ll look at a quick way of recovering files and firmware from a DVR to analyse on our own machines.