格式化字符串基础

发布于 2023-04-02  293 次阅读


第一个示例:

第二个:flags可以理解为占位符。

第三个示例:c也可以是d、s ,可以输出指定大小的字符。

可以看出输出了很长的空格。

第四个示例:保留小数点后面的几位。

可以看出输出了3.142

第五个:经常和n来配合使用

*************************************************************************************************

若对应a的值是123,则会先转换成十六进制再输出值0x7b。

我们知道,因为延迟绑定机制,函数的真实地址是由got表里的一个地址指向的,通过%n$s来演示,

输出的__libc_start_main的真实地址

再gdb调试核查下:

示例:

可以看到程序先输出了100个空格,然后%n将已输出的空格数给写到a的地址里,即a的内容变为100。

示例:

可以看到单独使用%n$p来泄露报错,必须连续使用。

看下%a的作用:

可以看到输出的是栈顶上方的数据。

############################

############################

示例:

第一个printf:

第二个printf:

由于先前输进去了三个%p,会把对应连续的三个地址输出来

可以看到格式化字符串会从其输入位置的下一个栈开始泄露出三个地址。输入的%p越多泄露的地址越多,如下图输入5个%p :

再看下64位程序下的情况:

示例:

第一个printf处:

第二个printf处:

由于先前输入了三个%p,会将格式化字符串存放的RDI寄存器后边的寄存器存放的内容依次泄露出来。

################################

################################

示例:

那么我们可以用%6$p来定位泄露栈上第六个位置的内容

再来看下64位程序:

可以看输入的aaaa格式化字符串被存到了RDI寄存器,然后还有五个寄存器要存参数,对应%1$p到%5$p,%6$p才开始泄露的是栈上的数据。


穿过云层我试着努力向你奔跑