isomer reached out on Discord that they smelt something funny about the SuperFox verification system. They were investigating the system in hopes of creating an open source implementation. The usual red flags presented themselves - closed binaries, very few bits, hardcoded magics. I originally assumed this system was just using TOTP like some of the other dxpeditions in the past, but in a more automated / online fashion, but it seemed not.

I was in quite a bit of pain and struggling to sleep due to running a half marathon with patellofemoral pain syndrome (do not recommend, the recovery sucks) so an opportunity struck.

isomer: WHY AREN’T YOU ASLEEP

One of the first things I like to do is poke around Git for clues. Commit messages, changed files, accidental additions. Commit 8b6744 stood out.

Replace executables for Windows and Linux by stripped versions.

This was a good start. While it wasn’t strictly required to make progress is certainly helped to quickly validate some findings later on. Opening foxchk in Ghidra revealed a lot of isomers initial findings. A hashing algorithm along with some bitwise shifts and xors. The initial focus was on foxchk as it was much smaller surface area to start with. Running foxchk directly it was able to produce output without any sort of external key/cert input so magic was happening entirely inside the foxchk app.

Rather than just trying to guess what the inputs and outputs were meant to be for foxchk I decided to focus on generating some end to end test data so that each part could be monitored with tools like strace to ensure our assumptions on how things worked was valid. This is when I shifted to looking at sftx.

The SuperFox mode requires keys which are provisioned by a third party. Without a key that matches your callsign the modulator will not modulate. Since I wanted to generate test data I needed to know what my SuperFox key would be. This is why I switched to looking at sftx - how was it validating the key?

From what we learnt in foxchk it was easy to pick out the hashing / signature functions also present in sftx. It was also pretty easy to follow the program flow with Ghidra, noting where arguments were passed and used. What stood out the most was a _memcmp between the provided key and one that’s generated. So we now know that sftx can validate the key - and it does so by generating one. At this point I knew that it didn’t matter if we never worked out how foxchk algo worked or how the signature was formed as it was likely we could just generate SuperFox keys using the application itself.

As a proof of concept I started poking in gdb and ended up with the below. This runs the sftx app and breaks when it performs the comparison. It then prints out the SuperFox key.

# Will only work on wsjtx_2.7.0-rc6_amd64.deb
# shasum ./usr/bin/sftx 
#c7f5171efca080ee98718ce977391f9d69fb8dae  ./usr/bin/sftx

gdb -batch-silent \
-ex "set logging file /dev/stdout" \
-ex "b _gfortran_getarg_i4" \
-ex "run" \
-ex "finish" \
-ex "delete" \
-ex "b *(\$pc+117)" \
-ex "continue" \
-ex "set logging enabled on" \
-ex "printf \"%.9s\n\", (char[9])*\$rdi" \
--args ./usr/bin/sftx "sfox_1.dat" N0CALL 123-456 # don't worry about the code here - its just a placeholder

I actually really like this GDB solution because it’s sort of a “no code” approach to obtaining the SuperFox key.

GDB also served helpful for validating our assumptions on how the hashing algorithm worked. We discovered that the hashing is done using Bob Jenkins lookup3 hashing function. This isn’t a secure hashing function. After which some scrambling is performed. A very clever puppy will likely have a write up on exactly how the scrambling works on their cohost.

It wasn’t too hard to figure out the process from reverse engineering with the help of Ghidra then write a replacement foxchk app. Made even easier by nhash.c being included in wsjt-x source code. The crew has since made rust, and javascript versions. The problem however was that a replacement open source foxchk essentially had to reveal how the signature/key was generated….

The options seemed a bit like:

Decision was made to try to keep the details a secret until after Jarvis Island dxpedition. We knew however there would be a risk that others would likely start looking (if not already) and could easily replicate what we did. I have the assumption that the people with the skills to do this sort of reverse engineering likely wouldn’t do so in bad faith.

We also want to demonstrate that we had successfully cracked SuperFox, which is why we generated and displayed the SuperFox key for N0CALL.

It was also important for us to provide useful suggestions on better methods. Shout out to everyone involved here as this turned out to be a lot more work than I anticipated. There’s not many bits to play with in a transmission and coming up with a suitable solution is very tricky. Given the increase in processing speeds and memory size/speed I suspect we are right on the edge of viable security options using key signing for a low data mode like SuperFox. These suggestions have been sent to Joe directly.

The crack

A windows 98 looking window with a prompt for callsign and ouputting a SuperFox key

The way the SuperFox key was generated and validated reminded me of all the old software cracking. Firing up your favorite x86 debugger and stepping through code. Because of this I spent far too much time (mostly on/off in between things) and effort building my own “keygen” style webpage. Enjoy my SuperFox crack.

Not the first?

During writing of this post I checked in on wsjt-devel mailing list to find some discussion around HH2AA call using SuperFox. Checking dx spotting websites many spots list that SuperFox mode was used. It turns out that this station didn’t apply or was issued with a SuperFox key. To be clear I, nor any of group involved with this post or previous post were involved in generating a SuperFox key for this station - or providing details into how to do it. It’s not surprising that others would be looking into this.