As part of the GNURadio Conference 2021, the Radio Resilience Competition created a custom competition just for the conference. This is similar to the Capture the Flag (CTF) that has been a mainstay of the GRCon. The cool thing about this competition is that it was not just for bragging rites but real prizes! The main talk describing the competition can be viewed on the stream of the conference. Click the link below the embedded youtube image to go straight to the correct time.
If I have sparked your interest in the GRCon you can check out my full conference coverage below.
The full details of the GRCon competition can be found on the Radio Resilience website. This details all of the setup and how to register and clone the code repo from Gitlab. The competition ran the length of the conference but has now finished, but you can still signup for the main competition to get your radio scored.
I had previously competed in their previous competition and created a blog post on my experience and the challenges that I faced. You can read about that below as a primer for this post, as I go into more details of how the competition is run.
Simulator
The simulator is simple in design, there are two blue radios that need to send packets from one to the other to be submitted for scoring. The packets must be submitted in order, this means that if you drop one packet that is your final score even if you are able to keep delivering packets. This process is executed over a simple gaussian noise channel with a red radio that tries to interfere with your transmission and make it difficult for you to get a high score.
The nice thing about this competition is that the developers provide a fully functional basic blue radio system that already accomplishes most of the complexity for sending data across the channel. Your task as a competitor is to try and modify that system to improve performance, or you can design your own from scratch if you are capable enough.
The simulator and the radios are fully open source so you can clone it and get started right away. This makes the barrier to entry low for those that are just getting started in Software Defined Radio. And since it’s all software you don’t need to buy expensive radio hardware.
The simulator is built off of GNURadio which allows you to use the integrated blocks to graphically design your system but allows you to design and create your own blocks if you have the know-how. The base blue radios also take advantage of the liquid-DSP library which is a super powerful DSP and radio communications library designed in C.
Design
For my system of blue radios, I decided to take advantage of some of my previous work and enable a MAC layer between the packets the transmitter receives and that the receiver submits to the scoring marshal. This allows me to control which packets I need to send and prevents me from submitting an incorrect packet to the scoring marshal.
The next piece is a Two-way radio design for the Blue1 and Blue2 radios where each has both a transmitter and a receiver path. For simplicity’s sake, I will always refer to the Blue1 radio as the transmitter as it is the original transmitter of the scoring packets and Blue2 as the receiver even though they contain both functions. Since the simulator environment does not allow for multiple channels this means both transmissions need to be somewhat overlapping which could cause unintended interference. To mitigate this I leveraged my liquid-DSP modified transmitters to upsample the blue2 transmission so that it became a very narrow band in comparison to the blue1 scoring packet transmission, I also only send data intermittently, so the interference occurs very rarely.
The other piece of the design is an interference monitor in the blue1 radio, this is used to try and sense when interference is occurring and gate the blue1 transmission. That was the original purpose but since the blue1 radio needs modification in the liquid-DSP processing to stop real data from going out this does not work as intended. I actually use this piece as a transmission limiter that accumulates to a point then turns off the blue1 packet transmission in the MAC this allows for the actual transmitter to not get overwhelmed and allows me to change which packets really go over the channel once the blue1 radio gets information back from the blue2 radio about which packets need to be retransmitted.
Another limitation of the simulator is that IQ data needs to flow over all of the channels to get the simulator mux to start and not hang. So since the blue2 radio has nothing to send in the beginning the whole simulation will stop and we get a chicken and egg problem. to prevent this a one-time keep-alive signal is sent from the blue2 radio which interferes with the first scoring packet, this was mitigated by just sending that first packet a few times which will become apparent later on why we need this first packet in the optimization section.
The flow graphs enable these custom MAC layer functions using the embedded python blocks of GNURadio and the PDU messages. These embedded blocks let you write python code directly in the GNURadio companion graphical user interface to do signal processing. It has a bit of a learning curve but I am trying to do a more in-depth write-up to help people get started with them.
Algorithm
I created a simple algorithm that takes advantage of the packet encapsulation that I designed during the process of the previous competition run, I call it the Fast Filing Protocol. For this protocol I set a target score I want to achieve, this is a bit limiting but could be modified to work in steps, and the transmitter sends only the packets up to that point in sequence over the channel.
after it has sent all the packets once it goes into a mode where it re-sends the packets in a shuffled sequence, basically at random but does not repeat a packet till all has been sent again. This mode is used as a waiting period till the receiver sends back information on what packets are missing.
once it receives the list of packets it only sends those packets till the time period runs out. This allows the system to fill in the pockets of packets that were missing from the target number.
For this algorithm to work the receiver must keep track of which packets were received and the next score that should be submitted to the marshal. The receiver must also send that list back to the transmitter so that the transmitter can fill in the missing gaps.
Optimize
This is where things get interesting! now that I have the basics I need to optimize the system. I can change the modulation format and FEC algorithms to improve data rate and transmission reliability as in the base simulator. But I also have way more to play with. I can change the blue2’s transmission bandwidth and frequency, I can change the target score, I can change… etc. So this is a super-wide search space now! The good thing about this competition is that the red radio was fixed so you knew what you were competing against in, in the previous you could only speculate. This made it much easier to make improvements and limit that one area of the attack surface.
One of the main optimizations that I made was to compress the data packets being sent. I was able to do this because I could encapsulate them into my own format. I applied 2 different kinds of compression the first was what is known as delta compression this is because I noticed the scoring packets contained similar data from one to the next so I only really need to send the difference between them. For ease, I just used the first packet which is why I needed to replicate its transmission to avoid the narrowband keep-alive signal. Then I applied a normal compression algorithm that just removes redundant data inside that delta-compressed format.
This compression reduced the amount of data I needed to send to create a scoring packet, and with reduced data that meant I could send the packets faster!
The other major optimization was in the sending of the retransmission data from blue2 to blue1. I was originally sending just a big list of numbers but that would take a lot of time to send over the narrow channel. This meant more interference with the data signal and more wasted time before a change in the protocol state machine could happen. So I realized that large portions of this big list of numbers were contiguous regions ie numbers like [10,11,12,13,14,18,19,20,21] etc.
This list could be “compressed” down to [(10,14),(18,21)] much smaller! This compression algorithm I had to write myself and was made easier by the fact that the original list was already in order. I created a small JupyterNotebook to test it out because it was hard to debug in the simulator.
Conclusion
Alas, I did not win, but I did do much better than in my previous competition getting a score of 1500 points. I was able to make a few improvements after the competition formally ended and can consistently hit a target score of 4000! My next goal is to modify the algorithm to work in a step target fashion so it will try to target 1000, then 2000, then 3000, etc filling in the gaps to get it to each next step!
For now, check out a short video of my final submission!
The code will be available soon, on my official Radio Resilience Gitlab repo project, where you can investigate the GNURadio flow graphs and the embedded python blocks that make it possible.