Samsung TV root
I built working root exploits for the two Samsung TVs I own: a QN90B purchased in 2022 and a QN90F purchased in July 2026. I use them to make the TVs less annoying: remap the remote to whichever Arch Linux computer is connected, control my window manager and MPV, control active YouTube, Plex, and X.com playback through CDP, and collect diagnostics from the TV.
My TVs are blocked from the internet after Developer Mode is enabled. A host-side controller reacquires root whenever either TV powers on.
The QN90B took about a day with Codex in March 2026. The QN90F took about three hours with a newer version of Codex in July 2026, right out of the box. This public repository is a clean subset of my setup; it does not contain Samsung firmware, Samsung binaries, or extracted AES keys. It works for me every day. Ask if you run into problems. Enjoy.
What is this
Source and host tooling for obtaining volatile root on two tested Samsung Tizen TVs, keeping root available while the TV is on, observing or remapping physical remote input, controlling selected native TV functions, and recovering Samsung SWU firmware keys.
The source tree does not track Samsung firmware, Samsung's sdb binary,
extracted keys, device tokens, serial numbers, private network configuration, or
precompiled exploit payloads. Release archives contain payloads built from this
source.
Tested TVs
| Profile | Exact model | Installed firmware | Internal build | Platform |
|---|---|---|---|---|
qn90b |
QN55QN90BAFXZA |
T-PTMAKUC-1602.3 |
T-PTMAKUC-REL-202310071804 |
Tizen 6.5, Linux 5.4.77, ARMv7 |
qn90f |
QN75QN90FAFXZA |
1203.0 |
T-RSMFAKUC-0090-REL-202512092052 |
Tizen 9.0, Linux 5.4.261, AArch64, Mali-G510 r48p0 |
qn90f |
QA55QN90FAUXEG |
1301.0 |
T-RSMFUABC-0090-REL-202607141954 |
Tizen 9.0, Linux 5.4.261, AArch64, Mali-G510 r48p0 |
The QN90F root path was live-tested on firmware 1203.0 and 1301.0. The 1301.0
validation used the public v0.0.3 Windows x86-64 release on QA55QN90FAUXEG and
confirmed the SDB foothold, authenticated UID/GID 0 root agent, full capability
mask, credential and GPU page-table restoration, root command execution, and
volatile UEP disable. Its UI firmware string was reported as
T-RSMFUBAC-0090-1301.0; the authoritative on-device build fingerprint and
Samsung package use T-RSMFUABC-0090.
Other screen sizes and model variants are untested. The preflight reports
tested, compatible-untested, or incompatible from the platform
requirements instead of rejecting every build-number change.
Included
- The public
SVE-2025-50109SDB package-name injection for the initialuid=901(sdk)command foothold. - A QN90B
/dev/sdp_pqe_fdetphysical-memory exploit. - A QN90F Mali-G510 r48p0 exploit based on
CVE-2025-0072. - A model-independent SDK archive-launcher root route, live-tested on my QN90B and QN90F.
- Interactive root shells and authenticated root command execution.
- UEP status and volatile disable controls for unsigned native execution.
- An event-driven host controller that reacquires root after TV boot or root agent loss.
- Opt-in remote observation, suppression, remapping, and structured events.
- HDMI source, local-dimming, PC/Game/Input Signal Plus, and Picture Off controls where listed as implemented below.
- Speaker-volume control and opt-in native TV event streams.
- QN90F retained-frame screenshots and bounded compositor overlays.
- SWU firmware-key extraction for both tested models.
Root and UEP changes remain volatile. The controller makes root appear semi-persistent by reacquiring it from another computer after a TV reboot. It does not install a TV-side boot service.
Capability status
implemented means the public adapter and release payload are present.
proven_not_packaged means the operation was validated on the stated TV but
the public adapter is not included. not_investigated means this project has
not established an answer for that model. unsupported is reserved for a
verified platform limitation; no row below currently makes that claim.
| Capability | QN90B | QN90F |
|---|---|---|
| Root, command execution, UEP control | implemented |
implemented |
| Source list, current source, HDMI selection | implemented |
implemented |
| HDMI presentation recovery | not_investigated |
implemented |
| Local-dimming status, set, toggle | implemented |
implemented |
| PC mode, Game Mode, Input Signal Plus status/enforcement | not_investigated |
implemented |
| Picture Off, display status, display wake | implemented |
implemented |
| Remote input observation, filtering, TV-native actions | implemented |
implemented |
| Speaker volume get/set and native change events | implemented |
implemented |
| Foreground app, source, lifecycle, HDMI receiver events | implemented |
implemented |
| Processed 960x540 HDMI capture | not_investigated |
implemented |
| Transparent text and graphics overlays | not_investigated |
implemented |
The running controller exposes the machine-readable inventory:
samsung-tv-root capabilities my-tv samsung-tv-root -o json capabilities my-tv
Run from source
Python 3.12 or newer can run the host CLI directly; a standalone release is not required. From a clone of this repository:
python -m venv .venv .venv/bin/python -m pip install -e . .venv/bin/python -m samsung_tv_root doctor .venv/bin/python -m samsung_tv_root preflight qn90f 192.0.2.50
On Windows, use py -3.12 to create the environment and replace
.venv/bin/python with .venv\Scripts\python.exe. Pass --sdb before the
subcommand when Tizen Studio is not in its default location:
.venv\Scripts\python.exe -m samsung_tv_root --sdb C:\tizen-studio\tools\sdb.exe preflight qn90f 192.0.2.50Preflight needs only Python and Samsung's sdb. Root operations also need the
TV payloads: install the .NET 6 SDK and run make payloads once in the source
tree, then use the same python -m samsung_tv_root qn90f root ... form.
uv sync --locked followed by uv run samsung-tv-root ... is the equivalent
developer workflow.
Install a release
Download and extract the archive matching the host:
- Linux x86-64 or ARM64:
.tar.gz - macOS Intel or Apple Silicon:
.tar.gz - Windows x86-64 or ARM64:
.zip
Each archive contains a standalone host executable, TV payloads built from this
source, documentation, and the corresponding source tree. Samsung's sdb is
not redistributed; install Tizen Studio
separately.
Run the installation check:
./samsung-tv-root doctorUse samsung-tv-root.exe on Windows. Put an unusual Tizen Studio location
before the command, for example
./samsung-tv-root --sdb /path/to/tizen-studio/tools/sdb doctor.
Create the configuration once, then replace the example name and address with the TV's values:
./samsung-tv-root config init ./samsung-tv-root config check
Each table under televisions is a named profile. Direct preflight, root,
uep, and serve commands infer the profile when the configuration contains
exactly one TV for that model. If it contains multiple TVs of the same model,
select one with --profile NAME. Supplying a host explicitly remains supported.
For a nonstandard Tizen Studio installation, add a top-level
sdb = "C:/path/to/tizen-studio/tools/sdb.exe"; explicit --sdb still wins.
Enable Developer Mode
Use a Samsung BN59-01199F full-button IR remote for this step. On the TV,
open Smart Hub, open Apps, focus App Settings, and enter 12345 with the
remote's number keys. Enable Developer Mode, enter the controller computer's
IPv4 address, and reboot the TV.
Verify that sdb sees only the intended TV:
export TV_IP=192.0.2.50 export SDB=/absolute/path/to/tizen-studio/tools/sdb "$SDB" connect "$TV_IP:26101" "$SDB" devices
On the tested retail firmware, a plain interactive sdb shell prints closed
and exits. That is expected and does not show whether the exploit works. The
exploit instead invokes the allowed package installer with a crafted package
name; preflight verifies that separate path with a bounded execution-timing
probe before testing the callback.
In Windows Command Prompt, set the full sdb.exe path before testing:
set TV_IP=192.0.2.50 set SDB=C:\tizen-studio\tools\sdb.exe "%SDB%" connect "%TV_IP%:26101" "%SDB%" devices samsung-tv-root.exe preflight qn90f "%TV_IP%"
One root session
With one configured QN90F profile, run the fingerprint preflight and open a root shell without repeating its address:
./samsung-tv-root preflight qn90f ./samsung-tv-root qn90f root
The equivalent explicit-host form is:
./samsung-tv-root preflight qn90f "$TV_IP" ./samsung-tv-root qn90f root "$TV_IP"
Without --command, the QN90F command opens one persistent Bash process on a
real PTY. Shell state such as cd and exported variables persists; terminal
control, clear, Ctrl-C, full-screen programs, and window resizing are relayed.
Type exit or press Ctrl-D to close it. The temporary TV listener accepts only
the selected controller address, defaults to TCP port 22222, and is removed
when the session ends. Use --shell-port PORT if that port is unavailable.
Run a local Bash script as root without Samsung's script-filename signature check:
./samsung-tv-root qn90f root "$TV_IP" --script ./httptoolkit.shThe authenticated root agent uploads the script to a private per-session
directory under /run, invokes Bash with the script sourced through -c, and
removes the directory when the agent exits. It does not replace /bin/bash or
install the script. Repeat --script-argument VALUE to pass arguments. UEP must
first be disabled for the current boot only when the script itself launches
unsigned native executables.
The QN90F preflight first compares a no-op with a bounded two-second delay to prove that the SDB package-name injection executed. It then stages a read-only fingerprint script through SDB, reports the exact callback address and port, and runs that script through the already-authorized shell. The command does not change firewall rules, configure logging, or run the root exploit. Override route detection when needed:
./samsung-tv-root preflight qn90f "$TV_IP" --callback-host 192.0.2.10If the timing probe succeeds but the callback times out, the package-installer exploit ran and the remaining failure is in staging, script execution, or the reverse callback path. A failed timing probe means shell execution itself was not confirmed.
To make one explicit attempt without the compatibility preflight:
./samsung-tv-root qn90f root "$TV_IP" --skip-preflightThis skips only the fingerprint gate. Root acquisition still requires the TV to connect back to the listening host.
Use qn90b for the older TV. Run one command with:
./samsung-tv-root qn90f root "$TV_IP" --command 'id; uname -a'With a configured profile, inspect or disable UEP for the current boot:
./samsung-tv-root qn90f uep status ./samsung-tv-root qn90f uep disable
The explicit-host forms are:
./samsung-tv-root qn90f uep "$TV_IP" status ./samsung-tv-root qn90f uep "$TV_IP" disable
disable is idempotent. A successful result reports a validated kernel
neighborhood and either uep_status_action=disabled with
uep_status_after=0, or uep_status_action=already-disabled with
uep_status_before=0. Run it before opening the root shell when that shell will
launch uploaded native ELF programs. If a root shell is already open, exit it,
run uep disable, and reopen it; do not start a second exploit session in
parallel just to change UEP.
A normal sdb shell remains closed on the tested retail firmware. sdb push
works for the controller staging directory:
"$SDB" -s "$TV_IP:26101" push ./local-file /home/owner/share/tmp/sdk_tools/local-fileThe Windows Command Prompt form is:
"%SDB%" -s "%TV_IP%:26101" push local-file /home/owner/share/tmp/sdk_tools/local-file
TV paths passed to sdb are POSIX paths even on a Windows host, so prefer
/home/owner/share/tmp/... there as well. Current retail firmware can reject
sdb pull with You cannot pull files from this path even when the Unix mode
allows the SDK user to read the file. Pull through the authenticated root
session instead:
./samsung-tv-root qn90f root "$TV_IP" \ --pull /home/owner/share/tmp/remote-file ./remote-file
samsung-tv-root.exe qn90f root "%TV_IP%" --callback-host 192.0.2.10 ^ --pull /home/owner/share/tmp/remote-file remote-file
The controller reads the source without modifying it, stages bounded chunks
only under volatile /run/samsung-tv-root, verifies the complete SHA-256, and
atomically replaces the local destination after successful verification.
UEP compatibility differs from root compatibility. The model reproduction document describes the tested boundaries and both supported application execution paths.
Archive root route
This separate root method uses the SDB package-name foothold, a
capability-bearing Samsung dotnet, a private mount namespace, and Samsung's
signed-archive launcher. motodrizzle
reported the capability/namespace/launcher route on an S90D; this implementation
adapts that route. It has no model whitelist: it checks the SDB foothold,
capabilities, tar support, and .NET runtime on the target and chooses its payload
accordingly. It was live-tested on my QN90B and QN90F with an
authenticated UID/GID 0 agent, root command execution, unchanged system-file
hashes, and per-run staging cleanup. The S90D firmware has matching platform
components, and its owner reported the same underlying route, but this exact
implementation has not been run on an S90D. The agent still has Samsung's
User SMACK label; UID 0 is not proof that every security boundary is gone.
./samsung-tv-root archive-root probe "$TV_IP" ./samsung-tv-root archive-root root "$TV_IP" --command 'id'
Use -o json before archive-root for machine-readable identity and cleanup
evidence. The older archive-root probe MODEL HOST spelling still works, but
the model label no longer selects or limits the route. --command can be
repeated. This option does not yet provide an interactive PTY, disable UEP, or
run through the host controller. The existing root commands remain the
defaults. It never replaces /etc/passwd, the verification key, or the
installed Bash on disk: the helper binds per-run views inside its own mount
namespace. Its archive and payloads are staged under
/home/owner/share/tmp/sdk_tools and normally removed after the session; an
interrupted run may leave those files on persistent user storage. The ephemeral
signing private key stays on the controller computer.
Continuous controller
Create the default no-remap configuration if one was not already created for the direct commands:
./samsung-tv-root config init ./samsung-tv-root config check ./samsung-tv-root daemon run
Edit the generated TV name, model, and address. The daemon follows TV lifecycle
events, acquires root, and starts explicitly configured remote and native-event
sessions.
my-tv in the examples below is that user-chosen configuration name.
On Linux with a systemd user manager, install the host service explicitly:
./samsung-tv-root service install --enable --now ./samsung-tv-root service status
Automatic service installation for macOS and Windows is not implemented. Run
daemon run under the service manager of your choice on those hosts.
Once the controller is running:
./samsung-tv-root status ./samsung-tv-root root acquire my-tv ./samsung-tv-root execute my-tv 'id; uname -a' ./samsung-tv-root source list my-tv ./samsung-tv-root source select my-tv HDMI2 ./samsung-tv-root local-dimming toggle my-tv ./samsung-tv-root volume status my-tv
Both models implement display status, Picture Off, and wake. QN90F also implements HDMI policy, retained-frame screenshots, and bounded overlays:
./samsung-tv-root hdmi-policy enforce my-tv --source HDMI2 ./samsung-tv-root display picture-off my-tv ./samsung-tv-root display wake my-tv ./samsung-tv-root screenshot my-tv frame.png ./samsung-tv-root overlay message my-tv 'Hello' --seconds 5
Native TV events are disabled by default. Enable the profile's events table,
restart the host controller, then use events status or events watch. The
event agent has no restart policy or TV-side boot unit and exits when its
authenticated host connection closes.
See the controller and remote input guides for configuration and extension details.
Firmware keys
Firmware-key extraction is included for both tested models. Its advanced, source-oriented procedure is in the SWU AES extraction research note.
Build from source
Source development requires Python 3.12, uv, a .NET 6 SDK, and Clang/LLD with
ARMv7 support:
uv sync --all-groups make payloads swu-preloads make lint test audit make release
GitHub Actions tests Linux, macOS, and Windows, builds the TV payloads, packages
the supported host architectures, and publishes archives for v* tags.
Documentation
Start with the quick start. The documentation index separates practical end-user guides from implementation and reverse-engineering research notes.
This project is released under the Unlicense.