日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

计算机系统实验:二进制炸弹+缓冲区炸弹 (自我学习笔记)

發(fā)布時(shí)間:2024/1/1 windows 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 计算机系统实验:二进制炸弹+缓冲区炸弹 (自我学习笔记) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本來(lái)沒(méi)想寫(xiě)個(gè)博客,結(jié)果得知還要驗(yàn)收,發(fā)現(xiàn)自己全忘了,那就趁著復(fù)習(xí)的功夫再捋一遍吧>-<

一、使用工具:IDA-pro

簡(jiǎn)單使用方式:?

1、打開(kāi)IDA,open需要反匯編的exe。

選則win32debugger,process option可以傳入命令行參數(shù)(該實(shí)驗(yàn)中為學(xué)號(hào))。

2、F9會(huì)運(yùn)行exe,直到斷點(diǎn)停止。F8 step over, F7 step into;? F5顯示C代碼(32bit的IDA有,64位沒(méi)有)

3、展示出的匯編指令為x86,采用Inter格式 ,no?ATT,通常目的操作數(shù)在前(與課內(nèi)正好相反)。

4、空格鍵使得代碼在純文本<->graph之間切換。graph便于查看分支,跳轉(zhuǎn)的目的地。

F9后,右側(cè)可查看寄存器與棧的地址與對(duì)應(yīng)的值,地址為32位,用16進(jìn)制表示。下方有存儲(chǔ)器不過(guò)不常用。

5、用IDA 運(yùn)行exe,在exit后,運(yùn)行框直接消失;

所有答案弄完后,用命令行會(huì)方便些,便于查看所有結(jié)果。

win+r, cmd, cd 到指定文件夾,bomb.exe 001044;

或者用powershell ,在文件夾中shift+右鍵運(yùn)行powershell ? .\bomb.exe 001044

二、解題思路

首先找正確通關(guān)條件。找到后向上推,尋找關(guān)鍵的控制指令,滿足xxx條件才可正確跳轉(zhuǎn)。

當(dāng)然指令不一定完全按graph的順序執(zhí)行,有時(shí)按圖中的路徑無(wú)法運(yùn)行到想要的代碼,這時(shí)需要強(qiáng)行修改pc使跳轉(zhuǎn)到正確通關(guān)的位置。

理論上暫時(shí)想到強(qiáng)行修改pc的方式有以下幾種:

ret:? ? ? ? pc=stack[esp--]

jmp:? ? ? pc=JTA

mov?eip? xxx

三、流程

首先是一些關(guān)于讀入的函數(shù):(僅限于大意,不求甚解,不影響流程推進(jìn)即可)

readline:把輸入的一行當(dāng)成字符串讀到起始目標(biāo)地址。

sscanf: 把readline得到的字符串轉(zhuǎn)化為數(shù)字,返回?cái)?shù)字個(gè)數(shù)

二進(jìn)制炸彈:

第一關(guān):? ?字符串比較

進(jìn)入phase1,由explode_bomb向上推 ,-> eax==0 -> al==0 ,然后就不太好懂,必須開(kāi)始推。

觀察generaterandomstring函數(shù):

int __cdecl GenerateRandomString(int a1) {signed int v1; // edi@1int result; // eax@5v1 = 0;do{GenerateRandomNumber(2);if ( rand_div == 1 )*(_BYTE *)(v1 + a1) = 65;else*(_BYTE *)(v1 + a1) = 97;GenerateRandomNumber(26);result = v1 + a1;*(_BYTE *)(v1++ + a1) += rand_div;}while ( v1 < 10 );*(_BYTE *)(v1 + a1) = 0;return result; }

?不然看出函數(shù)隨機(jī)生成了一個(gè)長(zhǎng)度為10的字符串,起始地址為a1,并將a1[10]置為0;

回到匯編中,結(jié)合棧結(jié)構(gòu),其實(shí)a1=ebp-8 ,則[ebp-8,ebp+1]存的就是隨機(jī)生成的字符串。

由右方可知,ebx為起始地址存了輸入的字符串。

接下來(lái)的邏輯:

?起始時(shí)ecx+edx=生成字符串的起始地址(ebp-8),ecx為讀入字符串的起始地址。

至于為何ecx為首地址:

push eax?
call ? _read_line
pop?eax

IDA的邏輯中,通常傳參的方法是在call之前把參數(shù)push入棧。

我們的目的是 do [ecx]==[ecx+edx](while ecx++),直到[ecx+1]==0時(shí)達(dá)到目的。顯然輸入的字符串前10位要與生成的相同即可。? 運(yùn)行完randstring()后讀取出生成的字符串即可。

通關(guān)密碼:AxOlSPKPVo (后面可以隨便追加字符)

第二關(guān):尋找6個(gè)數(shù)滿足的一定規(guī)則

本人的_rand_div為6,進(jìn)入phase_2_6:

觀察call read_six_number 上下文邏輯,得到:讀入了長(zhǎng)度為6的int類(lèi)型數(shù)組,起始地址edx=ebp-0x18

依次關(guān)注以下的分支邏輯:

a[0]=_rand_div+1=4;? ? ? ? 6個(gè)數(shù)都>0;? ? ? ? ?rep(i,2,5)a[i]=a[i-1]*a[i-2];? ?a[2]+a[3]+a[4]+a[5]>4

綜合上述條件,一組通關(guān)密碼:4 1 4 4 16 64?

第三關(guān):

先看讀入:

call ? ?_read_line
push ? ?eax ? ? ? ? ? ? ; Src
call ? ?_phase_3

_phase_3中:

push ? ?ebx
mov ? ? ebx, [esp+4+Src]

則ebx=_readline_line返回值
然后對(duì)于每個(gè)子階段,都push ebx,即傳入的參數(shù)。

本人randomnumber修改randdiv=4,進(jìn)入phase3_4

3_4中,將輸入的字符串變?yōu)榱似鹗嘉恢脼閑bp-4的int數(shù)組。

