# 格式化字串漏洞
## 1、什麼是格式化字串
要研究格式化字串漏洞首先我們必須得明白什麼是格式化字串。
我們用c語言中常見的printf來舉例
```bash
printf()函式是格式化輸出函式, 一般用於向標準輸出裝置按規定格式輸出
資訊。在編寫程式時經常會用到此函式。函式的原型為:
`int printf(const char *format, ...)`;
函式返回值為整型。若成功則返回輸出的字元數,輸出出錯則返回負值。
printf()函式的呼叫格式為:
`printf("《格式化字串》", 《參量表》);`
其中格式化字串包括兩部分內容: 一部分是正常字元, 這些字元將按原
樣輸出; 另一部分是格式化規定字元, 以"%"開始, 後跟乙個或幾個規定字元,
用來確定輸出內容格式。
參量表是需要輸出的一系列引數, 其個數必須與格式化字串所說明的輸出
引數個數一樣多, 各引數之間用","分開, 且順序一一對應, 否則將會出現意想
不到的錯誤。
看的有些模糊是吧,沒關係。總的來說就是`printf`這個函式的第乙個引數(第乙個逗號前面的東西)就叫做格式化字串。
它是由兩部分組成:
- 格式化說明符:特點明顯,「%「號開頭,後面緊跟幾個字元,例如:
```bash
%d - 十進位制 - 輸出十進位制整數
%s - 字串 - 從記憶體中讀取字串
%x - 十六進製制 - 輸出十六進製制數
%c - 字元 - 輸出字元
%p - 指標 - 指標位址
%n - 到目前為止所寫的字元數
+ 普通字串
#### 例子
我們拿個例子來說
```cpp
#include
int main(void){
printf("my name is %s","buryia");
return 0;
在這個的**printf**中,「my name is 」就是普通字串,而「%s」則是格式化說明符。學過c語言的應該知道,這個程式的執行結果是會列印一行
my name is buryia
很明顯,格式化說明符將後面的引數以特定格式替換到了格式化說明符的位置
### 重點
那麼問題來了,為什麼我們要這麼詳細的說明這個東西呢。不知道大家有沒有發現我上面寫的乙個格式化說明符「**%n**」,**它的功能是將%n之前列印出來的字元個數,賦值給乙個變數**
例如:```cpp
#include
int main(void)
int c = 0;
printf("the number is %n", &c);
printf("%dn", c);
return 0;
你能猜一下它的結果麼?
好吧,咱們不猜它,有圖有真相,直接看結果
![在這裡插入描述](
好了,暫時先說到這,其他的你們可以先自由的發揮一下想象
## 2、漏洞點
一般情況我們用**printf**是這樣用的
```cpp
#include
int main()
char arr[100];
scanf("%s", arr);
printf("%s", arr);
return 0;
可是,不知道有沒有人試過這樣寫:
```cpp
#include
int main()
char arr[100];
scanf("%s", arr);
printf(arr);
return 0;
這樣寫對不對呢?我們來執行一下試試
![在這裡插入描述](
咳咳,有些小意外,**scanf**輸入的時候遇到空格就會停止,所以後面的就沒有輸入進去,但……無妨,很明顯的可以看到,它成功的輸出了。
腦子轉的快的可能已經想到了,這個時候我們就可以控制它的格式化字串,使它變成我們想要的東西。
格式化字串漏
當printf系列函式的格式化串裡包含使用者提交的資料時,就有可能出現格式化串漏洞。函式包括 snprintf vfprintf vprintf vsprintf vsnprintf 除了這呰函式外,其他接受c風格格式符的函式也可能存在類似風險,例如wind0ws上的wprintf函式。攻擊者可能提...
字串格式化
sprintf snprintf snprintf std stringstream std strstream boost lexical cast boost format cstring format 1 sprintf 使用 sprintf 不安全,輕則破壞資料的準確性,重則程式崩潰。請看下...
格式化字串
通常在使用字串的時候,會對字串進行格式化,然後輸出或呼叫 一般我們使用替換標記對字串進行格式化 string str1 string.format add is 1,2,3 而且在c 中的替換標記可以以任意順序和次數出現在格式化字串中,但替換值是按順序排的,而且替換標記不能超出索引範圍 string...