One of our field agents got lucky – he has sneaked into a suspect’s office and took a photo of a very important document. The picture has been developed and we’ve received an archive with its scan today.

As I am very busy right now and have a very important meeting, look at the link below and take care of that.

OK, so it’s not gonna be obvious. We have an archive with almost 77k files that obviously compress nicely as the uncompressed size is over 670 MB where the downloaded archive is 2.3 MB. Let’s unpack and learn something about the files:

I’ve just picked first, last and some random. They all seem to be 320×240 PCX images. I have opened few of them. They all seem to be a black rectangle but… if you wear glasses you may need them – there seem to be one pixel that’s not black. In fact the pixel colour varies and the position seems to be different for every image.

#Putting the information together
So we have 76800 (nice, round number) of 320×240 images, each with one light pixel. Incidentally, 76800 = 320*240. So there are exactly as many images as there are pixels on a single image. You see, where I’m going?

#The solution
At first I wanted to use imagemagick to combine all the images but either I am too stupid or it’s not really possible to synthesise a command that does it the way I need. So I turned to my old friend GO and the resulting code is incredibly short (shitty error handling though):

It takes some time to generate the solution but not slow enough to make me implement multi-threading. In fact, I leave it as an exercise to to the reader – it’s quite easy really.
Anyway, this is the very important document it was all about:
(it says “HOLIDAY POSTCARD”)

If you can, please give our technicians a hand with this. They are currently occupied fixing our electrohydroturbobulbulator.

Good luck!

First glance

When you download and unpack the file, you’ll get a normal *.wav. Nothing fancy this time (uffff…). I used Audacity to listen and take a look. When you play it, you’ll notice only two distinct sounds and looking at the sound wave you can easily tell that each squeal takes 1 second. If it’s not a kind of binary encoding, then I could give up right now. Plotting the spectrum only confirms that there are two main frequencies:

What is it?

Gynvael said it could be solved with a pen and a piece of paper and this is how I decided to start. I assumed I was working with bytes (I had no clue if that was the case but it’s the simplest thing to do) and wanted to decode like three of them to have something to begin with. Audacity has been very helpful with the task as it provides a spectrogram view:

The first 3 bytes are 01100010, 01001110, and 10100110. And they don’t tell me a thing at first (Gynvael’s secretes are normally ASCII letters). I tried flipping the bits, morse code, changing the order of the nibbles (sorta “endianess” on bytes). Only after a good nap I’ve spotted that the LSB is always 0. In fact every 8th signal in the whole recording is 0. You know what is also always 0? The MSB in the ASCII range. Just reverse the bits and you’ll get F, r, e which, taking into account the nature of this mission, may be the beginning of the word “Frequency”. We’re home.

Solution

The solution is in GO again. The hardest part has been to find the frequency played each second. I tried playing with the Fast Fourier Transform but having no clue about signal processing, I’ve failed miserably. As the whole thing is below 60 lines, I can post it here:

As you can see, I’ve found a library that calculated the fundamental frequencies for me. For the calculations I have used only a quarter of a each seconds because that gave me much better speed and also accuracy – without this hack the frequencies were sometimes waaaay off, screwing the result up.
The most interesting parts are the loops in lines 31, 42 and 52 that read all the samples in, calculate the fundamental frequency for each second, and put the bits in the right order accordingly.

— Operator’s Manual
1. Drone is equipped with a spinning LIDAR.
2. Drone automatically scans each new position with the LIDAR.
3. The scan is made in 10-degree interval; the results are in meters.
4. 0-degree angle means north.
5. There may be some imprecision, especially in tight passages.
6. The LIDAR has 50m range. Everything above that returns “inf”.
7. The scan is made at constant height of 1m above the ground.
8. Drone always moves exactly 1m.
9. Drone reports its position in meters on the W-E and N-S axis. The position
is relative to a (fixed) sender.
10. Drone can only move in the E/W/N/S direction.

The task (or what do we really have to do)

As in every mission the objective is to find a secret passphrase. So probably the best idea is to visualise the data. This would be our second task.
The first thing to do is to actually get the data.

The tools (and why)

Even though I’d be perfectly capable of writing some C(++) and using curl to get the files (I do such things on a daily basis), I decided to give the go language a try. I’m trying to learn it (I still suck, what is clearly visible in the code) and thought it’d be fun. Additionally I took a sneak peek at KrzaQ’s solution (PL) just to have an idea if I’d have had enough time and I’ve learned that I shouldn’t try to solve it without parallelism 😉 So GO it is.

Downloading

