Skip to content

Reverse THIS! #1 Mystery Cache

Hidden : 4/18/2006
Difficulty:
2.5 out of 5
Terrain:
1 out of 5

Size: Size:   micro (micro)

Join now to view geocache location details. It's free!

Watch

How Geocaching Works

Please note Use of geocaching.com services is subject to the terms and conditions in our disclaimer.

Geocache Description:

Cache *NOT* at posted co-ords! Oh YES, another Team Roboknight, computer puzzle!!!
The series is finally complete!
Also in the series: The Digital Detective, To Catch a Cacher
FTF: Vinny&Sue Team. Congrats!

I grew up just like any other boy. I played with LEGOs, I learned to ride a bike, I ran around outside. All pretty normal. Then, right about my 8th Christmas, I got an Atari 2600. It took all kinds of cartridges and I could play Combat, Pitfall, Pac-Man... All kinds of things. Suddenly I separated myself a little from the other boys. Some of them played video games, but back then, video games weren't quite enough to hold a kids attention forever because the block graphics and repetitive nature of many games. Once you mastered it (and it didn't take long), you were back outside or playing with the other toys. But, I still played them a little more than most. I was fascinated that someone could make something so *COOL*. It flashed, it had neat noises, and I KNEW I wanted to figure out how these things worked. Then, the next Christmas came and I got my first COMPUTER! It was an Atari 400 with a membrane keyboard. I learned about BASIC, I tried 6502 assembly with little luck, and my dad eventually even gave me a C compiler for the thing. So I read book after book, made program after program. Mostly simple things.  I did, however, come up with a "menued" program even before Windows. Almost submitted it to Analog or Antic magazine (you Atari fans will know those), but my dad said it wasn't good enough so it didn't go anywhere. Anyway, here I am now and what am I doing? I'm still programming. Only now, I've learned quite a bit more and added several new skills to my repertoire. Now I take programs apart and see how they work.

And that brings us to this puzzle.

This is the first in my reverse engineering series. I'm going to start off easy by giving you the source code I used to convert the target co-ordinates into a "key" of sorts. Your job will be to reverse the key generating algorithm into the co-ordinates. I don't care HOW you do it. You can work it out by hand, you can use COBOL, ALGOL, C, C++, C#, BASIC, Pascal, FORTRAN, or assembly language even. I don't even care which processor you use or what platform. You might even try Java to make your solution machine independent. Or you might even be able to script it in PERL, Python or one of the many other scripting languages. You MIGHT even be able to hack it with an Excel spreadsheet. All I care about is that you DO hack it. When you sign the log for this one, don't leave your solution, but do leave something telling me what you used to create your solution. For example, if you write a program in Pascal to solve it, then just note that in the log.

The algorithm presented is based on something I reversed quite a while ago. It seemed like an appropriate algorithm. There may even be some out there who recognize it, albeit very few I'd gather. Unfortunately, I would have rather given the other half of the algorithm, because reversing it might have been a bit more difficult, but it also would reveal the answer directly. It is presented as source code and not a complete reversing challenge due to some restrictions here on www.geocaching.com.

The actual key: JQIS5QIQ53X3A5RH

#include <stdio.h>
#include <stdlib.h>

int coords[2];

unsigned char translation_1[64] = { 0x00, 0x71, 0x02, 0x73, 0x04, 0x75, 0x06, 0x77,
                                   0x10, 0x61, 0x12, 0x63, 0x14, 0x65, 0x16, 0x67,
                                   0x20, 0x51, 0x22, 0x53, 0x24, 0x55, 0x26, 0x57,
                                   0x30, 0x41, 0x32, 0x43, 0x34, 0x45, 0x36, 0x47,
                                   0x40, 0x31, 0x42, 0x33, 0x44, 0x35, 0x46, 0x37,
                                   0x50, 0x21, 0x52, 0x23, 0x54, 0x25, 0x56, 0x27,
                                   0x60, 0x11, 0x62, 0x13, 0x64, 0x15, 0x66, 0x17,
                                   0x70, 0x01, 0x72, 0x03, 0x74, 0x05, 0x76, 0x07};
                                                                      
