好奇心の足跡

飽きっぽくすぐ他のことをしてしまうので、忘れないため・形にして頭に残すための備忘録。

Rice Tea Cat Panda CTF writeup [Forensics]

2020 1/21(火) 1:00 ~ 1/25(土) 16:59 JST に開催された、Rice Tea Cat Panda CTF の Forensics ジャンルのwriteup。

writeup一覧・戦績はこちら

kusuwada.hatenablog.com

[Forensics] BTS-Crazed (75pt)

My friend made this cool remix, and it's pretty good, but everyone says there's a deeper meaning in the music. To be honest, I can't really tell - the second drop's 808s are just too epic.

Hints

https://github.com/JEF1056/riceteacatpanda/raw/master/BTS-Crazed (75)/Save Me.mp3

Save Me.mp3がDLできます。

strings -> grep で出た。

$ strings Save\ Me.mp3 | grep rtcp
rtcp{j^cks0n_3ats_r1c3}N

[Forensics] Allergic College Application (100pt)

I was writing my common app essay in Mandarin when my cat got on my lap and sneezed. Being allergic, I sneezed with him, and when I blew my nose into a tissue, the text for my essay turned really weird! Get out, Bad Kitty!

Common_App_Essay.txtが配布されます。

Ëæ×Åʱ¼äµÄÍÆÒÆ£¬ÎÒƳ¼ûÁËÎҵĻ𳵵ǻúƽ̨¡£¾ÍÏñÒ»¸ö·è¿ñµØÔڷ籩ÖÐÑ°ÕҸۿڵĴ¬³¤£¬ÎÒÔÚÈËÃǶ¯µ´µÄº£ÑóÖÐÍÏÀ­×Ô¼º£¬ÊÔͼ±ÜÃâÔÚÊÀ½çÉÏ×î³¾ÍÁµÄ³ÇÊÐÖб»À§ - »ò±»¼ṳ̀£º±±¾©£¬ÖйúµÄÊ׶¼ºÍÑÌÎí¡£

ÐÒÔ˵ÄÊÇ£¬ÎÒµÇÉÏÎҵĻð³µÖ»Ð輸ÃëÖÓ£¬¶øÇÒûÓбä³É¼å±ý - ×ÜÊÇÒ»¸ö¼ÓºÅ¡£ÊÛƱԱ»¶Ó­ÎÒÉÏ´¬¡£×îºó£¬ÊÇʱºò»Øµ½ÉϺ£ÁË¡£

ÕâÊÇ2012ÄêµÄÏÄÌ죬ÉϺ£²»»á³¤¾Ã»Ø¼Ò¡£ÔÚÁíÒ»¸öÐÇÆÚ£¬ÎÒ½«´©Ô½È«Çò£¬ÔÚÒ»¸öÃûΪÏÄÂåÌصÄÒìÓò¿ªÊ¼ÐµÄÉú»î¡£

ÄĸöÊǼң¿ÎÒÒªÀ뿪µÄµØ·½»¹ÊÇÎÒҪȥµÄµØ·½£¿µ½´ï»¹ÊÇÀ뿪£¿¾ÍÏñÒ»¸ö´ÅÌõ¶ÏÁѵÄÖ¸ÄÏÕ룬ÎÒÎÞ·¨¾ö¶¨ÎÒÕæÕýµÄ±±·½¡£

²»Îȶ¨£¬ÎÒתÏòÎÒÓÀÔ¶´æÔÚµÄÊéÒÔ»ñµÃ°²Î¿¡£½ñÌìÊÇTim O'Brien´øÀ´µÄ¶«Î÷£¬ÒѾ­Ä¥Ëð£¬ÂÔ΢Öå°Í°Í¡£ËûÃÇ˵×îºÃµÄÊé»á¸æËßÄãÄãÒѾ­ÖªµÀµÄ¶«Î÷£¬ÓëÄã×Ô¼ºµÄ˼ÏëºÍÇé¸Ð²úÉú¹²Ãù¡£ÔÚÎÒ¶Áµ½µÄʱºò£¬¾ÍºÃÏñÎÒµÄÏë·¨µÄ·ç±©ÔÚÖ½ÉÏƴд³öÀ´¡£µÙÄ·¡¤°Â²¼À³¶÷£¨Tim O'Brien£©µÄÕ½Õù»°ÓïÖÐÒç³öµÄ³¬ÏÖʵ¸ÐÉø͸µ½ÁËÎÒµÄÊÀ½ç¡£ËûµÄ»°Óï²»ÖªºÎ¹Ê³ÉΪÎҵĻ°ÓËûµÄ¼ÇÒä³ÉÁËÎҵļÇÒä¡£¾¡¹Ü×Óµ¯ÁгµËٶȺܿ죬µ«ÎÒµÄ˼Ð÷ÈÔÈ»ÍêÃÀ - ±»À§ÔÚÊéµÄÐðÊöºÍÎÒ×Ô¼ºÉú»îµÄÐðÊöÖ®¼ä¡£

