Rayhunter · Volume 8

Rayhunter Volume 8 — Reading the Recordings

Pulling QMDL/PCAP off the device, reviewing the recorded control plane in Wireshark, cross-referencing serving cells against public tower databases, and a host-side summary workflow


8.1 About this Volume

Everything here is post-hoc review of the detector’s own exported logs. Rayhunter records the modem’s control-plane diagnostic stream while it runs; this volume is about getting those files onto a host and reading them to understand what the detector saw. It is review and sanity-checking, not attack methodology — the only cellular traffic in view is the control plane the operator’s own device already exchanged with the network, saved by the operator’s own detector.

The two things worth being clear about up front. First, Rayhunter records the control plane — the signalling between the device and the tower (identity requests, security mode, system-information broadcasts, connection setup/release) — not user traffic (calls, texts, data payloads are not its subject). Second, reading a recording is how a warning gets turned from a coloured line into something an operator, or an expert they hand it to, can reason about. Volume 5 explains the analyzers; this volume explains reading their raw material.


8.2 What Rayhunter records: QMDL and PCAP

Qualcomm modems expose a diagnostic (“DIAG”) interface that streams the modem’s internal control-plane events. Rayhunter records that stream to a QMDL file (Qualcomm MoDem Log) — the native, lossless capture of the DIAG messages. For analysis in standard tooling, the same control plane is also made available as a PCAP, the universal packet-capture format that Wireshark and the tshark/pcap ecosystem read directly.

Table 1 — 2. What Rayhunter records: QMDL and PCAP

ArtifactWhat it isRead it with
QMDLThe modem’s native DIAG log — the raw, complete recordRayhunter’s own analyzers; Qualcomm-aware tooling
PCAPThe control-plane messages in standard packet-capture formWireshark / tshark, and any pcap library

The web UI’s Download control exports a recording for off-device review. The PCAP is the one most users open first, because Wireshark dissects LTE RRC and NAS messages natively; the QMDL is the artifact to keep as the lossless original and to feed back through Rayhunter’s analyzers (§8).

Why the control plane is enough to detect behaviour. The analyzers (Vol 5) key off control-plane events — an identity request without authentication, a redirect to 2G, a null-cipher suggestion, a stripped-down system-information broadcast. None of that requires user-plane content, which is why Rayhunter can be useful while recording nothing a user would consider private traffic.


8.3 Pulling the files off the device

Two routes, matching the two web-UI access paths from Volume 6.

Over the web UI (simplest). Browse to http://<device>:8080, pick the recording, and use Download. Because Rayhunter serves plain HTTP, the browser may show an “insecure download blocked” prompt — expected on the local link, and safe to accept for this device. This gives the QMDL and/or PCAP straight to the host’s download folder.

Over USB/ADB (Orbic). With ADB set up (Vol 6 §6), the port-forward that exposes the UI (adb forward tcp:8080 tcp:8080) also lets a host reach the download endpoint at http://localhost:8080. Recordings can be retrieved the same way without joining the device’s Wi-Fi.

# Host side, Orbic over USB: forward the UI/download port, then pull via the web UI
adb forward tcp:8080 tcp:8080
# → browse http://localhost:8080 and use Download, or script the download endpoint

# Keep an organized, per-trip archive on the host (untrusted data in its own dir)
mkdir -p ~/rayhunter/2026-10-17-trip && cd ~/rayhunter/2026-10-17-trip
# place the exported .qmdl and .pcap here
ls -la
# rayhunter_2026-10-17_143022.qmdl
# rayhunter_2026-10-17_143022.pcap

Handle recordings as sensitive data. A recording is a log of where the device was and the control plane it saw. Store exports in a dedicated per-trip directory, keep them off shared machines, and delete the on-device original only after the export is safely archived (Vol 7 §8, Vol 10 OPSEC).


8.4 Opening the PCAP in Wireshark

Opening the exported PCAP in Wireshark shows the control plane Rayhunter recorded as a packet list. The dissectors to lean on are the LTE ones:

  • LTE RRC (Radio Resource Control) — the layer carrying system-information broadcasts (SIBs), connection setup, reconfiguration, and release/redirect. This is where a redirect toward 2G, or a system-information block that ranks 2G/3G above LTE, shows up.
  • NAS-EPS (Non-Access Stratum) — the layer carrying identity requests, authentication, and the security-mode command. This is where an identity request without authentication, or a null-cipher security-mode command, appears.

A practical reading pass, mapping to the analyzers rather than hunting blindly:

Table 2 — A practical reading pass, mapping to the analyzers rather than hunting blindly

In Wireshark, look at……to see the pattern behind
nas-eps identity-request messages, and whether authentication followsIMSI Requested analyzer
lte-rrc connection-release with a redirect to a 2G carrier2G Downgrade analyzer
lte-rrc SIB6 / SIB7 contents and the priority they assign 2G/3G vs LTELTE SIB6/7 Downgrade analyzer
The RRC security-mode / cipher suggested (EEA0 = null)Null Cipher analyzer
The NAS security-mode command’s cipher after authenticationNAS Null Cipher analyzer
Whether SIB1 schedules at least two further SIBs (e.g. SIB3/4/5)Incomplete SIB analyzer
Connect/disconnect events framing a sessionDiagnostic Information (context, not a warning)