觀察分支指令,輸入的第一個(gè)整數(shù)應(yīng)為rand(8)+0xDC

此后rand_div+6=第二個(gè)數(shù)

通關(guān)密碼:223 83 (后面的輸入無(wú)所謂)

第四關(guān):

進(jìn)入4_20。同上,容易得到ebp-4為讀入int數(shù)組的首地址。

觀察分支,要求返回值為1,那么只能輸入一個(gè)數(shù)!

接下來(lái)兩個(gè)分支要求輸入的一個(gè)數(shù)(記為temp)>1 且 >3E8h,那不就是>3E8h嗎,這個(gè)>1屬于沒(méi)看懂有啥意義。

接著觀察分支,要求[ebp+eax*4+var_20]==ebx。 跑一遍得到左邊==720。而ebx=func4_2([ebp-4])。 結(jié)合F5容易看出func4_2(x)=x!。

然后就是讓我百思不得其解的一段指令:

mov edx, 10624DD3h imul edx sar edx, 6 mov eax, edx shr eax, 1Fh add eax, edx

F5才知道這段指令功能是eax/=1000,具體為啥一臉懵,堪比平方根倒數(shù)算法帶給我的震撼程度。

那就不求甚解了。(temp/1000)!=720?, 則輸入數(shù)字在[6000,7000)內(nèi)即可.

第五關(guān):

先輸入Y。 再輸入突防指令,字符串地址eax作為參數(shù)傳入phase_impossible。

先來(lái)看phase_impossible調(diào)用的幾個(gè)內(nèi)置函數(shù):

call ? ?__imp__GetTickCount@0 ; GetTickCount()? ,返回從操作系統(tǒng)啟動(dòng)所經(jīng)過(guò)的毫秒數(shù),具體用處聽(tīng)老師說(shuō)是檢測(cè)程序運(yùn)行時(shí)間不能過(guò)長(zhǎng),否則爆炸(不太明白,暫咕,回來(lái)補(bǔ)上)。不過(guò)好像對(duì)本關(guān)沒(méi)啥限制。

call ? ?__imp__IsDebuggerPresent:函數(shù)會(huì)檢測(cè)debugger是否正在工作,如在工作就炸。這意味著我們不能設(shè)斷點(diǎn)動(dòng)態(tài)調(diào)試?其實(shí)不然。

?當(dāng)指令運(yùn)行到該函數(shù)上方,強(qiáng)行在此函數(shù)后一條指令set IP,跳過(guò)即可。(實(shí)際上要跳得更后,避開(kāi)這個(gè)分支。)

按照之前找通關(guān)點(diǎn)的邏輯看到最后,也沒(méi)發(fā)現(xiàn)如何正確通關(guān),而是全部指向bomb。那就可能涉及到指令強(qiáng)行修改pc。觀察_goto_buf_0,1,2,發(fā)現(xiàn)其作用均為 設(shè)置pc=eax;?而eax=ebp-0x100

_goto_buf_0,1,2分別對(duì)應(yīng)rand()函數(shù)的返回值為0,1,2。而rand()參數(shù)為3,也就是說(shuō)不論如何都會(huì)調(diào)用其中一個(gè)goto_buf。