ÎÒ¾õµÃÎÒÓ¦¸Ã¸Ðµ½²»°²£¬µ«ÎÒ²»ÊÇ¡£ÎÒ¶ÁÁË×îºóÒ»Ò³²¢¹ØÉÏÊ飬¶¢×ÅÉÁÁÁµÄÓãÌÁºÍÄþ¾²µÄµ¾ÌïµÄ´°»§¡£ÎÒ¾õµÃ»ð³µÍâÃæÓÐÒ»ÍŻҳ¾£¬Æ¯¸¡£¬Âú×ã²¢ÇҺܸßÐËÔÚÄ¿µÄµØÖ®¼ä¡£

ÎÒÔÚÊÀ½çÖ®¼äµÄ¼Ò¡£ÎÒ˵ӢÓïºÍÖÐÎÄ£ºÖÐÎÄÊÇÊýѧ£¬¿ÆѧºÍ¹ý³Ì£¬µ«ÎÒ¸üϲ»¶Ó¢Ó²»ÂÛÊÇÒÕÊõ£¬Çé¸ÐºÍÃèÊö¡£ÃÀ¹úÓµÓÐÎÒµÄͯÄ꣬³äÂúÁËËÉÊ÷£¬Ò»Ãù¾ªÈ˵ĵçÓ°ºÍÌ«ºÆºþµÄÑ©;ÖйúÓµÓÐÇà´ºÆÚ£¬°éËæ׏¤ÒµÑÌÎí£¬Ñ¸ËÙµÄÁ÷¶¯ÐԺͿì½Ú×àµÄÉç½»³¡¾°¡£

ÎÒÃÇÕýÔÚ½øÈëÉϺ£ºçÇÅÕ¾¡£ÎÒµÄåÚÏ벢ûÓнáÊø£¬µ«ÎÒ¶Ô×Ô¼ºµÄÎÊÌâÓÐÁ˴𰸡£ÎÞÂÛÊÇÃÀ¹ú»¹ÊÇÖйú£¬¼Ò¶¼²»Êǵ½À´Ò²²»Êdzö·¢¡£¼ÒÊÇÖмäµÄ£¬¹ý¶ÉµÄ¼â¶Ë - ÕâÊÇÎҸе½×îÂúÒâµÄµØ·½¡£

ʲôÓÐÓã¿

ÔÚÎÒÃǵÄѧԺÂÛÎÄClich¨¦s±ÜÃâ·¢Ìûʱ£¬ÎÒÃǽ¨ÒéѧÉú²»ÒªÐ´¹ØÓÚ´ÓÍâ¹úÒƾÓÃÀ¹úµÄÎÄÕ¡£ºÜ¶àʱºò£¬ÕâЩÎÄÕÂÊǹ«Ê½»¯µÄ£¬Ã»ÓÐÎüÒýÁ¦ - ±Ï¾¹£¬ËäȻѧϰһÃÅÐÂÓïÑÔºÍÎÄ»¯¿Ï¶¨ÊÇÒ»¸öÌôÕ½£¬µ«Ã¿Ì춼ÓÐÊý°ÙÍòÈËÕâÑù×ö£¬ËùÒÔËü¸ù±¾²»ÊÇÈÃѧÉúÓëÖÚ²»Í¬µÄ¶«Î÷¡£

