使用的条件是编译参数开了 -D_FORTIFY_SOURCE=2
且优化等级不低于 O1
该函数会对 fmt_string
进行检查,禁止下列情况:
%N$
标签存在跳过某些项的情况(如只出现了 %2$s
却没有出现 %1$s
)fmt_string
包含%n,但在可写段所以即便开启了FORTIFY检查,仍然可以通过格串来leak一些信息
printf和__printf_chk对浮点数的处理是特殊的,通过xmm寄存器来传参,其中浮点数参数的个数会通过 eax
寄存器(实际上是al
)来传递
在内部处理时,printf会判断al
是否为零,来决定是否将xmm寄存器入栈保存(一旦非零,则会将所有xmm寄存器都入栈)
传入的eax
的值是在编译时就根据格式化字符串确定的,但如果我们提供的格串是一个变量,由于无法预知浮点数个数,编译器就会将eax
置为0,如果此时我们在格串中填入浮点数相关的内容,由于 eax
为0,xmm不会被入栈,在后续的处理中就会打印栈上的垃圾信息,从而leak出有效地址