Start with the artifact: at 2147.5 MHz, on PCI 201, FalconEye now produces Wireshark-readable MAC-LTE output, RLC-LTE output, decoded paging S-TMSI rows, and structured DCI-0 uplink grant rows from a HackRF Pro. No transmit path. No decryption. No “trust me, the waterfall looked spicy.” RF humour is allowed, but the RF ocean does not care about vibes.
Start with the previous catch
This post is the next chapter after A Peak Is Not a Decode. That earlier build log is the precedence for this one: before we could talk about MAC, RLC, paging, S-TMSI, or uplink grants, we had to stop FALCON from confusing “there is LTE energy here” with “the receiver has enough truth to decode.” The MIB work mattered because PBCH/MIB acceptance is the first hard gate in the chain. If the receiver lies at that layer, every later RNTI, grant, and packet export inherits the lie with better formatting.
The first runs were messy in the useful way. Cell search could show peaks; FalconEye could drift through tracking states; but MIB recovery was brittle. We found and fixed the kind of plumbing that does not look like RF research until it ruins RF research: short Soapy reads getting treated like complete buffers, acquisition and MIB decode getting separate timing assumptions, discontinuities carrying stale synchronization state forward, and FalconGUI not passing the same RF args and fixed gain that made the CLI path work. The work was less “invent a decoder” and more “make the decoder stop eating wet cardboard and calling it a frame.”
That hardening changed the standard of proof. The receiver now requires bounded reads, explicit failure modes, reset behaviour on discontinuity, two agreeing CRC-valid MIB observations with valid SFN progression, a continuous 15.36 Msps HackRF stream, and tests around replay, negative fixtures, PBCH stage capture, receiver recovery, and stale-worker generation tagging. By the time this post begins, the focused reliability suite is at 27/27. The important part is not the number by itself. It is that the later PCAPs and CSVs are downstream of a receiver that had already been forced to become more boring.
Credit where the signal came from
This work sits on other people’s antennas. FALCON, by Robert Falkenberg and Christian Wietfeld, gave us the control-channel monitor and the useful warning that PDCCH observations can be polluted by false assignments unless the receiver is careful. LTESniffer from SysSec KAIST showed the larger target shape: decode PDCCH first, then use DCI/RNTI state to reach PDSCH and PUSCH. LTE-Cell-Scanner and LTE-Tracker supplied the older HackRF-friendly cell-search and tracking reference points. The NDSS paper on passive multi-target GUTI identification by Byeongdo Hong and Gunwoo Yoon is the privacy north star here: passive RF correlation can become identity linkage when control-plane timing and identifiers are handled badly. Logos Red’s HackRF/LTESniffer walkthrough is a practical public write-up in the same terrain, and it is refreshingly blunt about legal boundaries.
Our version is a closed-lab build note. It is about measuring what passive LTE control-plane work exposes, not about cracking subscriber traffic. If encrypted user-plane payload is the fish you are imagining, the net is in the wrong ocean.
The first job was making HackRF boring
The early work was not glamorous. FALCON could see peaks and then fail downstream. So we stopped treating a peak as proof. We tightened the receive contract: short reads became explicit failures, receive discontinuities reset synchronization/CFO/PBCH state, and acquisition/MIB decode got a shared wall-clock deadline. Then we changed the radio path so the HackRF stayed in one continuous 15.36 Msps stream instead of retuning between cell search, MIB, and full-band decode. The less the radio changed underneath the decoder, the less the decoder had to pretend.
Gate by gate, this got us from cell search to two agreeing CRC-valid MIBs, then to PDCCH/DCI and live RNTIs in both the CLI and FalconGUI. The GUI fix was almost rude in its simplicity: it was not passing RF args or fixed gain into EyeCore. In a lab with multiple SDRs attached, empty Soapy args are not “automatic”; they are a small séance. We added RF Args, defaulted them to driver=hackrf, exposed fixed gain, and made the GUI follow the same path as the CLI.
Then we made the output useful
Seeing RNTIs scroll is nice. Saving evidence is better. We added MAC-LTE PCAP export for decoded PDSCH transport blocks and RLC-LTE PCAP export for MAC SDUs so Wireshark can inspect the layers that FALCON is actually recovering. Then we added a paging parser on P-RNTI/PCH payloads to pull S-TMSI values into a CSV. That gives the passive “who is being paged in this cell” signal.
sudo ./build-validation/src/FalconEye \
-a driver=hackrf -f 2147500000 -g 40 -q 300 -r \
-M /tmp/falcon-mac-lte.pcap \
-U /tmp/falcon-rlc-lte.pcap \
-J /tmp/falcon-paging-tmsi.csv \
-G /tmp/falcon-ul-grants.csv
The GUI now exposes the same operator path: save DCI PCAP, MAC-LTE PCAP, RLC-LTE PCAP, paging S-TMSI CSV, and DCI-0 uplink grant CSV. The command line is still where the lab proof is easiest to pin, but the GUI is no longer a decorative waterfall machine with a radio habit.
The DCI-0 bridge
The next logical step was Msg3, because RRCConnectionRequest can carry the UE identity that makes passive movement correlation more interesting. The hard part is that Msg3 is on PUSCH. To decode it, you need the UL grant from DCI Format 0, the RB allocation, MCS, HARQ/RV, and the DMRS parameters. FALCON already had the in-memory grant objects; we added a CSV writer at the DCI collection boundary.
if(ulGrantCsvWriter.isOpen()) {
ulGrantCsvWriter.writeCollection(subframeInfo);
}
Each row records epoch_us, SFN/subframe, PDCCH TTI, FDD PUSCH TTI guess, RNTI, DCI hex, CCE location, RIV, RB start, PRB length, hopping, MCS, TBS, RV, NDI, CQI request, TPC, and DMRS fields. That is not Msg3 yet. It is the contract for the future uplink receiver.
What works now
- FALCON acquires PCI 201 on the HackRF Pro at 2147.5 MHz and reaches full-band PDCCH/DCI processing.
- MAC-LTE and RLC-LTE PCAPs can be opened in Wireshark with the right DLT/heuristic settings.
- Paging S-TMSI records are decoded from PCH and saved as CSV.
- DCI-0 uplink grants are exported as structured rows for later PUSCH work.
- The focused reliability suite currently passes 27/27.
Where the wall is
One HackRF parked on downlink can tell us when the network grants uplink resources. It cannot also be listening to the paired uplink at that same moment. The next step toward MAC -> TMSI through Msg3 is a second simultaneous receiver tuned to the uplink, time-aligned well enough to use the DCI-0 CSV as the schedule. LTESniffer’s uplink path points the way, but its tested hardware assumptions lean toward USRP/Lime-class setups. Porting that chain onto this HackRF-centred lab means being honest about timing, clocks, and capture loss.
That is why the MIB work remains part of this story instead of background noise. PUSCH/Msg3 is harder than PBCH/MIB, but it has the same personality: timing must be real, state must reset when samples go missing, and every successful-looking decode needs a falsifiable artifact behind it. The earlier post established that discipline on the downlink acquisition path. This one extends the artifact trail outward: first to Wireshark, then to paging identities, then to the uplink-grant schedule we will need when the second receiver joins the party.
The line we reached is useful: downlink-derived identity and grant evidence is working. Msg3 is not blocked by courage. It is blocked by needing the actual uplink samples.
Next cast
The passive correlation engine is now the boring software step: join paging CSV rows and future Msg3 S-TMSI rows into a timeline of (timestamp, S-TMSI, cell_id, C-RNTI). The radio step is less boring: add a second RX chain, capture uplink around the DCI-0 grant timing, then demodulate PUSCH with the grant and DMRS parameters we are already exporting. After that, Msg4 on PDSCH can confirm contention resolution.
For now, the ocean is talking. We have the net labelled, the buckets timestamped, and the fish finder is finally saving PCAPs. That counts as progress, even if the next fish swims four milliseconds and one paired frequency away.
References
- FALCON: An accurate real-time monitor for client-based mobile network data analytics, Robert Falkenberg and Christian Wietfeld.
- LTESniffer, SysSec KAIST.
- LTE-Cell-Scanner, JiaoXianjun / Evrytania lineage.
- Passive Multi-Target GUTI Identification via Visual-RF Correlation in LTE Networks, Byeongdo Hong and Gunwoo Yoon.
- How to Intercept 4G Traffic with HackRF, LTESniffer & DragonOS, Logos Red.