ÕâƪÎÄÕÂÊÇÈçºÎ½²ÊöÒÔ¶ÀÌØ·½Ê½ÒƾÓÃÀ¹úµÄ¹ÊʵÄÒ»¸öÀý×Ó¡£ÕâÃûѧÉúרעÓÚÒ»¸öÎÊÌâ - ÔÚÄÄÀ - Ïò¶ÁÕßչʾÁËËû×÷Ϊһ¸öÈ˵ÄÉí·Ý¡£Í¨¹ýÕâƪ¾«ÐıàдµÄÎÄÕ£¬ÎÒÃÇÁ˽⵽ѧÉú¹ý×ŷdz£¹ú¼Ê»¯µÄÉú»î£¬Ñ§ÉúÓÐÎÄ×Ö£¬Ñ§Éúϲ»¶ÎÄѧ£¬Ñ§ÉúÊÇË«ÓѧÉú¶Ô±ä»¯¸Ðµ½ÐË·Ü¡£ÕâƪÎÄÕÂÊÇÒ»ÖÖÔĶÁµÄÀÖȤ£¬·ÖÏíÁËѧÉú¸öÐÔµÄÏêϸһƳ£¬¶ø²»ÊǸоõËüÊÔͼÁгö»ý¼«µÄ¸öÈËÆ·ÖÊ¡£

{ÎÒ_Ö»_ÐÞ¸Ä_ÁË_Á½_´Î}

文字化けしたみたいになってるけど、最後がflagっぽい。

問題文にin Mandarinとあるので調べてみた。文字化けだとしたら、何語なのかがわかるかと思って。

マンダリン (Mandarin)

マンダリン (官僚) - 官吏。以下はこれから派生。

中国語の官話(北京官話)のこと。17世紀、華南に渡来した宣教師が、土着の言語のほかに官署で話されている公用語があることに気付き、これを官僚(マンダリン)の言語と呼んだことに由来する。

それに由来して、中国語の標準語である標準中国語(中華人民共和国普通話中華民国の国語など)のこと。

という事で中国語が怪しい。
他の問題で使ってみた、CyberChefを試してみます。

f:id:kusuwada:20200126100309p:plain

今回みたいに、色々ササッと試したい時は、とても使いやすくて良い!!

最後の -*-*{我_只_修改_了_两_次}をflag形式に直してrtcp{我_只_修改_了_两_次}を入れたら通りました!

[Forensics] cat-chat (125pt)

nyameowmeow nyameow nyanya meow purr nyameowmeow nyameow nyanya meow purr nyameowmeow nyanyanyanya nyameow meow purr meow nyanyanyanya nya purr nyanyanyanya nya meownyameownya meownyameow purr nyanya nyanyanya purr meowmeownya meowmeowmeow nyanya meownya meowmeownya purr meowmeowmeow meownya purr nyanyanyanya nya nyameownya nya !!!!

Hints

once you've figured this out, head to discord's #catchat channel.

問題文をよーく見ると、nya, meow, purr しか出てきていない。しかもpurrは単独で使われることしかなさそうだ。なので、実質nya, mewo。2値といえば バイナリデータ か モールス信号かな?今回は空白があること、purrが改行っぽいことからモールス信号と当たりをつけて変換してみます。

手動でちょこちょこやったらそれっぽかったので、猫ちゃん語を人語に変換するツールを作った。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

catchat = "nyameowmeow nyameow nyanya meow purr nyameowmeow nyameow nyanya meow purr nyameowmeow nyanyanyanya nyameow meow purr meow nyanyanyanya nya purr nyanyanyanya nya meownyameownya meownyameow purr nyanya nyanyanya purr meowmeownya meowmeowmeow nyanya meownya meowmeownya purr meowmeowmeow meownya purr nyanyanyanya nya nyameownya nya"

mors_map = {"A": ".-",
            "B": "-...",
            "C": "-.-.",
            "D": "-..",
            "E": ".",
            "F": "..-.",
            "G": "--.",
            "H": "....",
            "I": "..",
            "J": ".---",
            "K": "-.-",
            "L": ".-..",
            "M": "--",
            "N": "-.",
            "O": "---",
            "P": ".--.",
            "Q": "--.-",
            "R": ".-.",
            "S": "...",
            "T": "-",
            "U": "..-",
            "V": "...-",
            "W": ".--",
            "X": "-..-",
            "Y": "-.--",
            "Z": "--..",
            "0": "-----",
            "1": ".----",
            "2": "..---",
            "3": "...--",
            "4": "....-",
            "5": ".....",
            "6": "-....",
            "7": "--...",
            "8": "---..",
            "9": "----.",
            "(": "-.--.",
            ")": "-.--.-",
            "-": "-....-",
            "_": "..--.-",
            ".": ".-.-.-",
            ",": "--..--",
            ":": "---...",
            "?": "..--..",
            "start": "-...-",
            "end": ".-.-."
            }

