格式化字符串介绍
格式化字符串(format string),是一些程序设计语言在格式化输出API函数中用于指定输出参数的格式与相应位置的字符串参数,例如C、C++等程序设计语言的print类函数,其中的转换说明(conversion specification)用于把随后对应的0个或多个函数参数转换为相应的格式输出;格式化字符串中转换说明以外的其他字符原样输出。
通俗的来说,格式化字符串函数就是将计算机内存中表示的数据转换为我们人类可读的字符串格式。
print函数运行的大致流程如下:
格式化字符串的在进入print函数后,函数首先会获得第一个参数,也就是格式化字符串,依次读取格式化字符串中的每一个字符,如果该字符是%,则继续读取下一个非空字符,获取对应的参数解析并输出;如果该字符不为%,则直接输出到标准输出。
例子:printf("My name is %s,I'm %d years old.","tom",20)
C语言printf函数代表的一类格式化字符串的基本格式如下:
%[parameter][flags][field width][.precision][length]type
parameter可以忽略,或者是n$,用来获取格式化字符串中的指定参数,比如
int a=0x1111,b=0x2222,c=0x3333;
printf("%3$p",a,b,c)
输出为0x3333
flags可以为一个或者多个,可以是这些字符:+,空格,-,#,0
field width给出显示数值的最小宽度
precision常指明输出的最大长度
length指出浮点型参数或整型参数的长度,可以是以下字符
hh:输出1byte h:输出2byte
l:输出4byte ll:输出8byte
在格式化字符串漏洞利用中我们通常使用hh和h,也就是一次性写1字节和一次性写2字节
type,也称转换说明,可以是如下字符
d/i:有符号整型,int u:无符号整型,unsigned int
x/X:16进制unsigned int,x使用小写字母输出,X使用大写字母输出
s:输出null结尾字符串直到精度规定的上限;如果没有指定精度,则输出所有字节
c:把int参数转为unsigned char类型输出,格式化漏洞利用中通常使用其输出大量字符
p:void*类型,输出对应变量的值
n:不输出字符,但是把已经成功输出的字符个数写入对应的整型指针参数所指的变量。
格式化字符串漏洞原理介绍
通过格式化字符串泄露出栈中相关地址的信息
栈上有flag那就–泄露栈内存
利用 %x 来获取对应栈的内存,但建议使用 %p,可以不用考虑位数的区别。 利用 %s 来获取变量所对应地址的内容,只不过有零截断。
附:常见的格式化字符串函数
输入:scanf、sscanf
输出:printf、fprintf、sprintf、snprintf、vsprintf、vsnprintf、vfprintf、vprintf