ShmooCon is a great security conference, held early each year in Washington, D.C. They frequently feature a puzzle contest connected to the conference badges. In 2006, the badges were die-cut pieces of metal that could all fit together to create one large badge. Renderman figured that one out. In 2008, they had 16 different plastic badges that looked like punch cards, and somehow or other eventually gave you a PDP-8 program that would decrypt some text and, well, that one was a bit crazy and nobody solved it.

But ShmooCon V, held February 6-8, 2009, is what I’m finally getting around to writing about. This was the year that Shmoo finally gave in to their inner moose. The badges were large plastic rectangles, with a Moose sihlouette cut out. Along each long edge of the badge was Morse code, and across the neck of the moose a barcode was diagonally printed. The codes, and the contest that goes with them, were generated by G. Mark Hardy, a frequent contributer to ShmooCon, DEFCON, and the security industry in general.

If you’d like to try to solve this for yourself, then **STOP** reading now. The rest is full of spoilers. G. Mark has made the original badge codes available, which will give you as much as we had after collecting all 8 badges.

The first problem was figuring out how many badges there were. We “collected” badges from other attendees and eventually decided that there were a total of 8 different badge codes. Speaker, security, shmoo, and other staff-like badge variants simply differed in the color of the plastic, but the codes were all one or another of the 8 variants.

Another problem was how to read the Morse code. Holding the badge horizontally, and reading the code left-to-right across the top edge, made the most sense. But then, do you read the bottom at the same time, or do you turn the badge 180 degrees and read the other line also left-to-right? An interesting thing about Morse, most of the codes also mean something in reverse. As we collected badges, we eventually determined that it was read across the top, turned, and then read across the “other” top.

The next problem was the barcodes. They were harder to read, because of the diagonal printing and quality of the screening. Fortunately, I had a buddy with me (gypak) who got pretty good at squinting at the codes and reading them live off the badge. Really, since the barcodes matched the Morse (that is, no two badges with the same Morse code had different barcodes), we only had to identify 8 barcodes.

Eventually, we ended up with 8 strings of text, and 8 barcodes to go with them:

Unfortunately, this is about as far as we got during the con. We tried some simple attacks, and some outlandish ones, but simply didn’t have access to a computer and weren’t really trying it on paper. So most of the work that follows happened offline over the next several days. G. Mark was kind enough to keep a running tab of all the hints and suggestions on a webpage, and we (and several others) kept at the puzzle via email and twitter for some time.

At some point, gypak noticed an error on one of the printed badges — what looked like a “Z” (- - . .) was instead supposed to be a “G” (- - .). But nobody was far enough along that this was really significant at this point. (This was the second badge in the list above — changing MOOSENUGGET to MOOSENUGZET.) Seems this error crept in somewhere between the original submission and the final pre-print proofs, and got missed all along.

We continued to attack the problem for days. Early on, I started calling the leftover letters on each badge “telomeres,” after the “junk DNA” sequences that don’t seem to mean anything. Turns out here they did mean something. But the question was, are they the only ciphertext? Depending on how you read the text (like is it “Moosle Defense” or “DefenseS”), you could end up with exactly 32 telomeres — so are we to use just those as a ciphertext? Or use everything all at once? It seemed unlikely that we could use everything, because that would mean you have a ciphertext that partially reads in English (sort of). Still, we tried everything. Viginere, various Caesar shifts, Playfair, etc., etc., and got nowhere. Used SHMOO, SHMOOCON, SHMOOCONV, etc., as keys, again, no dice. I really liked “SHMOOCONV” as a key, since that was also printed on the badge (reinforcing that “everything you need is on the badges”).

The one thing that we knew we had right so far was the ordering of the badges. The first digit in the barcodes suggested the ordering, and the presence of a “GMARK” autograph in the last column sealed it for us. Beyond that, though, we were pretty much swimming in a sea of crazy ideas.

We’re also looking hard at the barcode data. Every badge had almost exactly the same barcode, though the 1st digit varied from 1-8, and the last digit seemed to be almost random. We considered for a while that the first and last digits somehow worked as pointers to string the badges together, like a linked list, but as it turns out that last digit was just the barcode checksum, and really not part of the puzzle at all.

Of course, the digits in the middle of each barcode, the same on each badge, were terms in the well-known Fibbonacci sequence: 1 1 2 3 5 8 13 21. So we had to work that into the puzzle somehow.

