【c4r0@log】history

個人の備忘録。セキュリティ関連多め。

【writeup】justCTF2020 振り返り

久しぶりですが友達を誘ってCTFに参加したのでwriteupまとめておきます。

Sanity Check 

問題文

https://www.youtube.com/watch?v=CM3jcGsS0Po :)

やったこと

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の構造を調べてみるとヘッダ、ボディ、クロスリファレンステーブル、トレイラーから構成されるみたいです。以下のサイトとかかなり参考になります。

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が出力されました。 f:id:c4r0:20210202162306p:plain

英弱なので内容を正しく理解できているわけではないですが、なんとなく分かったことは

  • 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にコピーして保存すると画像が表示されました。

f:id:c4r0:20210202164441j:plain

justCTF{BytesAreNotRealWakeUpSheeple}

簡単なのしか解けませんでしたが久しぶりのCTF楽しかったです。
またやりたい。