这两道题主要目的是科普与 Unicode 相关的一些知识。目前 Unicode 字符集及其相关的 UTF-8 等编码在互联网上得到了广泛应用,但很多开发者仍然对 Unicode 及其编码的一些「坑点」缺乏认知,如认为 UTF-16 是定长的,认为 UCS-4 中一个码位就是一个字符,没有充分考虑到正则化和 Unicode 的国际化特征等等。
本题两问均有实际背景。
这道题的背景见 Hacking Github with Unicode。
代码的意思是:如果我们输入一个字面上不是 "flag" 但转换为大写后会变成 "FLAG" 的字符串,就可以得到 flag。
我们可以以 "unicode uppercase collision" 为关键字搜索,不难找到一个连字(ligature)
fl (0xFB02)
这个“字符”将在转换为大写时变成 FL
两个字符!因此,只需输入 flag
即可得到 flag。
flag{badunic0debadbad}
这道题的背景见 remove UTF-7 from browser encoding menus。
代码的意思是:如果我们输入一个字面上不是 "flag" 但从 UTF-7 转换为 UTF-8 后会变成 "flag" 的字符串,就可以得到 flag。
不妨查阅 UTF-7 相关资料。可以得知:一个 Unicode 字符串,在 UTF-7 编码下,可能有多种编码,甚至纯粹的 ASCII 字符串也可以有多种编码!
那么事情就简单了。我们依照 Wikipedia 等参考资料给出的 UTF-7 编码算法,可以构造出 "flag" 的另一种“写法”。比如,选择 f
下手。
f
的 Unicode 码位是 0x66- 将 0x66 写成 16 位二进制数:
0000 0000 0110 0110
- 重新分组:
000000 000110 011000
- 使用 base64 的编码表,将每组变成一个字符:
AGY
那么最终 "flag" 的另一种 UTF-7 替代写法就是 +AGY-lag
,输入即可得到 flag。
flag{please_visit_www.utf8everywhere.org}
(是的,你应该去看这个网站!)