def morse_to_message(mor):
    arry = mor.split(' ')
    message = ''
    try:
        for a in arry:
            message += [k for k, v in mors_map.items() if v == a][0]
    except:
        message += a
    return message

## create morse
signal = ''
arry = catchat.split()
for a in arry:
    while a != '':
        if a.startswith('nya'):
            signal += '.'
            a = a[3:]
        elif a.startswith('meow'):
            signal += '-'
            a = a[4:]
        elif a.startswith('purr'):
            signal += '\n'
            a = a[4:]
        else:
            raise('what is ' + a)
    if not signal.endswith('\n'):
        signal += ' '
# print(signal)

## comvert morse to message
human = ''
for l in signal.split('\n'):
    human += morse_to_message(l.strip())
    human += (' ')
print(human)

実行結果

$ python solve.py
WAIT
WAIT
WHAT
THE
HECK
IS
GOING
ON
HERE

いい感じ。さて、変換できたので、今度はDiscordの#catchatチャンネルに行ってみます。

f:id:kusuwada:20200126100333p:plain

おびただしい数の猫語での会話。100個はあるんじゃなかろうか。これ全部翻訳していくのはプログラムがあっても大変そう...。
けど、Dicordの特定チャネルの内容をAPI取得するのは、Rule的に禁止されているようなのでやめて、結局会話をテキストファイルに全部コピペして変換しました。

上記のプログラムを、テキストから読み出すように変更し、

$ python solve.py > human.txt

human.txtRTCPを検索するとflagが出てきました。

TH15_1Z_A_C4T_CH4T_N0T_A_M3M3_CH4T

flag: rtcp{TH15_1Z_A_C4T_CH4T_N0T_A_M3M3_CH4T}

モールス信号、今までなんとなくオンラインツールや手動で変換してたので、副産物でモールス信号解読スクリプトができた✌。

[Forensics] catch-at (129pt)

636274425917865984

これだけ。ヒントもなし。

タイトルがさっきのcat-chatとハイフンの位置だけ違うのが気になる。あと情報量が少なすぎるので、さっきの情報量が多すぎたcat-chatと関連があるような気がする。

ということで、Discordの#cat-chatチャネルにまた戻って眺めていると、URLが

https://discordapp.com/channels/624036526157987851/633364891616411667/{行のID}であることに気づく。
最後の行に 636274425917865984 を入れてアクセスすると、猫語が一つ手に入る。これをさっきのスクリプトで翻訳すると

$ python solve.py 
OH BY THE WAY, HERE'S A LITTLE SOMETHING: W0W_D15C0RD_H4S_S34RCH_F34TUR35 

flag: rtcp{W0W_D15C0RD_H4S_S34RCH_F34TUR35}

[Forensics] Chugalug's Footpads (150pt)

Chugalug makes footpads that he can chug and lug. However, his left one is different from his right... I wonder why?

left.jpgright.jpgが配布されます。

f:id:kusuwada:20200126100538j:plain:w200 f:id:kusuwada:20200126100459j:plain:w200

macのプレビューで開くと、明らかに左が壊れています。

  • chug: 一気飲み/ぽっぽと音を立てる
  • lug: 引きずる
  • chug-a-lug: 一気に飲む

うーん、完全に英語のお勉強(でもよくわからない)になっている。海外CTFはそこが難しくて楽しい。(でもよくわからない)

$ cmp -l left.jpg right.jpg 
  1720 162 122
  1721 164 115
  2041 143 105
  2042 160 121
  2328 173 160
  2329 124 165
  2330 150 102
  2854  63 240
  2855 172  63
  2856 145 154
  3016 137 144
  3017 136 201
  3019 162  24
  3110  63 161
  3332 137  14
  3626 156  21
  3627  60 232
  4215 124 112
  4405 143  40
  4413 110   2
  4775  64  62
  4776 156 347
  5125 103  57
  5149  61 114
  5150 141 112
  5400  65 364
  5401 175 362

とりあえずバイナリの比較を出してみた。壊れている左足のほうの値を8進数の配列としてchr(n)してあげると、flagが出てきた。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

