https://play.picoctf.org/playlists/18?m=146 The Beginner's Guide to the picoGym を解きます。

picoCTF の過去問を埋めていきますがこのプレイリストが最初のガイドらしいのでこれを解いていきます。

Obedient Cat

チュートリアル問題です。 添付ファイルの中身を見るとフラグが書いてあるため、そのフラグを Submit します。

Super SSH

https://play.picoctf.org/playlists/18?m=147

指定された

  • ユーザ
  • ドメイン
  • ポート番号 に対して SSH 接続をおこなうことで SSH フラグが得られます。

-p で SSH 接続先ポートを指定できるのですね。

~ [☁️ ]
 ssh [email protected] -p 60328
[email protected]'s password:
Welcome ctf-player, here's your flag: picoCTF{hoge}
Connection to titan.picoctf.net closed.

what’s a net cat?

nc コマンドを利用して特定のドメインの特定ポートにアクセスしてね、という問題です。

nc は TCP UDP それぞれで接続の受付やパケットの送信ができる汎用コマンドらしいです。 特定のポートで通信を待ち受けることや、特定のポートへ文字を送ることができます。

server
 nc 127.0.0.1 -l 33333
hoge
ge
kkfa
 
client
 nc 127.0.0.1 33333
hoge
ge
kkfa
^C
 

下記のようにドメイン&ポートに向かって接続すればフラグが帰ってきます。 おそらく該当ポートの該当ドメインで TCP 接続を受け付けたら下記のテキストを返すプログラムが動いているのだとおもいます。

 nc jupiter.challenges.picoctf.org 25103
You're on your way to becoming the net cat master
picoCTF{hoge}

Mod 26

ROT13 というシーザー暗号をおこなう問題です。 #CyberChef という文字列操作レシピが大量にあるサイトがあるらしく、こちらを使って楽をします。 13 文字ずらすプログラムを書く、のであれば Go か Python、もしくは AI に書かせるのがよさそうです。 今回は CyberChef でやってしまいます。

https://gchq.github.io/CyberChef/

複数の操作をドラッグドロップで連結できそうでいいですね。

Imgur

Warmed Up

0x3D を 10 進数にすると?という問題です。 をしましょう。

2Warm

42 を 2 進数にすると?という問題です。 #競技プログラミング をやっていることはすぐできましたが、社会人になったいま忘れてますね…。

Bases

base64 する問題です。

base64 とはすべてのデータをアルファベットもしくは文字にする encoding 方式です。

❯ echo "bDNhcm5fdGgzX3IwcDM1" | base64 --decode
l3arn_th3_r0p35%

base64 は下記のように

  1. 6 bit ずつに分割し、6 bit に満たない分に 0 を足す
    1. 6 bit の理由は 通りの文字に変換するため
    2. az, 09, +, / で 64 個の文字
  2. 4 文字ずつ = 24bit = 3byte ごとに変換をおこなう
    1. 6bit を 1 文字に変換する、を 4 回おこなう
  3. ここで、もし 4 文字ずつ処理できない場合は = を末尾に入れる

というフローで変換します。 64 は 6 bit ごとに分割し、 2^6 = 64 文字に変換しよう、から来ていたのですね。

Imgur

Wave a flag

warm というファイルが与えられ、それを Linux で実行する、という問題でした。 warm = binary file だったため Mac のコマンドラインで実行しようとしたところエラーになり、Linux マシンで実行したら通りました。

ganyariya in 🌐 ganyariya-ubuntu in [☸ default] ~ [☁️ ganyariya]
 ./warm
Hello user! Pass me a -h to learn what I can do!
 
ganyariya in 🌐 ganyariya-ubuntu in [☸ default] ~ [☁️ ganyariya]
 ./warm -h
Oh, help? I actually don't do much, but I do have this flag here: picoCTF{b1scu1ts_4nd_gr4vy_755f3544}

Linux の実行可能ファイルの形式は ELF というものらしく readelf でバイナリファイルの解析が行えるようです。

ganyariya in 🌐 ganyariya-ubuntu in [☸ default] ~ [☁️ ganyariya]
❮ readelf -h warm
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x5d0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          8760 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         34
  Section header string table index: 33

Tab, Tab, Attack

深いディレクトリ階層を zip 化したファイルが与えられるためそれを unzip して tab key で移動してファイルを見つけてね…という問題でした。

実行ファイルがことごとく Linux のため kali linux VM を proxmox で立てたほうがよさそう…。

Insp3ct0r

