匯編與反匯編
phase_1? 比較字符串是否相同
步驟一: 反編譯??
將二進(jìn)制可執(zhí)行文件變?yōu)閰R編語言
objdump -d bomb > bomb.s
反編譯命令?objdump -d
步驟二:調(diào)試?
執(zhí)行二進(jìn)制可執(zhí)行文件
gdb bomb
gdb命令
一步一步學(xué)調(diào)試——gdb命令小結(jié)
斷點(diǎn)
設(shè)置斷點(diǎn) b 運(yùn)行 r? 退出ctrl+d 或 quit
x/3i $pc顯示3條指令(3為示范挂签,數(shù)字可選)
display result?
display相當(dāng)于添加監(jiān)聽變量,每一次run后都會給出result的值划咐。而print就對應(yīng)著IDE中的鼠標(biāo)停留時(shí)顯示變量的值掷空。
$pc 指向當(dāng)前程序運(yùn)行地址
display/i $pc 跟蹤顯示命令
?1.查看display設(shè)置的自動顯示的信息
info display 。
2.刪除自動顯示洽沟,dnums意為所設(shè)置好了的自動顯式的編號以故。如果要同時(shí)刪除幾個(gè),編號可以用空格分隔裆操,如果要?jiǎng)h除一個(gè)范圍內(nèi)的編號怒详,可以用減號表示(如:2-5)
undisplay dnums…
deletedisplay dnums…
3.disable和enalbe不刪除自動顯示的設(shè)置,而只是讓其失效和恢復(fù)踪区。
disabledisplaydnums…
enabledisplaydnums…
(gdb)(e)x(amine)
語法:
x/
n選擇從當(dāng)前地址向后顯示幾個(gè)
f是顯示格式昆烁,還有s字符串和i整型
u表示從當(dāng)前地址往后請求的字節(jié)數(shù),如果不指定的話缎岗,GDB默認(rèn)是4個(gè)bytes静尼。u參數(shù)可以用下面的字符來代替,b表示單字節(jié)传泊,h表示雙字節(jié)鼠渺,w表示四字節(jié),g表示八字節(jié)眷细。當(dāng)我們指定了字節(jié)長度后拦盹,GDB會從指內(nèi)存定的內(nèi)存地址開始,讀寫指定字節(jié)溪椎,并把其當(dāng)作一個(gè)值取出來普舆。
例子:
x/3uh 0x54320表示,從地址0x54320讀取校读,h表示以雙字節(jié)為單位沼侣,3表示三個(gè)單位,u表示十六進(jìn)制
問題:
解決過程:
通過命令? readelf -l 地址 | grep interpreter 查找原因
原因?yàn)椋?lib/ld-linux.so.2
解釋:系統(tǒng)為64位歉秫,缺少32位依賴蛾洛,無法運(yùn)行32位程序
解決方案:
安裝如下三個(gè)依賴:
sudo apt-get install libc6:i386
sudo apt-get install lib32stdc++6
sudo apt-get install lib32z1
gdb調(diào)試
設(shè)置斷點(diǎn)? b 地址?
查看斷點(diǎn) info br
刪除斷點(diǎn)? 單個(gè)刪除 delete 序號? 如delete 1 多個(gè)刪除 delete 范圍序號 如delete 1-3
phase1 比較字符串
由上面代碼,主要關(guān)注strings_not_equal端考,就是比較字符串是否相同:那應(yīng)該有一個(gè)樣例與所輸入的進(jìn)行比較雅潭,因此壓棧操作引起了我的注意揭厚,查看其內(nèi)容并輸入,發(fā)現(xiàn)第一個(gè)成功破解扶供。
phase2
* LEA指令
??? lea 7(%edx, %edx,4), %eax??? ==> 將寄存器%eax的值置為 5 * %edx + 7.
??? base(offset, index, i) 計(jì)算方法為base + offset + index * i
phase_2 循環(huán)? 尋找數(shù)字間的邏輯
可以看出第一個(gè)爆炸點(diǎn)是比較第一個(gè)數(shù)字與第四個(gè)數(shù)字大小筛圆,相等才不會爆炸。
由上圖可以得知椿浓,由ebp地址開始每四個(gè)字節(jié)存儲一個(gè)數(shù)字太援,ebp-0x38為第一個(gè)數(shù)字,ebp-0x2c為第四個(gè)數(shù)字扳碍。
lea -0xc(%ebp),%eax? ?incl? (%eax)
由分析可知 ebp-0xc為計(jì)數(shù)器 提岔,假設(shè)用N表示,每次循環(huán)后加一
分析第一個(gè)紅框炸彈點(diǎn):
mov -0xc(%ebp),%eax
mov? ? -0xc(%ebp),%edx
簡單分析邏輯笋敞,首先eax和edx賦值為N
mov -0x38(%ebp,%eax,4),%eax
cmp? ? -0x2c(%ebp,%edx,4),%eax
六個(gè)數(shù)字存儲用數(shù)組A[6]表示碱蒙,因?yàn)槊?字節(jié)存儲一數(shù)字,每次N增加一夯巷,其相當(dāng)于向后挪一位數(shù)赛惩,從第1個(gè)和第4個(gè)開始對比,遍歷到所有數(shù)字趁餐。?
-0x38(%ebp,%eax,4)為ebp+4N-0x38就相當(dāng)A[0+N]
0x2c(%ebp,%edx,4)為ebp+4N-0x2c就相當(dāng)A[3+N],
對比A[0+N]與A[3+N]喷兼,不等則爆炸。
分析最下面紅框第二個(gè)爆炸點(diǎn):
mov -0x38(%ebp,%eax,4),%edx
lea? ? -0x10(%ebp),%eax
add? ? %edx,(%eax)
ebp-0x10 存儲每次累加的和?
cmpl $0x0,-0x10(%ebp) jne 80489ee? call 80487de
和為零則爆炸
簡易邏輯如下:
phase_3?
相當(dāng)于switch函數(shù)后雷。
分析第一個(gè)爆炸點(diǎn)
首先隨意輸入了4個(gè)數(shù)字
通過觀察sscanf運(yùn)行前后的內(nèi)存狀態(tài)及觀察內(nèi)容季惯,發(fā)現(xiàn)其功能是讀取兩個(gè)數(shù)字,存儲在ebp-0x4和ebp-0x8位置臀突,并用eax存儲其個(gè)數(shù)勉抓。這也就是第一個(gè)爆炸點(diǎn)要求的輸入的個(gè)數(shù)大于1。
分析第二惧辈、三個(gè)爆炸點(diǎn)
首先有cmp可知要求第一個(gè)數(shù)字小于7琳状,否則爆炸。
接下來讀取第一個(gè)數(shù)字到eax中盒齿,并進(jìn)行邏輯左移,移兩位困食,就相當(dāng)于擴(kuò)大4倍边翁。例如,0x1邏輯左移兩位后變?yōu)?x100硕盹,就由1變?yōu)榱?符匾。由于每四字節(jié)存儲一個(gè)數(shù)字,就是每四個(gè)地址存儲一個(gè)數(shù)字瘩例。并且mov 0x8049060(%eax),%eax可翻譯為eax=0x8049060+4*第一個(gè)數(shù)字啊胶〉楦鳎可以看出我們輸入的一個(gè)數(shù)字對應(yīng)一個(gè)地址。
通過觀察由0x8049060開始的內(nèi)存內(nèi)容及代碼段地址焰坪,可發(fā)現(xiàn)他們之間的關(guān)聯(lián)趣倾。輸入的第一個(gè)數(shù)字決定跳轉(zhuǎn)的位置,第一個(gè)數(shù)字范圍0-7某饰。
跳轉(zhuǎn)的代碼作用:存入數(shù)字儒恋。
之后代碼作用:見下圖,使存入的數(shù)字并與第二個(gè)數(shù)字進(jìn)行比較黔漂,相同則安全诫尽,不同則保證。注意上面是16進(jìn)制數(shù)炬守,輸入時(shí)要轉(zhuǎn)換為10進(jìn)制數(shù)牧嫉。
舉例:如第一個(gè)數(shù)輸入1,則對應(yīng)0x1b7减途,換為10進(jìn)制為439.
phase_4 遞歸函數(shù)
可以看出驹止,只讀取了一個(gè)數(shù)字,讀取到ebp-0x8观蜗,eax計(jì)數(shù)為1臊恋。因此應(yīng)該輸入一個(gè)數(shù)字。
介紹下面拆除前墓捻,首先分析函數(shù)調(diào)用及返回抖仅,調(diào)用時(shí)將該函數(shù)的下一行代碼地址壓入棧,上圖就應(yīng)該是0x8048b0b砖第,函數(shù)結(jié)束應(yīng)該執(zhí)行下條語句撤卢,也就是地址0x8048b0b。
由上面可知梧兼,ebp-0x8是我們所輸入的數(shù)字放吩。但隨著fun4的調(diào)用,我們數(shù)字的存儲位置為ebp+0x8
因此上面的循環(huán)可以解釋為每次羽杰,每次該數(shù)字減1渡紫,并壓棧,下次繼續(xù)取出直至減到0才能繼續(xù)考赛。
如果不為0惕澎,則繼續(xù)進(jìn)入func函數(shù),就會在下一行代碼留下個(gè)標(biāo)記點(diǎn)颜骤,如果輸入的數(shù)字為3唧喉,則留下3次標(biāo)記點(diǎn),直至減至0才開始向下進(jìn)行,由代碼可知0時(shí)eax賦值為1八孝。
接下來分析橘黃框董朝,edx=8*eax;eax=edx-eax干跛;結(jié)果就為eax=7*eax 每次變?yōu)樵瓉淼?倍子姜;
已知0時(shí)eax=1,之后開始恢復(fù)標(biāo)記點(diǎn)驯鳖;1時(shí)eax=7闲询;2時(shí)eax=7*7;3時(shí)eax=7*7*7浅辙;
這就是我們熟悉的遞歸函數(shù)扭弧。
拆除爆炸點(diǎn):
cmpl $0x1cb91,-0x4(%ebp) 不等則爆炸;?
0x1cb91變?yōu)槭M(jìn)制數(shù)為117649 為7的6次冪记舆,因此輸入的數(shù)字應(yīng)為6
phase_5
看到string_length很自然想到比較字符長度鸽捻,同時(shí)根據(jù)以上實(shí)驗(yàn)的經(jīng)驗(yàn),一般eax寄存器用來計(jì)數(shù)泽腮,事實(shí)證明御蒲,本關(guān)也是。因此第一個(gè)爆炸點(diǎn)就是要求字符串長度為6诊赊,不等則爆炸厚满。
分析第二段代碼,這是一個(gè)循環(huán)碧磅,可以看出循環(huán)六次碘箍,可以聯(lián)系與輸入的字符串有些關(guān)系【ń迹可以看出紅框的add語句和黃框的mov語句丰榴,都是向下取值,其中ebp+0x8及0x804a620引起我們的注意秆撮;接下來可以看出綠框四濒,ebp-0x8是存儲累加值的,這個(gè)值就是下個(gè)爆炸點(diǎn)的判斷职辨;ebp-0x4是存儲計(jì)數(shù)的盗蟆。
查看ebp+0x8存儲的內(nèi)容為一地址,繼續(xù)查看改地址就是我們所輸入的字符串拨匆,因此add操作相當(dāng)將字符串中的內(nèi)容逐個(gè)取出姆涩,并存入eax進(jìn)行下一步操作。
通過觀察0x804a620惭每,我們可以聯(lián)想到數(shù)組,每個(gè)位置存儲固定的數(shù)字。
mov 0x804a620(,%eax,4),%edx可翻譯為edx=(0x804a620+4*eax)
這個(gè)可以看出我們輸入的字符串的內(nèi)容台腥,影響著取出的內(nèi)容宏赘,他們之間是一一對應(yīng)關(guān)系,比如輸入0取出的就是0x00000002等等黎侈,由于數(shù)字只能為0-9取出的范圍4*eax為0-36察署;考慮到16進(jìn)制,可以輸入字母a-f峻汉,這樣就擴(kuò)大了范圍贴汪。
之后lea -0x8(%ebp),%eax? add? ? %edx,(%eax) 是將取出內(nèi)容進(jìn)行累加,并存到ebp-0x8中休吠;
分析最后一個(gè)爆炸點(diǎn)扳埂,要求累加的和等于0x25,也就是37瘤礁;
綜合考慮輸入字符串有個(gè)數(shù)6個(gè)限制阳懂,觀察對應(yīng)的數(shù)組,相加的和等于37柜思;因此可以有多種組合岩调,列舉其中一種:033355
phase_6
首先看代碼,好多循環(huán)赡盘。号枕。。
第一個(gè)為兩層循環(huán)陨享,目的是:是輸入的6個(gè)數(shù)各不相同葱淳,且范圍是1-6;否則爆炸霉咨。
上面兩個(gè)壓棧的地址蛙紫,引起我們注意ebp-0x38及ebp+0x8,驗(yàn)證可知途戒,是存儲輸入6個(gè)數(shù)的位置坑傅。
因?yàn)榇舜螠y試輸入的為123456,因此一一對應(yīng)喷斋。
輸入? ? -0x58存儲內(nèi)容? ?相對于值? ? ? ? ? ? ? ? 大小
1? ? ? ? 0x0804a69c? ? ? ? 0xce? ? ? ? ? ? ? ? ? ? ? ? ?6
2????????0x0804a690? ? ? ? 0x3c8? ? ? ? ? ? ? ? ? ? ? ?1
3????????0x0804a684? ? ? ? 0x106? ? ? ? ? ? ? ? ? ? ? ?5
4????????0x0804a678? ? ? ? 0x21f? ? ? ? ? ? ? ? ? ? ? ? 3
5????????0x0804a66c? ? ? ? 0x276? ? ? ? ? ? ? ? ? ? ? ? 2
6????????0x0804a660? ? ? ? 0x158? ? ? ? ? ? ? ? ? ? ? ? 4
可以看出唁毒,每個(gè)數(shù)對應(yīng)一個(gè)地址,存儲在ebp-0x58星爪;且每個(gè)地址對應(yīng)一個(gè)值浆西,按值的大小排序,輸入順序應(yīng)該為 2 5 4 6 3 1
第三個(gè)循環(huán)目的是將輸入所對應(yīng)的地址串聯(lián)起來顽腾,就是第一個(gè)對應(yīng)的地址+0x8存儲下一個(gè)數(shù)對應(yīng)的地址近零,如上圖诺核。
可以看出侄柔,這個(gè)循環(huán)是比較大小嚷堡,前一個(gè)數(shù)所對應(yīng)地址存儲的值大于后一個(gè)为严,則安全肢执;
根據(jù)前面分析輸入范圍為1-6攻人,且輸入各值不同蒿辙;按照所對應(yīng)地址的值從大到小排序邦尊,輸入順序應(yīng)為2 5 4 6 3 1.