Display filters keep the view tractable:

nas-eps.emm.type_mm == 0x55        # EMM Identity Request (NAS identity ask)
lte-rrc.sib6_element               # presence of SIB6 content
lte-rrc.sib7_element               # presence of SIB7 content
lte-rrc.c1 == 4                    # RRC Connection Release (redirect lives here)

(Exact filter names track the Wireshark version’s LTE dissectors; use the detail pane to confirm field names, then right-click → Apply as Filter.)


8.5 Cross-referencing the serving cell against tower databases

A recording carries the identifiers of the cells the device attached to — the operator’s MCC/MNC (country + network), the TAC (tracking area), and the Cell ID / eNB ID. Those identifiers can be checked against a public, crowdsourced tower database to sanity-check whether a cell the device saw is a known, legitimately-mapped cell at that location, or one with no public record.

OpenCelliD (opencellid.org) is the common reference — a free, community-maintained database of cell towers keyed by MCC/MNC/LAC-or-TAC/CellID with approximate coordinates. The sanity-check reasoning:

  • A serving cell whose identifiers resolve to a known tower at roughly the location the device was in is unremarkable.
  • A serving cell with identifiers that don’t appear in the database, or that map to a wildly different location, is worth a second look — not proof of anything (crowdsourced databases are incomplete, and new/temporary legitimate cells exist), but a data point that lines up with, or against, an analyzer warning.

Table 3 — 5. Cross-referencing the serving cell against tower databases

IdentifierWhat it isUse in the check
MCC / MNCMobile country code / network codeConfirms the carrier is the expected one
TAC / LACTracking / location area codeNarrows the area; a mismatch with location is notable
Cell ID / eNBThe specific cellThe key for a tower-database lookup

A database miss is not a detection. OpenCelliD does not list every legitimate cell, and carriers add, move, and retire cells constantly. “Not in the database” is a weak signal that gains weight only alongside an analyzer warning and the surrounding context. Treat tower lookups as corroboration, never as an independent verdict.


8.6 Analyzer → meaning → what to check

The reference table for turning a fired analyzer into a review action. (Volume 5 is the authority on how each analyzer decides; this maps each to a plain-language meaning and what to look at in the recording.)

Table 4 — 6. Analyzer → meaning → what to check

Analyzer (Vol 5)Category-level meaningWhat to check in the recording
IMSI RequestedThe network asked for the device’s permanent identity (IMSI/IMEI) in a suspicious pattern — e.g. new tower → identity asked → no authentication → disconnectNAS identity-request messages; whether authentication followed; whether a connection even preceded the request
Connection Release / 2G DowngradeA base station released the connection and redirected the device to a 2G cell, where interception is easierRRC connection-release with a redirect to a 2G carrier; what cell it pointed at
LTE SIB6/7 DowngradeAn LTE tower broadcast SIB6/SIB7 giving 2G/3G frequencies higher priority than LTE (a well-behaved tower ranks 4G neighbours higher)SIB6/SIB7 contents and the reselection priorities they set; malformed SIB7 is the more common of the two
Null CipherThe cell suggested the null cipher (EEA0) at the RRC layer — radio encryption off, which should almost never happen outside test/regulated casesThe RRC security-mode / cipher negotiated
NAS Null CipherA NAS-layer security-mode command suggested EEA0 after successful core-network authentication — possible attack (e.g. via SS7-obtained key material) or a rare misconfigurationThe NAS security-mode command’s cipher choice and its position after authentication
Incomplete SIBSIB1 failed to schedule at least two further SIBs (commonly SIB3/4/5); fake base stations often omit themSIB1’s scheduling list; weak alone, strong combined with IMSI Requested
Diagnostic InformationContext: logs tower connect/disconnect to aid PCAP review — informational, not a warningUse as the timeline that frames the other analyzers’ events
No NAS Messages (experimental, default off)≥5 min of diagnostic traffic with no NAS message — may mean a missing/inactive/improperly-seated SIM or no reachable networkSIM state and whether the device had service; prone to false positives
Test Analyzer (default off)Fires on every SIB1 broadcast — a noisy self-test to confirm Rayhunter is aliveOnly ever used to confirm the detector works; expect constant firing

Read combinations, not single hits. The design intent is that several lower-confidence signals together are stronger than any one alone — an Incomplete SIB on its own might be a misconfigured tower, but an Incomplete SIB alongside an IMSI Requested is a much stronger indicator. The severity ladder (Vol 7 §5) already reflects some of this; the recording lets the reviewer see the co-occurrence directly.


8.7 A host-side summary workflow

A realistic review session: pull the files, get a quick packet-level summary with tshark (Wireshark’s CLI), then a small script to turn that into a per-trip, human-readable digest. All of it reads the detector’s own output.