特定のウェブサイトが与えられるためそれを調べてね、という問題でした。 HTML, CSS, JS それぞれからフラグを探せばよいです。

Imgur

strings it

Can you find the flag in [file](https://jupiter.challenges.picoctf.org/static/fae9ac5267cd6e44124e559b901df177/strings) without running it? というシーザー暗号をおこなう問題です。

file をダウンロードして実行してみると strings コマンドを試してみたら?と表示されます。 最初このテキストを見たときに、ダウンロードしたファイルを man で見ればいいのか?となりましたが違いました…。

ganyariya in 🌐 ganyariya-ubuntu in [☸ default] ~/ctf [☁️ ganyariya]
❯ wget https://jupiter.challenges.picoctf.org/static/fae9ac5267cd6e44124e559b901df177/strings
--2025-08-11 02:33:07--  https://jupiter.challenges.picoctf.org/static/fae9ac5267cd6e44124e559b901df177/strings
Resolving jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)... 3.131.60.8
Connecting to jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)|3.131.60.8|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 776032 (758K) [application/octet-stream]
Saving to: ‘strings’

strings                          100%[=======================================================>] 757.84K   714KB/s    in 1.1s

2025-08-11 02:33:09 (714 KB/s) - ‘strings’ saved [776032/776032]


ganyariya in 🌐 ganyariya-ubuntu in [☸ default] ~/ctf [☁️ ganyariya] took 2s
❯ mv strings hoge

ganyariya in 🌐 ganyariya-ubuntu in [☸ default] ~/ctf [☁️ ganyariya]
❯ chmod +x hoge

ganyariya in 🌐 ganyariya-ubuntu in [☸ default] ~/ctf [☁️ ganyariya]
❯ ./hoge
Maybe try the 'strings' function? Take a look at the man page


ganyariya in 🌐 ganyariya-ubuntu in [☸ default] ~/ctf [☁️ ganyariya]
❯ strings hoge | grep picoCTF
picoCTF{5tRIng5_1T_7f766a23}

strings でファイルをみたところフラグが得られました。

strings はバイナリファイルの中のうち、人間が読める部分を抽出してくれるプログラムのようです。 https://atmarkit.itmedia.co.jp/ait/articles/1703/09/news038.html

-n で指定した以上の文字が続いている箇所を取れるため、 -h などのオプションテキストを読み出せるようです。 バイナリファイルにおいてもヘルプオプションなどのキャラクタはそのまま格納されているのですね… (はえ〜)

❯ strings /bin/cat -n 20
/lib64/ld-linux-x86-64.so.2
__ctype_get_mb_cur_max
program_invocation_name
program_invocation_short_name
_ITM_deregisterTMCloneTable
_ITM_registerTMCloneTable
Written by %s and %s.

First Grep

grep するだけです。

where are the robots

Can you find the robots? `https://jupiter.challenges.picoctf.org/problem/56830/` ([link](https://jupiter.challenges.picoctf.org/problem/56830/)) or http://jupiter.challenges.picoctf.org:56830

のように robots を見つけられますか?という問題でした。 robots → robots.txt だなとなるため、 robots.txt を見てみます。 Imgur

上記のように設定されており、該当の html をクローラーはクロールしないでね、となっています。 ganyariya は人間なので上記の html を見てみると無事フラグが見つかりました。

Python Wrangling

Python スクリプトとフラグテキスト、パスワードが与えられます。 Python スクリプトを利用してフラグテキストを復号する、という問題です。

Python スクリプトをみて、いい感じにコマンドを実行します。 ひさしぶりに python を触りましたがなにも覚えてないですねぇ…。

 python3 Downloads/ende.py -d Downloads/flag.txt.en
['Downloads/ende.py', '-d', 'Downloads/flag.txt.en']
Please enter the password:68f88f9368f88f9368f88f9368f88f93
picoCTF{4p0110_1n_7h3_h0us3_68f88f93}

PW Crack 1

python のコードを読むことで解けます。

PW Crack 2

下記のように chr で分かりづらくされています。

def level_2_pw_check():
    user_pw = input("Please enter correct password for flag: ")
    if( user_pw == chr(0x64) + chr(0x65) + chr(0x37) + chr(0x36) ):

スクリプトを少し書き換えて実際にテキストにすればよいです。

print(chr(0x64) + chr(0x65) + chr(0x37) + chr(0x36))

PW Crack 3

このなかのどれかが正しいんだけど… と書いてあるので for で総当りします。

# The strings below are 7 possibilities for the correct password. 
#   (Only 1 is correct)
pos_pw_list = ["6997", "3ac8", "f0ac", "4b17", "ec27", "4e66", "865e"]
 
for pw in pos_pw_list:
    level_3_pw_check(pw)

PW Crack 4

PW Crack3 と同じです。 for で総当たりすればいいです。

PW Crack 5

下記のように総当りします。 なんかもっといいやり方 permutations みたいなやつがあった気がする…

hex_chars = "0123456789abcdef"
 
for c1 in hex_chars:
    for c2 in hex_chars:
        for c3 in hex_chars:
            for c4 in hex_chars:
                level_5_pw_check(c1+c2+c3+c4)

Enhance!

SVG 画像が与えられるためフラグを探してね、という問題です。 SVG は Vector 画像であり XML 形式で定義されています。 そのため、ただのテキストファイルでありテキストとしてみるとフラグが隠されています。

Big Zip!

大量のファイルと大量のディレクトリからなる Zip が与えられます。 そこからフラグを探してね、というものです。

grep -r で再帰的に picoCTF という文字を探したところ見つかりました。

 folder_geompbqzxd jrdzivoqwdmt.txt rsrmvkrbfpxgeukobyz.txt zwzompvirggxfwhlri.txt
 folder_gfdesdtwcu jvuiuibk.txt rufgczrvlaavlcm.txt zycxiljatekrtoejqflozui.txt
 folder_gmxxziwjqx jvutlpnevmtboneswt.txt rxabjiwplbcb.txt
 
~/Downloads/big-zip-files [☁️ ]
 grep -r "picoCTF" .
./folder_pmbymkjcya/folder_cawigcwvgv/folder_ltdayfmktr/folder_fnpfclfyee/whzxrpivpqld.txt:information on the record will last a billion years. Genes and brains and books encode picoCTF{gr3p_15_m4g1c_ef8790dc}
 

vault-door-training

Java ファイルが与えられます。 ここで、えぇ〜 java 実行環境用意しないといけないの〜とテンションが下がりましたが、ファイルの中身をみると直接パスワード=フラグが書いてあったためこれを提出するだけです。

keygenme-py

py の中身をみると sha256 で特定の場所をパスワードとして使っている箇所があります。 それを抜き出して提出します。 (プログラム読むのしんどく、gemini に解いてもらいました…)

buffer overflow 0

#define FLAGSIZE_MAX 64
 
char flag[FLAGSIZE_MAX];
 
void sigsegv_handler(int sig) {
  printf("%s\n", flag);
  fflush(stdout);
  exit(1);
}
 
void vuln(char *input){
  char buf2[16];
  strcpy(buf2, input);
}
 
int main(int argc, char **argv){
  
  FILE *f = fopen("flag.txt","r");
  
  fgets(flag,FLAGSIZE_MAX,f);
  signal(SIGSEGV, sigsegv_handler); // Set up signal handler
  
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
 
  printf("Input: "); fflush(stdout);
  char buf1[100];
  gets(buf1); 
  vuln(buf1);
  printf("The program will exit now\n");
  return 0;
}
 

上記が動いているインスタンスが与えるため、これからフラグを取得します。

signal(SIGSEGV, sigsegv_handler) とあり、 シグナル SIGSEGV が発生したときにフラグを print するハンドラが登録されています。 #signal https://www.ibm.com/docs/ja/zos/2.5.0?topic=functions-signal-handle-interrupts

signal とはプロセスとプロセスが通信するときに情報をやりとりするための信号です。 そのうち、 SIGSEGV はセグフォのシグナルです。

url: https://ja.wikipedia.org/wiki/%E3%82%BB%E3%82%B0%E3%83%A1%E3%83%B3%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%81%95%E5%8F%8D
title: "セグメンテーション違反 - Wikipedia"
host: ja.wikipedia.org
favicon: https://ja.wikipedia.org/static/favicon/wikipedia.ico
image: https://upload.wikimedia.org/wikipedia/commons/4/42/KDE_Crash_Handler_screenshot.png

ただし今回の C プログラムの場合は OS Kernel が SIGSEGV を生成し、実行中の C プログラムがそれを検出してハンドラを実行する、という流れになります。

よって、今回の問題ではセグフォを引き起こせばいいです。

17 文字入力すれば vuln の buf2 のメモリ幅を超えて、他の領域を書き換えたことが検知され SIGSEGV が引き起こされる可能性が高いです。

今回は 17 文字ぐらいをいれることでフラグが得られました。