We were also receiving hints from G. Mark all along. Some of these were helpful, while others just seemed to muddy the waters somewhat. At some point, I started adding characters up in columns and in rows, but didn’t go too far. Finally, I apparently got really close one night, but had made some kind of transcription error and had things off by one or so (I really can’t remember).

In the end, what needed to happen was for us to adjust the row locations based on the numbers from the barcodes. So for the first two badges, the text needed to start in column 1, the third badge, in column 2, then 3, 5, 8, etc. The last badge wrapped around and started in column 5.

Unfortunately, there was no clear indication that this was done properly (no new word popped out at us or anything), though G. Mark did try to show how certain letters in the telomeres should be marked. These spelled out BRUCE, HEIDE [sic], XO, and of course GMARK. None of these were really lined up at any point, so it was hard to see them. But the point was, once you’d marked those letters, you were left with exactly 16 letters in the telomeres.

Doing the badge text shift based on the Fibbonacci numbers caused those to “align” such that no single column had more than one leftover telomere in it. Which sort of gives a sense of “cool, next stage done!”, but only if you’d been able to remove the other letters. Though it was sort of cool to see those names inserted into the code (even if Heidi’s name was misspelled), it really didn’t help any for solving. And wasn’t really necessary, since all you needed was the Fibbonacci offsets. So this wasn’t nearly as helpful as G. Mark hoped it’d be. :(

To sum up so far:

Decode Morse code to get a 16-character string for each badge

Put the strings in order based on the first digit of each badge’s barcode

Apply the Fibbonicci numbers from the barcodes to each badge in turn, shifting the string to start at the column specifyed by each term of the sequence

Now the table is complete. Not long after having the flash of inspiration that got me past the whole BRUCE/HEIDE/lining-things-up confusion, I thought “let’s just add up all the columns.” Didn’t work. At the time, it seemed to make so much sense, was just so easy, but it didn’t work, and so I was quite disappointed. That was at about 22:00 or so, on Thursday the 26th.

Sometime the next morning, I tried it again. Apparently I must’ve made some simple error, because now the answer jumped right out at me. I sent G. Mark an email at 9:23, asking “Is the answer in pig latin?” Turns out I probably should’ve just given him the answer, as there was another team breathing right down my neck. Twenty minutes later, G. Mark replied “Aybe may. What’s your guess?” So a few minutes later, I saw his reply, and sent in my solution.

The official “winning entry” was therefore stamped at 9:55 am on Friday the 27th, three full weeks after the con started. But I could’ve gotten it a half hour earlier. In fact, I could have gotten it 12 hours earlier, if I’d not screwed up the shifting at home the night before. The runner-up team of Beakmyn, Grey Frequency, and Calypso sent in their answer at 11:08, 1:13 after my winning entry. So I’m really glad I gave it one more try that morning.

The final step, then, is: Add up all the columns of letters, using modulo-26 arithmetic.

This means that A+A = B, A+B = C .. A+Z = A, wrapping around the end of the alphabet. For example, assuming A=1, B=2, etc., we get:

Modulo arithmetic means divide and pay attention only to the remainder. So 113 mod 26 is same as the remainder for 113 / 26. In this case, 9. And the ninth letter is ‘I.’ Continuing this for the rest of the columns gives the following text:

So, what did I learn? Mostly, I reinforced the already certain knowledge that, almost every single time, I try the most complicated, convoluted, crazy approach to a puzzle. And that’s never the right way. I also learned that it’s very difficult to give a useful hint that doesn’t give away too much, while also not leading the players down crazy blind alleys. Finally, I learned that when you think you’ve solved it, go for broke and give the judges the answer RIGHT AWAY, because you have no idea who might be just behind you.

In the end, though this puzzle was really hard to solve, the actual mechanics were pretty simple. No complicated ciphers, permutations, transpositions, substitutions, nothing at all like that. Just decode the Morse, put ‘em in the right order, shift the rows, and add the columns. The trick was figuring all that out. And that might’ve been easier if I hadn’t been trying to solve complicated ciphers, permutations, transpositions, etc. Which is probably the most important lesson for these sorts of puzzles — chances are, it’s easier than you think.

Still, there’s nothing like the thrill of solving it, except maybe the thrill of knowing you’re the first to solve it!