cipher = [162, 164, 143, 160, 173, 124, 150, 63, 172, 145, 137, 136, 162, 63, 137, 156, 60, 124, 143, 110, 64, 156, 103, 61, 141, 65, 175]

for c in cipher:
    print(chr(int(str(c),8)), end='')

実行結果

$ python solve.py 
rtcp{Th3ze_^r3_n0TcH4nC1a5}

[Forensics] BASmati ricE 64 (150pt)

There's a flag in that bowl somewhere...

Replace all zs with _ in your flag and wrap in rtcp{...}.

rice-bowl.jpgが配布されます。

f:id:kusuwada:20200126100756j:plain

画像系なので、とりあえず GitHub - DominicBreuker/stego-toolkit: Collection of steganography tools - helps with CTF challenges にかけてみます。いろいろ試した所、steghide を実行したら何か出てきました。

# steghide extract -sf rice-bowl.jpg -xf output.txt
Enter passphrase: (just press enter)
wrote extracted data to "output.txt".
# cat output.txt
?I??Y??;a?x9?
??y??=?

flagにはちょうど良さそうな長さのデータが抽出されています。
バイナリとして読み込んで表示させてみたところ、\xb3I\xb7\xb7Y\xb7\xe7;a\xd6x9\xcc\n\xf7\xcfy\xdc\xd0=\xddとのこと。
intの配列になおすと 179, 73, 183, 183, 89, 183, 231, 59, 97, 214, 120, 57, 204, 10, 247, 207, 121, 220, 208, 61, 221。レンジ的にそこそこ良心的っぽい。

ここでタイトルに注目します。大文字だけ見るとBASE64。あやしい。
ということで、このバイナリ列を base64 decode してみましたが、paddingが不正とのこと。じゃあ逆にencodeしたれ!と思ってやってみた。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import base64

with open('steghide.txt', 'rb') as f:
    data = f.read()

print(data)

decoded = base64.b64encode(data)
print(decoded)

実行結果

$ python solve.py 
b'\xb3I\xb7\xb7Y\xb7\xe7;a\xd6x9\xcc\n\xf7\xcfy\xdc\xd0=\xdd'
b's0m3t1m35zth1ng5zAr3z3nc0D3d'

おや!読めるものが出てきたぞ!問題文の通り、z_に置換してrtcp{}で囲ったら、通った!

flag: s0m3t1m35_th1ng5_Ar3_3nc0D3d (sometimes things are encoded)

[Forensics] League of Asian Grandmas (200pt)

We recently intercepted an exorbitantly delicious and commodious shipment containing cleaned rice, unrealistically sweet-smelling jackfruit, elegantly peeled rambutan, seedless lychee, large, round and plump grapes, succulent nectarines, viscid peaches, and fried rice (among other things).

I'm not too sure, but this seems a tad bit suspicious, don't you think? Just looking at this makes me dizzy....

Hints

https://github.com/JEF1056/riceteacatpanda/tree/master/League of Asian Grandmas (200)

リンク先のgithubディレクトリには、png画像が4つ。

f:id:kusuwada:20200126100837p:plain:w200 f:id:kusuwada:20200126100841p:plain:w200 f:id:kusuwada:20200126100850p:plain:w200 f:id:kusuwada:20200126100854p:plain:w200

画像をよーーーく眺めてみると、特に4枚目、右下の方に E} というフラグの終端っぽい画像が見える気がします。

このグネグネをどうやって直したら良い?下記、手当り次第やってみたこと。

  1. gimpなどの画像描画ツールで「フィルター」>「変形」>「渦巻と吸い込み」的な効果を試すと、それっぽく少しは補正されるんだけども…。全部は読めない。
  2. グネグネした画像がムンクの叫びに似ているので、それにちなんだ名前のついたツールが付いていないかなどを探してみる。
  3. strings,zstegしたときに出てくる文字列の中から、それっぽいツール名がないか探してみる

うーん、どれもパットしないまま協議機関終了。
writeup書くためにこのブログに画像を貼って気づいたんだけど、これ4枚つなげると1枚の大きな画像になるんだな。

終了後に、1.の路線で再度挑戦。まずは一枚ずつのぐるぐるを直します。多分これ、4枚つながった状態で一度大きいぐるぐるフィルターがかけられ、更に4つに分割したあとに1枚ずつぐるぐるフィルターがかかってるっぽい。その逆をしてみました。

