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注入變數的時候,這個變數就找不到會報錯。這個...