Hacking a Livestream Broadcaster Pro

Have you tried turning it off and on again?

Everything started on a Saturday evening when a friend of mine told me he got 3 of these red little boxes and asked me if I'll help him to get root on them and that he'd give me one of them for free. As I recently wanted to get an HDMI capture device anyway I couldn't resist the offer.

While we were talking he also told me that there is a device that looks like it has basically the same hardware - the Teradek VidiU. Upon taking a closer look at the Broadcaster - aka taking out the screws and looking at the PCB - it was an easy task to spot the "VIDIU-2xx" marking and a Teradek logo that confirmed that those two were exactly the same devices. So the question was:
How hard could it be to get root and to swap the firmware and have a device afterwards that isn't bound to the Livestream platform and their expensive software?

Network

The first thing I took a look at was the network interface. After a first run of Nmap I found nothing of too much interest. There was just a lighttpd webserver displaying a static page that contains nothing but the Livestream logo, a dropbear SSH server I don't know the password for and a ZeroMQ instance. The next thing was a Wireshark packet capture which also didn't reveal a lot. The only things of interest were the fact that the connectivity check tries to connect to the Apple website and that the firmware update uses HTTPS.
Wait a minute!

Firmware updates usually are a pretty good point of entry.

So after poking around the Wireshark capture a bit more without finding anything of use, I fired up mitmproxy to find a few very interesting things:

  • First, the firmware updater doesn't care about the validity of the certificate and happily connects anyways which saves us a lot of trouble.
  • Second, the updater connects to https://cdn.livestream.com/broadcasterpro/firmware/latest.json which seems to hold the information about available firmware versions because immediately after downloading this file the Broadcaster tells me that there is a new firmware version available.

Sure enough, the JSON file contained what I thought it would contain:

{ "latest":  { "version": "2.1.6", "url": "https://cdn.livestream.com/broadcaster2/firmware/lsb_v2.1.6r26877.bin" }, "force_upgrade_versions": [  ] }

Firmware

After downloading the firmware file the thing to do is of course to run binwalk on it but this time I was surprised by the results:

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             Squashfs filesystem, little endian, version 4.0, compression:gzip, size: 17615326 bytes, 18 inodes, blocksize: 131072 bytes, created: 2016-09-19 22:13:26

So a simple unsquashfs did the trick and I had what looks like a way too complicated firmware update mechanism:

checksums            nand-rootfs.tgz
cleanup              partitions
derivative           platforms
install              rootfs
MGVERSION            signature.bin
nand-bootloader.bin  signature.lst
nand-fstype          upgrade_files.lst
nand-initrd.img      upgrader.sh
nand-kernel.img      VERSION

Signature? That doesn't sound like something we want...

Thankfully they use the Sony way of implementing security:
The signature.lst file seems to list all the files used to create the signature in signature.bin. A quick poke around in the firmware's rootfs (nand-rootfs.tgz) confirmed that they only check files listed in the signature.lst file.
The signature check also fails if the aforementioned file is empty or doesn't exist. So what can we do about that check? well...
Let's just copy all the files into the same directory, append .old and only list the .old files inside the signature.lst file.
To try it out I edited the VERSION and the install script to just show something on the screen and tried to apply the update by faking their CDN on a local webserver.

BINGO!

The "update" seems to apply just fine which means I got root on the device!

Livestream Broadcaster Pro displaying 'Dickbutt 1337' on its OLED screen.
The maturest of all test messages.

So what next? Well I was too hyped and quickly grabbed the VidiU firmware from the Teradek website, built myself a firmware image that bypasses the signature check and flashed it. After waiting quite a long time, the thing seems to be stuck at the Livestream boot screen...

Serial

Assuming that the Broadcaster crashes very early in the boot process and no network connectivity is established I tried using the recovery method described on the Teradek FAQ page for the VidiU. Sadly it doesn't look like the Broadcaster does come with a recovery firmware though.
Now it was time to find another way of entry so I popped open the device again and found something interesting: Out of quite a lot of pin headers, one comes populated from the factory.
So I quickly cobbled together an adapter for the 1mm pin header to your standard 2.54mm pin spacing and hooked up my logic analyzer. Finding the pins didn't take long as the bootlog was easy to spot using the logic analyzer.

Picture of the Broadcaster's PCB with connected wires for serial communication and a closeup of the adapter.
Unusual pin spacing but nothing really problematic.

The pinout (pin 1 being the pin closest to the DRAM):

1     2     3     4     5     6
GND   ?     ?     RX    TX    ?

Console

So now I got a boot log which revealed not too much information except for a few errors.

Mboot start... bootdevice: NAND
initramfs script version 1.0.
[42949375.820000] Loading additional devices for Broadcaster Mk2
[42949377.190000] power_supply max17042_battery: driver failed to report `present' property
Executing autoupdate script
Root filesystem is now ready, start init.
init started: BusyBox v1.14.2 (2017-03-31 15:18:12 PDT)
          _       _   _
 /\   /\ (_)   __| | (_)  /\ /\
 \ \ / / | |  / _` | | | / / \ \
  \ V /  | | | (_| | | | \ \_/ /
   \_/   |_|  \__,_| |_|  \___/
Version: 2.4.9r28704
MG Version: SDK7.RC15r28615
Starting system...
Using hardware I2C interface
==> MAC: 00:1E:C0:D6:DE:5C
connect error: No such file or directory
connect error: No such file or directory
connect error: No such file or directory

Please press Enter to activate this console.

Hm. Console?

Password(s)

Please press Enter to activate this console.
Password:

DANG IT!

So we need a password huh? Well...
We got the /etc/shadow file in the firmware upgrade image. After a few minutes of running HashCat on the (DESCRYPT) hashed password I now know that the root password is upsetdac.

Password:
Password Incorrect

Hm. crap.
Lets poke around a bit more in the firmware files...

After a bit of searching I found the following in /etc/inittab:

ttyS0::askfirst:-/bin/slogin

/bin/slogin? What's that?

Well this shellscript checks if /etc/remote_access exists and if so, automagically allows you to login without a password.
If it doesn't exist, like in my case because I forgot to look over the rootfs before flashing the VidiU firmware, it runs /bin/tdlogin. After running /bin/tdlogin through radare2 together with Stephan, a good friend of mine who knows how to use radare a lot better than I do, we found out that it calls the td_license_create function from /usr/bin/libtd.so which looks roughly like this when disassembled:

td_license_create(token) {
    mac = get_board_ethernet_mac();
    return sha1(sha512("0x5f3759df" + mac + token));
}

The token passed by /bin/tdlogin is a constant with the content password and the MAC address string. After finding this, Stephan wrote a basic Ruby script to generate the password for your device that can be run in the interactive Ruby shell:

require "digest"
Digest::SHA1.hexdigest(Digest::SHA512.digest('0x5f3759df' + '00:FF:11:EE:22:DD' + 'password'))

This script worked like a charm and I was finally greeted by a busybox shell.

root@Broadcaster-Pro-XXXXX #

Fixing the Firmware

Now with shell access lets go find out why this firmware doesn't boot.
First thing I noticed is that the original firmware quite often uses the board id box2 that gets written to /proc/board from an internal I2C EEPROM at boot. After running a recursive diff over the (almost identical) firmwares from both Teradek and Livestream I could find multiple places where a boot would fail with the Teradek firmware if the board ID wasn't vudu like it expected it to be. So upon further inspection I could find the i2crw utility on the rootfs and dumped the content of the EEPROM. It contained strings like Livestream, Broadcaster Pro and box2 and seems to be the only way for the firmware to tell apart different devices. I tried replacing every occurence of box2 by vudu (luckily both are 4 bytes so there won't be any length problems).

