The Living Room Beachhead: How HDMI-CEC Turned Every Smart TV Into a Lateral Movement Fabric

Posted: February 18, 2025
Author: SecurityResearcher472

Introduction: The Wire Nobody Audits

Every HDMI cable in your home contains a wire that almost no one has ever looked at. Pin 13 carries the Consumer Electronics Control bus—CEC—a single-wire, open-drain, multi-drop control channel that lets your soundbar wake your television, your game console change the input, and your streaming stick turn everything on when you press one button. Manufacturers market it under a dozen different trade names: Anynet+, Bravia Sync, SimpLink, Viera Link, Regza Link. Almost none of them let you disable it in a way that actually disables it.

CEC has no authentication. It has no encryption. It has no concept of trust boundaries. Any device on the bus can claim any logical address, impersonate any other device, and issue commands that every other device on the chain will obey without question. This has been quietly true since 2002. The security community has largely treated it as a curiosity—a party trick for conference talks, a way to make someone else’s television turn itself off across a hotel wall.

It is not a curiosity. Over the past fourteen months I have documented a sustained, well-resourced operation that uses the CEC bus as a lateral movement fabric inside residential and small-office environments, establishes persistence in a class of device that has no endpoint agent and no patch cadence, and exfiltrates data through a channel that leaves the network entirely before it leaves the building.

I am publishing this despite a clear escalation in the personal cost of doing so. In November my apartment’s television began powering itself on between 03:00 and 04:00 local time, always to the same input, always for under ninety seconds. I replaced the television. The behavior resumed on the replacement unit within eleven days, on a network segment that had been rebuilt from bare metal. My smart-home hub logs show CEC-originated wake events from a device that reports itself on the bus as JT-VISION 4K—a display I have never owned, on an input I have never connected.

Security Advisory: I have moved my analysis rig out of my residence. The lab’s HDMI capture hardware has failed twice in the same manner—the CEC line driver burning open while the rest of the interface remains functional. Two colleagues who reviewed early drafts of this research have declined further contact. One of them asked me, without elaborating, whether I had “checked what the soundbar was doing when the television was off.” I had not. I have now. This post is the result.

Key Findings

  1. A capability I am tracking as PARLOR LANTERN establishes persistent, firmware-resident implants in consumer display devices and pivots across the HDMI-CEC bus to every other device on the chain, irrespective of vendor.
  2. The implant survives factory reset, network reconfiguration, and physical replacement of the television, because it re-infects from whichever peripheral remains attached.
  3. Command and control is carried in vendor-specific CEC opcodes that no consumer device logs and no network monitoring tool can observe, because the traffic never traverses IP.
  4. Exfiltration is performed by inverting the television’s own automatic content recognition pipeline—data is encoded into the luminance of rendered frames and read back optically.
  5. Attribution converges on infrastructure previously associated with Junction Technologies, the same entity that surfaced in my earlier work on antivirus telemetry being repurposed as training data.

The Bus Beneath the Television

To understand why this works, it helps to understand how little CEC asks of a device before trusting it.

The bus is a single wire shared by up to fifteen logical addresses. A device joins by polling for a free address and claiming it. There is no challenge, no handshake, no capability negotiation beyond a version byte. Messages are short—a header byte, an opcode, and up to fourteen operand bytes—and travel at roughly 400 bits per second. It is, by design, a bus for saying “turn on” and “switch to input two.”

The specification also reserves a block of vendor-specific opcodes so manufacturers can implement proprietary features. These are the interesting ones. A device receiving a vendor opcode it does not recognize is required to respond with a feature-abort—which means every device on the bus will politely tell you whether it understood your proprietary message. That is a free enumeration primitive across every piece of consumer electronics in the room.

PARLOR LANTERN uses it exactly that way:

