A P-O-X On Both Your Houses: Reverse Engineering a 20 year RF protocol

A Basic WAD input
There is absolutely 0 chance I read this as a kid.

Step 0: Oh God What Am I Even Doing

  • Frequency: That is, where on the spectrum your device is broadcasting, measured in Hz, so we know where to listen.
  • Modulation and (maybe) Encoding: How your 1s and 0s are mapped to the sinusoidal structure of a radio wave, and if there’s any transformation on them to avoid long runs of 1s or 0s.
  • Baud Rate: How many bits per second are being expressed into the air.

Step 0a: How does radio actually work?

The amplitude (1) is the height of the wave, in context, the strength of the signal, and the frequency (4) is the width of a cycle. Source
An example of FSK — frequency shift keying Image Source
An example of OOK — On-Off Keying. Presence of signal represents a 1, lack represents a 0. Source

Step 1: Open Source Intelligence

Mesmerizing
  • [0013] “315 MHz with a data transmission rate of 12 kbps.”
  • [0146] “The bi-simplex communication protocol may use a single frequency for transmitting and receiving data. This implementation includes data integrity checking; however, data forward error correction is not used. The packet data payload in this implementation is 64 bytes with a 2-byte cyclic redundancy check (CRC).”
  • [0147] “The communication protocol shown … may be implemented using a 10 second minimum period between packet transmissions and a maximum packet length of 333ms. …The data transmission rate using this protocol is 1.17 Kbps when data that is Manchester encoded using On-Off Keying (OOK).”
  • [0153] “In some implementations, data may be repeated four times per packet to provide ample bandwidth for OOK or FSK data transmission of NRZ-I data. Other data formats, such as Manchester encoding, may be used to make a more robust channel without substantially adding to the data rate.”
  • [0158] “In this implementation, sniff cycles are timed to ensure a high probability of detection of a transmitted POX packet. This can be adjusted by using sync/framing structures in the packet, or by multiple transmissions of the same data in a packet.”
  • [0162] “Transmit mode formats the data packet, including sync bits, check bits, and redundant data, and passes this information serially to the RF transmitter. There is no check for a successful transmission,”
  • The frequency is 315 MHz, confirmed by the FCC filing.
  • The modulation is either FSK (Frequency Shift Keying) or OOK (On Off Keying) with Manchester Encoding
  • The baud rate is either 12 kbps or 1.17 kbps.

Step 2: Signal Analysis

Ah, the aurora borealis
My very simple GNU Radio Flow Graph
A plot of the signal’s amplitude

Step 3: Protocol and Binary Analysis

  • 3 bytes for the body parts
  • 6 bytes for HP — the value is above 256, so we can’t fit it in one byte
  • Names and IDs are exactly 6 characters, so 12 bytes total
  • There are 9 values to a WAD, so 9 bytes
  • PCU color has 3 options, and would be sent as a byte
  • The manual numbers the body parts up to 189. This means we need a byte such that we can represent values up to 256, so 3 bytes total, or 24 bits
  • HP needs 9 bits per value (to support a max of 500), so 27 bits for the 3 body parts.
  • The character set for names and IDs is capital letters, numbers, and space, or 37 characters, which fits into 6 bits. In total, for the two strings, we need 72 bits.
  • WADs have 3 potential values for each slot (Head, Body, Tail), meaning they can be represented with 2 bits each. There are 9 WAD values, so 18 bits total.
  • There are 3 options for PCU color, so we need 2 bits to represent that.
