PicoCTFのらいとあっぷみたいなやつ。(General Skillsの旅)

はじめに

picoCTFに取り組んで行くときの考えていたことを書き記す。writeupというより、解いた道筋を書いていますので、最短距離を知りたい人にとっては意味わからないものかもしれません。ご了承ください。begginerのお戯れと思って暖かく見守っていただければ幸いです。一般的な技術も必要と思ったので取り組む。それでもまずは10000solves以上のものに取り組んで行こうと思う。

開閉

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コマンドをたたく。あれ。思ってたのと違う。そこまで簡単じゃないようだ。filestringsコマンドを行ってみる。 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ゲット。

考察 ここまでできるものをやってきたがここからちょっと苦戦しつつある。 頑張っていこうと思う。
[2023/12/20]

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コマンドでマニュアルは開けれる。

開いたら下に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によるバージョン管理をしているので、そこから履歴を見つける問題かな?

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 loggit 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出る。

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 (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