-
-
[原创]格式化字符串漏洞
-
发表于: 2021-6-12 11:17 8112
-
格式化字符串漏洞本身并不算缓冲区溢出漏洞,主要是针对一些格式化函数,如printf、sprintf、vsprintf等。这些格式化函数利用格式化字符串来指定串的格式,在格式串内部使用一些以“%”开头的格式说明符(format specifications)来占据一个位置,在后面的变参列表中提供相应的变量,最终函数就会使用相应位置的变量来代替那个说明符,产生一个调用者想要的字符串。
下面列出几个比较关键的参数格式:
·%x(%lx):替换为参数的值(十六进制)。
·%p:替换为参数的值(指针形式)。
·%s:替换为参数所指向内存的字符串。
.%n:参数对应整型指针,将该参数之前输出的字符数量写入参数指向的地址中。
在C语言程序中,多数含有可变参数的函数都使用stdarg.h头文件中定义的宏stdarg来访问它们的可变参数:
printf()函数扫描格式化字符串,直到遇到一个格式说明符'%',此时,printf()函数调用va_arg()来获得当前va_list指针指向的可变参数,同时va_arg()把指针移到下一个可变参数,把获得的参数看成什么类型的数和把va_list指针移动多少距离取决于格式规定符的类型。
在正常的情况下,格式化字符串所需的参数是依次往后索引的,如“%p,%x”,其对应于第1、2个参数。
也有一些特殊情况,如
“%d$m”形式:
其中,d代表数字(1,2,.…),用来定位参数列表中的第d个参数(从1开始算);
m为前面所述的关键参数格式之一(x,p,s,n,...).
通常,格式化函数是一种变长参数函数,后面的参数需要根据栈的参数传递来进行释放,x86的参数全在栈上,x64的参数从第4个开始放在栈上。这些格式化函数遇到格式说明符的关键字符之后,会按照传参规则去寻找参数来进行替换或者修改,并不会关心真实的传参情况。所以如果实际参数数量小于所需的参数数量,则其依然会将对应位置的数值当成参数进行转换,从而引发格式化字符串漏洞。由此可见,利用格式化字符串漏洞既能够泄露信息,又能够修改信息,功能比较强大。
未检查真实的参数列表
“nil”表示无值,任何变量在没有被赋值之前的值都为nil,对于真假判断,只有nil与false、0表示假,其余均为真。
信息修改主要是利用格式化字符串中的‘%n’对参数进行写入,写入的值是格式化字符串中%n之前的字符数量。
修改宽度控制具体如下:
·%n:修改4字节。
.%hn:修改2字节。
.%hhn:修改1字节。
#include <stdio.h>
#include <stdarg.h>
int
myprint(
int
Narg,...)
{
int
i;
va_list ap;
va_start(ap,Narg);
for
(
int
i
=
0
; i<Narg;i
+
+
)
{
printf(
"%d\t"
,va_arg(ap,
int
));
printf(
"%f\n"
,va_arg(ap,double));
}
va_end(ap);
}
int
main()
{
myprint(
1
,
2
,
3.5
);
myprint(
2
,
2
,
3.5
,
3
,
4.5
);
}
#include <stdio.h>
#include <stdarg.h>
int
myprint(
int
Narg,...)
{
int
i;
va_list ap;
va_start(ap,Narg);
for
(
int
i
=
0
; i<Narg;i
+
+
)
{
printf(
"%d\t"
,va_arg(ap,
int
));
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
- [求助]Android auto 7451
- web渗透-清理痕迹 3829
- [求助]web渗透是找个师傅好还是自学好? 4954
- linux系统/etc/shadow文件密码项 14566
- 小端存储 3650