現(xiàn)在要關(guān)注的是,ebp-0x100處是啥。觀察_to_hex函數(shù)。 由函數(shù)名可猜測(cè),這是把某個(gè)東西轉(zhuǎn)化成16進(jìn)制。函數(shù)有兩個(gè)參數(shù),ebx,eax. 分析可知,ebx為輸入字符串的首地址,eax=ebp-0x100.

此時(shí)就可以盲猜結(jié)論了(不求甚解),_to_hex函數(shù)的作用是將輸入的字符串轉(zhuǎn)化為16進(jìn)制機(jī)器碼,存儲(chǔ)于ebp-0x100處。而_goto_buf后會(huì)運(yùn)行輸入的這些指令。

我們的目標(biāo)是,輸入一串指令使得pc跳轉(zhuǎn)到正確通關(guān)的地方。

先找到目標(biāo)pc。在main函數(shù)的graph中找到通關(guān)部分的指令:

那么pc要跳到0x00401240.

同時(shí)為了維護(hù)下棧的平衡,要把esp初始為phase_impossible之前的狀態(tài)。容易想到如下指令:

mov esp, ebp pop ebp push 0x00401240 ret

?這還沒(méi)做完。_to_hex下面還有函數(shù)_check_buf_valid()來(lái)控制分支。其傳入的參數(shù)為_(kāi)rand_div,ebp-0x100. F5后得到函數(shù)功能是:將從ebp-0x100開(kāi)始的256個(gè)字節(jié)存儲(chǔ)值異或起來(lái),判斷是否==_rand_div的低8位。

為使之相等,可得到上述指令的機(jī)器碼,后面加上補(bǔ)償異或值的對(duì)應(yīng)數(shù)字即可。

ps:x86指令->機(jī)器碼可參考網(wǎng)站:?鏈接

不過(guò)注意到這里的通關(guān)提示還有彩蛋,于是找彩蛋。在左側(cè)的函數(shù)欄中成功找到_phase_secret。

指令修改為如下:

mov esp, ebp pop ebp push 0x00401240 push 0x004014F0 ret

update:不過(guò)這樣還是沒(méi)有維護(hù)棧平衡,似乎漏掉了call _phase_impossible的返回地址、、、

那就修改成如下,不返回0x00401240了,直接返回call _phase_impossible的返回地址。

mov esp, ebp pop ebp push 0x004014F0 ret

最終的第五關(guān)指令:89EC5D68F0144000C3F0?

最終效果:

緩沖區(qū)炸彈:

首先與二進(jìn)制炸彈不同,緩沖區(qū)的1-4關(guān)不是連續(xù),一次程序跑完的,而是相互獨(dú)立的,也就是說(shuō)要跑四次,每次都有一個(gè)密碼。具體原因可分析流程,發(fā)現(xiàn)關(guān)于讀入的只有 main函數(shù)->test函數(shù)->getbuf函數(shù),然后停止到getxs函數(shù)處理讀入。

推進(jìn)一遍流程,發(fā)現(xiàn)按照graph順序跑一遍是找不到想要的木馬的,那就必須要用到強(qiáng)行修改pc的方式。觀察哪些指令有可能協(xié)助pc跳轉(zhuǎn)。

一番搜尋發(fā)現(xiàn)唯一可疑的地方是getbuf函數(shù)的ret指令。那就先研究一下代碼邏輯和棧結(jié)構(gòu),如下:

?

棧地址內(nèi)容具體值操作說(shuō)明
test返回地址
0019FEF8原來(lái)的ebp此后ebp=此地址,記為esp0
金絲雀0DEADBEEF
……
0019FEDC第二關(guān)=cookie
getbuf返回地址
0019FED4esp0此后ebp=此地址,記為esp1
esp1-12輸入機(jī)器碼的起始地址第三關(guān)跳到這里
esp1-12作為參數(shù)傳入getxs
getxs返回地址


test函數(shù)到getbuf之前,大概實(shí)現(xiàn)了設(shè)置金絲雀,并調(diào)用chkstk函數(shù)(仔細(xì)研究發(fā)現(xiàn)其功能就是開(kāi)辟棧空間,就是_alloca),不過(guò)chkstk對(duì)通關(guān)沒(méi)啥影響。。

進(jìn)入getbuf。如上方棧結(jié)構(gòu),記esp1=0x0019FED4. 然后令eax=esp1-0xC,并作為參數(shù)傳入getxs。 隨便輸入幾次字符后可以猜測(cè)出getxs的功能 : 處理輸入的字符串,變?yōu)橐詄ax為首地址的對(duì)應(yīng)機(jī)器碼。?紅色標(biāo)注的棧內(nèi)容,是getbuf函數(shù)的返回地址。試想:如果我們輸入的字符串覆蓋掉了原先的返回地址,那么可以為所欲為了。