unsigned char translation_2[16] = { 0x9, 0xf, 0x3, 0x5, 0x8, 0x2, 0xb, 0xa,
                                   0x1, 0x7, 0x4, 0x0, 0x6, 0xe, 0xc, 0xd};
unsigned char translation_3[32] = { 0x1f, 0x17, 0x09, 0x0a, 0x0b, 0x00, 0x10, 0x18,
                                   0x1e, 0x16, 0x08, 0x0f, 0x0c, 0x01, 0x11, 0x19,
                                   0x1d, 0x15, 0x07, 0x0e, 0x0d, 0x02, 0x12, 0x1a,
                                   0x1c, 0x14, 0x06, 0x05, 0x04, 0x03, 0x13, 0x1b};

unsigned char c_output[32] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";

void do_xlate_step_one(unsigned char *output, unsigned char *input) {
       int key_bit,shift;
       unsigned char mask,byte, bit;

       for(key_bit = 0; key_bit < 8; key_bit++)
               output[key_bit] = 0;

       for(key_bit = 0; key_bit < 64; key_bit++) {
               shift = (translation_1[key_bit] & 0xf0) >> 4;
               mask  = 0x01 << shift;
               byte  = (translation_1[key_bit] & 0x0f);
              
               bit = (input[byte] & mask) ? 1 : 0;
               output[key_bit/8] = (output[key_bit/8] << 1) | bit;
       }
}

void do_xlate_step_two(unsigned char *output, unsigned char *input) {
       unsigned char nibble_a, nibble_b;
       int _i;
      
       for(_i = 0; _i < 8; _i++) {
               nibble_a = input[_i] & 0x0f;
               nibble_b = (input[_i] & 0xf0)>>4;
               output[2*_i] = c_output[translation_3[translation_2[nibble_a]]];
               output[2*_i+1] = c_output[translation_3[2*translation_2[nibble_b]]];
       }
}

int main(int argc, char **argv) {
       unsigned char output_step1[0x8], output_step2[17];

       if(argc < 3) {
               printf("%s <latitutde in decimal degrees as integer> <longitude in decimal degrees as integer>\n",argv[0]);
               return -1;
       }
      
       output_step2[16] = 0;
       coords[0] = atoi(argv[1]);
       coords[1] = atoi(argv[2]);
      
       do_xlate_step_one((unsigned char *)output_step1, (unsigned char *)coords);
       do_xlate_step_two((unsigned char *)output_step2, (unsigned char *)output_step1);
       printf("output: %s \n",output_step2);
       coords[0] = 0; coords[1] = 0;

       return 0;
}

 

Here are a few examples so you can TEST your program.  If you get the examples, you will probably find the cache. 

 

So here they are:

 

output: KJW2LJLQLJYJXGKH
input was: N 38421111, E 77398140
 

output: Q3KHP2KQX342AEIT
input was: N 53259876, E 63874321
 

If you don't have a C compiler, fear not, just translate it into your favorite language. 

However, I used the MinGW32 compiler with the following compile line:

 

gcc -o keygen.exe keygen.c

Then simply run the result.

If you are looking at this puzzle and hoping it gets easier, then look for our other puzzles. We've tried to put out interesting stuff. You don't need to find this, or ANY of our puzzles. We hope you'll try, but its all for fun. I happen to like providing fun for those who have bits instead of blood; bitstreams instead of veins. If you are not so inclined, leave this one alone. It may annoy you no end that there's a cache you can't get. If it really bothers you THAT much, then find someone who can explain the problem to you and SOLVE it. I promise you the feeling of accomplishment will be worth it.

There are 10 different types of people in the world;
those who understand binary numbers and those who don't.

Anon

Additional Hints (Decrypt)

Sorry, none available.

Decryption Key

A|B|C|D|E|F|G|H|I|J|K|L|M
-------------------------
N|O|P|Q|R|S|T|U|V|W|X|Y|Z

(letter above equals below, and vice versa)