i2crw /dev/i2c-main 0xa0 0x34 0x76
i2crw /dev/i2c-main 0xa0 0x35 0x75
i2crw /dev/i2c-main 0xa0 0x36 0x64
i2crw /dev/i2c-main 0xa0 0x37 0x75

After running the commands above and rebooting the Broadcaster I was thrilled to see the "VidiU" boot splash and some startup messages on the screen of the device but it still didn't manage to boot entirely. While ethernet and the WiFi hotspot worked now, the webinterface was utterly broken and the on screen menu didn't look right either.

The Livestream Broadcaster Pro's OLED showing the Teradek VidiU logo bootup splash screen.
It's the right logo now!

After diving into more library calls using radare I figured that the cause must be the other two strings.
Apparently the VidiU firmware expects Teradek and VidiU instead of Livestream and Broadcaster Pro. Just replacing the beginning of the string and filling up the rest of the bytes with zeros results in the Livestreamer not booting. However digging deeper into the firmware I found out that the byte just before any string represents it's length. Annoyingly changing the length of any string forces the following EEPROM contents to be shifted either left or right which is not exactly easy to automate. However after some manual bit-banging I got myself a booting VidiU!

The partly disassembled Broadcaster displaying the main menu of the Teradek VidiU firmware.
It can do useful things now!

Other Useful Things

After looking through the file system a few interesting things could be found, most noteably a way to change the MAC, update the firmware, and other bits and bops using nothing more than an USB drive. According to the script a firmware update should be flashed automatically when a drive is plugged in that contains a file with the name firmware.txt containing the name of the firmware blob on the same level. Sadly this never worked for me because udev refuses to run the script automatically. You can however simply run /lib/udev/check_cue.sh from a shell.

A good idea before playing more is to flash the Teradek recovery (which Livestreamer doesn't ship) to be able to return to a clean slate state after doing a derp. To flash it you just repeat the same steps as with the main firmware but use the recovery blob that you can download from Teradek's website instead. If you already flashed the Teradek firmware, no hacks are neccessary and you should be able to just install the recovery using the firmware update function of the webinterface. After that you can drop into a recovery with a nice webinterface by holding the reset button while powering on the Broadcaster.

Once the Broadcaster was successfully converted into a VidiU, I lost SSH access as the Teradek firmware doesn't come with a SSH server. After some digging in the webserver's CGI scripts I found a way to temporarely enable a telnet server. Remeber the serial console password generation? Just replace the string password in there with the string tdtest and open a webbrowser to http://192.168.1.170/cgi-bin/test.cgi?command=telnet&key=eb8fa66737973507cfd29d4f18c084d8d1ab73fb&enable=1 (obviously you have to replace IP and key with your values). Once you did that, you can log in via telnet.

Conclusion

Playing around with this little box was - while taking a bit over three days - a very fun and interesting experience but seeing that the Broadcaster usually costs around 700€ I'd probably never attempted this if I had to buy it.

After looking over all the things I did I should've been a lot more careful before flashing the Teradek firmware. I could've saved my self a lot of time and trouble by just enabling the SSH server and passwordless login beforehand.

Update

After I got many requests about crossflashing the little red boxes I borrowed a second Broadcaster Pro from a friend and started to develop a shellscript to generate a firmware image for crossflashing.

I also found out that the method for enabling telnet outlined above also works on the original Livestream firmware and that a firmware update can be forced by running fw_upgrade http://your.http.server.url/firmware.bin on the device. Before crossflashing I strongly recommend dumping the EEPROM content by calling i2crw --count 256 /dev/i2c-main 0xa0 0x00 and saving the output somewhere as recovering from a failed flash without this could be difficult.

WARNING: I tested the generated firmware successfully on my device but I can not take any responsibility for bricked Broadcasters. Recovery from bricks usually is possible but requires quite some expertise with Linux and embedded devices.

You can find the scripts to create the firmware image below. Just run the download_firmware.sh script and you'll find the resulting firmware file in the same folder.
VidiU Crossflash Firmware Generator