GPS receivers ingest data from space.

That sentence sounds obvious until you start thinking about it like a security engineer. A GPS receiver is a computer with a very strange network interface. Instead of Ethernet or Wi-Fi, its input arrives as an extremely weak radio signal transmitted by satellites roughly 20,000 kilometers overhead. The receiver acquires that signal, demodulates it, reconstructs navigation words, validates parity, maintains state across messages, and feeds the results into firmware responsible for position and time.

That is a parser.

And parsers are where dreams go to die.

The Weird Field

Inside the legacy GPS L1 C/A navigation message is a 176-bit field called the special-message field. It lives in Subframe 4, Page 17, appears once during the 12.5-minute LNAV page cycle, and contains 22 characters whose contents are left to the discretion of the GPS Operating Command. Recent research has focused on what those 22 bytes may contain.

I am less interested in what they mean. I want to know what happens when a receiver has to process them.

The field is interesting because it is:

  • Legitimately part of the navigation-message specification
  • Operator-controlled
  • Not required for a normal civilian position solution
  • Capable of carrying changing and non-human-readable data
  • Parsed by proprietary receiver firmware
  • Potentially handled differently across receiver implementations

That makes it a useful test surface.

The Extremely Sophisticated Laboratory

My initial lab consists of:

  • A Raspberry Pi 5
  • A SparkFun breakout containing a u-blox NEO-F10N receiver
  • An active L1/L5 GNSS antenna
  • An RTL-SDR
  • Two short SMA cables
  • Some attenuators
  • A DC block
  • Python
  • A growing collection of hexadecimal output

The attenuators and DC block are for later. The first phase is passive: receive authentic satellite signals, collect what the receiver reports, and build a reliable parser for the raw navigation data. No spoofing. No transmitting. No accidentally redirecting somebody’s DoorDash order to the China.

First Contact

The NEO-F10N normally produces familiar NMEA messages:

$GNGGA,...
$GNGSA,...
$GNGSV,...
$GNRMC,...

Those messages are useful if you want:

  • Position
  • Altitude
  • Time
  • Visible satellites
  • Speed
  • Fix quality

They are not especially useful if you want to dig into the underlying GPS navigation message. For that, I enabled the u-blox UBX-RXM-SFRBX output. This exposes the raw navigation words decoded from each satellite. I then captured the receiver’s serial output for one hour.

The resulting binary file was approximately 3.3 MB and contained:

Valid UBX messages:       7,389
Invalid UBX checksums:        0
GPS L1 C/A subframes:     1,971

That zero matters.

Before trying to interpret anything strange, I wanted to establish that I was not parsing corrupted serial garbage. Every complete UBX message passed checksum validation. One final record was truncated when the capture timer stopped the process, which is exactly what should happen when a byte stream is terminated in the middle of a message. The receiver also collected Galileo traffic and one lonely BeiDou message apparently stopping by to see what everybody else was doing.

Pulling Out Page 17

The next parser had to:

  1. Locate valid UBX-RXM-SFRBX records
  2. Filter for GPS L1 C/A
  3. Decode the ten 30-bit LNAV words
  4. Identify the subframe
  5. Locate Subframe 4
  6. Read the page identifier
  7. Find Page 17
  8. Reassemble the 176-bit payload

The capture contained 16 copies of the same payload:

5A F8 57 43 3A 57 47 42 F8 47 4F 54 22 30 38 35 43 22 48 33 52 22

Rendered using the character encoding defined for the Page 17 field, it becomes:

Z°WC:WGB°GOT"085C"H3R"

The degree symbols are not parser errors. The byte 0xF8 maps to the degree sign in the character set used by the GPS special-message specification.

Does that string mean anything?

I have no idea and that is fine.

The payload itself is not the result I care about. The important result is that I now have a repeatable way to isolate the input being processed by the receiver firmware.

The Message Does Not Matter. The Parser Does.

A correctly implemented civilian receiver should treat Page 17 as isolated discretionary data.

It should not allow the contents of that field to affect:

  • Position
  • Time
  • PPS output
  • Satellite tracking
  • Navigation-message synchronization
  • Receiver availability
  • Recovery behavior
  • Other receiver interfaces

That is the expectation. Security research is what happens when we test the expectation. The attack surface is not necessarily the meaning of the payload. It is the code responsible for receiving, validating, storing, transforming, exposing, or ignoring that payload.

The questions become much more interesting.

Does the receiver reject malformed content cleanly?

A parity error should not cause a crash, reset, or persistent state problem.

Does the receiver normalize the data?

Some receivers may expose corrected navigation words rather than the original transmitted representation. That can be useful, but it may also hide what the receiver actually encountered.

Can the message confuse an internal state machine?

Navigation decoders maintain state across words, subframes, pages, satellites, and time. Unexpected transitions may expose assumptions that were never tested.

Can message changes create resource problems?

Rapidly changing content might affect:

  • Internal logging
  • Serial output
  • Event queues
  • Memory use
  • CPU use
  • Host-side applications consuming receiver data

Can handling the field cause a reset?

