# Reverse Engineering a TV Firmware ## It started with a second-hand TV and ended with a full firmware teardown. I bought a second-hand TV. It had an engineering menu. That menu had all sorts of advanced settings — picture processing, panel configurations, service codes. I tweaked everything I could. Then I got curious: what's actually running under the hood? That curiosity led me down a rabbit hole of firmware extraction, entropy analysis, and binary archaeology. Here's the full story. --- ## But Why, Really? Mostly because I'm currently working with colleagues who were former employees of the manufacturer in question. I wanted to be able to say *"Take a look at your firmware, is it any better?"* during a heated discussion while mocking them for their past work. A good dose of whataboutism can be useful sometimes. Yeah yeah, sorry. First blog post, first clickbait. Here's the actual timeline of events: * Bought a second-hand TV * Discovered it has an engineering menu * Tweaked every possible setting * Got curious about what's under the hood * **Decided to find out** --- ## How Do You Even Get a TV Firmware? There are a few ways to obtain firmware from an embedded device: 1. **Intercept an OTA update** with a proxy 2. **Dump directly** from SPI/eMMC via JTAG 3. **Find UART** on the PCB for a root shell 4. **Download a USB update image** from the support page I'm no hardware expert, and OTA updates usually only contain deltas of the base rootFS. So I went with the easiest option — the manufacturer's support page. One Google search later, I found their download center. It asks for the serial number and firmware language. ![download-center](img/download-center.png) *The manufacturer's firmware download center* I filled out the info and got redirected to download the latest firmware: `KPGRMR.-.-.-.-.V06.013.00.rar` RAR? That's a bit odd. But there were bigger issues: ![https-error](img/https-error.png) *Yes, an HTTPS error on their download page* Ever heard of [Let's Encrypt](https://letsencrypt.org/)? It's free, guys... Anyway — I had my firmware file. Time to dig in. --- ## First Look at the Contents ```bash $ tree -L 3 . └── KPGRMR.-.-.-.-.V06.013.00 ├── Release info.txt └── Target_KP ├── BIN_FILES │ ├── 3D_Emitter_Attiny9 │ ├── CI_Plus │ ├── keys │ ├── KP_ACOUSTIC_FILES │ ├── KP_EDID_FILES │ ├── KP_FPGA_FILES │ ├── KP_PANEL_FILES │ ├── KP_URSA_FILES │ ├── panel │ └── SSL ├── image │ ├── KP_Boot.bin │ ├── KP_Rom_Boot.bin │ └── KP_SWImage.bin ├── ProjectReleaseVersion.txt └── script ``` Sub-system firmwares, installation scripts, pre-configs. The interesting stuff would be in the biggest files: ```bash $ find . -type f -exec ls -lh {} \; | sort -hr -k5 | head -n 5 -rwxrwxrwx 1 can can 111M ./Target_KP/image/KP_SWImage.bin -rwxrwxrwx 1 can can 1.5M ./Target_KP/image/KP_Boot.bin -rwxrwxrwx 1 can can 110K ./Target_KP/script/crc32generatorWin.exe -rwxrwxrwx 1 can can 78K ./Target_KP/image/KP_Rom_Boot.bin -rwxrwxrwx 1 can can 5.9K ./Target_KP/script/[[writeProductionKeys ``` **111 MB.** That's our target — `KP_SWImage.bin`. Let's see if `file` recognizes it: ```bash $ file KP_SWImage.bin KP_SWImage.bin: data ``` Nope. Time for the bigger guns. --- ## Enter Binwalk [Binwalk](https://github.com/ReFirmLabs/binwalk) is a CLI tool for analyzing and extracting content from binary files. It scans for known file signatures, compressed archives, and embedded executables. It can also generate entropy graphs — and that's where the real fun begins. ## What Is an Entropy Graph? > An entropy graph is a visual representation that measures and displays the randomness of data within a file or binary. In firmware analysis, entropy graphs serve as powerful reconnaissance tools that can quickly reveal the internal structure of a firmware file without deep technical inspection. — *Claude 3.7* ![entropy-sample](img/entropy-sample.png) *An example entropy graph from a random modem firmware* In practical terms: * **High entropy** (flat line near the top) — data is compressed or encrypted * **Low entropy** — structured data like executable code or plain text * **Spikes** — transitions between different data sections, marking boundaries These spikes are the key. They tell you where one section ends and another begins — essentially a roadmap of the binary's internal structure. --- ## Entropy Analysis of the Firmware ```bash $ binwalk -E KP_SWImage.bin ``` ![entropy-firmware](img/entropy-firmware.png) *Entropy graph of KP_SWImage.bin* The graph reveals a clear structure. In general, an embedded device needs three main blocks to boot: **bootloader**, **payload**, and **rootFS**. The manufacturer was kind enough to provide these as individual files in their *RAR*: ```bash └── image ├── KP_Boot.bin → boot payload ├── KP_Rom_Boot.bin → bootloader └── KP_SWImage.bin → rootFS (our target) ``` Since all low-level firmware updates are sourced from other files, `KP_SWImage.bin` likely contains a known Linux filesystem structure without any hardware firmwares for early bootloader stages. The entropy graph shows two large high-entropy blocks — likely two separate volumes. The early spike probably indicates a file table for disk layout configuration, which is common in embedded systems. The two big chunks? Perhaps rootFS and an applications volume — common in TV platforms where vendors provide a reference design that OEMs customize. > **TL;DR:** There are two big volumes storing data, and a partition table at the beginning. --- ## Analyzing KP_SWImage.bin Running binwalk in signature scan mode revealed a long list of LZMA compressed sections: ``` $ binwalk KP_SWImage.bin DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 32768 0x8000 LZMA compressed data, uncompressed: 510848 bytes 229376 0x38000 LZMA compressed data, uncompressed: 1410284 bytes 622592 0x98000 LZMA compressed data, uncompressed: 4194304 bytes ... 14843904 0xE28000 LZMA compressed data, uncompressed: 40518623 bytes ... 56066048 0x3578000 LZMA compressed data, uncompressed: 51187907 bytes ... ``` This is expected — modern embedded firmware is organized as a series of compressed sections for modular updates. Most of these are false positives from binwalk matching hex patterns. The real volumes are the ones with large uncompressed sizes. Our candidates: * **`0xE28000`** — ~40 MB of data * **`0x3578000`** — ~50 MB of data These match the two big blocks on the entropy graph. The X axis is scaled at 1e8, and converting our hex offsets confirms the alignment: ```python 0x3578000 = 56066048 0xE28000 = 14843904 ``` --- ## The Partition Table What about the first 32K bytes that binwalk didn't flag? Let's extract and check: ```bash $ dd if=KP_SWImage.bin of=first_32k.data bs=1 count=32768 $ file first_32k.data first_32k.data: ASCII text, with very long lines (463) ``` **Plain ASCII text.** It's a partition table script — and it's a goldmine: ``` $ cat first_32k.data | grep -A1 Partition # File Partition: kernel filepartload 0xBC600000 $(UpgradeImage) 0x3c8000 0x344127 #kernel -- # File Partition: ROOTFS filepartload 0xBC600000 $(UpgradeImage) 0x748000 0x6cbc69 #ROOTFS -- # File Partition: mslib filepartload 0xCF600000 $(UpgradeImage) 0xe28000 0x272896d #mslib -- # File Partition: applications filepartload 0xCF600000 $(UpgradeImage) 0x3578000 0x317a2f4 #applications -- # File Partition: config filepartload 0xD8800000 $(UpgradeImage) 0x6718000 0x174b2f #config -- # File Partition: certificate filepartload 0xD8800000 $(UpgradeImage) 0x68a8000 0xdea5 #certificate -- # File Partition: tee filepartload 0xBC600000 $(UpgradeImage) 0x6c38000 0x20746e #tee ``` Now I had the full mapping. Every section, its offset, its size, its name. The firmware was an open book. --- ## Extracting the Filesystem With the partition map in hand, I extracted the main system volume using `dd`: * `skip=14843904` is the decimal equivalent of offset `0xE28000` * `count` was calculated from the difference between section starting points Decompressing with standard `lzma` failed: ```bash $ lzma -d main_system.lzma unlzma: main_system.lzma: Unexpected end of input ``` Not surprising. Firmware manufacturers often use slightly modified compression formats. Standard tools choke on them. Binwalk's built-in extraction worked better: ```bash $ binwalk -e KP_SWImage.bin ``` This produced what I was after: ``` main_system~ (141MB): Linux rev 1.0 ext4 filesystem data ``` An ext4 filesystem! Mounting it directly still failed due to non-standard modifications — but examining the extracted data was enough to reveal the TV's entire software architecture. --- ## What's Inside a Smart TV? The extracted libraries tell the whole story: ``` libMStarSDK.so libmstarlauncherserviceproxy.so libgstreamer-0.10.so libQtCore.so.4.8.2 libWebAppMgr.so libdirectfb-1.4.so.0 libmsrv_dvbc.so libPQ.so libPQ_cus.so libHbbtvLauncher.so ``` From library names alone, we can map out the entire stack: **Core System** — Linux-based OS with MediaTek MStar SDK for hardware abstraction. **Graphics** — DirectFB 1.4 for low-level display access, Qt 4.8.2 for the UI layer, Cairo and Pango for text rendering. **Media** — GStreamer 0.10 for audio/video decoding, with custom media players for different content types. **Smart TV** — WebKit-based browser engine, DLNA media sharing, HbbTV interactive TV support. **Broadcast** — DVB-C (cable), DVB-T (terrestrial), DVB-S (satellite). **Security** — Trusted Execution Environment and DRM modules. The most interesting finds were the `*_customer.so` libraries — customization points where the manufacturer modified MediaTek's reference implementation. And for my original goal of tweaking picture settings: `libPQ.so` and `libPQ_cus.so` are almost certainly the picture quality processing pipeline. --- ## Conclusion Modern smart TVs are specialized Linux computers with layered software architectures. This particular one runs on a MediaTek MStar platform with a surprisingly standard open-source stack — Qt, GStreamer, DirectFB, WebKit — wrapped in proprietary customization layers. The firmware followed a predictable pattern with clearly demarcated sections. The approach outlined here could be applied to other MediaTek-based TVs with minimal adaptation. For those wanting to go further: forensic tools like **TestDisk** would likely have better success mounting these modified filesystems than standard Linux utilities. And specialized MediaTek firmware tools exist that handle the non-standard compression formats these manufacturers love to use. --- *Did I ever get to mock my colleagues about their firmware? Absolutely. Was it worth the hours of binary analysis? Also absolutely.*