Gynvael’s mission 006 [en]

This time a mission from an English stream. As usual we have to discover a hidden message. This time we got this.

Now I must admit I had a lot of luck here. Being after technical studies with a lot of maths, that looked just like some vectors. So the first thought was to draw them as if they were points.

Since it’s too much work by hand, I’ve written a piece of terrible c code to do it for me (warning – no error checking):

#include <stdio.h>
#include <string.h>

int main(int argc, char** argv) {

    unsigned char buf[25*25];
    memset(buf, 0xff, 25*25);

    FILE* f = fopen(argv[1], "r");
    int x,y;
    while(fscanf(f, "[%d, %d]\n", &x, &y) == 2) {
        buf[25*y + x] = 0x0;
    }
    fclose(f);

    f = fopen("out.data", "w");
    fwrite(buf, 1, 25*25, f);
    fclose(f);

    return 0;
}

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…

flipped
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

buf[25*y + 24-x] = 0x0;

instead. Then you’ll get this:

qr

Gynvael’s mission 004 – the weird way ;)

The mission description isĀ here. It’s in Polish, but it doesn’t really matter. We just have to figure out the password from this code:

#include
int check(char*b){char*p;for(p=b;*p;p++);if(((p-b)^42)!=47)return(
~0xffffffff);unsigned long long ch=0x1451723121264133ULL;for(p=b;*
p;p++)ch=((ch<<9)|(ch>>55))^*p;return!!(14422328074577807877ULL==
ch);}int main(void){char buf[1234];scanf("%1233s",buf);puts("nope"
"\0good"+check(buf)*(6-1));return 0;}

which is simply an obfuscated C.
First: formatting:

#include <stdio.h>

int check(char* b)
{
    char* p;
    for ( p = b; *p; p++ )
        ;

    if ( ( ( p - b ) ^ 42 ) != 47 )
        return ( ~0xffffffff );

    unsigned long long ch = 0x1451723121264133ULL;
    for ( p = b; *p; p++ )
        ch = ( ( ch << 9 ) | ( ch >> 55 ) ) ^ *p;

    return !!( 14422328074577807877ULL == ch );
}

int main(void)
{
    char buf[1234];
    scanf("%1233s", buf);
    puts( "nope\0good" + check( buf ) * ( 6 - 1 ) );
    return 0;
}

Now things that are pure noise:

#include <stdio.h>
#include <string.h>

int check(char* b)
{
    if ( ( strlen( b ) ^ 42 ) != 47 )
        return 0;

    unsigned long long ch = 0x1451723121264133ULL;
    for ( char* p = b; *p; p++ )
        ch = ( ( ch << 9 ) | ( ch >> 55 ) ) ^ *p;

    return 0xC82666F8975A8A05ULL == ch;
}

int main(void)
{
    char buf[1234];
    scanf("%1233s", buf);
    puts( "nope\0good" + check( buf ) * 5 );
    return 0;
}

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:

int check(char* b)
{
    if ( strlen( b ) != 5 )
        return 0;

    unsigned long long ch = 0xC826628A2E462424ULL;
    unsigned long long pw = 0x0ULL;

    for ( char* p = b; *p; p++ )
        pw = ( ( pw << 9 ) | *p );

    return ( pw ^ ch ) == 0xC82666F8975A8A05ULL;
}

And there is the XOR! Time to recover the password from the already known formula:

#include <stdio.h>

int main(void)
{
    unsigned long long ch    = 0xC826628A2E462424ULL;
    unsigned long long magic = 0xC82666F8975A8A05ULL;
    unsigned long long pw = ( magic ^ ch );
    for( int i = 45; i >= 0; i -= 9 )
        putchar( (char)(pw >> i) );

    return 0;
}

This code prints GWGW! when executed.