A crash or watchdog reset would be an obvious result. A less obvious result would be a quiet reacquisition cycle that interrupts timing or position output without explaining why.

Does timing remain trustworthy during a fault?

A receiver can continue outputting a pulse-per-second signal even when other internal state has degraded.

The critical questions are:

  • Does the PPS remain active?
  • Is it still aligned correctly?
  • Is time marked invalid?
  • Does the receiver output stale time?
  • Does the host understand that confidence has changed?

What happens downstream?

A fault inside a GNSS receiver does not necessarily remain inside the receiver.

Navigation-message parser
Receiver firmware state
Position and timing output
Operating-system clock
Applications and security controls

A field that is not itself navigation-critical may still be processed inside the same device responsible for navigation-critical outputs. That shared fault domain is the interesting part.

Valid Signal, Hostile Content

The initial testing I want to perform is not random RF noise or obviously corrupted messages. Those cases are useful, but they are also easy. A receiver should reject a damaged radio message.

The harder problem is handling data that is:

  • Correctly framed
  • Parity-valid
  • Correctly identified as Page 17
  • Syntactically legitimate
  • Semantically unusual

This is the GNSS equivalent of sending a completely valid network packet containing a field value the application developer never expected. The packet is valid, however the assumption is not.

A useful test corpus could include:

  • Valid restricted-character text
  • Repeated 0xAA patterns
  • All-zero payloads
  • Incrementing byte sequences
  • Pseudorandom payloads
  • Identical payloads across multiple satellites
  • Different payloads for every satellite
  • Rapid payload changes
  • Long periods of one value followed by an abrupt transition
  • Valid pages with deliberately damaged parity
  • Valid pages appearing at unexpected points in the cycle

The objective is not merely to see whether the message is accepted. It is to determine whether the receiver fails safely.

Why Multiple Receivers Matter

Testing one u-blox receiver will not tell me how every GNSS receiver behaves.

The eventual comparison set should include:

  • u-blox
  • SkyTraq
  • Android GNSS implementations
  • GNSS-SDR
  • Other affordable receivers exposing raw navigation data
  • Possible good-faith collaborations with companies that have a vested interest in this research

Identical RF input may produce different external behavior. One receiver might expose the complete message. Another might suppress it. Another might normalize it. Another might log an error. Another might reset. Another might continue producing a position while quietly entering a degraded internal state. Those differences are the research result.

The question is not simply:

Does the receiver support Page 17?

The better question is:

What does the receiver trust, what does it expose, and how does it recover when that trust is violated?

The Next Phase

The passive collection pipeline is now working, but several validation steps remain.

Next, I need to:

  1. Map all 16 observations to their transmitting PRNs and GPS times
  2. Confirm whether the payload was shared across multiple satellites
  3. Validate the extraction using an independent decoder
  4. Compare the result against the published historical Page 17 corpus
  5. Collect longer observation windows
  6. Add receiver-health and timing telemetry
  7. Measure PPS and navigation-state changes
  8. Add at least one independent receiver implementation

The RTL-SDR provides a path toward recording raw IQ data and testing the same signal through GNSS-SDR.

Once the passive work is stable, the next major step is a contained conducted-RF laboratory:

Waveform generator
SDR transmitter
DC block and attenuation
RF splitter
Multiple GNSS receivers

The transmitting side will not use an antenna. Everything will remain inside coaxial, attenuated, and shielded paths. That will allow every receiver to receive the same controlled waveform without radiating a counterfeit GNSS signal into the surrounding environment.

What Would Count as a Finding?

“I made a GPS receiver crash” would be interesting, but incomplete.

The more useful result would explain:

  • Which input triggered the fault
  • Whether the input was structurally valid
  • Which firmware versions were affected
  • Whether other receivers behaved differently
  • Whether position remained valid
  • Whether timing remained valid
  • Whether PPS continued
  • Whether the receiver reported degradation
  • How long recovery took
  • Whether downstream systems recognized the failure
  • What design change would prevent it

The goal is not merely to produce a fault. The goal is to understand the fault boundary.

Why This Matters

GPS receivers are frequently treated as appliances. They are installed, given an antenna, and trusted to provide position or time. But they are still computers processing remote input. The input format is old. The implementations are often proprietary. The receivers maintain complex internal state.

Their outputs may feed:

  • Network timing
  • Cellular infrastructure
  • Industrial systems
  • Financial systems
  • Logging platforms
  • Authentication systems
  • Tactical networks
  • Navigation systems
  • Other embedded devices

A receiver does not need to calculate the wrong latitude and longitude to cause a security problem.

It could:

  • Stop producing time
  • Continue producing stale time
  • Lose PPS
  • Reset repeatedly
  • Mark invalid data as valid
  • Fail to communicate a loss of confidence
  • Cause downstream applications to make the wrong trust decision

The payload may only be 176 bits. I suspect the fault domain could be much larger.


Sources and Further Reading

GPS Signal Specification

GPS Page 17 Research

u-blox Receiver Documentation

Software-Defined GNSS Receiver