Inspectrum is a tool for analyzing signals recorded by software-defined radios (SDRs). It provides interactive visualization and analysis capabilities for IQ (In-phase/Quadrature) data, making it invaluable for RF protocol reverse engineering, signal forensics, and wireless security research.
sudo apt-get update
sudo apt-get install inspectrum
sudo pacman -S inspectrum
brew install inspectrum
git clone https://github.com/miek/inspectrum.git
cd inspectrum
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install
# Install GNU Radio
sudo apt-get install gnuradio gnuradio-dev
# Install USRP support (if using USRP devices)
sudo apt-get install libuhd-dev libuhd4.0
# Install RTL-SDR support
sudo apt-get install librtlsdr-dev
# Install HackRF support (if applicable)
sudo apt-get install libhackrf-dev
| Command | Description |
|---|
inspectrum | Launch GUI with no file |
inspectrum <file.iq> | Open IQ recording file |
inspectrum -r <sample_rate> | Specify sample rate |
inspectrum -f <center_freq> | Set center frequency |
inspectrum -s <file_format> | Specify file format |
| Format | Extension | Description |
|---|
| Complex int8 | .ci8 | 8-bit signed IQ samples |
| Complex int16 | .ci16 | 16-bit signed IQ samples |
| Complex int32 | .ci32 | 32-bit signed IQ samples |
| Complex float32 | .cf32 | 32-bit floating point IQ |
| Complex float64 | .cf64 | 64-bit floating point IQ |
| Unsigned int8 | .u8 | Raw unsigned samples |
| USRP DAT | .dat | USRP native format |
| WAV | .wav | WAV audio format |
┌─────────────────────────────────────────────┐
│ Inspectrum - Signal Analyzer │
├─────────────────────────────────────────────┤
│ Spectrogram View (Time-Frequency) │
│ ┌───────────────────────────────────────┐ │
│ │ │ │
│ │ [Colormap visualization] │ │
│ │ │ │
│ └───────────────────────────────────────┘ │
├─────────────────────────────────────────────┤
│ Power Spectrum View (FFT) │
│ ┌───────────────────────────────────────┐ │
│ │ Frequency distribution │ │
│ └───────────────────────────────────────┘ │
├─────────────────────────────────────────────┤
│ Timeline & Navigation │
│ ├─────────────────────────────────────┤ │
│ | ← |═════════════════════════════════| → │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
| Control | Action |
|---|
| Mouse Wheel | Zoom time axis |
| Ctrl + Mouse Wheel | Zoom frequency axis |
| Left Click + Drag | Pan in time/frequency |
| Right Click + Drag | Select region |
| Space Bar | Play/Pause signal |
| Home | Jump to start |
| End | Jump to end |
| Shift + Left/Right | Move by sample |
| Ctrl + Left/Right | Move by burst |
File Operations:
Ctrl+O Open file
Ctrl+S Save analysis
Ctrl+E Export selection
Navigation:
Space Play/Pause
Home First sample
End Last sample
Left Previous sample
Right Next sample
+ Zoom in
- Zoom out
Analysis:
Ctrl+A Select all
Ctrl+D Deselect
Ctrl+Z Undo
Ctrl+Y Redo
Vertical Axis: Frequency
Horizontal Axis: Time
Color Intensity: Signal Power
Bright colors = Strong signal
Dark colors = Weak signal/Noise
FSK (Frequency Shift Keying)
- Clear frequency shifts between two states
- Used in simple digital protocols
- Example: Frequency hops between f1 and f2
ASK (Amplitude Shift Keying)
- Amplitude variations at constant frequency
- Used in amplitude-based communications
- Example: On/Off keying
PSK (Phase Shift Keying)
- Phase shifts at constant frequency
- Appears as continuous line with phase changes
- Used in advanced digital modulation
OFDM (Orthogonal Frequency Division Multiplexing)
- Multiple tones across bandwidth
- Appears as filled frequency block
- Used in WiFi, LTE, 4G/5G
Ctrl + Scroll Up: Zoom in on frequency
Ctrl + Scroll Down: Zoom out on frequency
F Auto-scale frequency axis
Scroll Up: Zoom in on time
Scroll Down: Zoom out on time
T Auto-scale time axis
Left Click Drag: Pan in both axes
Shift + Drag: Pan frequency only
Ctrl + Drag: Pan time only
1. Open signal file
2. Select region in spectrogram
3. View power spectrum below
4. Identify peak frequencies
5. Measure frequency separation
1. Zoom to signal of interest
2. Identify -3dB points (half power)
3. Calculate difference: BW = f_high - f_low
4. Document for protocol analysis
1. View spectrogram
2. Identify distinct time intervals
3. Note duration of each burst
4. Calculate burst pattern
5. Extract sample boundaries
1. Enable ruler display
2. Mark burst start time
3. Mark burst end time
4. Calculate duration
5. Note inter-burst gaps
1. Right-click on spectrogram region
2. Select "Export selection"
3. Choose output format (cf32, ci16, etc.)
4. Specify file path
5. Click Export
1. Select time/frequency region
2. Tools → Export as WAV
3. Set sample rate
4. Set bit depth (16/24/32-bit)
5. Save file
1. Right-click on signal feature
2. Select "Add marker"
3. Name the feature
4. Add frequency/time annotation
5. Export markers as text
1. Load IQ recording file
2. Identify signal presence
3. Determine occupied bandwidth
4. Note center frequency
5. Identify modulation type
1. Zoom to individual bursts
2. Measure burst duration
3. Note inter-burst spacing
4. Identify preamble patterns
5. Isolate payload data
1. Export signal samples
2. Use GNU Radio for demodulation
3. Select appropriate demod block
4. Process with matched filter
5. Generate bit stream
1. Analyze decoded bits
2. Identify framing patterns
3. Extract header fields
4. Decode payload
5. Document protocol structure
# Example GNU Radio Python script
import numpy as np
from gnuradio import gr, digital, blocks
class Demodulator(gr.top_block):
def __init__(self, sample_rate, center_freq):
gr.top_block.__init__(self, "Signal Demodulator")
# File source
source = blocks.file_source(
gr.sizeof_gr_complex,
'captured_signal.cf32',
repeat=False
)
# FSK demodulation
fsk_demod = digital.fsk_demod(
baud_rate=9600,
sample_rate=sample_rate
)
# Sink
sink = blocks.file_sink(
gr.sizeof_char,
'demodulated_bits.bin'
)
self.connect(source, fsk_demod, sink)
if __name__ == '__main__':
tb = Demodulator(1e6, 433e6)
tb.run()
#!/bin/bash
# Process multiple recordings
for file in *.cf32; do
echo "Processing $file..."
inspectrum "$file" --batch-mode
done
1. Enable "Frequency Track" option
2. Select signal with time-varying frequency
3. Tool automatically follows frequency shifts
4. Export tracked frequency vs. time
5. Use for chirp/frequency-hopping analysis
1. Open Tools menu
2. Select "Noise Floor Estimation"
3. Measure background power level
4. Set detection threshold
5. Automatically identify signals above noise
1. Select time window
2. Tools → Periodicity Analysis
3. Computes autocorrelation
4. Identifies repeating patterns
5. Useful for symbol/frame detection
# Simple RTL-SDR recording
rtl_sdr -f 433000000 -s 2000000 -g 40 output.iq
# Parameters:
# -f: Center frequency (Hz)
# -s: Sample rate (Hz)
# -g: Gain (0-50)
# output.iq: Output file
# HackRF capture
hackrf_transfer -r output.iq -f 433000000 \
-s 20000000 -g 40 -a 1 -x 20
# Parameters:
# -f: Frequency
# -s: Sample rate
# -g: Gain
# -x: Frequency offset compensation
# USRP recording via GNU Radio
uhd_rx_cfile -f 433e6 -s 2e6 -g 30 -d 1 \
--type float32 output.cf32
# Or using Python script
from gnuradio import uhd
# Create appropriate blocks and capture
#!/usr/bin/env python3
import subprocess
import os
from datetime import datetime
# Configuration
input_dir = "captures/"
output_dir = "analysis/"
sample_rate = 2000000
# Create output directory
os.makedirs(output_dir, exist_ok=True)
# Process each file
for filename in os.listdir(input_dir):
if filename.endswith('.iq'):
filepath = os.path.join(input_dir, filename)
# Run analysis
cmd = [
'inspectrum',
filepath,
f'--samplerate={sample_rate}',
f'--output={output_dir}/{filename}.analysis'
]
print(f"Processing {filename}...")
subprocess.run(cmd)
print(f" Completed at {datetime.now()}")
#!/usr/bin/env python3
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
def detect_bursts(iq_data, threshold_db=-50):
"""Detect signal bursts above noise floor"""
# Calculate power
power = np.abs(iq_data) ** 2
power_db = 10 * np.log10(power + 1e-10)
# Detect above threshold
bursts = power_db > threshold_db
# Find burst boundaries
edges = np.diff(bursts.astype(int))
starts = np.where(edges == 1)[0]
ends = np.where(edges == -1)[0]
return list(zip(starts, ends))
def analyze_burst(iq_data, start, end):
"""Analyze individual burst"""
burst = iq_data[start:end]
return {
'duration': len(burst),
'peak_power': np.max(np.abs(burst)),
'avg_power': np.mean(np.abs(burst)),
'bandwidth': estimate_bandwidth(burst)
}
# Load data
data = np.fromfile('signal.cf32', dtype=np.complex64)
# Find bursts
bursts = detect_bursts(data)
print(f"Found {len(bursts)} bursts")
# Analyze each
for idx, (start, end) in enumerate(bursts):
info = analyze_burst(data, start, end)
print(f"Burst {idx}: {info}")
# Check file properties
file signal.iq
# Determine IQ format from properties
# Common: cf32 (complex float32), ci16 (complex int16)
# If unsure, check file size:
# Size = samples * bytes_per_sample
# cf32: 4 bytes per sample (2 float32 per IQ pair)
# ci16: 4 bytes per sample (2 int16 per IQ pair)
# Calculate sample count
ls -lh file.iq
# Divide file size by bytes per sample
inspectrum file.raw -t cf32 -r 2000000
Solution 1: Reduce zoom level
Solution 2: Select smaller time window
Solution 3: Close other applications
Solution 4: Use power-of-2 FFT sizes
Solution 5: Disable advanced features
# Check available memory
free -h
# For large files, limit display range
# In Inspectrum: Zoom in to smaller region
# Or process in sections with scripts
1. Check gain settings during capture
2. Reduce FFT size for better sensitivity
3. Increase averaging/integration time
4. Verify antenna connection
5. Check frequency offset
Known frequency: 433.050 MHz
Displayed at: 433.055 MHz
Offset: 5 kHz
Corrected capture frequency: 433.050 - 0.005 = 433.045 MHz
Recapture with corrected frequency
- Use appropriate sample rate (2x signal bandwidth minimum)
- Document gain and antenna settings
- Record reference signals for calibration
- Capture full protocol exchange
- Include quiet periods for noise analysis
- Start with full signal overview
- Zoom to isolate features of interest
- Take screenshots of important findings
- Export key regions for further analysis
- Document modulation parameters
- Identify all signal features
- Extract individual transmissions
- Analyze frame structure
- Build bit stream from demodulated data
- Cross-reference with known protocols
- Validate decoding assumptions
Current stable: Inspectrum 0.8+
Cross-platform: Linux, macOS, Windows
Architecture: x86_64, ARM64
Language: C++ with Qt
License: GPL-3.0
Dependencies: Qt5, GNU Radio, Boost, FFTW