The world is full of IoT (Internet of Things) devices, and they all run their own firmware – software that isn’t meant to be updated often, if ever. It’s often Linux-based, often insecure, and often a quickly-hacked-together mess with the goal to get it to work and then immediately ship, regardless of how maintainable or well-written the code behind it is.
I picked up some Blu-ray players from Goodwill that were manufactured from 2010-2013 from Sony and LG, and was curious to see, a little bit, how they worked…
Now, I’m not going to attempt to truly “reverse-engineer” the firmware. I’m basically clueless at understanding disassembled ARM (let alone 32-bit ARM EABI 5). Also, there is going to be a point where the protections massively increase – after all, this is a Blu-ray player and keeping the decryption and copy-protection implementations secret is a high priority for the designers, at least in theory.
Blu-ray Copy Protection is not going to be explored much here. For a quick recap, there are two main technologies used for protecting Blu-ray Discs: AACS and BD+. BD+ is used on relatively few discs, while AACS is mandated on all pressed discs (and costs a 4 cent license fee per disc). AACS and BD+ together were expected to be resilient for about 10 years according to their designers when they launched in 2006, but in practice, the scheme was quite broken by 2008-2009. There was also the massive 09 F9 controversy in 2007, which goes to show that (in my opinion) DMCA Section 1201 is just flat-out unconstitutional and unworkable.
Constitutional or not, 1201 has been a disaster encouraging the installation of DRM schemes everywhere, while not succeeding in preventing the cracking of DRM, ultimately annoying the living daylights out of legitimate buyers while only slightly inconveniencing pirates. (Also, fun fact, BD+ is a big reason why movies studios supported Blu-ray, as both HD-DVD and Blu-ray had AACS. They backed Blu-ray for what ultimately turned out to be a disappointing protection measure that didn’t last long. I wish HD-DVD won just because it was a better, more self-explanatory name.)
I’m not going to specify the exact model of Blu-ray firmware I downloaded, but I went and got a copy of some firmware for a LG Blu-ray player:
That… doesn’t tell us much. It’s just a giant “.ROM” file, what on earth could be inside?
Well, the answers will come from a tool called binwalk. It’s open-source, freely-available, and you can get it from Homebrew on macOS. It’s also a great entry-point for any firmware, as long as it is not encrypted or weirdly formatted. binwalk is excellent at breaking apart how a file is constructed, and if we run binwalk against the firmware, we see:
This actually tells us quite a bit about the system. At the beginning of the firmware, we see two entries for a Mediatek Bootloader. Mediatek is a Taiwanese chip design company that offers several chips designed exclusively for Blu-ray players, and is very popular with cheaper Android devices and, well, multiple Blu-ray manufacturers.
Next are two certificates in DER format – which is a little unfortunate. It means something is digitally signed. It’s not immediately clear what, and there are ways to work around digital signatures, but it is not easy. It is easier on these older systems which have less-advanced hardware root of trust systems than, say, a modern iPhone which is currently impregnable, but it does show there is some sort of protection against running arbitrary code on the system startup.
Next, we see some CRC32s. These are checksums, likely to verify that certain parts of the image are not corrupt, maybe even by the software updater.
Below that is where things get actually interesting. Combined, we see a Linux 2.6.35 Operating System image, 2 file systems (one for recovery, one for playback?), 2 encrypted areas with an unknown algorithm (though binwalk could be misunderstanding them), and a PNG image.
The PNG image is, surprise… the boot screen.
Seems a little unnecessarily low-res at 720×480 for a Full HD 1080p Blu-ray player, but whatever.
Now, if we run binwalk again with an -e flag (and have certain other utilities for uncompressing SquashFS installed), it will actually extract what it can out of the firmware into a nice folder structure:
squashfs-root-0 is the much-smaller partition that, I believe, is used for only recovery or some factory setup, while squashfs-root is the interesting one.
But there’s more to the story than that. When you run the extraction:
When you look at the logs, there are actually a bunch of symbolic links to an encrypted mount point at /mnt/rootfs_enc_it which, as far as binwalk can tell, doesn’t exist, so it replaces them with links to /dev/null to avoid a security risk.
This is very interesting and is some of that copy-protection I mentioned earlier. If you look at the files that were replaced with /dev/null links, look at their names:
The first two are obviously the libraries that implement the AACS and BD+ copy-protection schemes. CA-Bundle might be for a web browsing component, or it could maybe contain the device-specific key used for decrypting Blu-rays, which is a big deal to keep locked down and secret.
These files were symbolic links to a partition that doesn’t exist. Remember there are two encrypted (likely) file systems in the firmware with mcrypt, so it is likely the code for AACS and BD+ is in one of those encrypted blocks, and then is decrypted on boot and mounted into Linux so that they can be securely used without being transparent on a firmware dump.
If we observe those Files in Finder, they are indeed links to nowhere:
Now, you might be wondering if the key to unlock the mcrypt areas containing those decryption files can be found in the firmware download, and then these files could be read. I doubt that because, let’s say I run a search for that /mnt/rootfs_enc_it folder:
Code referring to rootfs_enc_it occurs in three other files. If we look in a hex editor at them, they look generally like this:
It appears to be a map of what the internal structure will look like, as they all list other partitions and not just that partition or code to mount it, in particular.
I suspect that this is code for the Mediatek Bootloader and boot system, before the system starts Linux, though I could be wrong on that. It has instructions for where to put things for when the Linux image starts (at least, what it appears to me), and mentions that there is an encrypted mount point there. Maybe the key is blended in the surrounding hex code, but I doubt that the designers of this would have been that stupid.
Instead, I suspect that the key for unlocking the mcrypt areas containing the copy protection and decryption code is locked with a device-key hidden inside the chip itself, possibly programmed in during manufacturing. The chip has the key most likely in its own silicon, which it can decrypt that firmware area and load it into Linux with. It’s what I would do if I was building a copy protection system – I wouldn’t make it this easy to retrieve.
On the other hand, this does leave a fairly significant weakness. A Linux system running Linux 2.6.35, with networking abilities, with that likely hardware-encrypted mount point mounted and unlocked. If one were to find a root vulnerability, I would assume it to be very possible to dump those protected files for disassembly.
I’m not going to go that far, at least not in this article. However, I would expect cracking a Linux 2.6.35 system to be fairly ~easy considering the wide attack surface and over a decade of new exploits later.
Looking at what else is in the dump though, we’ve surprisingly got all our basic utilities:
A little surprising that BusyBox isn’t used, but this isn’t a low-memory system so maybe it was easier. However, there is something suspicious with how many of them just-so-happen to be exactly 585 KB in size.
Running a file:
If I wanted to build a cross-compiler, that’s pretty important information.
Continuing a probe around the firmware:
A folder full of unencrypted wifi-related shell scripts. Written in English too. Fun.
This is more telling:
/lib is full of what appear to be references or shims for Linux. directfb is mentioned at the top (and elsewhere in the files not shown), indicating that this CPU actually does not have a GPU. Everything is software-rendered, except for the video stream which is decoded using the embedded H.264 Decode block.
This is pretty common – not licensing a GPU makes development simpler, cheaper, and easier to produce. It also explains why there are so few animations in the user interfaces of most Blu-ray players, and why the few animations there are seem to run at 8FPS.
Qt is also mentioned, and lower down it’s got a ton of libraries:
Qt and WebKit is a pretty predictable choice for something like this, but it’s cool to see.
In a /res folder (the only non-Linux standard root folder), there’s what appears to be images or binaries of images:
There’s also a folder with some Pulse-Code-Modulated Audio (think CD format) files for something called “fanfare”:
However, PCM is kind of a difficult file to play if you don’t know the exact Khz, Mono/Stereo, Start position, and all those other factors. Trying in Audacity made nothing but static, but 100_fanfare.pcm is 2.5MB in size and likely playable with the right setup.
/usr/local/bin is where things get fun:
Meet bdpprog. It’s a massive, 18.6MB executable for everything. There’s no shell like bash or sh here (at least, not easily accessible on startup) – it just boots into bdpprog for everything as far as I can tell.
bdpprog is massive, most likely responsible behind everything, and also appears to be derived from a Mediatek-written original version. bdpprog also appears on Samsung, Oppo, Panasonic, and Sony Blu-ray players. It’s also what crashed and caused boot-looping when Samsung sent out a malformed XML file to some of their players a while back. As mentioned there on Samsung firmware (even though the player I am looking at is an LG device):
“After the crash, the main program, bdpprog, is terminated by the kernel,” said Gray. “Since bdpprog is the main program, its termination results in a reboot by init. Even less fortunately for Samsung, the code for parsing the logging policy XML file is hard-coded to run at every boot. The result is that the player is stuck in a permanent boot loop as has recently been experienced by thousands of users worldwide.”
Still though, if you are a Blu-ray player manufacturer, Mediatek has it all down for you. They’ve got this custom chip, extra security for the libraries that handle the copy protection with the encrypted folder, and a mostly-written Blu-ray player boilerplate you can apparently just tweak for your branding and features and ship out.
While this would seem ingenious… that is also why a lot of Blu-ray players (not just this one, all three of my Goodwill players as well) are stuck on Linux 2.6.35, and are likely vulnerable to the exact same vulnerabilities as discovered on other brands.
Scrolling down on the window, you can see this interesting bit:
Some code for the Vudu client, and for some reason a script to launch the client. (Why not launch it directly from bdpprog? 🤷🏻♂️). Note the commented-out #LD_PRELOAD=/lib/libSegFault.so. Here it’s been commented out on the latest software version from 2015, with good reason. In 2014, a security researcher took a look at some Blu-ray players, and found a very similar line in a similar file called browser.sh was not commented out and instead read:
Note the /mnt/sda1 there, and you’ll realize the stupidity of the mistake. /mnt/sda1 on this system is not the root filesystem – it’s the mount point for external USB Flash devices. So, just make a fake libSegFault.so, launch “Browser” (which was used for Vudu in earlier versions) and you’d have an easy root exploit. Whoops. Too bad he didn’t dump the decrypted /mnt/rootfs_enc_it, whatever those files said.
Not that it would be that hard depending on how involved on this reverse-engineering I go (and depending on what’s legal, of course). This thing has network access with a stack that’s super old – probably a bunch of bugs there. These things have less-advanced hardware root of trust, and region-free mod kits require flashing custom firmware, so there is doubtlessly a way to fool it into doing something stupid. Maybe there’s another USB exploit or a bug in the media stack.
For now, this looks interesting:
Looks almost like a way to load apps from a USB stick. Another curiosity, I’m not sure what LG’s intentions with this code were:
Another possible stupid entry point, let’s connect to a non-HTTPS server for the NetCast App Store…
It appears, at least for now, the built-in NetCast App Store is the most obvious way in, with it appearing to allow loading Apps from a USB stick and downloading apps over what appears to be an unencrypted connection without a pinned certificate. All without any actual decompilation or reverse-engineering, just in plain English scripts.
That’s how far I’ll go for now. I’m not sure what the legalities are for going deeper beyond, well, just reorganizing information without decrypting or decompiling anything (which this is). It also is probably far more work with little benefit… but who knows.