1枚ずつのぐるぐるを取って、4枚貼り付けます

f:id:kusuwada:20200203130801p:plain

ここから更に大きいぐるぐるを…取り切れない。

f:id:kusuwada:20200203130820p:plain:w300 f:id:kusuwada:20200203130836p:plain:w300

撮りきれませんでしたが、渦を調整しながら少しずつ読んでいくと、下記で通った。case・leet文字はもしかしたらinsensitiveかも。

flag: rtcp{Y3P_N0Th1Ng_t0_S33_H3rE}

今回私はgimpオンリーでやったけど、良いツールとかあったのかしら。「力技!」って感じの問題でした。

[Forensics] Clean Pandas (250pt)

You see, I want my pandas to be squeaky clean, just like the Holy Rice Goddess requires you to make your rice squeaky clean before cooking.

pandas.pkl,soap.pklが配布されます。

問題文からすると、soapでrice...はないので、pandasを洗ってあげるのが良さそう(意味不明)

pkl 拡張子 で検索すると、こんな記事が引っかかりました。

Pythonでコマンドラインからpickleの中身を確認する - Qiita

おお、これっぽい。pythonのpickleってやつ。pythonのドキュメントはこちら

pickle モジュールは Python オブジェクトの直列化および直列化されたオブジェクトの復元のためのバイナリプロトコルを実装しています。"Pickle 化" は Python オブジェクト階層をバイトストリームに変換する処理、"非 pickle 化" は (バイナリファイル または バイトライクオブジェクト から) バイトストリームをオブジェクト階層に復元する処理を意味します。

こんなのがあるんですね。知らなかった。
配布されたファイルを、非pickle化してみます。

$ python -m pickle soap.pkl 
[b'sI33vvCGh735Lt9I5r2FNLbt-aigcrcADtEJWml-D8I=',
 b'2xruhrC7Gbkne6DAwl9R6UwcVG5PRgdezJJEkxzdGco=',
 b'WCE6_c1QCjGLp6LsnYki9pCPSmQZepgDrdi5p4LejR0=',
 b'm_Modz8huoecjj3GatHepBDPt4eGUdHLwwmXMOaQBIw=',
 b'OE4w7zepYc3KO0XdZl-BTKffJJGgEWBHOAT1ws6my_4=',
 b'b5tgnBeA1ac5S6fMHWv2civwLcKAlK8JrroYN5fktkE=',
 b'x-nsrRdnmU7RQpn57_48iT-BRinBhVT3fOOcgYJb9Ks=',
 b'gZINGc-CaTbKAvKQPkN-lcDqMa9HnPe5jqTRupLAF3s=',
 b'rqu87SluCPDRxCUQlgeK56yiXekrJjq3_owc9NApDbg=',
 b'_mLyz6HuEXa3Kh13QBGgf5NE2gLN2oupWhz7Dj2motM=',
 b'KL27tGZETxxDFbyEc1PH8d4ptnGppGQLNVVbCfdDIzY=',
 b'LuqCo-qavxRNuIR2ipLiQ6l6s0aQIo508nzoMcGMKaM=']

同じくpandas.pklを非pickle化しようとすると、ModuleNotFoundError: No module named 'pandas'が出たので、
pip install pandas==0.24.1でinstall。※最新版の0.25.*だと warning が発生したため、暫定的にバージョンを下げてみた。
再度非pickle化してみます。

$ python -m pickle pandas.pkl 
                                            Todolist  ...                    unknown step 923426390324272983
0  b'gAAAAABdpj5DDTyLF2fNzCGlbiIChbh5-02R0a-nugJX...  ...  b'gAAAAABdpj5EoybPiqaRJtGayObj_1Up3D9PqlCxySI5...
1  b'gAAAAABdpj5DqNjA20qHEjrCBvFbCW-D5Fo96UPt_177...  ...  b'gAAAAABdpj5EqMj7oG_qZ2gSNSlwSKUvrw84537w6xgM...
2  b'gAAAAABdpj5DcrqcD3GMoaiWO2P5_4TI-qLJilzQIro3...  ...  b'gAAAAABdpj5EBtvM821QtU9bF7IoLptiI_rQgY0bjzNo...
3  b'gAAAAABdpj5DQEcMd-8Uy2iVADyWzpmWIBNsGu1vw8Jb...  ...  b'gAAAAABdpj5ENHdnxYWHu4KI0lIOVrIUWlKxuK41FZUq...

