格式化字符串漏洞
0x01. 前置栈知识
通过前面的函数调用细节以及栈中数据的分布情况,我们可以发现,局部变量是在栈中挨个排放的,如果这些局部变量中有数组之类的缓冲区,并且程序存在数组越界的问题,那么越界的数组就有可能破坏栈中相邻变量的值,进而破坏EBP的值、返回地址等重要数据。
![[Pasted image 20260325082234.png]]
0x02. 格式化字符串漏洞原理
首先,什么是格式化字符串呢,举个简单的例子:
1 | printf("CTF(Capture the flag) is DEAD!"); |
执行该函数后将返回字符串:CTF(Capture the flag) is DEAD!
该printf函数的第一个参数就是格式化字符串,它来告诉程序将以什么格式输出。printf()函数的一般形式为:printf("format" , 输出列表),我们对format比较关心,它的结构是:% {标志}{输出最小宽度}{.精度}{长度}类型,其中跟格式化字符串漏洞有关系的主要有以下绩点:
- 输出最小宽度:用十进制整数来表示输出的最少位数。若实际位数多于定义的宽度,则按实际位数输出,若实际位数少于定义的宽度,则补以空格或0。
- 类型:
Text 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
%c : 输出字符,配上%n可用于向指定地址写数据
%d:输出十进制整数,配上%n可用于向指定地址写数据
%x:输出16进制数据,如%i$x表示要泄漏偏移i处4字节长的16进制数据,%i$lx表示要泄漏偏移i处8字节长的16进制数据,32bit和64bit环境下一样。
%p:输出16进制数据,与%x基本一样,只是附加了前缀0x,在32bit下输出4字节,在64bit下输出8字节,可通过输出字节的长度来判断目标环境是32bit还是64bit。
%s:输出的内容是字符串,即将偏移处指针指向的字符串输出,如%i$s表示输出偏移i处地址所指向的字符串,在32bit和64bit环境下一样,可用于读取GOT表等信息。
%n:将%n之前printf已经打印的字符个数赋值给偏移处指针所指向的地址位置,如%100×10$n表示将0x64写入偏移10处保存的指针所指向的地址(4字节),而&$hn表示写入的地址空间为2字节,%$hhn表示写入的地址空间为1字节,%$lln表示写入的地址空间为8字节,在32bit和64bit环境下一样。有时,直接写4字节会导致程序崩溃或等候时间过长,可通过%$hn或%$hhn来适时调整。
%n是通过格式化字符串漏洞改变程序流程的关键方式,而其他格式化字符串参数可用于读取信息或配合%n写数据。
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Sy-Blog!





