pyjail wiki

ScriptCTF 2025 - Modulo

Challenge

極めて厳しい文字制限を持つ pyjail。1800チーム中20チームのみ解答。

import re
code = input()
# ホワイトリスト: 大文字 A-Z、小文字 'c' のみ、括弧、%+:*.,[]
if not re.match(r'^[A-Zc()+%:*.\[\],]+$', code):
print("Invalid!")
exit()
exec(code, {'__builtins__': {}})

制約:

  • 大文字 A-Z のみ (小文字は ‘c’ のみ)
  • 数字なし
  • 限られた記号: (), %, +, :, *, ., [], ,

Solution

%c フォーマットによる文字構築

"%c" % ASCII_CODE で任意の文字を生成:

"%c" % 97 # 'a'
"%c" % 111 # 'o'

数値の生成

数字が使えないため、別の方法で数値を生成:

# True は 1、加算で数値を作る
# ただし小文字が使えないため別のアプローチが必要

変数を使った数値構築

1つの変数に数値を蓄積:

A = (A + A) # 2倍
A = (A + A + A) # 3倍

26,578バイトのペイロード

最終的なペイロードは約26KB:

# 大量の加算で必要な ASCII コードを構築
# %c で文字に変換
# 文字を結合してコマンドを構築
# exec で実行

Technical Details

%c フォーマット

# 単一の整数を文字に変換
"%c" % 65 # 'A'
"%c" % 97 # 'a'
# 複数の変換
"%c%c%c" % (111, 115, 46) # 'os.'

数値生成の代替手段

方法
len()len("A") → 1
ord()ord("A") → 65
True + True2
[].count()0

文字制限下での構築

# 'A' から始めて数値を構築
A = len(C) # C が定義されていれば
A = A + A # 2
A = A + A # 4
# ... 繰り返し

Alternative Solutions

別解1: eval の再構築

# __builtins__ から eval を取得するチェーンを構築

別解2: Jinja SSTI ガジェット

# Object サブクラスから os にアクセス

Flag

scriptctf{...}

References