HSCTF 7 writeup
6/1(月) 21:00(JST)~6/6(土) 9:00(JST)に開催されたHSCTF 7に参加にソロ参加。
約1週間の長期開催だったので、色んな問題に触れられたので楽しかった。 まだまだ難しい問題を解けるレベルではないけど、SharkyCTFと比較すると解けた問題が結構増えた感じ。
Binary Exploitation
Intro to Netcat 2: Electric Boogaloo
ncコマンドを叩くとフラグゲット。
Boredom
ソースファイルと実行ファイルが渡される。
ソースから、setup()でバッファを初期化し、main()内のgets()で入力を受け取る事がわかる。
よって、バッファオーバーフローを起こし、リターンアドレスをflag()に書き換えるとフラグが取れる。 gdbで解析すると、flag()のアドレスは0x4011d5であり、オフセットが216である事が判明。
適当な文字*216 + flag()のアドレスを入力するもフラグ取れず。
適当な文字*208 + flag()のアドレスにするとフラグゲット。
オフセットの計算間違えたかな…
スタックは以下のようになると予想。
(低)
buffer 200byte
フレームポインタ(ベースポインタ?)8byte
リターンアドレス8byte ←ココをflag()に書き換える
(高)
Forensics
Mad Libs
Steganography Onlineでdecodeするとフラグゲット。
ツールに頼らない場合、どうやるんだろうか…
Comments
Comments.zip内に1.zip~8.zipのzipファイルが圧縮されている。バイナリエディタで見るも、特に怪しいところはない。
全て解凍し、zipinfoで全てのzipのメタ情報を見る。file comment内の文字を1つずつ繋げるとフラグゲット。
Meta Mountains
exiftoolを実行すると、3分割された形でフラグが書いてある
Picture Lab: Activity 10
データとpdfファイルが与えられる。pdfを読む限り、データをPNG画像とみなし、chunkを修正すればフラグが取れそう。
ファイル名をmogodb.pngに変更し、バイナリエディタで開く。マジックナンバーを「89 50 4E 47 0D 0A 1A 0A」に変更し、IHDR, IDAT, IEND chunkをそれぞれ付け加えてpngcheckを実行すると整合性が取れ、画像が開けるようになったので開くとフラグが書いてある。
SharkyCTFでの経験が活かせた◎
Algorithms
Pythagorean Tree Fractal 1
pdfファイルをみると、Stage 50の時の長方形の数がフラグになるらしい。Stage 7の長方形の数のカウントは断念。
Stage 3を見ると、Stage 1の長方形の頂点2つから新しく長方形できており、さらに、互いに重なっていない頂点から長方形が2つ新しくできている。
おそらくStage 2は、Stage 3の赤丸で繋がれた長方形までと推測。これをもとに、以下に各Stage毎の長方形の数を示すと、
Stage 1: 1個
Stage 2: 3個
Stage 3: 7個
となるため、長方形の数が2の累乗単位で増加している事がわかる。よって、Stage 50まで計算するプログラムを書いてフラグゲット。
※ググると、ピタゴラスの木というみたい。こっちを調べたほうが早かった…
Pythagorean Tree Fractal 2
Stage 1の面積が70368744177664のとき、Stage 25の面積を答える問題。
wikipediaより、
n回目の作図操作で一辺が(√2/2)^{n}の正方形が2^{n}個付け足されるので、新しく付け足される正方形の面積の合計は常に1になる。そのため、木の面積は無限に増加するように見える。しかし、5回の反復を超えると、いくつかの正方形が重なり始めるため、面積は有限となり、6×4の長方形内に収まることになる。 とある。
面積が70368744177664の正方形が25個分になるので、70368744177664*25を計算してフラグゲット。
Reverse Engineering
AP Lab: Computer Science Principles
javaのソースを見ると、入力値inpをshift2(shift(inp))したものが「inagzgkpm)Wl&Tg&io」であればinpがフラグになるらしい。 そのため、これを逆算?するコードを書くと良さそう。 javaは未経験のため開発環境がなかったので、paizaで以下のコードを実行し、フラグゲット。
public class Main { public static void main(String[] args) { String st = "inagzgkpm)Wl&Tg&io"; String flag = shift2(shift(st)); System.out.println(flag); } public static String shift(String input) { String ret = ""; for (int i = 0; i<input.length(); i++) { ret+=(char)(input.charAt(i)+i); } return ret; } public static String shift2(String input) { String ret = ""; for (int i = 0; i<input.length(); i++) { ret+=(char)(input.charAt(i)-Integer.toString((int)input.charAt(i)).length()); } return ret; } }
AP Lab: English Language
Computer Science Principlesと同様に、「1dd3|y_3tttb5g`q]^dhn3j」をflagの形に直す。 xor()は変更せず。 transpose()の逆変換をする関数transpose2()を作成し、for文で回すとフラグゲット。
public class Main { public static void main(String[] args) { String bf = "1dd3|y_3tttb5g`q]^dhn3j"; for (int i=0; i<3; i++){ bf = xor(bf); bf = transpose2(bf); } System.out.println(bf); } public static String transpose2(String input) { int[] transpose = {11,19,7,20,16,6,9,13,4,22,21,0,8,14,15,2,17,5,1,3,18,10,12}; String ret = ""; for (int i: transpose) { ret+=input.charAt(i); } return ret; } public static String xor(String input) { int[] xor = {4,1,3,1,2,1,3,0,1,4,3,1,2,0,1,4,1,2,3,2,1,0,3}; String ret = ""; for (int i = 0; i<input.length(); i++) { ret+=(char)(input.charAt(i)^xor[i]) ; } return ret; } }
Crypto
XORed
XORの性質から、A xor B = Cのとき、A xor C = Bが成り立つ。よって、
key3 = key1 ^ 0x9a13ea39f27a12000e083a860f1bd26e4a126e68965cc48bee3fa11b
key4 = key3 ^ 0x996e59a867c171397fc8342b5f9a61d90bda51403ff6326303cb865a
key5 = key1 ^ key4 ^ 0x7b33428eb14e4b54f2f4a3acaeab1c2733e4ab6bebc68436177128eb
key2 = key3 ^ key5 ^ 557ce6335808f3b812ce31c7230ddea9fb32bbaeaf8f0d4a540b4f05
これでkeyが全て求められたので、以下でフラグを計算
flag = key1 ^ key2 ^ key3 ^ key4 ^ key5 ^ 0x306d34c5b6dda0f53c7a0f5a2ce4596cfea5ecb676169dd7d5931139
結果をそのままsubmitしても弾かれたので、Discordを確認してみると、ASCIIに変換するとの事なので、cyberchefで変換してフラグゲット
Unexpected
N=PQ、N=QR、N=PRの時に暗号文C1,C2,C3を復号する問題。
同じ素数を使いまわしてNを生成しているので、Common Factor Attackを使いP、Q、Rを求める。
その後各Nに対応する秘密鍵(d1,d2,d3)を求め、m = cd (mod n)を計算し平文M1,M2,M3を導出する。その後、asciiに変換するとフラグゲット。
※python2にてasciiに変換。
("%x"%m1).decode('hex')
【参考】 picoCTF writeup Low Entropy · GitHub
Misc
Do Stars Spin? 1
discord内で"stars"で検索し、古い順に並び替える。すると、PMPというユーザが2019/05/24にDo stars even spin?といった、本問に関係のありそうな事を発言しているのを発見。
発言内の"dostarsevenspin"でググるとredditのページが表示されるも、投稿は全て削除されており、flag{no}とだけある。
web.archive.orgで検索すると、2020/05/27にアーカイブがとられており、内容を見ると削除された投稿が表示され、フラグゲット。
※余談だが、この問題を解いている時archive.orgがダウンしていたため、以下のようなサイトをひたすら調べていた…
Blurry Eyes(Web)
CTFdの紹介ページに飛ぶ。ページ最下部にぼかされた箇所があり、そこがflagっぽい。
開発者ツールで該当箇所のコードを見ると、ランダムな文字列のspan classがあり、展開するとCSS疑似クラスである::afterが出てくるので、クリックするとflagが表示される。
Web
Inspector Gadget
開発者ツールを見るとコメント文にフラグが書いてある
Debt Simulator
ボタンを押すと、ランダムで所持金が増減するゲームが始まる。-1000ドル以下になると負けとなる。
Burp Suiteでボタンを押した時の通信を見ると、 function=getPay
function=getCost
のいずれかの値を送っている事がわかる。
getPayだと所持金が増えるみたいなので全てfunction=getPayでリクエストを送るも、結果は変わらず。
開発者ツールでデバッグ実行してみる。
App.jsの26行目にonClick()の挙動が書かれているので、ここにブレークポイントを置く。27行目をステップ実行すると、35行目に飛ぶ。URLが書かれているので、アクセスしてみると、
{"functions":["getPay","getCost","getgetgetgetgetgetgetgetgetFlag"]}
と書かれている。 よって、先ほどのBurp Suiteで
function=getgetgetgetgetgetgetgetgetFlag
を送るとフラグが表示される。
所持金を増やせば勝ちだと思っていたのでかなり苦戦した…
Very Safe Login
ソースを見るとusernameとpasswordが書かれているので入力してフラグゲット。