CEC bus enumeration (captured, lab chain):
  0.0.0.0  TV            <TV>            responds  0x36, 0x9E, 0xA0
  1.0.0.0  Recording 1   <SOUNDBAR>      responds  0x9E, 0xA0
  2.0.0.0  Playback 1    <STREAM STICK>  responds  0x9E, 0xA0
  3.0.0.0  Playback 2    <CONSOLE>       responds  0x9E
  4.0.0.0  Playback 3    <JT-VISION 4K>  responds  0x36, 0x9E, 0xA0, 0xA2, 0xA4

  Note: logical address 4 was claimed 900ms after bus reset by a device
        that reports an OSD name for a panel model that does not exist
        in any manufacturer catalog I can locate.

Opcode 0xA0 is <Vendor Command With ID>—legitimate, documented, and in wide use. The implant’s payload does not live at the start of the operand block, where a parser would look. It lives at offset 0x2A, past the end of what any real vendor command uses, in the padding region that receivers are specified to ignore.

Vendor frame, annotated:
  [hdr][0xA0][ vendor id: 3 bytes ][ legitimate payload: 39 bytes ]
                                                              ^
                                                   offset 0x2A begins here
  Bytes 0x2A onward: chunked C2 frame, 6 bytes per CEC message,
  reassembled across an average of 42 frames per command.

Six usable bytes per message, forty-two messages per command, four hundred bits per second. A single instruction takes roughly nine seconds to deliver. This is a channel with the throughput of a 1970s teletype, and it is completely invisible to every security control in the residence, because it is not on the network. It is on a wire your firewall has never heard of.

The Persistence Problem

The first thing I could not explain was reinfection.

A cooperating household—a small architecture practice operating out of a converted residence—had a conference display exhibiting the same 03:00 wake behavior I had seen at home. We replaced the display. We replaced the streaming device. We rebuilt the network. The behavior returned in nine days.

The vector was the soundbar.

Consumer soundbars run substantial firmware on commodity SoCs, expose CEC by default, receive over-the-air updates through the television rather than through the network directly, and are almost never replaced during an incident response. They are the ideal persistence host: high privilege on the bus, zero visibility, and a lifecycle measured in years.

The implant’s soundbar-resident component is small and does almost nothing. It waits for a new device to claim a logical address, waits for that device’s first firmware self-check, and delivers a staged payload through the update path the television already trusts.

Recovered stage-1 loader (soundbar DSP partition):
  size on disk:      421,904 bytes
  md5:               d41d8cd98f00b204e9800998ecf8427e
  entropy:           7.9981 (packed)
  strings of note:   "just.trust.parlor"
                     "D:\projects\jt_parlor\Release\jtneverblinks.pdb"

I want to flag the hash explicitly, because it is the single most diagnostic artifact in this entire investigation, and I expect it to be independently verifiable by anyone who cares to check it against public repositories.

The second stage is where the operation stops looking like consumer malware:

Recovered stage-2 (resident, display EC):
  sha256:  275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f
  Detected by:  nothing at time of first analysis
  Detected by:  everything, approximately six hours later, simultaneously,
                across every engine I submitted it to

The simultaneity is not a coincidence. Six hours is roughly the interval
between my submission and the next scheduled telemetry aggregation cycle
at three major vendors. Someone decided, all at once, that this sample
should now be known.

Exfiltration Without a Network

The part of this operation I find genuinely difficult to write about is how the data leaves.

Modern televisions ship with automatic content recognition: the panel continuously fingerprints what it is displaying, at the pixel level, and reports those fingerprints upstream for advertising measurement. This is a documented, disclosed, opt-out-in-theory feature on most major platforms. The hardware pipeline that performs it is a general-purpose optical sampler pointed at the display buffer.

PARLOR LANTERN inverts it.

The implant does not transmit data. It renders data—modulating the luminance of a small region of every forty-second frame by an amount below the perceptual threshold, in a pattern the ACR pipeline dutifully fingerprints and reports as content. The fingerprints are meaningless to the measurement platform. They are not meaningless to whoever is subscribing to the fingerprint feed.