[4 rows x 13 columns]

この文字列、soapの方は base64 decodeできそうに見えますが、意味の有りそうな文字列になりません。pandasのほうはgAAAAAで始まるのが目に付きますが、なんのことやら?

しばらくほっといたあと、Wrath of the Rice Goddess チャレンジを解いていたら同じような文字列が出てきたので、これだ!と
cryptography.fernetを疑ってみました。鍵の長さもpaddingの数も合ってそうです。

が、soapkey,pandasをencoded dataとして解読を試みるも、

cryptography.exceptions.InvalidSignature: Signature did not match digest.

と冷たい反応。そういえば、上の pandas の unpickle の出力、なんか省略されてるような感じなんだよなぁ…。[4 rows x 13 columns]って書いてあるけど、そんなに無いし…。

更にしばらく期間をおいていたら、pandasライブラリにunpickleの機能があればフルの情報がunpickleされて見れるのでは?と思いつき、pandasライブラリを調べてみました。

pandas.DataFrame, Seriesをpickleで保存、読み込み(to_pickle, read_pickle) | note.nkmk.me

ありました!read_pickle()関数を使えば良さそう。早速実装してみます。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

from cryptography.fernet import Fernet
import pandas as pd

soap_df = pd.read_pickle('soap.pkl')
pandas_df = pd.read_pickle('pandas.pkl')

print(pandas_df.columns)

for j in range(12):
    for i in range(4):
        for k in range(12):
            key = soap_df[k]
            f = Fernet(key)
            try:
                dec = f.decrypt(pandas_df[pandas_df.columns[j]][i])
                print(dec.decode(), end='')
                #print(str(k))
                break
            except:
                continue
    print()

column一覧を表示してみると、めっちゃ出てきたので行けたっぽい!ので、そのまま復号まで実装してみました。

実行結果

$ python solve.py
Index(['Todolist', 'Side note', 'unknown step', 'unknown step 0',
       'unknown step 1246523', 'unknown step 39865432',
       'unknown step 26745643547', 'unknown step 69821830',
       'unknown flag 394052487124', 'unknown step 446537364',
       'unknown step 53920324379187589', 'unknown step 890348',
       'unknown step 923426390324272983'],
      dtype='object')
slayDemon
notUseful
binary image
binary to string
shift by lucky number
binary to string
base 32
byteencode to integerthough bytes from hex
rtcp{CAr3fu1_wH^t_y0u_c134n_696}
split in intervals of 5
base 85

unknown flag 394052487124の行を復号すると、flagが出てきました٩(๑❛ᴗ❛๑)尸

この問題、自分が時間が取れるぎりぎりで解いたので、この問題を解いたら出てきた問題に手がつけられなかった…。けど、明らかに情報がたくさん得られていて、flag以外の行自体がもう問題みたいになってるので、きっとこれを使う問題があるに違いない。

[Forensics] Motivational Message (200pt)

My friend sent me this motivational message because the CTF organizers made this competition too hard, but there's nothing in the message but a complete mess. I think the CTF organizers tampered with it to make it seem like my friend doesn't believe in me anymore, but it's working like reverse psychology on me!!!!

Hints

https://github.com/JEF1056/riceteacatpanda/tree/master/Motivational Message (200)

ヒントのリンクから、バイナリデータを入手できます。
ヒントの文章it's working like reverse psychology on meと、バイナリを見ると先頭付近にDNEIという文字列が確認できるので、バイナリを全部reverse(逆)にしてあげるとPNGファイルになりそう。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

with open('motivation!!!!!.txt', 'rb') as f:
    data = f.read()

rev = b''
for d in data:
    rev = d.to_bytes(1, 'little') + rev

with open('rev.png', 'wb') as f:
    f.write(rev)

こんな画像が出てきました。

f:id:kusuwada:20200205205744p:plain

rtcp{YOU_GOT_THIS!}を投げてみたけど違ったので、stego-toolkitで画像を解析してみたりしていたら、Steganography Onlineのサイトに投げたところでflagがdecodeされました。

f:id:kusuwada:20200205205834p:plain