Python3 以奇怪的方式处理非 ASCII 字符

Python3 handling non-ASCII characters in a weird way

我试图用 Python 3 解决一个 pwnable。为此我需要打印一些不在 ASCII 范围内的字符。

Python 3 正在将这些字符转换成一些奇怪的 Unicode。

例如,如果我在 Python 3 中打印 "\xff",我会得到:

root@kali:~# python3 -c 'print("\xff")' | xxd
00000000: c3bf 0a                                  ...

\xff 转换为 \xc3\xbf

但在 Python 2 中它按预期工作,如下所示:

root@kali:~# python -c 'print("\xff")' | xxd
00000000: ff0a                                     ..

那么如何在 Python 3 中打印出来呢?

在Python2中,strbytes是一回事,所以当你写'\xff'时,结果包含实际的字节0xFF .

在Python 3中,str更接近Python 2的unicode对象,而不是bytes的别名。 \xff不再是请求插入一个字节,而是请求插入一个Unicode字符,其编码可以用8位来表示。该字符串使用您的默认编码(可能是 UTF-8)打印,其中字符 0xFF 被编码为字节 \xc3\xbf。当 \x 出现在字符串中时,\x 基本上是 \u 的 one-byte 版本。不过,当它出现在 bytes 中时,它仍然和以前一样。

现在寻求解决方案。如果你只想要一些字节,做

b'\xff'

这将与 Python 中的工作方式相同 2. 您可以将这些字节写入二进制文件,但您不能直接打印,因为您打印的所有内容都会转换为 str .打印的问题是所有内容都以文本模式编码。幸运的是,sys.stdout 有一个 buffer 属性,可以让你直接输出 bytes

sys.stdout.buffer.write(b'\xff\n')

这只有在您不将 sys.stdout 替换为没有 buffer 的花哨的东西时才有效。

在Python2中,print '\xff'直接向终端写入一个字节串,所以你得到你打印的字节。

在 Python 3 中,print('\xff') 使用默认编码将 Unicode 字符 U+00FF 编码到终端...在您的情况下为 UTF-8。

在Python3中直接输出字节到终端不能用print,但是可以用下面的跳过编码写一个字节串:

python3 -c "import sys; sys.stdout.buffer.write(b'\xff')"