%字符串格式中的字符含义(printf样式格式)

时间:2018-02-04 21:06:07

标签: python format-string

我目前正在使用格式字符串exploit(writeUp config console picoctf)并遇到了奇怪的语法(作为用于pwn的python脚本的一部分):

payload += ("%%%du|%%17$hn|" % 2493).rjust(16)

我知道作者打算用上面的值覆盖一个内存地址(2493)。我可以使用以下语法实现相同的目标:

payload += "%2493x%17$hn".rjust(16)

所以我知道第二部分中$和hn的含义。

我主要对多重'%'在上面的第一个版本和那个' %2493'出现在连字符之外。 我试图谷歌,但它只会导致标准格式字符串解释。

有人可以解释上面的第一个版本,或者可能有一个解释相同的链接。

2 个答案:

答案 0 :(得分:2)

$hm没什么特别的,它们只是你字符串中的字符。只需运行字符串格式代码,您就会看到:

>>> "%%%du|%%17$hn|" % 2493
'%2493u|%17$hn|'

在上面的字符串%d2493替换为%%%用于在字符串中显示%,因为单个%带有% - 字符串格式中的特殊含义。休息是正常的字符串字符。

% - 格式化(也称为printf-style string formatting)是旧式的Python格式化字符串格式,现在通常使用str.format函数来完成。 PEP 3101建议使用新的高级字符串格式替换Conversion Meaning 'd' Signed integer decimal. 'i' Signed integer decimal. 'o' Signed octal value. 'u' Obsolete type – it is identical to 'd'. 'x' Signed hexadecimal (lowercase). 'X' Signed hexadecimal (uppercase). 'e' Floating point exponential format (lowercase). 'E' Floating point exponential format (uppercase). 'f' Floating point decimal format. 'F' Floating point decimal format. 'g' Floating point format. Uses lowercase exponential format if exponent is less than -4 or not less than precision, decimal format otherwise. 'G' Floating point format. Uses uppercase exponential format if exponent is less than -4 or not less than precision, decimal format otherwise. 'c' Single character (accepts integer or single character string). 'r' String (converts any Python object using repr()). 's' String (converts any Python object using str()). 'a' String (converts any Python object using ascii()). '%' No argument is converted, results in a '%' character in the result. 运算符。

两者之间的比较非常好:"Python string formatting: % vs. .format"

"printf-style String Formatting" document开始,它允许使用 转换类型

+------+--------------------------------------------------------------------------------------------------------------+
| Flag | Meaning                                                                                                      |
+------+--------------------------------------------------------------------------------------------------------------+
| '#'  | The value conversion will use the “alternate form” (where defined below).                                    |
+------+--------------------------------------------------------------------------------------------------------------+
| '0'  | The conversion will be zero padded for numeric values.                                                       |
+------+--------------------------------------------------------------------------------------------------------------+
| '-'  | The converted value is left adjusted (overrides the '0' conversion if both are given).                       |
+------+--------------------------------------------------------------------------------------------------------------+
| ' '  | (a space) A blank should be left before a positive number (or empty string) produced by a signed conversion. |
+------+--------------------------------------------------------------------------------------------------------------+
| '+'  | A sign character ('+' or '-') will precede the conversion (overrides a “space” flag).                        |
+------+--------------------------------------------------------------------------------------------------------------+

并将 转换标记 字符设为:

db.user.aggregate([
    {
       "$addFields": {
           "subscriptions": { "$objectToArray": "$channelSubscription" }
       } 
    }
])

答案 1 :(得分:1)

您在引号外看到的%是一个运算符(对数字采用模数的运算符)。当它的左参数是一个字符串时,它会执行“旧式”字符串格式化。这是Python 2.6引入str.format之前的主要字符串格式,所以你会在旧代码中看到很多。 %运算符使用的格式化语言非常受C printf的启发,所以一些习惯于C的程序员也可能更喜欢它而不是更新的,也许更多的“Pythonic”格式化方法。 / p>

在您的示例中,格式字符串的最相关部分是%d,它将参数格式化为整数。 %是用于在格式字符串中引入替换的字符,这就是为什么在其他两个地方的格式字符串中有另一个有趣的功能。如果要在输出中使用单个百分号,则需要在格式字符串中放置两个:%%。你有两次,一次就在%d之前,一次之后。

最后得到的字符串,"%2493x%17$hn"并不意味着Python有什么特别之处,但它可能在某些其他语言或某些特殊环境中。它不会再作为格式字符串工作,因为%17$不是有效的格式说明符(%2493x是有效的,尽管可能只是巧合)。