2 回入れ替えればもとに戻る… よね?
import os
flag = os.environ.get("FLAG", "Alpaca{*** REDACTED ***}")
inp = input("> ")
# This must be true, isn't it?
if inp == inp.swapcase().swapcase():
print("Check passed!")
else:
print("Check failed - !?")
print("Here is your flag:", flag)
The program reads a string inp and checks:
inp == inp.swapcase().swapcase()
It assumes that applying swapcase() twice will always return the same string.
Your goal is to provide an input that makes the condition false so the code prints the flag.
swapcase() relies on Unicode case mappings, and some mappings are not involutive functions.
In particular, certain characters can expand from one character into multiple characters.
A classic example is German sharp s: ß (U+00DF).
"ß".swapcase() becomes "SS".swapcase() again turns it into "ss".Therefore, the expression
"ß" == "ß".swapcase().swapcase() is false.
One reliable method is to brute-force all Unicode code points and report any failed cases.
bad_count = 0
for cp in range(0x110000):
ch = chr(cp)
if ch != ch.swapcase().swapcase():
bad_count += 1
print(cp, ch, ch.swapcase().swapcase())
print("breaks:", bad_count)
U+00B5 µ 1 μ 1
U+00DF ß 1 ss 2
U+0130 İ 1 İ 2
U+0131 ı 1 i 1
U+0149 ʼn 1 ʼn 2
U+017F ſ 1 s 1
U+01F0 ǰ 1 ǰ 2
U+0345 ͅ 1 ι 1
U+0390 ΐ 1 ΐ 3
U+03B0 ΰ 1 ΰ 3
U+03C2 ς 1 σ 1
U+03D0 ϐ 1 β 1
U+03D1 ϑ 1 θ 1
U+03D5 ϕ 1 φ 1
U+03D6 ϖ 1 π 1
U+03F0 ϰ 1 κ 1
U+03F1 ϱ 1 ρ 1
U+03F4 ϴ 1 Θ 1
U+03F5 ϵ 1 ε 1
U+0587 և 1 եւ 2
U+1C80 ᲀ 1 в 1
U+1C81 ᲁ 1 д 1
U+1C82 ᲂ 1 о 1
U+1C83 ᲃ 1 с 1
U+1C84 ᲄ 1 т 1
U+1C85 ᲅ 1 т 1
U+1C86 ᲆ 1 ъ 1
U+1C87 ᲇ 1 ѣ 1
U+1C88 ᲈ 1 ꙋ 1
U+1E96 ẖ 1 ẖ 2
U+1E97 ẗ 1 ẗ 2
U+1E98 ẘ 1 ẘ 2
U+1E99 ẙ 1 ẙ 2
U+1E9A ẚ 1 aʾ 2
U+1E9B ẛ 1 ṡ 1
U+1E9E ẞ 1 SS 2
U+1F50 ὐ 1 ὐ 2
U+1F52 ὒ 1 ὒ 3
U+1F54 ὔ 1 ὔ 3
U+1F56 ὖ 1 ὖ 3
U+1F80 ᾀ 1 ἀι 2
U+1F81 ᾁ 1 ἁι 2
U+1F82 ᾂ 1 ἂι 2
U+1F83 ᾃ 1 ἃι 2
U+1F84 ᾄ 1 ἄι 2
U+1F85 ᾅ 1 ἅι 2
U+1F86 ᾆ 1 ἆι 2
U+1F87 ᾇ 1 ἇι 2
U+1F90 ᾐ 1 ἠι 2
U+1F91 ᾑ 1 ἡι 2
U+1F92 ᾒ 1 ἢι 2
U+1F93 ᾓ 1 ἣι 2
U+1F94 ᾔ 1 ἤι 2
U+1F95 ᾕ 1 ἥι 2
U+1F96 ᾖ 1 ἦι 2
U+1F97 ᾗ 1 ἧι 2
U+1FA0 ᾠ 1 ὠι 2
U+1FA1 ᾡ 1 ὡι 2
U+1FA2 ᾢ 1 ὢι 2
U+1FA3 ᾣ 1 ὣι 2
U+1FA4 ᾤ 1 ὤι 2
U+1FA5 ᾥ 1 ὥι 2
U+1FA6 ᾦ 1 ὦι 2
U+1FA7 ᾧ 1 ὧι 2
U+1FB2 ᾲ 1 ὰι 2
U+1FB3 ᾳ 1 αι 2
U+1FB4 ᾴ 1 άι 2
U+1FB6 ᾶ 1 ᾶ 2
U+1FB7 ᾷ 1 ᾶι 3
U+1FBE ι 1 ι 1
U+1FC2 ῂ 1 ὴι 2
U+1FC3 ῃ 1 ηι 2
U+1FC4 ῄ 1 ήι 2
U+1FC6 ῆ 1 ῆ 2
U+1FC7 ῇ 1 ῆι 3
U+1FD2 ῒ 1 ῒ 3
U+1FD3 ΐ 1 ΐ 3
U+1FD6 ῖ 1 ῖ 2
U+1FD7 ῗ 1 ῗ 3
U+1FE2 ῢ 1 ῢ 3
U+1FE3 ΰ 1 ΰ 3
U+1FE4 ῤ 1 ῤ 2
U+1FE6 ῦ 1 ῦ 2
U+1FE7 ῧ 1 ῧ 3
U+1FF2 ῲ 1 ὼι 2
U+1FF3 ῳ 1 ωι 2
U+1FF4 ῴ 1 ώι 2
U+1FF6 ῶ 1 ῶ 2
U+1FF7 ῷ 1 ῶι 3
U+2126 Ω 1 Ω 1
U+212A K 1 K 1
U+212B Å 1 Å 1
U+FB00 ff 1 ff 2
U+FB01 fi 1 fi 2
U+FB02 fl 1 fl 2
U+FB03 ffi 1 ffi 3
U+FB04 ffl 1 ffl 3
U+FB05 ſt 1 st 2
U+FB06 st 1 st 2
U+FB13 ﬓ 1 մն 2
U+FB14 ﬔ 1 մե 2
U+FB15 ﬕ 1 մի 2
U+FB16 ﬖ 1 վն 2
U+FB17 ﬗ 1 մխ 2
breaks: 104