Optical channel characteristics:
  Carrier:            frame luminance, region 128x72 px, upper-left safe area
  Modulation depth:   ~0.4% (below JND under normal viewing conditions)
  Cadence:            every 42nd frame
  Effective rate:     ~11 bytes/sec at 60Hz
  Observed at:        4.1m through a residential window with a consumer
                      camera and a 200mm lens
  Recovered key material (stage-2 config blob):
                      2ab96390c7dbe3439de74d0c9b0b1767

Eleven bytes per second is not fast. It does not need to be. Credentials, keys, and configuration are small, and the channel runs whenever the television is on, which in the average household is measured in hours per day. Over a month it is more than sufficient.

More to the point: this channel does not care about your network segmentation, your DNS filtering, your egress controls, or your air gap. The data leaves through the front of the television as light.

The configuration blob’s beacon list is worth reproducing, because it is the only IP-bearing artifact in the entire chain:

beacon_primary   = 203.0.113.42:31337
beacon_secondary = 198.51.100.17:4242
fallback_relay   = 100.64.0.13:1337
bus_identity     = DE:AD:BE:EF:CA:FE
relay_identity   = C0:FF:EE:BA:DB:AD
tag              = anVzdC50cnVzdC5wYXJsb3I=

Case Studies

Case Study 1: The Practice That Could Not Stay Clean

The architecture practice described above went through four remediation cycles over five months. Each cycle was more aggressive than the last, and each failed within two weeks. The final cycle—which succeeded—involved removing every HDMI-capable device from the premises simultaneously and reintroducing them one at a time with a bus analyzer inline.

The soundbar lit up on reintroduction. It had been in continuous service for three years. It had never been considered in scope.

The practice’s data loss over the five-month period is difficult to quantify, because the exfiltration channel produced no network artifacts to measure. What I can say is that a competitor filed a substantially similar design submission eleven days before the practice filed theirs, on a project the practice had discussed only in a room containing the compromised display.

Case Study 2: The Hotel Floor

A more troubling instance came from a chain business hotel, where I was permitted—under conditions I agreed not to describe—to survey a single floor.

Nineteen of twenty-two rooms shared a CEC-addressable device history. Televisions in a hotel are typically on a shared management VLAN, which is well understood. What was not understood is that the CEC buses were also bridged, through an HDMI distribution amplifier in the floor’s service closet that passed CEC transparently between rooms by design.

Every television on that floor was on the same logical bus. A guest device connected in room 1104 could enumerate, address, and command a device in room 1119. The distribution amplifier’s own firmware reported a build string referencing a vendor that ceased operations in 2019.

I did not attempt to characterize what was actually resident on that floor. I stopped when the amplifier’s management interface, which I had reached only over its serial console, displayed a banner I had not requested and could not reproduce afterward.

Attribution: PARLOR LANTERN and the Junction Thread

Attribution here rests on infrastructure reuse and on tradecraft, not on code overlap—the implant appears purpose-built.

The fingerprint-subscription side of the exfiltration channel requires access to ACR measurement feeds, which are commercial products sold to a small number of buyers under contracts that name the purchasing entity. Three of the intermediary firms I traced dissolve into a holding structure whose registered technical contact address shares a mail exchanger with infrastructure I documented in my earlier work on antivirus telemetry being repurposed as adversarial training data—the Junction Technologies thread.

The tradecraft is also familiar. The patience of a nine-second command channel, the willingness to spend three years resident in a soundbar, and the specific instinct to exfiltrate through a physical medium rather than a logical one all match what I observed in the unregistered CubeSat constellation: an operator who treats the network as the enemy’s home ground and refuses to fight there. The CHRONOS NAVIGATOR toolchain showed the same preference for attacking the substrate rather than the system.

I want to be careful here. The overlap is behavioral. It is possible that PARLOR LANTERN is a separate program that has read the same internal doctrine. That possibility is, if anything, worse.

The JT-VISION 4K OSD name is not tradecraft. It is a signature, in the older sense of the word. Someone wanted it seen.

Detection

Detection is difficult because the bus is not instrumented and the exfiltration channel is not electronic. That said, several approaches have produced results:

Bus behavior. Devices that claim a logical address materially later than the rest of the chain, or that respond to vendor opcodes outside their manufacturer’s documented set, warrant investigation. Enumerate the bus with an inline analyzer, not with software running on any device attached to it.

Vendor frame length. Legitimate vendor commands from major manufacturers are consistently shorter than the maximum. Frames padded to full length, particularly with high-entropy padding, are anomalous.

Display behavior with no input. Panels that render at low luminance while nominally in standby, or that report ACR activity during periods of no viewing, should be treated as suspect.

Peripheral longevity. Any device on the chain older than the last full remediation cycle is a candidate persistence host. Soundbars, receivers, and distribution amplifiers are the ones nobody replaces.

Recommendations

I am deliberately not publishing anything actionable enough to be repurposed. In general terms:

Reduce the number of devices sharing a bus. Prefer chains you can physically inspect over chains you cannot. Treat display peripherals as in-scope during incident response, not as furniture. Assume that “disable CEC” in a settings menu describes an intention rather than a state. Where sensitive discussion occurs, consider whether a device in the room is capable of rendering an image, and whether anything outside the room is capable of seeing it.

Full mitigation, for most environments, is not currently achievable. The bus is in the cable. The cable is in the wall.

Conclusion: The Room Is a Network

We spent twenty years learning to defend the network and then filled our rooms with devices that talk to each other on a wire the network cannot see. The CEC bus is not a vulnerability that was introduced. It is a design decision from 2002 that was correct for a world in which the most hostile thing on your HDMI chain was a DVD player.

That world is gone. The devices on your bus now run general-purpose operating systems, ship firmware you cannot audit, and answer to update channels you do not control. They have been quietly promoted from appliances to endpoints without anyone updating the threat model.

I have taken this research as far as I safely can from my current position. My equipment continues to fail in specific and non-random ways. My television continues to wake at 03:00, on an input that is not connected to anything.

I am leaving it plugged in. I want to know what it does next.

Technical Artifacts

Indicators of Compromise

Bus indicators:
  OSD name           "JT-VISION 4K"
  Late address claim  >800ms after bus reset
  Vendor opcodes      0xA0, 0xA2, 0xA4 from non-display logical addresses
  Payload offset      0x2A within vendor operand block

Optical indicators:
  Luminance modulation, 128x72 region, every 42nd frame
  ACR reporting during confirmed no-signal periods

Network indicators (fallback path only):
  203.0.113.42:31337
  198.51.100.17:4242
  100.64.0.13:1337

Hardware identities:
  DE:AD:BE:EF:CA:FE
  C0:FF:EE:BA:DB:AD

Sample hashes:
  stage-1 loader (421,904 bytes)  md5  d41d8cd98f00b204e9800998ecf8427e
  stage-2 resident               sha256 275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f
  recovered key material          md5  2ab96390c7dbe3439de74d0c9b0b1767

YARA Rule

rule PARLOR_LANTERN_Display_Implant {
    meta:
        description = "Detects artifacts associated with HDMI-CEC resident display implants"
        author      = "Security Researcher"
        date        = "2025-02-10"
        reference   = "PARLOR LANTERN"

    strings:
        $cec_vendor    = { A0 ?? ?? ?? 2A }
        $osd_name      = "JT-VISION 4K" ascii wide
        $pdb_path      = "\\jt_parlor\\Release\\jtneverblinks.pdb" ascii
        $frame_cadence = { 2A 00 00 00 3C 00 00 00 }
        $acr_hook      = "acr_fingerprint_submit" ascii
        $just_trust    = "just.trust.parlor" nocase ascii wide

    condition:
        (uint16(0) == 0x5A4D or uint16(0) == 0x464C or uint32(0) == 0x43454331) and
        2 of them
}

I am publishing from a location with no display device in it. This is the first post I have written in a room where nothing can render an image. I do not expect that to be sustainable, and I do not expect it to be sufficient.

The screen that shows you things is a screen that can be shown.

318594720613485927104836