I wanted to achieve parallel download. The problem was that every example I have found had its data set known in advance. Our must be discovered on the fly. My solution involves two channels, a WaitGroup, a Mutex and a map. (Warning! Ugly code ahead):

So here I basically create all the workers, kick off the download, wait until everything is downloaded and send the signal to the workers to finish. BTW: I had a stupid mistake here where I had only sent 1 item to the dwEnd channel. I have debugged it for an hour trying to figure out why doesn’t it finish…
Anyway, the trickiest part has been to synchronise it correctly.

The particularly difficult to place was the incrementing and decrementing the WaitGroup (wg), and adding the id to dwQueue. (FYI: the decrementing of wg must be placed after all the move links from current download are queued.

It has downloaded 187812 scan files. Over 95 megabytes of data…

Anyway, this part has been more like my fight with the new language.

Primary task solution

Parsing the data from the disk has been done in similar manner (also parallel). Nothing really interesting. The last part is mostly some basic geometry math:

So I precompute a table of sine and cosine then compute absolute point coordinates. The factor lets me scale the result. At 1.0 (100%) it’s however readable enough.
The hack when computing w and h is there to counteract the problems with float rounding. Without it you’ll get index out of bounds.
The last part just saves a raw bitmap on the disk. Ad because I’m lazy, it’s white-on-black. GIMP rendered this: Can you find the password?

Bonus

The bonus task was to create some kind of visualisation. For this. I have an amazing idea ( ;P ) but no time at the moment. I may however do this later, in which case I’ll share it here.

When compiled with gcc main.c -o mission006 and run like ./mission006 039e996d075c6ef746d4558fb4bd7f0dfc493198_mission006.data.txt, this will produce a raw bitmap with 8 bits/pixel. The 25*25 comes from a quick inspection of the file – values are exclusively between 0 and 24.
Then I opened it in GIMP, set mode to grey scale and size to 25×25 and saw…

At which point I grabbed my phone and scanned it. Turns out it encodes:

Mirrored QR? Seriously?!
One thing though. If you know the QR well or if you’re like me and you used the opportunity to do some reading, you’ll notice soon enough that this image is actually flipped horizontally. (Well you could also get a hint from the solution if you’re smarter than me…). It seems that my scanner doesn’t care but to be completely correct one should just flip it in GIMP or change line 12 of the code to say

Let's check what the return value of check should be. We can rewrite this line:

puts( "nope\0good" + check( buf ) * 5 );

to

puts( check( buf ) == 1 ? "good" : "nope" );

so it returns 1 for a good password.
In the check itself we have two return statements. The first one is a length restriction. There’s some nice XOR; and what do we know about XOR?a ^ b = c ==&gt; c ^ b = a, thus our password length is 47 ^ 42 = 5.

What about the bit shifting magic? That one came to me as a surprise. I took a look at the generated assembly and it’s simply a rotate-left by 9 bits. So each time we rotate the magic value by 9 and then XOR the last 8 bits (sizeof char). At the end we check if the result is another magic constant.

Because we never modify the same bits twice we can just rotate ch once by 45 bits. With that knowledge we can rewrite the code a bit:

The VLC media player is both – hated and loved. I tend to like it because it plays a lot of different formats and broken files pretty well in my experience.

Recently I set up a new Gentoo-based PC. I’ve emerged vlc with the recommended flags (see VLC media player for Gentoo Linux) and everything seemd well till I tried to play something with subtitles. It didn’t really matter if those were SRT, MicroDVD or any other. They just didn’t work. Funny thing though – the OSD as such worked. The file name has been displayed on playback start. As was other information like time, volume, etc. Continue reading →

I am a happy owner of a Samsung SCX-4200 printer/scanner combo. It’s already pretty old but serves me well and I’m not going to replace it only because of its age.
However useful it is for me, I have no place on my desk for it. It’s simply too big. So I’ve put in the corner of my room with other stuff. The downside was wherever I wanted to print or scan something, I had to take my laptop there to connect it via USB cable. Enough is enough, let’s make the Raspberry Pi useful 😉Continue reading →

Back in 2012 I’ve bought myself Raspberry Pi model B. I’m not really keen on playing with electronics and all those GPIO pins could be non-existent as far as I’m concerned. The only thing I wanted was a low-power linux server to manage my network and provide some additional services. My router has been pretty much useless as it forced me to choose between static IP configuration and DHCP. With RPi I’ve got both and more.

Just about a week ago I’ve read about Raspberry Pi v2. has been released. Quad-core and 1 GB of RAM should make my GitLab installation usable at the very least. Without much thinking I’ve bought it and today I’ve decided to replace the hardware.Continue reading →