#!/usr/bin/env bash
# review-trip.sh — summarize one Rayhunter trip's exported PCAP.
# Reads ONLY the detector's own recording. No network, no attack surface.
set -euo pipefail
PCAP="$1"   # e.g. ~/rayhunter/2026-10-17-trip/rayhunter_2026-10-17_143022.pcap

echo "== Capture overview =="
capinfos -aceu "$PCAP"           # packet count, duration, start/end times

echo; echo "== NAS identity requests (IMSI Requested signal) =="
tshark -r "$PCAP" -Y 'nas-eps.emm.type_mm == 0x55' \
       -T fields -e frame.number -e frame.time -e nas_eps.emm.id_type2

echo; echo "== RRC connection releases / redirects (2G-downgrade signal) =="
tshark -r "$PCAP" -Y 'lte-rrc.rrcConnectionRelease_element' \
       -T fields -e frame.number -e frame.time

echo; echo "== SIB6 / SIB7 presence (SIB downgrade signal) =="
tshark -r "$PCAP" -Y 'lte-rrc.sib6_element or lte-rrc.sib7_element' \
       -T fields -e frame.number -e frame.time

echo; echo "== Serving-cell identifiers seen (for OpenCelliD cross-check) =="
tshark -r "$PCAP" -T fields -e lte-rrc.cellIdentity -e lte-rrc.trackingAreaCode \
  | sort -u | sed '/^\t*$/d'
#!/usr/bin/env python3 -I
"""trip_digest.py — one-line-per-event digest from tshark JSON of a Rayhunter PCAP.
Run tshark with -T json -x over the detector's own export and pipe it here.
Reads untrusted capture data only as data; no exec, no network."""
import json, sys
events = json.load(sys.stdin)            # tshark -T json output
counts = {}
for pkt in events:
    layers = pkt.get("_source", {}).get("layers", {})
    if "nas-eps" in layers:
        counts["nas_identity_or_security"] = counts.get("nas_identity_or_security", 0) + 1
    if "lte-rrc" in layers:
        counts["rrc_control"] = counts.get("rrc_control", 0) + 1
print("Rayhunter trip digest")
for k, v in sorted(counts.items()):
    print(f"  {k:28s} {v}")
print("Review any NAS identity request without a following authentication (Vol 8 §6).")

The point of the script layer is not automation of judgement — it is to surface the handful of control-plane events worth a human’s eyes, so a reviewer opens Wireshark already knowing which frames to inspect.


8.8 Re-running the analyzers offline

Rayhunter’s analyzers (Vol 5) run on-device in real time, but the same heuristics can be applied to a saved QMDL after the fact on a host. Rayhunter’s codebase is a Rust workspace, and alongside the on-device daemon it builds tooling that ingests a recorded QMDL and reports which analyzers would fire — the offline counterpart to the on-device web-UI analysis view. This is useful for two things: reviewing a recording on a full keyboard-and-screen host rather than the hotspot’s tiny UI, and re-checking an old recording after an analyzer has been improved in a newer release.

The workflow shape (consult the repo’s current README and tool help for exact invocation, as the tooling tracks the release):

1.  Download the .qmdl (the lossless original) from the device  (§3)
2.  Build or obtain Rayhunter's host-side analysis tool from the repo (Rust / cargo)
3.  Point it at the .qmdl → it reports the analyzer findings, same heuristics as on-device
4.  Cross-read against the Wireshark PCAP view (§4) and the tower lookups (§5)

Keep the QMDL, not just the PCAP. The QMDL is the lossless native log; the PCAP is a derived, Wireshark-friendly view. Re-running improved analyzers, or handing a recording to an expert, both want the QMDL. Archive it as the original (Vol 7 §8).


8.9 What a log can and cannot tell you

The honest boundary of recording review:

A recording can:

  • Show the specific control-plane events behind a warning — the actual identity request, release/redirect, SIB, or cipher choice.
  • Let an analyzer’s finding be confirmed, contextualized, or discounted by a human or an expert.
  • Preserve the evidence of a suspicious session for later analysis, reporting, or comparison across trips.
  • Supply serving-cell identifiers for a tower-database sanity check (§5).

A recording cannot:

  • Identify who operated a suspicious cell, with what device, or for what purpose. The control plane does not carry that.
  • Turn a heuristic warning into a certainty. The analyzers flag patterns associated with cell-site simulators; legitimate networks sometimes produce similar patterns (Vol 7 §6).
  • Reconstruct user traffic — calls, texts, data payloads are not recorded and are not the subject.
  • Prove absence. A quiet recording is consistent with “nothing happened” and with “a stealthy technique the heuristics don’t catch” (Vol 9 covers Rayhunter’s limits).

When it matters, hand it to an expert. EFF’s own guidance frames the PCAP as something a user can pass to someone with cellular-security expertise for deeper review. The operator’s job is to capture, preserve, and do the first-order read; a definitive call on an ambiguous recording is expert territory.


Volume 9 places Rayhunter among the other detection projects — SnoopSnitch, CellGuard, SeaGlass, Crocodile Hunter — and situates where a general SDR like the HackRF One fits, with an honest account of what this class of tool can and cannot do.

Comments (0)

  1. Loading…

Comments are held for moderation — nothing appears until approved.