現(xiàn)在開(kāi)始分析關(guān)卡。

第一關(guān):

?把紅色的返回地址覆蓋為0x004011E0即可。覆蓋后有call exit,程序會(huì)自動(dòng)退出。

密碼:?00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ?E0 11 40 00? (前24字節(jié)隨意)

由于小端尋址,13-16 字節(jié)要與實(shí)際值反過(guò)來(lái)。

第二關(guān):

?

要求除了要強(qiáng)行把pc設(shè)置到這里來(lái),還要使得[esp+8]==cookie。

先跑一遍得到cookie的值,然后分析esp值:

getbuf的ret指令之前,esp=0019FED4, 對(duì)應(yīng)輸入字符的 13-16 字節(jié)。ret后esp+=4, trojan 2中esp-=4; 則mov ebx,[esp+8]指令中的esp=0019FED4. 那么把輸入字符的 21-24 位修改為cookie值即可。

通關(guān)密碼:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ?00 12 40 00 00 00 00 00 FE 65 C6 71?

第三關(guān):

容易看出通關(guān)要求global value==cookie. 那我們要做的就是通過(guò)插入指令修改global value。

我的做法是,使getbuf ret到修改global value的指令。?修改global value的指令完之后,要再緊跟修改pc的指令跳到trojan 3部分。這里我采用ret ,同時(shí)往棧中塞入trojan 3地址。

通關(guān)密碼:B9 FE 65 C6 71 89 0D 04 90 40 00 C3 00 00 00 00 ?C8FE1900 50124000

首先將getbuf返回地址覆蓋為 0019FEC8,也就是讀入機(jī)器碼的起始地址。 然后前12個(gè)字節(jié)代表的指令為:

mov ecx,0x71C665FE mov [0x00409004],ecx ret

注意:mov指令的目的操作數(shù)為存儲(chǔ)器時(shí),源操作數(shù)必須指定長(zhǎng)度,所以直接:mov [0x00409004],?0x71C665FE 是錯(cuò)誤指令。

ret后pc跳轉(zhuǎn)到0x401250。

第四關(guān):

與第三關(guān)唯一的不同是,第四關(guān)函數(shù)結(jié)尾不是exit, 而是ret。分析trojan 4棧結(jié)構(gòu),發(fā)現(xiàn)其函數(shù)是棧平衡的(即:call塞入的返回地址使esp-4 ,函數(shù)執(zhí)行過(guò)程前后esp不變,ret使esp+4)。

這意味著,如果繼續(xù)延用第三關(guān)密碼,pc將ret到輸入字符的21-24字節(jié)。

那我們把21-24字節(jié)改成想要的地址就好了。我的做法是設(shè)置21-24字節(jié)為exit()函數(shù)的地址。

通關(guān)密碼:B9 FE 65 C6 71 89 0D 04 90 40 00 C3 00 00 00 00 ?C8FE1900 A0 12 40 00 70 15 40 00

ps:?00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ?E4FE1900 A0 12 40 00 ?70154000 ?B9 FE 65 C6 71 89 0D 04 90 40 00這也是個(gè)合理的通關(guān)密碼,不過(guò)字節(jié)數(shù)長(zhǎng)了。

第0關(guān):

老師的要求是顯示:“ 不錯(cuò)哦,緩沖區(qū)溢出成功,而且getbuf返回xxxxxxxx ”。

觀察到這段話出現(xiàn)在test函數(shù)中,要求

(1)金絲雀不變。其實(shí)金絲雀那個(gè)地址的值一直都不變,輸入字節(jié)沒(méi)那么長(zhǎng)到影響金絲雀的地步。但是我們觀察指令是:cmp ? ? [ebp+var_4], 0DEADBEEF。

這意味著getbuf結(jié)束后ebp要回到原來(lái)的狀態(tài)!

結(jié)合棧結(jié)構(gòu)可知,設(shè)置輸入字符的13-16字節(jié)為ebp原先值即可。

(2)eax=cookie.? 類(lèi)似trojan 2, 在1-12字節(jié)填充指令:mov eax ,0x71C665FE;ret 。

再修改一下返回地址即可。

通關(guān)密碼:B8 FE 65 C6 71 C3 00 00 00 00 00 00 F8 FE 19 00 ?C8FE1900 81114000

總結(jié)

以上是生活随笔為你收集整理的计算机系统实验:二进制炸弹+缓冲区炸弹 (自我学习笔记)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。