I was only able to stay for part of the first day of DEF CON this year, but I’m glad I did. One of the things they’ve done for the last five years or so is put microcontrollers in the badges, and put in little Easter eggs for people to search for. This year’s had a Ninja Party mode which was locked by default, but you could unlock it by placing a series of 15 tumblers in the correct position.
They published the source code for the badges on the CD they gave out at registration (so perhaps I’m stupid for loading the CD on my laptop rather than smart for reverse engineering the badge). I opened up DC18_Badge.c and, searching for “Ninja” (the code was commented nicely), quickly found the following two C functions:
/*************************************/ /* NINJA ROUTINES /*************************************/ int dc18_ninja_validate(uint32_t val) { uint16_t a, b; a = (uint16_t)(val & 0xfff); b = (uint16_t)(val >> 12); if((a ^ b) == 0x916) { return 1; } return 0; } // encode tumbler states into // 24-bit value uint32_t dc18_encode_tumblers(tumbler_state_type *tumblers) { uint32_t x = 0, j = 1; uint16_t i; for (i = 0; i < TUMBLERS_PER_IMAGE; i++) { x += tumblers[i] * j; j *= 3; } return x; }
So the trick was to find the number that made (a ^ b) == 0x916
and then figure out the tumbler positions to represent that number. I wrote two small Python functions to automate those tasks. To find the number that would unlock Ninja Mode, I wrote this loop. I added a print statement to show how far into the search we were, thinking it might take some time to find it, but it popped out 6423 in no time at all:
while 1: a = i & 0xfff b = i >> 12 if i % 10000 == 0: print "# a: %d, b: %d, i: %d" % \ (a, b, i) if a ^ b == 0x916: print "DONE: %d" % (i) break i += 1 DONE: 6423
Now all that was left was to figure out the tumbler positions to represent 6423. Clearly, dc18_encode_tumblers
tells us how to do that. I whipped up this little function to convert the tumbler positions to a decimal number:
def enc_tumblers(tum): x = 0; j = 1; for i in range(15): x += tum[i] * j j *= 3 return x >>> enc_tumblers([1,1,1,1,1,2,2,2, 0,0,0,0,0,0,0]) 6439
I was going to write another loop to increment the tumbler array I was passing to enc_tumblers
, but my first guess was so close that I just manually entered the settings until I found the winning configuration:
>>> enc_tumblers([0,2,2,0,1,2,2,2, 0,0,0,0,0,0,0]) 6423
Once I had the configuration, I put the tumblers in the appropriate positions: 0 - up, 1 - middle, 2 - down. After that, well, I guess I'm a ninja now: