はじめに
picoCTFに取り組んで行くときの考えていたことを書き記す。writeupというより、解いた道筋を書いていますので、最短距離を知りたい人にとっては意味わからないものかもしれません。ご了承ください。begginerのお戯れと思って暖かく見守っていただければ幸いです。一般的な技術も必要と思ったので取り組む。それでもまずは10000solves以上のものに取り組んで行こうと思う。
開閉
- はじめに
- Lets Warm Up
- Lets Warm Up
- 2Warm
- what's a net cat?
- strings it
- Bases
- First Grep
- Description
- convertme.py
- fixme1.py
- fixme2.py
- Glitch Cat
- HashingJobApp
- PW Crack 1
- PW Crack 2
- PW Crack 3
- PW Crack 4
- PW Crack 5
- runme.py
- Description
- First Find
- Big Zip
- repetitions
- ASCII Numbers
- money-ware
- plumbing
- Based
- chrono
- useless
- Based
- flag_shop
- Super SSH
- Commitment Issues
- Time Machine
- Blame Game
- Collaborative Development
- binhexa
- Binary Search
- endianness
- dont-you-love-banners
- Permissions
Lets Warm Up
If I told you a word started with 0x70 in hexadecimal, what would it start with in ASCII?という言葉だけが渡されている。
0x70から始まるASCIIは何かということかな?0x70はpである。picoCTF{p}として終了。
Lets Warm Up
What is 0x3D (base 16) in decimal (base 10)?とうことでweb上のbase16とbase10を変換するツールを利用。終了。
利用ツール:Convert Base-16 to Base-10
2Warm
Can you convert the number 42 (base 10) to binary (base 2)?前の問題と同じな予感。 ツール利用して終了。
what's a net cat?
Using netcat (nc) is going to be pretty important. Can you connect to jupiter.challenges.picoctf.org at port 25103 to get the flag?という言葉が与えられている。
知識
netcat
netcatについてIPアドレスが指定されていないがどう利用していくのだろうか? 指定されているjupiter.challenges.picoctf.orgについて少し見ていく。
知識
.orgドメイン
.orgについて調べてみるとドメイン入力でncしているものもあったのでnc jupiter.challenges.picoctf.org 25103
を実行。flagゲット。
strings it
Can you find the flag in file without running it?ということで、ファイルが与えられているので、stringsコマンドをたたく。あれ。思ってたのと違う。そこまで簡単じゃないようだ。file
、strings
コマンドを行ってみる。
man pageを見ろってことかな?見てみたけど、man pageって仕様書のようなものなのでヒントにならなかった。
なんとなく、出力の中にflagがあるのだと思いstrings strings | grep "picoCTF"
を実行。flagゲット。
Bases
What does this bDNhcm5fdGgzX3IwcDM1 mean? I think it has something to do with bases. ベース64らへんでエンコードされてそう。ツール(https://www.en-pc.jp/tech/base64.php#result)でデコード。 l3arn_th3_r0p35 なんか思ってたんとちゃうけど、flagの{}内に入れて実行flagだった。
First Grep
Can you find the flag in file? This would be really tedious to look through manually, something tells me there is a better way.ということで毎度ファイルを渡された。
初手はfile
,strings
コマンド
テキストファイルでlineが多いという感じかな。この中から文字列を見つけるようだ。grep
ですね。終了。
Description
Run the Python script code.py in the same directory as codebook.txt.実行するだけ。
convertme.py
Run the Python script and convert the given number from decimal to binary to get the flag. 10進数を2進数に変換するようだ。とりま、実行。 ということでこれに答えて、あっていたらflagゲット。
fixme1.py
Fix the syntax error in this Python script to print the flag. なにかしらのエラーを修正する問題かな?実行してみましょう。 予期しないインデントがあるようだ。それを消したら終了。
fixme2.py
Fix the syntax error in the Python script to print the flag. 前問と同じようなことかな。トリマ実行。 同値の表し方が違っているようだ。直したら終了。
Glitch Cat
Our flag printing service has started glitching!
glitchingを知らない。一時的な障害の意味があるようだ。つまり、フラグを出してくれるサーバが故障したということかな?とりま、ncしてみましょう。nc saturn.picoctf.net 55826
つまり、chr(0xなんちゃら)を変換すればよさそうだ。つまり、ASCIIコード表に照らし合わせればよいのかな?
プログラムでも変換できるかも。google colabで実行したら予想通り変換してくれた。終了。
HashingJobApp
If you want to hash with the best, beat this test!ということで実行。
ということで、md5ハッシュ値を出力させに行く。
複数回問われるが、全問あっているとflagゲット。
PW Crack 1
Can you crack the password to get the flag? Download the password checker here and you'll need the encrypted flag in the same directory too. ということで、暗号化されたファイルとそれを解読するツール(python)が渡されている。
└─# python3 level1.py
Please enter correct password for flag: hugahuga
That password is incorrect
どうやらパスが正しくないと駄目なようだ。 level1.pyのコード自体を見てみる。そのとき、if文の条件にそのままパスが書かれている。 それを打ってみる。flagゲット。
PW Crack 2
前問題と同様な問題。 今回はif文の条件にそのまま書かれていない。 chr(0x64) + chr(0x65) + chr(0x37) + chr(0x36)と書いてある。 これをASCII文字コードを用いて文字列に直せばよいのかな。
出てきた。終了。
PW Crack 3
Can you crack the password to get the flag? Download the password checker here and you'll need the encrypted flag and the hash in the same directory too. There are 7 potential passwords with 1 being correct. You can find these by examining the password checker script.
今回はパスをハッシュ化して認証を行っているようだ。これでハッシュ値をべた書きでもパスはばれないかも。 ただ今回は7つのパス候補が渡されているので、それを総当たりしたらflagゲット。
PW Crack 4
前問題と似ているが異なるのはパス候補が100個あるということ。 プログラム的に回すのがいいのか。抜け道があるのか。
と思いましたが、pythonのコードを書き換えて(for文使う)総当たり攻撃でやりました。 フラグゲット。
[2023/11/23]
PW Crack 5
前問題と似ているが異なるのはパスがdictionary.txtというファイルで渡されていること。 プログラム的に回すのがいいと思った。ファイルを一行ずつ読み込んで入力するコードを回した。
つまり、pythonのコードを書き換えて(for文使う)総当たり攻撃でやりました。 フラグゲット。
runme.py
実行してもいいのだろうけど、ハードコードされていたので打ってみた。 終了。
Description
スクリプトを渡された。
└─# python3 serpentine.py Y .-^-. / \ .- ~ ~ -. () () / _ _ `. _ _ _ \_ _/ / / \ \ . ~ _ _ ~ . | | / / \ \ .' .~ ~-. `. | | / / ) ) / / `.`. \ \_ _/ / / / / / `' \_ _ _.' / / ( ( / / \ \ / / \ \ / / ) ) ( ( / / `. `. .' / `. ~ - - - - ~ .' ~ . _ _ _ _ . ~ Welcome to the serpentine encourager! a) Print encouragement b) Print flag c) Quit What would you like to do? (a/b/c)
実行すると以上のような結果が出る
つまり、bを選ぶとflagゲットですね。
Oops! I must have misplaced the print_flag function! Check my source code!
ただbを選んでもダメみたい。コードを見るとflagを表示する関数をbの実行部分に書かれていないことが分かった、ので、自分でコードを書くとflagゲット。 終了
First Find
Unzip this archive and find the file named 'uber-secret.txt' ということで、unzipしてから、該当ファイルを探すということらしい。
└─# unzip files.zip
をするとunzipしたときのフォルダ構造が表示されているので、そこから該当ファイルを見つけるだけ。
ファイルパスを表示するコマンドは
└─# find -name uber-secret.txt
とやると探したファイルパスが表示される。 終了
Big Zip
Unzip this archive and find the flag. ということで、unzipして探していく。
思っている以上に多い。 よって、ファイル内のpico{}をもとにファイルパスを見つけていこうと思う。 【find・grep】特定の文字列を含むファイルのリストを取得する方法。 を参考に見つけていこうと思う。
└─# grep picoCTF -rl big-zip-files
を実行すると一つのファイルが見つかる。 これによってそのファイルをcatして終了。
repetitions
Can you make sense of this file? Download the file here.
よくわからんファイルにはまずfileコマンド。
└─# file enc_flag enc_flag: ASCII text
テキストファイルらしい。
次はstringsコマンド。
└─# strings enc_flag VmpGU1EyRXlUWGxTYmxKVVYwZFNWbGxyV21GV1JteDBUbFpPYWxKdFVsaFpWVlUxWVZaS1ZWWnVh RmRXZWtab1dWWmtSMk5yTlZWWApiVVpUVm10d1VWZFdVa2RpYlZaWFZtNVdVZ3BpU0VKeldWUkNk MlZXVlhoWGJYQk9VbFJXU0ZkcVRuTldaM0JZVWpGS2VWWkdaSGRXCk1sWnpWV3hhVm1KRk5XOVVW VkpEVGxaYVdFMVhSbFZrTTBKVVZXMTRWMDVHV2toalJYUlhDazFyV25sVVZXaHpWakpHZEdWRlZs aGkKYlRrelZERldUMkpzUWxWTlJYTkxDZz09Cg==
と出てきた。これ、進〇ゼ〇でやったやつ!!と言わんばかりに最後に==とあるので、 Base64でエンコードされていると予想。cyberchefでfrom Base64を行う。 出てきた結果も==で終わっている。問題の名前がrepetitionsということでfrom Base64を繰り返していくのだと推測。 何回か重ねていくとflagゲット。
考察
ここまでできるものをやってきたがここからちょっと苦戦しつつある。
頑張っていこうと思う。
ASCII Numbers
Convert the following string of ASCII numbers into a readable string: 0x70 0x69 0x63 0x6f 0x43 0x54 0x46 0x7b 0x34 0x35 0x63 0x31 0x31 0x5f 0x6e 0x30 0x5f 0x71 0x75 0x33 0x35 0x37 0x31 0x30 0x6e 0x35 0x5f 0x31 0x6c 0x6c 0x5f 0x74 0x33 0x31 0x31 0x5f 0x79 0x33 0x5f 0x6e 0x30 0x5f 0x6c 0x31 0x33 0x35 0x5f 0x34 0x34 0x35 0x64 0x34 0x31 0x38 0x30 0x7dということで、16進数を文字列に直すようです。
pythonで変換した0xを接頭語にする16進数を数値に直すときはint(数値,0)とするようです。
string = "0x70 0x69 0x63 0x6f 0x43 0x54 0x46 0x7b 0x34 0x35 0x63 0x31 0x31 0x5f 0x6e 0x30 0x5f 0x71 0x75 0x33 0x35 0x37 0x31 0x30 0x6e 0x35 0x5f 0x31 0x6c 0x6c 0x5f 0x74 0x33 0x31 0x31 0x5f 0x79 0x33 0x5f 0x6e 0x30 0x5f 0x6c 0x31 0x33 0x35 0x5f 0x34 0x34 0x35 0x64 0x34 0x31 0x38 0x30 0x7d" lis = string.split(" ") ans = "" for number in lis: char = chr(int(number,0)) ans= ans + char
これで終了。
[2024/01/18]
money-ware
Flag format: picoCTF{Malwarename} The first letter of the malware name should be capitalized and the rest lowercase. Your friend just got hacked and has been asked to pay some bitcoins to 1Mz7153HMuxXTuR2R1t78mGSdzaAtNbBWX. He doesn’t seem to understand what is going on and asks you for advice. Can you identify what malware he’s being a victim of?
ということで、何かしらのマルウェアを特定する問題のようだ。ハッシュが渡されているのでvirustotalに入れてみたけど該当なし?原因はわからないけど無理ならば、googleで検索。終了。
plumbing
Sometimes you need to handle process data outside of a file. Can you find a way to keep the output from this program and search for the flag? Connect to jupiter.challenges.picoctf.org 14291.
ということで、よくわからぬのでjupiter.challenges.picoctf.org 1429にアクセスする。
nc jupiter.challenges.picoctf.org 1429
でアクセスすると大量の文字が出力された。
この中からflagを見つける問題のようだ。
文字列検索といったらgrep
を用いると考えた。
nc jupiter.challenges.picoctf.org 14291 | grep "picoCTF"
とコマンドを打ち込んで終了
Based
To get truly 1337, you must understand different data encodings, such as hexadecimal or binary. Can you get the flag from this program to prove you are on the way to becoming 1337? Connect with nc jupiter.challenges.picoctf.org 15130.
└─# nc jupiter.challenges.picoctf.org 15130 Let us see how data is stored test Please give the 01110100 01100101 01110011 01110100 as a word. ... you have 45 seconds..... Input: 01110100 01100101 01110011 01110100 WRONG!
となった。
[2024/01/19]
[2024/01/22]
chrono
How to automate tasks to run at intervals on linux servers?
タスクの自動化を行うように設定するようだ。全く知らない。
調べてみると「cron」というコマンドでタスクスケジュールを管理できるようだ。
知識(cron)
cron
(Linux - Job Scheduling) を参考にした。crontabというファイルを編集することで管理できる。crontabファイルを確認するとflagあり。終了。
useless
There's an interesting script in the user's home directory The work computer is running SSH. We've been given a script which performs some basic calculations, explore the script and find a flag.
picoplayer@challenge:~$ cat useless #!/bin/bash # Basic mathematical operations via command-line arguments if [ $# != 3 ] then echo "Read the code first" else if [[ "$1" == "add" ]] then sum=$(( $2 + $3 )) echo "The Sum is: $sum" elif [[ "$1" == "sub" ]] then sub=$(( $2 - $3 )) echo "The Substract is: $sub" elif [[ "$1" == "div" ]] then div=$(( $2 / $3 )) echo "The quotient is: $div" elif [[ "$1" == "mul" ]] then mul=$(( $2 * $3 )) echo "The product is: $mul" else echo "Read the manual" fi fi
ということで、./useless add 1 2 のようなコマンドを入力するとそれに応じた四則演算を返してくれるようだ。
どうやってflagを回収するのだろうか。
考えてみたがわからず、WriteUp見る(picoCTF 2023 100-points Write up)。「echo "Read the manual"」に引っかかったようだ。確かに最初のechoでcodeを読めなのに対して、manualを読めはおかしさを覚えてもよい。man
コマンドでマニュアルは開けれる。
知識(manコマンド)
manコマンド
(知っておくとちょっと便利!マニュアルを表示する man コマンド)開いたら下にflagあり。終了。
Based
To get truly 1337, you must understand different data encodings, such as hexadecimal or binary. Can you get the flag from this program to prove you are on the way to becoming 1337?ということらしい。 1337とはleetというものがあるらしい。つまり、置換やエンコードのようなものだと思う。
知識(1337)
1337
(Leet)まずは接続してみる。
└─# nc jupiter.challenges.picoctf.org 15130 Let us see how data is stored container Please give the 01100011 01101111 01101110 01110100 01100001 01101001 01101110 01100101 01110010 as a word. ... you have 45 seconds..... Input:
と出てくる。Inputにcontainerとすると次に進む。
container Please give me the 163 154 165 144 147 145 as a word. Input:
ここでcontainerを入力するとWRONGと出てくる。初めはわからなかったが、CyberChefを使うと簡単に攻略できる。magicという機能で初めの二進数はbinary(二進数)でASCII文字がエンコードされている。次の165のような大きなものはOctal(8進数)でASCII文字がエンコードされていた。それを突破すると
Input: sludge Please give me the 6c696d65 as a word. Input:
と出てくる。これはHex(16進数)でエンコードされているようだ。つまり、エンコードされているものをデコードするようにcyberchefを使えば、flagゲット。
[2024/01/30]
flag_shop
There's a flag shop selling stuff, can you buy a flag? Source. Connect with nc jupiter.challenges.picoctf.org 44566. ということで、flagを購入するプログラムが渡された。
見たい人はクリック
#include <stdio.h> #include <stdlib.h> int main() { setbuf(stdout, NULL); int con; con = 0; int account_balance = 1100; while(con == 0){ printf("Welcome to the flag exchange\n"); printf("We sell flags\n"); printf("\n1. Check Account Balance\n"); printf("\n2. Buy Flags\n"); printf("\n3. Exit\n"); int menu; printf("\n Enter a menu selection\n"); fflush(stdin); scanf("%d", &menu);
残高は$1100あることが分かる。 1が残高照会、2が購入、3が退出。
if(menu == 1){ printf("\n\n\n Balance: %d \n\n\n", account_balance); } else if(menu == 2){ printf("Currently for sale\n"); printf("1. Defintely not the flag Flag\n"); printf("2. 1337 Flag\n"); int auction_choice; fflush(stdin); scanf("%d", &auction_choice);
1だとそのまま残高を表示。 2だと2つのアクションが選べる。
if(auction_choice == 1){ printf("These knockoff Flags cost 900 each, enter desired quantity\n"); int number_flags = 0; fflush(stdin); scanf("%d", &number_flags); if(number_flags > 0){ int total_cost = 0; total_cost = 900*number_flags; printf("\nThe final cost is: %d\n", total_cost); if(total_cost <= account_balance){ account_balance = account_balance - total_cost; printf("\nYour current balance after transaction: %d\n\n", account_balance); } else{ printf("Not enough funds to complete purchase\n"); } } }
1つ目のアクションが900のコストを払って、flagを変えるようだ。でも表示される?
else if(auction_choice == 2){ printf("1337 flags cost 100000 dollars, and we only have 1 in stock\n"); printf("Enter 1 to buy one"); int bid = 0; fflush(stdin); scanf("%d", &bid); if(bid == 1){ if(account_balance > 100000){ FILE *f = fopen("flag.txt", "r"); if(f == NULL){ printf("flag not found: please run this on the server\n"); exit(0); } char buf[64]; fgets(buf, 63, f); printf("YOUR FLAG IS: %s\n", buf); } else{ printf("\nNot enough funds for transaction\n\n\n"); }} } } else{ con = 1; } } return 0; }
2つ目のアクションでは100000のコストで購入できるようだ。ここでflagが表示されるようだ。
ざっとコードを確認した。初手では持っている残高が1100でflagを購入することができない。増やすことを考えた。ここで、残高が動くのはメニュー1のDefintely not the flag Flagである。しかし、この中では残高を減らす作業しかない。そこで思ったのが、-*-=+
というようにマイナスをプラスにしようと考えた。しかし、intがせいであるか否かをifでチェックしているのでマイナスを扱うことができない。、、そこで思いついたのがint型のオーバーフローである。
知識(オーバーフロー(int))
オーバーフロー(int)
(C言語のint型で最大値を超えるとどうなるのか解説)を参考にした。つまり、int型では最大2147483647までしか表現できない。それ以上入力すると-で表現されてしまうということ。つまり、2147483648を入力すればできるのではないかと考えた。結論できない。確かに2147483648はintにとってはすでにマイナス値であるのではじかれてしまう。そこで2147483647で行ってみた。
These knockoff Flags cost 900 each, enter desired quantity 2147483647 The final cost is: -900 Your current balance after transaction: 2000 Welcome to the flag exchange We sell flags
お!増えた。
int total_cost = 0; total_cost = 900*number_flags;
ここのコードでオーバーフローを起こしているようだ。納得。
These knockoff Flags cost 900 each, enter desired quantity 2147483646 The final cost is: -1800 Your current balance after transaction: 2900
2147483647=-1、2147483646=-2といった感じ。つまり、2147483647から120くらい引いた2147483527を入力すればおK。終了。
Super SSH
Using a Secure Shell (SSH) is going to be pretty important.
Can you ssh as ctf-player to titan.picoctf.net at port 63095 to get the flag?
You'll also need the password f3b61b38. If asked, accept the fingerprint with yes.
If your device doesn't have a shell, you can use: https://webshell.picoctf.org
If you're not sure what a shell is, check out our Primer: https://primer.picoctf.com/#_the_shell
ということである。sshの構文をおさらい。(sshコマンド)を参考にした。ssh [option] (user@)host [command]
とするようだ。ユーザー名、ホスト名、ポート番号、パスワードを確認して、正しく打てばflagゲット。
Commitment Issues
I accidentally wrote the flag down. Good thing I deleted it!
You download the challenge files here:
challenge.zip
ということでzip解凍すると、message.txt
というファイルと.git
というディレクトリが渡された。gitによるバージョン管理をしているので、そこから履歴を見つける問題かな?
知識(git)
commitしていった内容を確認できればよいと考えた。調べるとできるようだ(commitしたファイルや変更箇所は"git show"で確認できる)。.gitがあるディレクトリで'git show'を行うと変更点とともにflagが手に入る。終了。
Time Machine
What was I last working on? I remember writing a note to help me remember...
さっきと同じようにgit show
で見えた。さっきの問題との違いは何だったのか、、
Blame Game
Someone's commits seems to be preventing the program from working. Who is it?
今回はcommitでditを邪魔した人を見てけらいいと思い、考えたのはcommitした人の名前が分かればいいと思った。ので(GitのCommitユーザを修正する方法)を参考に表示してみた。
└─# git log --pretty=full commit 83afd3ebd7899251a19d290df92fd1bfc9998adb (HEAD -> master) Author: picoCTF <ops@picoctf.com> Commit: picoCTF <ops@picoctf.com> important business work commit 760de15c177831fee8b2965e57d1461423ad5ed0 Author: picoCTF <ops@picoctf.com> Commit: picoCTF <ops@picoctf.com> important business work commit 7fce0961829b0262ed95799aa430822cac6c6a0b Author: picoCTF <ops@picoctf.com> Commit: picoCTF <ops@picoctf.com> important business work commit daa2679f1c00642ef399fadcd52cf8f9c16020f7 Author: picoCTF <ops@picoctf.com> Commit: picoCTF <ops@picoctf.com> important business work commit 7b07ab4c87df7198ce8c0ece9f67e8b7f1ddb9f8 Author: picoCTF <ops@picoctf.com> Commit: picoCTF <ops@picoctf.com> important business work
さっきとは違いそう。git logでやってもいい感じにならない。 そこで、(Gitでコミットメッセージや変更内容を検索して確認する方法)からmessage.pyに残っている文字列ができた時を見てみる。
└─# git log -S "Hello" commit c9e851509190f5887e91339ee18087e3e77ebfda Author: picoCTF <ops@picoctf.com> Date: Tue Mar 12 00:07:01 2024 +0000 create top secret project
さっきまでとは違う出力。でも、この時にファイルができたような感じだ。詳しく見てみる。
└─# git show c9e851509190f5887e91339ee18087e3e77ebfda commit c9e851509190f5887e91339ee18087e3e77ebfda Author: picoCTF <ops@picoctf.com> Date: Tue Mar 12 00:07:01 2024 +0000 create top secret project diff --git a/message.py b/message.py new file mode 100644 index 0000000..7df869a --- /dev/null +++ b/message.py @@ -0,0 +1 @@ +print("Hello, World!")
ビンゴ。この日に今のpythonが作成され始めているといえるでは、だれが、これを修正したかを見ていく。でも、このcommitIDの直近とかを表示するのがなさそう。(git logを使ってコミット履歴を閲覧する方法【初心者向け】)から特定のファイルに対するcommitに絞ることができるようだ。git log message.py
としたらflagゲット。
Collaborative Development
My team has been working very hard on new features for our flag printing program! I wonder how they'll work together?
となわけで、flag.pyと.gitを渡された。まずはflag.pyを見てみる。
└─# cat flag.py print("Printing the flag...")
特に変わったことはない。次にgit log
とgit show
を見てみる。
└─# git log commit eb19d0e3c28278752f0735c4451b885136a24105 (HEAD -> main) Author: picoCTF <ops@picoctf.com> Date: Tue Mar 12 00:07:49 2024 +0000 init flag printer
└─# git show commit eb19d0e3c28278752f0735c4451b885136a24105 (HEAD -> main) Author: picoCTF <ops@picoctf.com> Date: Tue Mar 12 00:07:49 2024 +0000 init flag printer diff --git a/flag.py b/flag.py new file mode 100644 index 0000000..77d6cec --- /dev/null +++ b/flag.py @@ -0,0 +1 @@ +print("Printing the flag...")
となる。ここも普通。hints見てみた。「git branch -a will let you see available branches」だそうだ。そういう機能もありましたね。
└─# git branch -a
feature/part-1
feature/part-2
feature/part-3
* main
(git branch コマンド)からリモートブランチを含んだブランチの一覧を見たようだ。 (git checkout解説)、(5. 並行で作業する)からbranchの機能を理解した。つまり、今は4つの分岐点(分岐してないかも)があるということ。今自身がいるのはmainというところにいる。つまり、checkou
└─# git checkout feature/part-1 Switched to branch 'feature/part-1
おー、そういうことね。branchに移動できた。 ちなみに1の方でもshowしてみる。
└─# git show commit 0cd57e0aedc31a1a92e0b79235c818de437cde8e (HEAD -> feature/part-1) Author: picoCTF <ops@picoctf.com> Date: Tue Mar 12 00:07:49 2024 +0000 add part 1 diff --git a/flag.py b/flag.py index 77d6cec..6e17fb3 100644 --- a/flag.py +++ b/flag.py @@ -1 +1,2 @@ print("Printing the flag...") +print("picoCTF{t3@mw0rk_", end='') \ No newline at end of file
flagの一部分が出てきた。つまり、異なるbranchで編集しているので引っ付ければよいということになる。考えられるのは1.異なるbranchに移動してshowして差分を自身でくっつける。2.margeみたいなのをすると勝手にくっついたりするのか?
└─# git show commit 7064732e2fd39d2247bd6ba2ccc4cf9576974d38 (HEAD -> feature/part-2) Author: picoCTF <ops@picoctf.com> Date: Tue Mar 12 00:07:49 2024 +0000 add part 2 diff --git a/flag.py b/flag.py index 77d6cec..7ab4e25 100644 --- a/flag.py +++ b/flag.py @@ -1 +1,3 @@ print("Printing the flag...") + +print("m@k3s_th3_dr3@m_", end='') \ No newline at end of file
└─# git show commit 8395824cc0ce486d1be9ab874bfedb2cec2ea398 (HEAD -> feature/part-3) Author: picoCTF <ops@picoctf.com> Date: Tue Mar 12 00:07:49 2024 +0000 add part 3 diff --git a/flag.py b/flag.py index 77d6cec..4672a5c 100644 --- a/flag.py +++ b/flag.py @@ -1 +1,3 @@ print("Printing the flag...") + +print("w0rk_2c91ca76}")
やはり、合体させればいいっぽい。hintsその2「How can file 'diffs' be brought to the main branch? Don't forget to !git config」つまり、差分だけをmainに持ってくることができるようだ。それがmargeなのかな。やってみる。
└─# git merge feature/part-1 Updating eb19d0e..0cd57e0 Fast-forward flag.py | 1 + 1 file changed, 1 insertion(+)
できたっぽい。
└─# cat flag.py print("Printing the flag...") print("picoCTF{t3@mw0rk_", end='')
おー!変更されている。
続いて、2のbranchもやってみる。
└─# git merge feature/part-2 Committer identity unknown *** Please tell me who you are. Run git config --global user.email "you@example.com" git config --global user.name "Your Name" to set your account's default identity. Omit --global to set the identity only in this repository. fatal: unable to auto-detect email address (got 'root@d6a342826ddd.(none)')
あら、権限がないみたいな感じ?いや、ただただ名前とメールアドレスがないだけ。適当に設定した。
└─# git merge feature/part-2 Auto-merging flag.py CONFLICT (content): Merge conflict in flag.py Automatic merge failed; fix conflicts and then commit the result.
違うエラーが出た。(6. マージでの衝突を解決する)を参考にする。
└─# cat flag.py print("Printing the flag...") <<<<<<< HEAD print("picoCTF{t3@mw0rk_", end='') ======= print("m@k3s_th3_dr3@m_", end='') >>>>>>> feature/part-2
競合しているっぽい。
└─# vi flag.py └─# git add flag.py └─# git commit -m "2ブランチをマージ" [main 3d173b4] 2ブランチをマージ
└─# git show commit 3d173b420ffaca852331ee8fe04682965c459823 (HEAD -> main) Merge: 0cd57e0 7064732 Author: pico <pico@gmail.com> Date: Fri Mar 15 11:25:29 2024 +0000 2ブランチをマージ diff --cc flag.py index 6e17fb3,7ab4e25..b8b48f5 --- a/flag.py +++ b/flag.py @@@ -1,2 -1,3 +1,2 @@@ print("Printing the flag...") - print("picoCTF{t3@mw0rk_", end='') - -print("m@k3s_th3_dr3@m_", end='') ++print("picoCTF{t3@mw0rk_m@k3s_th3_dr3@m_", end='')
としてcommit完了。この作業をfeature/part-3でも行えばflagゲット。
binhexa
How well can you perfom basic binary operations? Start searching for the flag here nc titan.picoctf.net 56491
└─# nc titan.picoctf.net 56491 Welcome to the Binary Challenge!" Your task is to perform the unique operations in the given order and find the final result in hexadecimal that yields the flag. Binary Number 1: 01101001 Binary Number 2: 00100011 Question 1/6: Operation 1: '*' Perform the operation on Binary Number 1&2. Enter the binary result:
ncコマンドしてみると以上のような出力が得られる。見た感じnumber1と2をOperationで与えられた演算をしていく問題のようだ。pythonで
BN1= int("01101001",2) BN2= int("00100011",2) bin(BN2+BN1)[2:]
として演算子を指定されたものに変えていけばflag出る。
Binary Search
Want to play a game? As you use more of the shell, you might be interested in how they work! Binary search is a classic algorithm used to quickly find an item in a sorted list. Can you find the flag? You'll have 1000 possibilities and only 10 guesses. Cyber security often has a huge amount of data to look through - from logs, vulnerability reports, and forensics. Practicing the fundamentals manually might help you in the future when you have to write your own tools! You can download the challenge files here: challenge.zip ssh -p 57597 ctf-player@atlas.picoctf.net Using the password f3b61b38. Accept the fingerprint with yes, and ls once connected to begin. Remember, in a shell, passwords are hidden!
あまりわからない。与えられたファイルは以下のようなbashが書かれている。
└─# cat guessing_game.sh #!/bin/bash # Generate a random number between 1 and 1000 target=$(( (RANDOM % 1000) + 1 )) echo "Welcome to the Binary Search Game!" echo "I'm thinking of a number between 1 and 1000." # Trap signals to prevent exiting trap 'echo "Exiting is not allowed."' INT trap '' SIGQUIT trap '' SIGTSTP # Limit the player to 10 guesses MAX_GUESSES=10 guess_count=0 while (( guess_count < MAX_GUESSES )); do read -p "Enter your guess: " guess if ! [[ "$guess" =~ ^[0-9]+$ ]]; then echo "Please enter a valid number." continue fi (( guess_count++ )) if (( guess < target )); then echo "Higher! Try again." elif (( guess > target )); then echo "Lower! Try again." else echo "Congratulations! You guessed the correct number: $target" # Retrieve the flag from the metadata file flag=$(cat /challenge/metadata.json | jq -r '.flag') echo "Here's your flag: $flag" exit 0 # Exit with success code fi done # Player has exceeded maximum guesses echo "Sorry, you've exceeded the maximum number of guesses." exit 1 # Exit with error code to close the connection
つまり、ランダムに生成された数値を10回の挑戦で当てるゲームということのようだ。hintとしてhighかlowかを教えてくれるようだ。1000の半分500からスタートしてhighかlowかでその範囲を狭めていけばいい。理論的に考えると210=1024ということで,半分ずつ狭めていけば、1000の内の1つの一意の数に定めることは可能と考えられる。
endianness
Know of little and big endian?
ということで、いちおうもう一度調べる。
知識(「ビッグエンディアン」と「リトルエンディアン」の違い)
「ビッグエンディアン」と「リトルエンディアン」の違い
(「ビッグエンディアン」と「リトルエンディアン」の違い)を参考にした。数値の並べる順番左読みか右読みかみたいな話かな?与えられた、ランダム文字列を与えられるようだ。それをリトルエンディアンにしたものを答えさせる。それをビックエンディアンでも答える。両方解けたらflagゲットといった感じ。コードを実行すれば答えが出てくるのではないか?自力で解かなくても良さそう。
与えられたコードのgenerate_random_word()で定義されるwordを与えられた文字列にして、実行すれば同じ答えが出力される。終了。
dont-you-love-banners
Can you abuse the banner?
The server has been leaking some crucial information on tethys.picoctf.net 55702. Use the leaked information to get to the server.
To connect to the running application use nc tethys.picoctf.net 62012. From the above information abuse the machine and find the flag in the /root directory.
だそうです、ncしてみる
└─# nc tethys.picoctf.net 62012
*************************************
**************WELCOME****************
*************************************
what is the password?
パスワードを求められる。何も知らない。 何位頭の情報を流している55702にアクセス。
└─# nc tethys.picoctf.net 55702 SSH-2.0-OpenSSH_7.6p1 My_Passw@rd_@1234
sshと何かしらのパスワードを教えてくれた。このパスが先に求められたパスではなさそう。
知識(ncコマンド)
ncコマンド
(ncコマンドでサーバーと通信させよう!)を参考にした。「ncコマンドは、netcatを省略したもので、TCPまたはUDPの通信を使ってコマンドラインからデータを送受信するコマンドです。」だそうです。つまり、pico側で立っているアプリに接続してプログラムと送受信している感じ仮名。パスではないと思っていたが、My_Passw@rd_@1234
がパスワードだった。
└─# nc tethys.picoctf.net 62012 ************************************* **************WELCOME**************** ************************************* what is the password? My_Passw@rd_@1234 What is the top cyber security conference in the world?
という質問が来た。調べてみてもいろいろあってわかりにくい。しかし、しらべて入力したらDEF CONで正解だった。
the first hacker ever was known for phreaking(making free phone calls), who was it?
次の質問はこれ。調べて入力したらあたってplayer@challengeにログインできた。
player@challenge:~$ ls ls banner text
player@challenge:~$ cat text cat text keep digging player@challenge:~$ cat banner cat banner ************************************* **************WELCOME**************** *************************************
となっている。今回の問題的にもrootにアクセスするのが目的。行ってみる。
player@challenge:/root$ ls ls flag.txt script.py player@challenge:/root$ cat flag.txt cat flag.txt cat: flag.txt: Permission denied
flagにはアクセスできないようだ。
player@challenge:/root$ ls -al ls -al total 16 drwxr-xr-x 1 root root 6 Mar 12 00:18 . drwxr-xr-x 1 root root 29 Mar 16 06:34 .. -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
rootにしか権限がない。
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
もう一つにはこんな感じのプログラムが動いていたようだ。さて、どうすればrootに入れるか。ポイントはもう一つのポートにアクセスしたときのsshである。
sshd_configを見てみると#PermitRootLogin prohibit-password
となっている。これはログインできないのではないだろうか?sshが何かしらのキーになっているようだが、わからん。
hintsにはsymlinksを知っているかと出てきた。調べてみる。
知識(symlinks)
symlinks
(Linux シンボリックリンクのチュートリアル: シンボリックリンクの作成・解除方法)を参考にした。ショートカットキーに似ているようだ。ふと思ったのは、/home/player/bannerを読み込んで表示する。このbannerがsymlinksで/root/flag.txtに紐づけされていたら表示されるのだろうか?やってみる。 この方法でできた。ハードリンクはできないがソフトリンクは権限がなくても作れるようだ。
player@challenge:~$ ls ls banner text player@challenge:~$ mv banner banner2 mv banner banner2 player@challenge:~$ ls ls banner2 text player@challenge:~$ ln /root/flag.txt banner ln /root/flag.txt banner ln: failed to create hard link 'banner' => '/root/flag.txt': Operation not permitted player@challenge:~$ ln -s /root/flag.txt banner ln -s /root/flag.txt banner player@challenge:~$ ls ls banner banner2 text
ということで、bannerが作れたのでアクセスするとflagが表示された。終了。
これより下は未解決
Permissions
Can you read files in the root file?ということで、ルート権限のファイルを読む方法を見つけるようだ。
homeディレクトリにはそれらしきものは見当たらない。一番上まで行ってみるが怪しいものはない。
WriteUp見るーーーーーーーーーーーーーーーーーーーーーーー
(picoCTF 2023 Writeup)
cronの時の配置と同じでchallengeというディレクトリの怪しさに気づかなかった。確かにここは怪しい。
picoplayer@challenge:/$ cd challenge/
-bash: cd: challenge/: Permission denied
はにゃ?WriteUpではここはすんなり入っていたのに。ここが問題なのだろうか。root権限がないとか入れないのだろうか。
picoplayer@challenge:/$ ls -al total 0 drwxr-xr-x 1 root root 51 Jan 22 03:56 . drwxr-xr-x 1 root root 51 Jan 22 03:56 .. -rwxr-xr-x 1 root root 0 Jan 22 03:56 .dockerenv lrwxrwxrwx 1 root root 7 Mar 8 2023 bin -> usr/bin drwxr-xr-x 2 root root 6 Apr 15 2020 boot d--------- 1 root root 27 Aug 4 21:32 challenge drwxr-xr-x 5 root root 340 Jan 22 03:56 dev drwxr-xr-x 1 root root 66 Jan 22 03:56 etc drwxr-xr-x 1 root root 24 Aug 4 21:32 home lrwxrwxrwx 1 root root 7 Mar 8 2023 lib -> usr/lib lrwxrwxrwx 1 root root 9 Mar 8 2023 lib32 -> usr/lib32 lrwxrwxrwx 1 root root 9 Mar 8 2023 lib64 -> usr/lib64 lrwxrwxrwx 1 root root 10 Mar 8 2023 libx32 -> usr/libx32 drwxr-xr-x 2 root root 6 Mar 8 2023 media drwxr-xr-x 2 root root 6 Mar 8 2023 mnt drwxr-xr-x 2 root root 6 Mar 8 2023 opt dr-xr-xr-x 2528 nobody nogroup 0 Jan 22 03:56 proc drwx------ 1 root root 23 Aug 4 21:32 root drwxr-xr-x 1 root root 54 Jan 22 03:57 run lrwxrwxrwx 1 root root 8 Mar 8 2023 sbin -> usr/sbin drwxr-xr-x 2 root root 6 Mar 8 2023 srv dr-xr-xr-x 13 nobody nogroup 0 Jan 22 03:56 sys drwxrwxrwt 1 root root 6 Aug 4 21:32 tmp drwxr-xr-x 1 root root 18 Mar 8 2023 usr drwxr-xr-x 1 root root 17 Mar 8 2023 var
ん?でも、challengeディレクトリのpermissionだれもいじれないように思う。
わからんので誰か教えてw