S4xCTF: Page Me Maybe Flag

This was one of the weirdest flags to ever grace a CTF, in my humble opinion. This was a fun flag to set up because it highlights one of the problems with 2FA systems – namely that cell phone text messages use an insecure radio protocol and may be intercepted. This isn’t a dire vulnerability – 2FA via text message is still a lot more secure than not using 2FA, especially since the requirements to actually receive someone SMS are quite challenging.

Our flag was meant to highlight the weakness of SMS, but without requiring rocket science nor legally sketchy ground in the form of cell phone interception. In this case, we used the much simpler POCSAG protocol on unlicensed spectrum so that we wouldn’t be violating any FCC rules.


Page Me Maybe was a triple threat challenge. Players had to set up an SDR listener, and muck with a web application, in order to find the answer. We didn’t want to make things too difficult, so we at least gave them some solid clues as to what frequency to monitor, and where the web application was.

A test page sent by one of the players

Throughout the contest, we had a 2FA transmitter operating. It sent an ‘encrypted’ POCSAG pager message every few minutes.  Players who set up their SDR were able to see the text message 115E21503C16361115780B0B76007600 transmitted to pager ID #17713 throughout the contest. Note that the frequency used is not actually a POCSAG frequency, although our Apollo pagers can receive messages on the frequency we chose.

A little background on how paging systems operate may be in order.  Pagers are very much still in use in certain industries, including industrial and hospital use.

POCSAG pagers in an area generally share the same frequency. A pager knows that it is supposed to receive a transmission by way of a CAPCODE, which is a header on the message that includes a pager ID. The CAPCODE doesn’t offer any real security, it is just a way of filtering out pages that a user is not interested in. Pagers can have their CAPCODE configured by their end user, and most pagers support multiple CAPCODEs. So, a user can eavesdrop on other people’s pages by simply entering a target CAPCODE. For hospitals, this can be advantageous: a specialized doctor can have several CAPCODEs in their pager, including a personal one for messages that are pages for that specific doctor, as well as a hospital-wide CAPCODE, so that the hospital can quickly page all staff during a mass-casualty event. Of course, the same rules apply to industrial applications.

The CTF POCSAG web application was a very simple interface which allowed a user to manually transmit a test message to the pager of their choice (their choice limited to ‘J1’ and ‘J2’ for two Judge pagers).  A look behind the scenes at the web code also showed that there was a hidden field on the form with a Debug flag (by default set to false). When set to True, this would greatly help players beat the challenge, by showing them the encrypted data as web application output. We added this in case players got stuck setting up their SDR listener.

A player is successfully receiving the 2FA pin message with ‘encrypted’ data

The actual message transmitted to the pager is in hexadecimal notation, so the message itself has to be quite small. The pager protocol doesn’t have a limit on the size of pages, but most pagers can only display 80 characters on their small screens. When encoded as hexadecimal, this limits a message to 40 characters that may be displayed on our Apollo pager.

Since players could transmit their own message to the Judge pagers, they could begin attacking the cryptography. The first thing to spot is that if you send the same message to the J1 and the J2 pagers, they don’t differ very much:

The second thing to spot is that if we send a page to J1, the RF signal sent the page to the pager with ID 18993 decimal, which corresponds to 0x4131, which is ‘J1’ in ASCII. Likewise if the player chose to send their message to J2, the page would transmit with the POCSAG ID of 18994 decimal (‘J2’ in ASCII). Further, when we XOR our plaintext message with the encrypted message to Judge 1, we get ‘J1J1J1J1J1J1J1J1…’ as the output.

This is basic XOR encryption, and the system is set up to use the target pager ID as the encryption key. Armed with this knowledge, players could decrypt the actual 2FA page, which was 17713 (0x4531 decimal, or ‘E1’ for Engineer #1). Once decoded, they would see the page message with the text “Today’s PIN:3131”. They then had the flag.

The code for this flag is available on Reid’s github page: https://github.com/reidmefirst/S4x17CTF/tree/master/PageMeMaybe . Note that it requires an installation of GNU radio, and is set up to use a HackRF as the pager transmitter. Also note that the TX stage of some HackRFs can be a bit finicky – one of our units receives POCSAG pages just fine, but transmitted a very dirty signal that could not be received by our Apollo pagers from more than a few inches away.  We settled on a second HackRF unit that did not have the TX problem, and were able to receive a clean signal from about 100 feet away from our transmitter – good enough for CTF work, and quite good considering the low transmit that a HackRF is limited to.  The code may be useful for people in building a home automation or security project, for example a pager that beeps when someone enters their garage at night…

Special thanks to Digital Bond alum Stephen Hilt for building the first working pocsag_tx module.