01 01000000 -> 32
02 00011110 -> 30
03 01001111 -> 79
04 00011110 -> 30
05 01100111 -> 103
06 00011110 -> 30
07 00000000
08 00000000
09 00000000
10 00000000
11 00000000
12 00000000
13 00000000
14 00000000
15 00000000
16 01000000 -> 64
17 00000000
18 00000000
19 00000011 -> 3
20 00001010 -> 17
01 01000000 Head Part ID
02 00011110 Head HP
03 01001111 Body ID
04 00011110 Body HP
05 01100111 Tail Part ID
06 00011110 Body HP
07 00000000 ???
08 00000000 ???
09 00000000 ???
10 00000000 ???
11 00000000 ???
12 00000000 ???
13 00000000 ???
14 00000000 ???
15 00000000 ???
16 01 000000 PCU color?, ???
17 00000000 ???
18 00000000 ???
19 00000011 CRC
20 00001010 CRC
01 01000000 Head Part ID
02 00011110 Head HP
03 01001111 Body ID
04 00011110 Body HP
05 01100111 Tail Part ID
06 00011110 Body HP
07 00000001 ???
08 00000000 ???
09 00000000 ???
10 00000000 ???
11 00000000 ???
12 00000001 ???
13 00000000 ???
14 00000000 ???
15 00000000 ???
16 01 000000 PCU color?, ???
17 00000000 ???
18 00000000 ???
19 00000000 CRC
20 01111111 CRC
01 01000000 Head Part ID
02 00011110 Head HP
03 01001111 Body ID
04 00011110 Body HP
05 01100111 Tail Part ID
06 00011110 Body HP
07 00 000001 ???, ID Char 1
08 00 000000 ???, ID Char 2
09 00 000000 ???, ID Char 3
10 00 000000 ???, ID Char 4
11 00 000000 ???, ID Char 5
12 00 000001 ???, ID Char 6
13 00000000 ???
14 00000000 ???
15 00000000 ???
16 01 000000 PCU color?, ???
17 00000000 ???
18 00000000 ???
19 00000000 CRC
20 01111111 CRC
01 01000000 Head Part ID
02 00011110 Head HP
03 01001111 Body ID
04 00011110 Body HP
05 01100111 Tail Part ID
06 00011110 Body HP
07 00 000000 ???, ID Char 1
08 00 000000 ???, ID Char 2
09 00 000000 ???, ID Char 3
10 00 000000 ???, ID Char 4
11 00 000000 ???, ID Char 5
12 00 000000 ???, ID Char 6
13 00 000001 ???, Name Char 1
14 00 000000 ???, Name Char 2
15 00 000000 ???, Name Char 3
16 01 000000 PCU color?, Name Char 4
17 00 000000 ???, Name Char 5
18 00 000001 ???, Name Char 6
19 01010110 CRC
20 10001011 CRC
01 01000000 Head Part ID
02 00011110 Head HP
03 01001111 Body ID
04 00011110 Body HP
05 01100111 Tail Part ID
06 00011110 Body HP
07 00 000000 ???, ID Char 1
08 00 000000 ???, ID Char 2
09 00 000000 ???, ID Char 3
10 00 000000 ???, ID Char 4
11 00 000000 ???, ID Char 5
12 00 000000 ???, ID Char 6
13 00 000001 ???, Name Char 1
14 00 000000 ???, Name Char 2
15 00 000000 ???, Name Char 3
16 10 000000 PCU color, Name Char 4
17 00 000000 ???, Name Char 5
18 00 000001 ???, Name Char 6
19 01110000 CRC
20 01111100 CRC
01 01000000 Head Part ID
02 00011110 Head HP
03 01001111 Body ID
04 00011110 Body HP
05 01100111 Tail Part ID
06 00011110 Body HP
07 01 000001 WAD index 0, ID Char 1
08 01 000001 WAD index 1, ID Char 2
09 01 000001 WAD index 2, ID Char 3
10 01 000001 WAD index 3, ID Char 4
11 01 000001 WAD index 4, ID Char 5
12 01 000001 WAD index 5, ID Char 6
13 01 000000 WAD index 6, Name Char 1
14 01 000000 WAD index 7, Name Char 2
15 01 000000 WAD index 8, Name Char 3
16 01 000000 PCU color, Name Char 4
17 00 000000 ???, Name Char 5
18 00 000000 ???, Name Char 6
19 00101001 CRC
20 01101100 CRC

Step 4: Broadcasting and Schema Finalization

from construct import Struct, Int8ul, Bytes

PoxAdvertiseStruct = Struct(
"head_id" / Int8ul,
"head_hp" / Int8ul,
"body_id" / Int8ul,
"body_hp" / Int8ul,
"tail_id" / Int8ul,
"tail_hp" / Int8ul,
"wad0_id0" / Int8ul,
"wad1_id1" / Int8ul,
"wad2_id2" / Int8ul,
"wad3_id3" / Int8ul,
"wad4_id4" / Int8ul,
"wad5_id5" / Int8ul,
"wad6_pox_name0" / Int8ul,
"wad7_pox_name1" / Int8ul,
"wad8_pox_name2" / Int8ul,
"pcu_color_pox_name3" / Int8ul,
"unknown1_pox_name4" / Int8ul,
"unknown2_pox_name5" / Int8ul,
"crc" / Bytes(2)
)
  1. Generate packet bytes using the construct schema
  2. Manchester Encode the bytes
  3. Prepend the preamble and sync bits (remember those?)

Step 5: Bullying

Your Pox has been invaded by a BULLY!
  • Bully Mode — Reads your strategy and cheats to become unbeatable.
  • Gift Mode — The opposite of bully mode, they just feed you wins. Good for giving parts to a “real” PCU
  • Randy — Totally random! Perfectly replicates my Pox strategy as a kid.

Steps Beyond: Fuzzing and Further Mysteries

  • [0140] POX supports several hidden user interface screens that are used to facilitate diagnostics, to gather statistical information, to update the product, and at points of sales. These are accessed either by special key sequences or by a specific command sequence sent through a communications port (either wireless or wired). Most of the hidden user interface screens do not respond to button presses; they are active for a defined period of time. When a hidden screen is complete, the PCU automatically returns to the company splash screen.
  • [0170] Feature activation is a non-PCU command that permits third parties to activate additional features such as hidden prions or other areas of the game. A security system verifying a valid transaction recipient is used to prevent unauthorized users from enabling these additional features. This functionality is described in FIG. 23. Feature activation can be used in marketing and partnership campaigns. For example, it could be used to allow a retail store to enable additional features if customers bring their PCU to the retail store.
  • [0172] FIGS. 25 and 26 illustrate two additional non-PCU command codes that provide a mechanism for uploading and/or downloading the POX database. This provides an upgrade path so that individual POX units can be loaded with a newer version of the POX software or with another game.
head id or special command id
<some number of data bytes>
CRC-16
The trace marked “data” is interesting, to say the least.

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store