読者です 読者をやめる 読者になる 読者になる

久しぶり

ksnctf

久しぶりにksnctfを解いた。
Q7
ksnctf.sweetduet.info

ぱっと見するとC言語だが空白として隠されているのがWhitespaceという言語。
ネットで調べて出てきたインタプリタに突っ込む。
Whitespace Interpreter written in JavaScript

変換されたJavascriptのコードを適当に読み取りpythonで再現した。

#!/usr/bin/python

stack=[]



stack.append(70)
stack.append(70)
print chr(stack.pop()),
stack.append(6)
stack.append(stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print chr(stack.pop()),
stack.append(11)
stack.append(-stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print chr(stack.pop()),
stack.append(6)
stack.append(stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print chr(stack.pop()),
stack.append(24)
stack.append(stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print chr(stack.pop()),
stack.append(26)
stack.append(-stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print chr(stack.pop()),
stack.append(40)
stack.append(stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print chr(stack.pop()),
stack.append(25)
stack.append(-stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print chr(stack.pop()),
stack.append(36)
stack.append(stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print chr(stack.pop()),
stack.append(66)
stack.append(-stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print chr(stack.pop()),
stack.append(16)
stack.append(stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print chr(stack.pop()),
stack.append(14)
stack.append(stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print chr(stack.pop()),
stack.append(14)
stack.append(stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print chr(stack.pop()),
stack.append(27)
stack.append(-stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print  chr(stack.pop()),
stack.append(5)
stack.append(stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print  chr(stack.pop()),
stack.append(29)
stack.append(stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print  chr(stack.pop()),
stack.append(4)
stack.append(-stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print  chr(stack.pop()),
stack.append(4)
stack.append(stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print  chr(stack.pop()),
stack.append(28)
stack.append(-stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print  chr(stack.pop()),
stack.append(22)
stack.append(stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print  chr(stack.pop()),
stack.append(34)
stack.append(-stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print  chr(stack.pop()),
stack.append(55)
stack.append(-stack.pop() +stack.pop())
stack.append(stack[len(stack) - 1])
print  chr(stack.pop()),

フラグをゲット。

Q34
ksnctf.sweetduet.info
Are you human ?
Yes,I'm human
大量の画像が入ったpngの画像とリードソロモン符号のエンコードスクリプトが与えられる。
画像には一枚あたり32個(最後の一個だけ10個)の英数字(というか16進数で使われる文字)が入っている。
この00000000.pngを見てみるとjpegのSOIと思わしき並びがあったので、これらを全てつなげたものが、与えられたスクリプトによってエンコードされたファイルであると思われる。
とりあえず白黒にしてメディアンフィルタにかけた上でtesseractで文字を読み取ろうと試みたところ、7571ファイル中3000ファイルくらいしか32文字ちょうどを読み取ることが出来なかった。
仕方がないので自分でノイズ(線)を消すプログラムを書くと、32文字ちょうどを読み取れなかったのは15ファイルほどになったので、それらを手作業で文字に落とし込んだ。
これらの16進数をバイナリにして一つのファイルに書き込んだ。
最後にこれをリードソロモン符号のデコードを試みた。
ネットで調べたところreedsoloというライブラリが出てきたのでこれを用いた。
画像64バイトに対して冗長191バイトであることが読み取れたのでこれらをくっつけてデコードした。
すると、エラーを吐いた。どうやら誤りが多すぎたみたいだ。多分画像データから16進数の文字を適切に読み取れなかったのだろう。
新しく画像のノイズを消すプログラムを書くのもめんどうだったのでとりあえず放置。