pyjail wiki

CSAW CTF Finals 2023 - Python Garbageman

Challenge

AST ベースのフィルタで数値リテラルが禁止されている。

import ast
code = input()
tree = ast.parse(code, mode='eval')
for node in ast.walk(tree):
if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
print("Numbers not allowed!")
exit()
result = eval(code)
print(result)

Solution

len() で数値を生成

len('') # 0
len('a') # 1
len('aa') # 2
len('aaa') # 3

chr() との組み合わせ

# 'a' = chr(97) = chr(len('a'*97))
chr(len('a'*97))

乗算による効率化

# 111 = 'o'
chr(len('a')*111) # NG: 111 は数値リテラル
# True を使用
chr(len('a')*(len('a')+len('a'))*(len('a')+len('a'))*(len('a')+len('a'))*(len('a')+len('a'))*(len('a')+len('a'))*(len('a')+len('a'))+(len('a')+len('a'))+(len('a')+len('a'))+(len('a')+len('a')))
# 複雑だが数値リテラルなし

True/False の活用

# True = 1, False = 0 (数値コンテキストで)
True + True # 2
True + True + True # 3

Technical Details

AST での数値検出

import ast
code = "123"
tree = ast.parse(code, mode='eval')
# Constant(value=123)
code = "len('aaa')"
tree = ast.parse(code, mode='eval')
# Call(func=Name(id='len'), args=[Constant(value='aaa')])
# 数値リテラルではない!

使用可能な数値生成方法

方法
len()len('aaa') → 3
True/FalseTrue + True → 2
ord()ord('a') → 97
bool()bool([]) → False (0)

Alternative Solutions

別解1: list の操作

len([[]] * ord('a'))

別解2: 文字列の長さ

len(__name__) # 環境依存

Flag

flag{...}

References

  • CSAW CTF Finals 2023 Official