Chapter: 9 (Week 11) Duration: 4 hr Substrate: URH + Inspectrum + Python; ANTSDR E200 or HackRF optional for replay Points: 12
Overview
Apply the full URH five-step protocol RE workflow (identify, isolate, decode, analyse structure, replay) to an instructor-supplied IQ file of an unknown protocol. The protocol is a real sub-GHz device operating in the 433 MHz ISM band. No prior specification is given.
IQ file: lab9-unknown-protocol.iq (centre freq: 433.92 MHz, sample rate: 250 kSPS)
Step 1: Signal Characterisation (30 min)
Before opening URH, analyse the signal in Python and Inspectrum.
Python analysis:
import numpy as np
import matplotlib.pyplot as plt
FS = 250000 # 250 kSPS
samples = np.fromfile("lab9-unknown-protocol.iq", dtype=np.complex64)
# Envelope
envelope = np.abs(samples)
t = np.arange(len(envelope)) / FS * 1000 # ms
plt.figure(figsize=(14, 8))
plt.subplot(3, 1, 1)
plt.plot(t[:5000], envelope[:5000], linewidth=0.5)
plt.title("Envelope (first 20ms)"); plt.xlabel("Time (ms)"); plt.ylabel("Amplitude")
# Instantaneous frequency
inst_phase = np.unwrap(np.angle(samples[:5000]))
inst_freq = np.diff(inst_phase) * (FS / (2 * np.pi))
plt.subplot(3, 1, 2)
plt.plot(t[:4999], inst_freq, linewidth=0.5, color='orange')
plt.title("Instantaneous frequency"); plt.xlabel("Time (ms)"); plt.ylabel("Hz")
# Spectrogram
plt.subplot(3, 1, 3)
plt.specgram(samples[:25000], NFFT=128, Fs=FS, noverlap=96, cmap='viridis')
plt.title("Spectrogram (first 100ms)"); plt.xlabel("Time (ms)"); plt.ylabel("Freq (Hz)")
plt.tight_layout(); plt.savefig("lab9-signal-characterisation.png", dpi=150); plt.show()
From these three plots, hypothesise:
- What modulation family? (Look at envelope: is it on/off? Look at frequency: is it two-level? Look at phase: is it phase-jumping?)
- Is the signal bursty (periodic transmissions) or continuous?
- What is the approximate burst duration (ms)?
- What is the approximate symbol rate? (Look at minimum pulse width in the envelope)
Step 2: URH Demodulation (60 min)
Open lab9-unknown-protocol.iq in URH.
- Set sample rate to 250000 in the Signal tab
- Click
Auto-detect parameters. Record the auto-detected modulation, bit rate, and deviation - Open the Analysis tab. Verify the demodulated bit stream looks like clean 0s and 1s (not noisy)
- Adjust threshold or demodulation parameters if the bit stream is noisy
Manual verification (if auto-detect is wrong):
- For OOK: check that bits are clean 0/1 from the envelope threshold
- For FSK: check that two frequency levels are clearly separated in the Analysis tab frequency plot
- For PSK: check phase transitions in the IQ view
Record:
- Auto-detected modulation type
- Auto-detected bit rate (bps)
- Deviation (if FSK)
- Screenshot of URH Signal tab showing the demodulated bit stream
Step 3: Frame Structure Analysis (60 min)
In the URH Protocol tab:
-
Click
Interpret Signalto auto-cluster messages. How many message types does URH identify? -
Identify the preamble: look for a recurring bit pattern at the start of each message. Common preamble patterns:
10101010101010(alternating),11111111(all-ones),00000000(all-zeros). -
Identify the sync word: the fixed bit pattern that follows the preamble and marks the payload start. This is typically 16-32 bits. It is the same in all messages.
-
After the sync word, look for:
- A stable field (same value in all captured messages) → likely the device address
- A varying field that shows limited values (e.g., only 2-4 different values seen) → likely a command or button code
- A final field that varies consistently with the payload → likely a checksum
Document your findings in this table:
| Field | Start bit | Length (bits) | Type | Notes |
|---|---|---|---|---|
| Preamble | 0 | ? | Fixed alternating | Describe the pattern |
| Sync word | ? | ? | Fixed | Hex value |
| Address | ? | ? | Fixed | Hex value (same in all messages) |
| Command | ? | ? | Enumerated | List all values observed |
| CRC/Checksum | ? | ? | Derived | Polynomial if identified |
Step 4: CRC Identification (30 min)
import crcmod
import numpy as np
# Paste your extracted payload bytes here (from URH output)
# Example - replace with actual bytes from your URH analysis
messages = [
bytes.fromhex("AA2DD4 42 01 B3".replace(" ", "")), # placeholder
bytes.fromhex("AA2DD4 42 00 B0".replace(" ", "")), # placeholder
]
# Test CRC polynomials
polys = {
"CRC-8 CCITT": (0x107, 0x00, 0x00),
"CRC-8 Dallas/Maxim": (0x131, 0x00, 0x00),
"CRC-8 SAE J1850": (0x11D, 0xFF, 0xFF),
"CRC-8 WCDMA": (0x19B, 0x00, 0x00),
}
for name, (poly, init, xor) in polys.items():
crc_fn = crcmod.mkCrcFun(poly, initCrc=init, xorOut=xor, rev=False)
match = True
for msg in messages:
payload, expected_crc = msg[:-1], msg[-1]
computed = crc_fn(payload)
if computed != expected_crc:
match = False
break
print(f" {name:30s}: {'MATCH' if match else 'no match'}")
Step 5: Signal Generation (optional, requires HackRF or ANTSDR E200 in RF-shielded enclosure)
Using the URH Generator tab, craft a test message with:
- Same preamble + sync word as the captured messages
- Your own device address (modify one bit of the captured address)
- A command value from your enumerated command set
- Correct CRC (compute with your identified polynomial)
Transmit via HackRF (osmocom Sink in GRC, or URH's built-in transmission with HackRF selected). Observe in a separate URH/Wireshark session whether the crafted frame appears as a valid frame.
This step is optional and requires RF-shielded enclosure and instructor authorization.
Deliverables
lab9-signal-characterisation.png(three-panel Python analysis plot)- URH Analysis tab screenshot showing demodulated bit stream
- URH Protocol tab screenshot showing labelled fields with your field-inventory table
- CRC analysis output (Python script output showing which polynomial matched)
- Written protocol hypothesis (1-2 pages):
- Modulation type + bit rate (with evidence)
- Encoding (NRZ, Manchester, etc.)
- Field inventory with hex values
- Identified CRC polynomial
- What device type you believe this is (based on frequency, modulation, frame structure)
- Limit of confidence: what are you confident about vs. what remains uncertain?
Grading (12 points)
| Item | Points |
|---|---|
| Signal characterisation plot with correct modulation identification | 2 |
| URH bit stream: clean demodulation (0/1 with ≤5% noise) | 2 |
| Field inventory table: preamble + sync word correctly identified | 3 |
| CRC polynomial identified (or documented as unknown with evidence) | 2 |
| Protocol hypothesis write-up with limit-of-confidence statement | 3 |