【writeup】justCTF2020 振り返り
久しぶりですが友達を誘ってCTFに参加したのでwriteupまとめておきます。
Sanity Check
問題文
やったこと
YoutubeのリンクはRule The Worldというタイトルので、最初はコメントとかにフラグがあるかなーとか思っていたんですが見つからず。
タイトルからしてRuleに関連ありそうだなと思ったので、justCTF2020のRulesページを探してみても見つからず。
Sanity Checkなのでフラグ例とかありえそうだなと思って入力してみたらとおりました。
justCTF{something_h3re!}
MyLittlePwny
問題文
Ponies like only one type of numbers!
nc mylittlepwny.nc.jctf.pro 1337
やったこと
ncで接続すると>の後に入力を求められ、適当な文字を入れてみると可愛いお馬さんがお出迎えしてくれました。
適当にいくつか入力してみると、バッククォートを入れてみるとエラーを吐きました。
[sfera]~ » nc mylittlepwny.nc.jctf.pro 1337 > ` /bin/sh: 2: Syntax error: EOF in backquote substitution >
バッククォートが閉じられていないエラーっぽいので、ls
のような形で任意のコマンドを送ってみます。
> `ls` __________________________________ < bin flag lib lib64 server.py usr > ---------------------------------- \ \ \ ▄ ▄▄▄██████▄▄ █▄▄ ▄████████████████▄▄ ▄ ▄███▄███▄██████████▄▄ ▀▀ ▄██████▄▄▄▄████████▄█████▄ ██▄▄███▄▄▄▄████▄▄█▄████████ █▄█▄█▄█▄▄███▄█▄██▄▄█▄█████▄ ▄█▄████████▄▄▄███▄█████████ ▀▀█▄▄█▄▄█▄▄██▄▄▄▄▄▄████▄█████ ▀█▄▄▄▄▄▄▄▄▄▄▄▄████▄▄█████▀ ▄▄▄▄█▄██▄▄▄▄▄▄▄████████▄▄▄▄ ▀█▄▄██▄█▄█▄███▄██████████▀ ▀▄▄▄▄▄▄█▄▄▄▄▄▄██████▀▀ ▄▄▄▄▄▄▄▄▄▄▄▄▄████▄ ▄▄▄▄▄▄▄▄▄ █▄▄▄▄▄▄▄▄████▀▀████▄ ▄███████████▄ ███▄▄█████▄▄▄█▄ ▄██████████████▄ ████████▄▄▄▄▄▄█▄▄▄▄▄▄▄▄▄██████████████ ▄██████▄▄▄▄▄▄▄███████████▄▄▀███████████ █▄█▄▄█▄▄▄▄▄▄██████▄▄▄▄▄▄▄██▄▄▄██████████ ▄▄▄▄▄█▄▄▄▄█▄▄▄▄████████████▄▄▄██████████ ██▄▄█▄▄▄█▄▄▄▄█▄▄▄▄▄▄▄▄▄▄▄▄▄█▄▄▀▀██████▀ ▀▀▀▄▄▄▄▄▄███▄▄▄███▄███▄▄▄▄▄▄ ▀████ ▀█▄▄██▄▄▄▄▄█▄▀▀▀▄▄▄██▄██▄▄ ▀██▄ ███▄▄█████▄█ ▀▄█▄█▄▄█▄█ ████▄███▄█▄▄ ██▄████▄▄▄ ██▄▄▄████▄██ ██▄███▄▄██ ██▄█▄██▄▄▄█▄▄ ██▄███▄▄▄▄█ ▀▀▀▀▀████████ ▀▀▀██▄█████ ▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀
うまく実行できてflagファイルがあることが確認できました。 あとはこれを表示してフラグゲットです。(catコマンドなど特定のコマンドは実行できないように処理されていたのでstringsを使いました)
> `strings flag` _________________________________ < justCTF{p0nY_t4lEs_b3giN5_h3r3} > --------------------------------- \ \ \ \ ▄▄▄▄ █▄▄▄▄▄██▄▄▄▄▄ ▄▄▄▄▄██▄▄▄▄▄█▄▄▄▄ ████▄█▄▄█▄▄▄███▄▄▄█ ▀▄▄▄▄▄▄████████▄▄███▄█████▄▄▄▄▄▄▄▄▄▄ ████▄▄███▄▄▄▄█████████▄███████████▄ ▀▄▄▄███▄▄█▄█▄███████▄▄████▄▄▄▄▄▄▄▄▄▄ ▀▄▄█▄▄▄███▄████▄██▄▄█▄██▄▄▄▄▄▄▄▄▄▄▄▄ ██████▄▄█▄▄▄▄▄████▄▄█▄▄████████████ █████▄▄█████████████▄▄█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄▄▄████▄▄▄█████████▄▄▄▄██▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄████▄▄▄▄████████▄▄███▄▄███▄▄ ██████████▄▄███▄▄▄▄▄▄▄▄███▄▄▄▄▄▄▄▄▄█▄▄▄▄██████ ▄█▀ ▀▀▀▄▄▄▄█▄▄▄██████████████████▄▄▄▄▄▄█████████ █▄ ▀▀████▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄██████▄▄▄██████▄ ▄ ▀█ ▄▄▄▄▄▄▄▄▄▄▄▄▄████████▄▄▄▄▄▄████▄▄█▄▄▄ ▀▀▀▀ ▀▀▀▄▄▀▀▀▀▀▀▀▄▄█▄▄▄▄▄▄▄▄████████▄▄██▄▀▀ ▄█ █▄▄████████▄▄▄▄▄▄▄▄█▄▄▄█ █▀ ▄ ▀████▄▄▄▄▀▀ ▄█▀▀▀ █▀ ▄ ▀▀▀▀ ████ ▀▀▀▀ ██ ▀
justCTF{p0nY_t4lEs_b3giN5_h3r3}
That's not crypto
問題文
This is very simple RE task, but you may need some other skills as well. :)
https://ams3.digitaloceanspaces.com/justctf/11456603-38e8-4b10-9863-296fc0cf0342/checker.pyc
やったこと
pycファイルが与えられます。.pycはPythonのコードをコンパイルしたデータが入っている認識だったので、とりあえずデコンパイルする方法を探しました。
検索してみるとuncompyle6を用いれば可能とのことなのでpipでインストールします。
# uncompyle6 version 3.7.4 from random import randint def make_correct_array(s): from itertools import accumulate s = map(ord, s) s = accumulate(s) return [x * 69684751861829721459380039 for x in s] def validate(a, xs): def poly(a, x): value = 0 for ai in a: value *= x value += ai return value if len(a) != len(xs) + 1: return False else: for x in xs: value = poly(a, x) if value != 24196561: return False return True if __name__ == '__main__': a = [1, -12036995612853156936286011036665,...] # 長いので省略 a = [ai * 4919 for ai in a] flag_str = input('flag: ').strip() flag = make_correct_array(flag_str) if validate(a, flag): print('Yes, this is the flag!') print(flag_str) else: print('Incorrect, sorry. :(') # okay decompiling checker.pyc
なんか色々やってますね。大雑把に読んでみると、処理の内容は入力した文字を用いてリスト作って比較してる感じですかね。
とりあえずvalidateメソッド内の最初if文から、フラグの長さが57とわかるので、あとはその後の処理でFalseが返らないよう適当に入力文字列変えてけばフラグがでそうですね。
汚いコードですがこんなのでも問題ないです。
# uncompyle6 version 3.7.4 from random import randint ANS_FLAG = [''] * 57 def make_correct_array(s): from itertools import accumulate s = map(ord, s) s = accumulate(s) return [x * 69684751861829721459380039 for x in s] def validate(a, xs, flag_str): def poly(a, x): value = 0 for ai in a: value *= x value += ai return value if len(a) != len(xs) + 1: #print('not match len') return False else: for j, x in enumerate(xs): value = poly(a, x) #print(value) if value != 24196561: return False ANS_FLAG[j] = flag_str[j] return True if __name__ == '__main__': a = [1, -12036995612853156936286011036665,...] # 長いので省略 a = [ai * 4919 for ai in a] import string printable_list = [i for i in string.printable] for num in range(0,57): for i in printable_list: #flag_str = input('flag: ').strip() correct_str = '' if not ANS_FLAG[num-1] == '': for k in range(0, num): correct_str += ANS_FLAG[k] flag_str = correct_str + i + 'a'*(57 - len(correct_str) - 1) flag = make_correct_array(flag_str) if validate(a, flag, list(flag_str)): print('Yes, this is the flag!') print(flag_str) else: pass #print('Incorrect, sorry. :(') # okay decompiling work/checker.pyc
justCTF{this_is_very_simple_flag_afer_so_big_polynomails}
PDF is broken, and so is this file
問題文
This PDF contains the flag, but you’ll probably need to fix it first to figure out how it’s embedded. Fortunately, the file contains everything you need to render it. Follow the clues to find the flag, and hopefully learn something about the PDF format in the process.
https://ams3.digitaloceanspaces.com/justctf/eccb3bff-69aa-4232-8087-a5e8eea0f581/challenge.pdf
やったこと
ダウンロードしたPDSファイルをとりあえず開いてみると、真っ白なページが表示されました。表示させる情報はファイルの中に全て入っているとのことなので、Hex Fiendで中身を覗いてみると、requireから始まるrubyのコードから始まっていました。
PDFの構造を調べてみるとヘッダ、ボディ、クロスリファレンステーブル、トレイラーから構成されるみたいです。以下のサイトとかかなり参考になります。
中身をもう少し見てみるとクロスリファレンステーブル(xref)が2つあるので、何か間に挿入されたのかな?と推測できます。その辺りに注目してみると、PK...からはじめるzipっぽいバイナリが見えます。
これらのファイルを抽出したいのでbinwalkを使ってみると、ZIPやその中身が抽出できました。
[sfera]~/Downloads » binwalk -e ./challenge.pdf DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 53 0x35 PDF document, version: "1.5" 350 0x15E HTML document footer 1636 0x664 HTML document header 1843 0x733 HTML document footer 1936 0x790 Zlib compressed data, best compression 3882 0xF2A Zlib compressed data, best compression 745265 0xB5F31 Zlib compressed data, default compression 745469 0xB5FFD Zlib compressed data, default compression 835474 0xCBF92 Zlib compressed data, best compression 836261 0xCC2A5 JPEG image data, JFIF standard 1.01 1866761 0x1C7C09 JPEG image data, EXIF standard 1866773 0x1C7C15 TIFF image data, little-endian offset of first image directory: 8 2716590 0x2973AE Zlib compressed data, best compression 2726679 0x299B17 Zlib compressed data, best compression 2734100 0x29B814 Zlib compressed data, best compression 2747120 0x29EAF0 Zlib compressed data, best compression 2757397 0x2A1315 Zlib compressed data, best compression 2767356 0x2A39FC Zlib compressed data, best compression 2774636 0x2A566C Zlib compressed data, best compression 2788994 0x2A8E82 Zlib compressed data, best compression 2797259 0x2AAECB Zlib compressed data, best compression 2811290 0x2AE59A Zip archive data, at least v1.0 to extract, name: feelies/ 2811356 0x2AE5DC Zip archive data, at least v2.0 to extract, compressed size: 27832169, uncompressed size: 38061512, name: feelies/mutool 30643597 0x1D3958D Zip archive data, at least v2.0 to extract, compressed size: 220, uncompressed size: 289, name: feelies/false_flag.md 30644149 0x1D397B5 End of Zip archive, footer length: -28825 30658564 0x1D3D004 Zlib compressed data, best compression 30666829 0x1D3F04D Zlib compressed data, best compression
false_flag.mdにはmutoolの使い方などが書かれていたので、mutoolを使ってみるとpngが出力されました。
英弱なので内容を正しく理解できているわけではないですが、なんとなく分かったことは
0x06がなんか悪さをしている
2642 didder "42bytes" object で検索すれば何かヒントが得られそう
くらいですかね。
PDFファイルの中で0x06の箇所を探してみると、streamオブジェクトの記述あたりで使用されていました。これを他の正常なPDFを参考に0Aに変更してみるとAdobeで表示させることができました。ただ内容としてはmutoolを使って出てきたpngと同様で、特に目新しい情報は得られませんでした。
次に 2642 didder "42bytes" objectで検索をかけてみると以下のサイトがヒットしました。
PDF Stream Objects | Didier Stevens
Stream Objectのフォーマットについて書かれていたので、PDFファイルの中で正しいフォーマットでない箇所を探すと、ZIPの箇所でLengthやFilterが指定されていないです。ただこの箇所は表示させる内容とは考えにくかったので、ここでかなりつまづきました...。
どこに目をつけたらいいのかわからなかったので、PDFに含まれているオブジェクトをとりあえず手当たり次第見てみました。xrefから50個のオブジェクトがあることは分かったいたので、順に探しているところ、オブジェクト番号が4919のものがありました。こいつを表示できれば何かヒントが得られそうです。
しかし、xrefやオブジェクト番号をいじってみても、うまく表示させることができませんでした。もう少しPDFのフォーマットについて詳しく調べる必要がありそうです。
ここでbinwalkで抽出したデータを眺めてると、気になるファイルがあることに気付きます。
FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 01 2C 01 2C 00 00 FF DB 00 43 00 08 06 06 07 06 05 08 07 07 07 09 09 08 0A 0C 14 0D 0C 0B 0B 0C 19 12 13 0F 14 1D 1A 1F 1E 1D 1A 1C 1C 20 24 2E 27 20 22 2C 23 1C 1C 28 37 29 2C 30 31 34 34 34 1F 27 39 3D 38 32 3C 2E 33 34 32 FF DB 00 43 01 09 09 09 0C 0B 0C 18 0D 0D 18 32 21 1C 21 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 ---略---
なんかのバイナリですね。
これをHex Fiendにコピーして保存すると画像が表示されました。
justCTF{BytesAreNotRealWakeUpSheeple}
簡単なのしか解けませんでしたが久しぶりのCTF楽しかったです。
またやりたい。