# 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.

*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:

*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*

*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 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.*