格式化字符串(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