再談格式化字串

2021-09-27 11:11:58 字數 2102 閱讀 1413

pwn真的是爸爸,好多已經做過的實驗再做一遍又會有不同的體會

還是這份**:

#include int main()
很明顯的格式化字串漏洞對吧

這次我用裝了gef外掛程式的gdb來除錯一下

當然我肯定是要把所有的保護措施都關掉的

gef➤  checkse

[+] checksec for '/root/chapter2/wiki_format'

canary : no

nx : no

pie : no

fortify : no

relro : partial

沒有canary,nx,piehhhh

看下main的反彙編

關鍵的地方:

0x080491a4 :    sub    esp,0x8

0x080491a7 : lea eax,[ebp-0x78]

0x080491aa : push eax

0x080491ab : lea eax,[ebx-0x1ff8]

0x080491b1 : push eax

0x080491b2 : call 0x8049050 <__isoc99_scanf>

0x080491b7 : add esp,0x10

0x080491ba : sub esp,0xc

0x080491bd : lea eax,[ebp-0x78]

0x080491c0 : push eax

0x080491c1 : push dword ptr [ebp-0x14]

0x080491c4 : push dword ptr [ebp-0x10]

0x080491c7 : push dword ptr [ebp-0xc]

0x080491ca : lea eax,[ebx-0x1ff5]

0x080491d0 : push eax

0x080491d1 : call 0x8049030 0x080491d6 : add esp,0x20

0x080491d9 : sub esp,0xc

0x080491dc : lea eax,[ebp-0x78]

0x080491df : push eax

0x080491e0 : call 0x8049030

先在printf處下兩個斷點

執行輸入%08x.%08x.%08x

來到第乙個printf處:

這時候你會發現gef幫我們將很多資訊都顯示出來了

看到printf的引數沒,從低位址往高位址處,依次是格式化字串,第乙個引數1,第二個引數0x22222222,第三個引數-1(此處是補碼),然後是第四個引數也就是我們輸入的變數s

注意到這裡有兩處%08x.%08x.%08x,至於為什麼我也沒想清楚,當時此時printf的格式化字串顯然只有四個,所以只會列印四個引數

continue一下

這個輸出是沒有問題的,但是下乙個printf就有問題了

此時停留在第二個printf處的斷點

這時候棧上第乙個是格式化字串,第二個呢?

因為格式化字串中是有3個%的,所以printf肯定會乖乖的列印三個值出來的,所以此時列印出來的值我不說你也知道就是0xffffd2d0,0xf7ffd950,0x08049189

驗證一下:

正好和我們想的一樣:

我們可以通過%1$s 去列印棧上被視為第二個引數的資訊(因為格式化字串算第乙個引數),其實就是說我們想列印printf的第n個引數(除去格式化字串),我們就可以直接輸入%n$s,當然%n$x也是可以的

比如%s直接把格式化字串本身列印出來了

%1所以%2

字串格式化

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...

字串格式化

例如 string s hello map.put target world string res format s,map 有什麼用呢?比如在some.properties中配置模板字串,但是如果用 這種方式,在配置了spring讀取properties注入變數的時候,這個變數就找不到會報錯。這個...