[ksnctf] Square Cipher

ksnctfにチャレンジ 第22問目です。

※ksnctfは常駐型のCTFサイトです。 ※問題のページはコチラです。

Square Cipher

発想重視の問題です。 タイトルの スクエア などから紆余曲折して

大文字部分を黒く塗ると QRコードになることに気がつくことが まず第一段階です。

次に このQRコードを読み取り可能な状態にする必要があります。 適当な言語で  小文字 -> 0 大文字-> 1 とでも変換したテーブルを用意することは 簡単ですが、この後 テーブルを QRコードの仕様にしたがってそのまま解釈 or テーブルを QRコード読み取りソフトで読み取れる画像に変換 のどちらです。

当然画像化のほうが簡単で手っ取り早いのでこちらを選択します。

画像化の方法ですが、ビットマップ画像 を生成したり HTML5などのコードを生成してブラウザに描いてもらったりと いろいろありますが、 最も最小のコードですむのは XPM 画像 だと思います。

XPM画像は ASCIIテキストだけで表現できる 画像フォーマットで 画像データそのものがCの配列の形をしており X Windows System でソースコード内に画像をそのまま埋め込むときに 使われています。

これならば printf 一本で画像が生成できてしまいます。

以下生成コード

#include <stdio.h>
#include <ctype.h>

#define XPM_BLACK30 "##############################"
#define XPM_WHITE30 "______________________________"

int main()
{
    int i,j,k;
    char c;
    char line[32];

    FILE *fp;
    fp = fopen("take22.txt", "rb");

    printf(
        " /* XPM */\n"
        "static char *take22_xpm[] = { \n"
        " \"%d %d 3 1\", \n"
        " \".   c none\",\n"       
        " \"#   c black\",\n" 
        " \"_   c white\",\n",

        (31*30), (31*30) 
     );

    for( i=0; !feof(fp); i++)
     {
        c=fgetc(fp);
        if(islower(c)) line[i] = '0';
        if(isupper(c)) line[i] = '1'; 
        if( c == '\n')
         {
            line[32] = '\0';
            i = -1;
            for(k=0; k<30; k++)
            {
                printf("\"");
                for(j=0;j<31;j++)
                 {
                  switch(line[j])
                    {
                      case '0':  printf(XPM_WHITE30); break;
                      case '1':  printf(XPM_BLACK30); break;
                    }
                 }
               printf("\",\n");
            }
         }
     }
     printf("};");
    fclose(fp);
}

line[] に 一行分の 黒白データのリストを作って 改行ごとに 一行分のデータを出力しています。

ASCII 1文字が 1pixel に対応するので1ブロックあたり 30x30 pixel 分 表示するのにちょっときたないループを回しています。 このあたりは綺麗に書きなおしてもうちょっと汎用的な QRコード生成器にしたいところです。

逆にいえばこんな雑なコードでちゃんと画像が作れます。

問題の暗号を take22.txt に保存して上記コードを走らせれば終了です。 QRコードを適当な方法で読み取れば FLAGが表示されます。

前述のとおり 生成された xpm画像の実体は Cのソースコードなので テキストエディタで開けて楽しいです。