Printf %NNN$hhn如何在格式字符串中工作?

Printf %NNN$hhn如何在格式字符串中工作?,printf,string-formatting,Printf,String Formatting,我正在尝试一个经典格式字符串漏洞。我想知道以下格式字符串是如何工作的: “%NNN$hhn”,其中“N”是任意数字 例如:printf(“%144$hhn”,…) 它是如何工作的?我如何使用它来用任意值覆盖我想要的任何地址 感谢和问候, Hrishikesh Murali这是一个POSIX扩展(在C99中找不到),它只允许您从参数列表中选择用于数据源的参数 使用常规的printf,每个%格式说明符从列表中获取当前参数,并将“指针”前进到下一个参数。这意味着,如果您想以两种不同的方式打印单个值,则

我正在尝试一个经典格式字符串漏洞。我想知道以下格式字符串是如何工作的:

“%NNN$hhn”,其中“N”是任意数字

例如:printf(“%144$hhn”,…)

它是如何工作的?我如何使用它来用任意值覆盖我想要的任何地址

感谢和问候,
Hrishikesh Murali

这是一个POSIX扩展(在C99中找不到),它只允许您从参数列表中选择用于数据源的参数

使用常规的
printf
,每个
%
格式说明符从列表中获取当前参数,并将“指针”前进到下一个参数。这意味着,如果您想以两种不同的方式打印单个值,则需要以下内容:

printf ("%c %d\n", chVal, chVal);
通过使用位置说明符,可以执行以下操作:

printf ("%1$c %1$d\n", chVal);
因为两个格式字符串都将使用第一个参数作为其源

维基百科页面上的另一个例子是:

printf ("%2$d %2$#x; %1$d %1$#x",16,17);
这将为您提供输出:

17 0x11; 16 0x10
它基本上允许您断开格式说明符的顺序与提供的值的连接,允许您以任何方式在参数列表中来回跳转,以任意顺序反复使用这些值

<>现在,你是否可以将它作为用户攻击向量,我怀疑,因为它只为程序员添加了一个改变数据源的方法,而不是将数据发送到哪里。
它的安全性不亚于常规样式的
printf
,我看不到任何真正的漏洞,除非您能够以某种方式更改格式字符串。但是,如果你能做到这一点,常规的
printf
也会被滥用。

谢谢!从应用程序安全的角度来看,当您存在潜在的格式字符串漏洞时,可以使用这种从堆栈访问随机参数的方法。例如:char*str=argv[1];printf(str);在这里,程序员假定输入不包含格式字符串。但是,当给定这样一个程序时,攻击者可以在参数字符串中插入格式字符串,从而允许我们查看和使用程序堆栈中的值。如果我们使用“%NNN$hhn”格式字符串,我们可以覆盖堆栈上的任何地址(可能是返回地址)来执行我们自己的代码。不,我不这么认为。虽然您可能会看到堆栈,但并不一定意味着您可以更改它。即使没有位置参数,用户输入字符串上的printf也易受攻击。是的,没有位置参数,用户输入字符串上的printf易受攻击,只是位置参数更易于利用。如果可以输入自己的格式字符串,则可以使用“%n”格式写入堆栈上的地址。您选择写入的地址基于格式字符串的格式。我这样说不对吗?@HrishikeshMurali:不对。位置参数并不指示您向何处写入,而是指示您从何处读取。使用
printf(“%4$d”,7)
printf(“%d%d%d”,7)
之间没有什么区别-它们都涉及访问
7
之外的堆栈以获取要打印的参数。它们(两者)绝不允许您在标准输出之外的其他地方写入该数据。在任何情况下,POSIX遵循ISO模型,即“应”一词对实现和/或程序提出了要求。所有的格式说明符都会说“参数应该是指向废话的指针”之类的话,这意味着如果参数是其他东西,或者您不提供参数,那么会发生什么是未定义的。POSIX语句更清楚地说明了这一点,“如果格式参数不足,则结果未定义”。