




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
SUNYAT-SKNI
《計算機組成原理實驗》
實驗報告
(實驗一)
學院名稱:數據科學與計算機學院
專業(班級):
學生姓名:
學號
時間:2019年10月8日
成績:
實驗一:X86匯編基礎二進制炸彈
一.實驗目的
(1)初步認識X86匯編語言;
(2)掌握閱讀程序反匯編代碼的方法,了解程序在機器上運行的實質;
(3)熟悉Linux環境、掌握調試器gdb和反匯編工具objdump的使用。
二.實驗內容
使用課程知識拆除一個"BinaryBomb”(,簡稱炸彈)來增強對程序的機器級表示、
匯編語言、調試器和逆向工程等理解。二進制炸彈是一個Linux可執行C程序,包含
phase.l~phase_6共6個階段和一個隱藏階段secret_phase0你將獲得一個唯一且每
位同學差異化的炸彈程序,炸彈運行各階段要求輸入一個字符串,若輸入符合程序預期,該
階段炸彈被“拆除”,否則“爆炸”。實驗目標是你需要拆除盡可能多的炸彈。
每個炸彈階段考察機器級語言程序不同方面,難度遞增。
階段1:字符串比較
階段2:循環
階段3:條件/分支:含switch語句
階段4:遞歸調用和棧
階段5:指針
階段6:鏈表/指針/結構
隱藏階段,第4階段的之后附加一特定字符串后才會出現
拆彈技術:為了完成二進制炸彈拆除任務,你需要
1.使用gdb調試器和objdump反匯編工具;
2.單步跟蹤調試每一階段的機器代碼
3.理解匯編語言代碼的行為或作用
4.進而設法“推斷”出拆除炸彈所需的目標字符串c
5.需要在每一階段的開始代碼前和引爆炸彈的函數前設置斷點,便于調試。
三.實驗器材
PC機一臺,裝有Linux操作系統的虛擬機一套。
四.實驗過程與結果
說明:根據需要書寫.相關內容,如:
程序流程圖、設計的思想與方法、分析、實驗步躲和實驗結果及分析等。
4.1第一關
在剛接觸這一大堆匯編代碼時,我是迷茫的。好在pdf上給出了第一關的解決方法,而
且第一關的難度也并不大,
Phase」函數一開始進行棧指針修改,后而我們知道這是函數調用時分配棧空間的必經
之路。然后函數壓棧兩個數據,執行一個函數并進行一個判斷,最后返回。
觀察至ijstrings_not_equal函數的調用,它判斷棧頂的前兩個元素。如果它們相等,就
修改eax為0;如此,緊隨其后的jne就不會觸發,也就不會導致<explode_bomb>的調用。
棧頂的兩個元素分別為我們的輸入,和$0x804a21c內存處的數據.用gdb查看,可知
它是字符串,為
Breakpoint1,0x08048b60inphase_l0
(gdb)disas
Jumpofassemblercodeforfunctionphase_l:
0x08048b5a<+0>:push%ebp
0x08048b5b<+l>:mov%esp,%ebp
0x08048b5d<:+3>:sub$0x10,%esp
>0x08048b60<+6>:push$0x804a21c
0x08048b65<+ll>:pushl0x8(%ebp)
0x08048b68<:+14>:call0x804904b<s:rings_not_equal>
0x08048b6cl<:+19>:add$0xl0,%esp
0x08048b70<+22>:test%eax,%eax
0x08048b72<:+24>:jne0x8048b76<phase_l+28>
0x08048b74<+26>:leave
0x08048b75<+27>:ret
0x00040b7G<+20>:call0x004927-f<explode_bomb>
0x08048b7b<:+33>:Jmp0x8048b74<phase_l+26>
Endofassemblerdump.
(gdb)x0x804a21c
0x804a21c:0x61632049
(gdb)x/sOxSO^aZlc
3x904a21c:<error:Cannotaccessmemoryataddress0x304a21c>
(gdb)x/s0x80021c
Ox804a21c:"IcanseeRussiafrommyhouseI"
(gdb)
只要讓它們相等即可,所以我們本關的答案毫無疑問就是
IcanseeRussiafrommyhouse!
4.2第二關
第二關脫離了指導開始獨立作業,我再一次迷茫了。第二關的代碼數量突然陡增,同樣
先觀察代碼;首先仍然是準備工作,然后程序調用了一個叫做<read_six_numbers>的函
數,我們找到這個函數一探究竟。
80492bf:55push%ebp
80492c0:89e5mov%esp,%ebp
80492c2:83ec08sub$0x8,%esp
S0492c5:8b450cmovOxc(%ebp),%eax
80492c8:8d5014lea0x14(%eax),%edx
80492cb:52push%edx
80492cc:8d5010lea0x10(%eax),%edx
80492cf:52push%edx
80492d0:8d530cleaOxc(%eax),%edx
80492d3:52push%edx
S0492d4:8d5008lea0x8(%eax),%edx
80492d7:52push%edx
80492d8:8d5004lea0x4(%eax),%edx
80492db:52push%edx
80492dc:50push%eax
80492dd:6861a40408pushS0x804a461
80492e2:ff7508pushl0x8(%ebp)
S0492e5:e826f5ffffcall8048810<_isoc99_sscanfgplt>
可以看到函數用scanf函數讀取用戶輸入的六個數據,地址間間隔為4;再深究可以在
gdb中找到格式化字符為%d整形,所以本關應該是要求我們輸入6個整數型。
8048b8f:8d45delea-0x24(%ebp),%eax
8048b92:50push%eax
8048b93:ff7508pushl0x8(%ebp)
8048b96:e824070000call80492bf<readsixnumbers>
我們知道0x8(%ebp)是我們的輸入,那么<read_six_numbers>就是把這個輸入變成
六個整形放入-Ox24(%ebp)中,可以假設這里是一個整形數組air。
再向下看,函數進行一次判斷
8048b9e:837dde05cmpl$0x5,-0x24(%ebp)
8048ba2:7707ja8048bab<phase_2^0x2e>
8048ba4:bb01000000mov$0x1,%ebx
8048ba9:ebOfjmp8048bba<phase_2+0x3d>
8048bab:e8cf060000call804927f<explode_bomb>
也就是arr[0]>5時就觸發爆炸。我們知道了輸入的第一個數不能大于5.
再繼續,下面進入一個循環語句。
8048bb2:83c301add$0x1,%ebx
8048bb5:83fb06emp$0x6,%ebx
8048bb8:7418je8048bd2<phase_2+0x55)
8048bba:8b449dd8mov-0x28(%ebp,%ebx,4),%eax
8048bbe:8945d4mov%eax,-0x2c(%ebp)
8048bcl:89d9mov%ebx,%ecx
8048bc3:d3eOshl%cl,%eax
8048bc5:39449ddeemp%ea|x,-0x24(%ebp,%ebx,4)
8048bc9:74e7je8048bb2<phase_2+0x35>
8048bcb:e8af060000call804927f<explode_bomb>
Ebx應該是循環的控制單位,每次循環自增1,等于6時跳出循環。eax保存一個變址尋
址的結果,然后進行eax位左移,并把它與當前尋址結果的前一個地址進行比較,不相等就
觸發爆炸。如果循環順利執行完畢,本關就被破解。
至此邏輯已經很明確r,我們可以把它翻譯成c代碼。
if(arr[0]>5)
explode_bombl);
for(inti=l;i!=6;i++){
inttmp=arr|i-l];
tmp<<i;
if(tmp!=arr[ij)
explode_bombl);
}
End
就這樣,假設我們的arHO1是1,則第一次左移1位,第二次左移2位…循環5次,我們
就得到arr數組應該裝著的6個整形數字。
Step1:1
Step2:2
Step3:8
Step4:64
Step5:1024
Step6:32768
所以本關的答案是12864102432768
4.3第三關
順利完成第二關終于提升了我的一點信心,再看第三關就沒那么可怕(不)
一開始函數壓棧4個數值,然后調用scanf函數,可以推斷它們都是scanf的參數。
8048bf9:8d45fOlea-0x10(%ebp),%eax
8048bfc:50push%eax
8048bfd:8d45eclea-0xl4(%ebp),%eax
8048c00:50push%eax
8048c01:686da40408push$0x804a46d
8048c06:ff7508Dushl0x8Rebp)
8048c09:e802fcffffcall8048810<_isoc99_sscanf@plt>
-OxlO(%ebp)和-Oxl4(%ebp)都是明確的地址,0x8(%ebp)是我們的輸入,這個
0x804a46d就顯得很可疑,gdb一看就知道它是格式化字符串。
(gdb)x/s0x804a46d
)x804a46d:"%d%d"
那么本關就是讓我們輸入兩個整形,它們分別存儲在-0xl4(%ebp)和-0xl0(%ebp)兩
個位置.scanf函數的返回值放在eax中,它的返回值是2(接受兩個參數),我們設
-0xl4(%ebp)和-0xl0(%ebp)的兩個參數為a和b0
緊跟其后的是判斷語句cmpl$0x7,-0xl4(%ebp)
ja8048ca8<phase_3-0xc0>〃爆炸
限制了a的取值,a必須小于等于7.又由于ja比較無符號數,ja還要大于等于0
下面的語句是解決本題的關鍵性語句jmp*0x804a26c(,%eax,4)
一個基址尋址,*0x204a26c里面的東西是什么?可能是一個跳轉表,用gdb杳看之。
(gdb)x/iuwxux?04adbc
0x804a26c:0x0E048c310x08048c380x08048c7e0x08048c85
0x804a27c:0x0E048c8c0x08048c930x08048c9a0x08048cal
0x804a28c<array.30E5>:0x7564616d0x73726569
果然如此,如此一來,我們的輸入a(0~7)就會導致8種跳轉。這應該是一個switch語句!
再往下就是一些算術悚作,對不同的a輸入會有不同的算術。唯一的生死點是一個判斷
語句cmpl,它限制了a的取值為0<=a<=5.
8048c60:837dec05cmpl$0x5,-0x14(%ebp)
8048c64:7f05jg8048c6b<phase_3+0x83)
8048c66:3945fOcmp%eax,-0x10(%ebp)
8048c69:7405je8048c70<phase_3+0x88)
8048c6b:e8Of060000call804927f<explode_bomb>
最后讓eax,也就是算術結果和第二個輸入b相等即可;我們也不需要通讀代碼來計算
輸入,只需要當程序執行到這句時,用gdb查看一下eax的值,就能拿到我們的第二個輸入
bo
本題應該有a為0,1,2,3,4,5六組答案.我們只取一種a=0的情況,這時計算得
到的b是-117.第三關的答案就是0-117!
4.4第四關
第四關與前面的不同在于它多了一個<func4>函數。
先觀察phase_4主體,發現和第三關的輸入方式一樣,都是兩個整形a和b。
8048d22:8d45f0lea-0x10(%ebp),%eax
8048d25:50push%eax
8048d26:8d45eclea-0x14(%ebp),%eax
8048d29:50push%eax
8048d2a:686da40408pushS0x804a46d
8048d2f:ff7508pushl0x8(%ebp)
8048d32:e8d9faffffcall8048810<_isoc99_sscanf€plt>
這次我們觀察到a的輸入范圍被限制到了0<=a<=14
8048d3f:837decOecmplSOxe,-0x14(%ebp)
8048d43:7605jbe8048d4a<phase_4+0x39>
8048d45:e835050000call804927f<explode_bomb>
緊跟其后的是壓棧三個參數,14,。和a,然后調用函數func4,我們判斷func4接受三
個參數,而這次調用就是七nc4(a,0,14)
8048d4d:6aOepush$0xe
8048d4f:6a00push$0x0
8048d51:ff75ecpushl-0x14(%ebp)
8048d54:e860ffffffcall8048cb9<func4>
好的我們進入func4的代碼
8048cc0:8b4508mov0x8(%ebp),%eax
8048cc3:8b550cmovOxc(%ebp),%edx
8048cc6:8b4d10mov0x10(%ebp),%ecx
8048cc9:29dlsub%edx,%ecx
8048ccb:89cbmov%ecx,%ebx
8048ccd:clebIfshrSOxlf,%ebx
8048cd0:01cbadd與ecx,%ebx
8048cd2:dlfbsar%ebx
8048cd4:01d3add%edx,%ebx
8048cd6:39c3cmp%eax,%ebx
8048cd8:7fObJg8048ce5<func4+0x2c>
8048cda:39c3cmp%eax,%ebx
8048cdc:7c1cjl8048cfa<func4+0x41>
8048cde:89d8mov%ebx,%eax
8048ce0:8b5dfcmov-0x4Rebp),%ebx
8048ce3:c9leave
8048ce4:c3ret
首先是從棧中拿出參數放入寄存器,然后對參數進行了一系列的加減移位計算,最后進
行兩次判斷,這樣就是三條分支語句;應該是if-elseif-else語句。
判斷1:ebx>eba時:
8048ce5:83ec04sub$0x4,%esp
8048ce8:8d4bfflea-0x1(%ebx),%ecx
8048ceb:51push%ecx
8048cec:52push%edx
8048ced:50push%eax
8048cee:e8cCffffffcall8048cb9<func4>
8048cf3:83c410add$0x10,%esp
8048cf6:01c3add%eax,%ebx
8048cf8:ebe4jmp8048cde<func4+0x25>
這時把eax,edx,ebx-1遞歸傳入func4,返回func4(eax,edx,ebx-l)。
判斷2:ebx<eba時:
8048cfa:83ec04sub$0x4,%esp
8048cfd:ff7510pushl0x10(%ebp)
8048do0:8d5301lea0x1(%cbx),%cdx
8048d03:52push%edx
8048d04:50push%eax
8048d05:e8afffffffcall8048cb9<func4>
8048d0a:83c410add$0x10,%esp
8048d0d:01c3add%eax,%ebx
8048d0f:ebcdJmp8048cde<func4+0x25>
這時把eax,ebx+1,原始的ecx遞歸傳入func4,返回func4(eax,ebx+l,ecx+edx)
乍一看這個函數很難知道它想用遞歸實現什么,但是用高級語言復現這個函數是很簡單
的,我們可以用python實現該函數,并逐一嘗試輸入a為0~14的情況。
Func4執行完畢后,返回值在eax中,隨后執行最后的步驟
8048d5c:83f8Ifemp$0xlf,%eax
8048d5f:7506jne8048d67<phase_4+0x56>
8048d61:837dfOIfcmpl$0xlf,-0x10(%ebp)
8048d65:7405je8048d6c<phase_4+0x5b>
8048d67:e813050000call804927f<explode_bomb>
判斷返回值和輸入b是否為0xlf(31),這樣我們的輸入a必須讓函數返回31,b必須是
31.
使用python模擬該程序的運行,結果如卜:
In二6二:deffun(a,d,c):
c-=d
b=c
b//=2
b+=d
ifb>a:
returnb+fun(a,d,b-l)
elifb<a:
returnb+fun(a,b+1,c+d)
else:
returnb
In二8二:foriinrange(1,14):
print(wheninput',i,',func4return',fun(i,0,14))
wheninput1,func4return11
wheninput2,func4return13
wheninput3,func4return10
wheninput4,func4return19
wheninput5,func4return15
wheninput6,func4return21
wheninput7,func4return7
wheninput8,func4return35
wheninput9,func4return27
wheninput10,func4return37
wheninput11,func4return18
wheninput12,func4return43
wheninput13,func4return31
可見輸入為13時,func4返回31.即a=13,b=31就是我們要的答案。
第四關答案為1331!
4.5第五關
我們已經掌握了一些套路,接下來的關卡雖然難度大了,但并沒有前幾關那么棘手了。
一開始還是觀察輸入格式,發現并沒有scanf的格式化輸入,可以判斷本關輸入是一個
字符串;程序一開始有mov0x8(%ebp),%ebx
push%ebx
call8049029<string_length>
cmp$0x6,%eax
jne8048dee<phase_5+0x6f>
把我們的輸入字符串放入一個string_length函數中,通過閱讀這個函數發現它會返回
字符串長度,保存在eax中。然后eax與6作比較,不相等則爆炸,于是我們判斷本關是要求
我們輸入一個6長度字符串。
緊隨其后的是一段循環語句
8048da2:b800000000mov$0x0,%eax
8048da7:Ofb61403movzbl(%ebx,%eax,1),%edx
8048dab:83e2Ofand$0xf,%edx
8048dae:Ofb6928ca20408movzbl0x804a28c(%edx),%edx
8048db5:885405edmov%dl,-0x13(%ebp,%eax,l)
8048db9:83cO01add$0xl,%eax
8048dbc:83f806emp$0x6,%eax
8048dbf:75e6jne8048da7<phase_5+0x28>
Ebx是輸入的字符串,設為str,eax應該是for循環的控制單位,也做下標使用,設為i。
程序每次循環讀取str[i]的值,然后用一個andOxf取其后四位。隨后有一個基址尋址
0x804a28c(%edx),不知道這塊內存存儲著什么,打開看一看。
(gdb)x/sOx804a28c
0x804o28c<array.3035>:"rraduicrsnfotvbylSoyouthinkyouconstopthebombwithCtrlc,doyou?'
|(gdb)
是一串字符串,設它為s,那么這句就是取s[str[i]&Oxf];后面還把它放入了
-0xl3(%ebp,%eax,l)這段地址中,如此一來我們就可以翻譯這段代碼為C代碼:
for(inti=0;i!=6;i++){
chartmp=s[str[i]&Oxf];
arr[i]=tmp;
}
再往后就是一個<strings_not_equal>函數的調用
8048dc8:6862a20408pushS0x804a262
8048dcd:8d45edlea-Ox13(%ebp),%eax
8048dd0:50push%eax
8048ddl:e875020000call804904b<strings_not_equal>
8048dd6:83c410add$0xl0,%esp
8048dd9:85cOtest%eax,%eax
8048ddb:7518jne8048df5<phase_5+0x76>
函數比較-0xl3(%ebp),也就是上面的arr,和0x804a262內存處的字符串。打開
0x804a262看看里面是什么.
(gdb)x/s0x804a262
0x804a262:"brums"
一個單詞bruins,要讓arr和它相等,就要從s中分別找到這六個字母的下標,然后用
把這些下標作為輸入的六個字符的后四位來形成我們需要的目的字符串。
尋找下標和轉為字符串的工作可以用高級語言實現,下面是python實現過程。
s=,zmaduiersnfotvbylSoz,
print(s.find(,bJ))
print(s.find(?r'))
print(s.find('u'))
print(s.find(,i))
print(s.find('n'))
print(s.find。s'))
13
6
3
4
8
一
我們要把找到的下標轉成字符形式
把高半個字節設置成0000可能會出現轉義字符不方便輸入
我們這里設置成0004,也就是數值上增力04X16=64
print(chr(64+s.findCb')))
print(chr(64+s.find('r')))
print(chr(64+s.find('u')))
print(chr(64+s.find(i)))
print(chr(64+s.find('n')))
print(chr(64+s.find('s')))
F
C
D
H
G
于是我們就得到了一種可能的答案MFCDHG。
即第五關的答案為MFCDHG。
4.6第六關
還是從輸入數據格式入手,發現和第二關的處理輸入的部分相同,都是借助
<read_six_numbers>函數,把輸入用scanf截獲為六個整數型0
8048el4:8d45c4lea-0x3c(%ebp),%eax
8048el7:50push%eax
8048el8:ff7508pushl0x8(%ebp)
8048elb:e89f040000call80492bf<read_six_numbers>
它們保存在-0x3c(%ebp)處的一個序列,設為arr。
緊隨其后的是一個嵌套的二重循環語句
8048e23:be00000000mov$0x0,%esi
8048e28:8b44b5c4mov-0x3c(%ebp,%esi,4),%eax
8048e2c:83e801sub$0x1,%eax
8048e2f:83f805cmp$0x5,%eax
8048e32:77Oc.ia8048e40<phase6+0x3f>
8048e34:83c601add$0x1,%esi
8048e37:83fe06cmp$0x6,%esi
8048e3a:7451je8048e8d<phase_6+0x8c>
8048e3c:89f3mov%esi,%ebx
8048e3e:ebOfjmp8048e4f<phase_6+0x4e>
8048e40:e83a040000call804927f<explode_bomb>
8048e45:ebedjmp8048e34<phase_6+0x33>
8048e47:83c301add$0x1,%ebx
8048e4a:83fb05cmp$0x5,%ebx
8048e4d:7fd9Jg8048e28<phase_6+0x27>
8048e4f:8b449dc4mov-0x3c(%ebp,%ebx,4),%eax
8048e53:3944b5cOcmp%eax,-0x40(%ebp,%esi,4)
8048e57:75eejne8048e47<phase_6+0x46>
8048e59:e821040000call804927f<explode_bomb>
8048e5e:ebe7jmp8048e47<phase_6+0x46>
第一層循環先拿出arr|i],然后做一個判斷
8048e28:8b44b5c4mov-0x3c(%ebp,%esi,4),%eax
8048e2c:83e801sub$0xl,%eax
8048e2f:83f805cmp$0x5,%eax
8048e32:77Ocja8048e40<phase_6+0x3f>〃爆炸
就是判斷arr[i]是否小于等于6,因為使用了無符號數判斷ja,還要滿足arHi]>=0。
后面有一個小循環,取當前的i并加1,然后增長到5,設這個變量為ii,則
8048e53:3944b5cOcmp%eax,-0x40(%ebp,%esi,4)
8048e57:75eejne8048e47<phase_6+0x46>
8048e59:e821040000call804927f<explode_bomb>
判斷語句讓air㈤==arr[i-l]時觸發炸彈。
把這段語句翻譯為C代碼如F:
for(inti=0;i!=6;){
if(arr[i]-l>5)
Explode_bomb();
i++;
for(intii=i;ii<=5;ii++){
if(arr[ii]==arr[i-l])
Explode_bomb();
)
}
也就是arr中的元素必須是0~6的數字,而且不能重復。
下面的一段程序又是一個二重循環
8048e60:8b5208mov0x8(%edx),%edx
8048e63:83cO01add$0xl,%eax
8048e66:39c8emp%ecx,%eax
8048e68:75f6jne8048e60<phase_6+0x5f>
8048e6a:8954b5demov%edx,-0x24(%ebp,%esi,4)
8048e6e:83c301add$0x1,%ebx
8048e71:83fb06emp$0x6,%ebx
8048e74:74leje8048e94<phase_6+0x93>
8048e76;89demov%ebx,%esi
8048e78:8b4c9dc4mov-0x3c(%ebp,%ebx,4),%ecx
8048e7c:b801000000mov$0xl,%eax
8048e81:ba54cl0408mov$0x804cl54,%edx
8048e86:83f901emp$0x1,%ecx
8048e89:7fd5jg8048e60<phase_6+0x5f>
8048e8b:ebddjmp8048e6a<phase_6+0x69>
這段代碼是循環尋找0x804cl54+arr[i]*8的地址,然后把這塊地址放到
-0x24(%ebp,%esi,4)+,它應該是儲存指針的數組,至于這是指向什么的指針,我們可以
在gdb中找至iJOx804cl54看一看。
(gdb)X/20WX0x804cl54
0X804C154<nodel>:0x0000005c0x000000010X0804C1600x000003b2
0X804C164<node2+4>:0x000000020x0804cl6c0x000000660x00000003
UX8U4C174<node3+8>:0X08D4C1780X0U00Q0C30X000000040X0804C184
0X804C184<node5>:0X000001C90x000000050x0804c1900x00000310
0X804C194<node6+4>:0x000000060x000000000x000000000x31333731
一個叫做node的結構體,那么數組-0x24(%ebp)就是node*nodes[]類型。
再觀察結構體的內部數據,由三部分組成,value,number和next,這是我們熟悉的
鏈表結構,C語言代碼如下:
Structnode{
Intval;
Intnum;
Node*next;
}
如此一來上面的步驟就說得通了,翻譯成C代碼(0x804cl54用L表示)
For(inti=0;i!=6;i-+){
Intc=arr[i],a=1;
Node*d=L;
If(c>l){
For(;a!=c;a++){
d=d->next;
)
Nodes[i]=d;
}
很顯然這段代碼就是按照我們輸入arr中的六個數,以L為鏈表頭搜索鏈表的第arr[i]個
結點。并把鏈表結點保存在nodes[i]中。
再下面的一段程序,很顯然是按照nodes的順序重新串接鏈表的一系列操作。
mov-0x24(%ebp),%ebx
mov-0x20(%ebp),%eax
mov%eax,0x8(%ebx)
mov-Oxlc(%ebp),%edx
mov%edx,0x8((H)eax)
mov-0xl8(%ebp),%eax
mov%eax,0x8(%edx)
mov-0x14(%ebp),%edx
mov%edx,0x8(%eax)
mov-0x10(%ebp),%eax
mov%eax,0x8(%edx)
movl$0x0,0x8(%eax)
最后一段判斷程序,遍歷鏈表并比較鏈表前一個元素和后一個元素
8048ebc:be05000000mov$0x5,%esi
8048ecl:eb08jmp8048ecb<phase_6+0xca>
8048ec3:8b5b08mov0x8(%ebx),%ebx
8048ec6:83ee01sub$0x1,%esi
8048ec9:7410je8048edb<phase_6+0xda>
8048ecb:8b4308mov0x8(%ebx),%eax
8O48ece:8b00mov(%eax),%eax
8048ed0:3903cmp%eax,(%ebx)
8048ed2:7defjge8048ec3<phase_6+0xc2>
8048ed4:e8a6030000call804927f<explode_bomb>
8048ed9:ebe8jmp8048ec3<phase_6+0xc2>
Eax是ebx的后一個鏈表結點,必須滿足ebx>eax才能不觸發炸彈,也就是整個鏈表的
值必須是降序的。
這樣這一關的用意就很明顯了,就是要我們輸入6個數字,這六個數字就是重排后鏈表
結點的順序;我們要保證這個順序是降序的,就要按照合適的順序輸入123456.
排序的工作可以借助高級語言完成,python的實現如下。
nodes=[(0x5c,1),(0x3b2,2),(0x66,3),(0xc3,4),(0xlc9,5),(0x310,6)1
nodes,sort()
nodes,reverse()
nodes
[(946,2),(784,6),(457,5),(195,4),(102,3),(92,1)]
答案為265431
即本關答案為265431
4.7隱藏關
我們驚喜地發現事情還沒有結束!在phase_6之后還有一段<secret_phase>,它要怎
么觸發呢?我們在源碼中搜索它,發現它出現在下面的位置。
804949a:75cajne8049466<phase_defused+0x5c>
804949c:83ecOcsub$0xc,%esp
804949f:681ca30408pushS0x804a31c
80494a4:e817f3ffffcall80487c0<puts@plt>
80494a9:c7042444a30408movlS0x804a344,(%esp)
80494b0:e80bf3ffffcall80487c0<puts@plt>
80494b5:e88dfaffffcall8048f47<secret_phase>
在<phase_defused>函數中,而這個函數是每次拆彈成功后才被調用的。讀代碼可以
發現這里先調用scanf,要我們輸入一段字符串;然后調用<strings_not_equal>,當相等
時才能調用<secret_phase>函數。可是每一關最后都調用這個函數,這個輸入應該出現在
哪里呢?找到scanf的輸入參數
lea-0x5c(%ebp),%eax
push%eax
lea-0x60(%ebp),%eax
push%eax
lea-0x64(%ebp),%eax
push%eax
push$0x804a4c7
push$0x804c8f0
call8048810<_isoc99_sscanf@plt>
查看其中的格式化字符如卜.:
(gdb)x/s0x804a4c7
)x804a4c7:H%d%d%s"
是跟在兩個整數后面的一段字符串!要輸入兩個整數的是第三關和第四關,而第三關已
經有了輸入數最的限制,所以觸發關卡是要在第四關后面多輸入一串特殊字符串。
push50x804a4d0
1ea-0x5c(%ebp),%eax
push%eax
call804904b<strings_not_equal>
后面把輸入字符串和0x804a4d0進行比較,打開Ox8O4a4do查看,它就是特殊字符串。
(gdb)x/s0x804a4do
0x804a4d0:"SecretSYSU1'
進關條件就是在第四關輸入1331SecretSYSU
Curses,you'vefoundthesecretphase!
Butfindingitandsolvingitarequitedifferent...
我們進入了關k,下面瀏覽這一關的代碼。
可以看見函數一開始調用了read」ine,把輸入放在eax中。然后是<strtol@plt>函數
的調用,strtol(%eax,NULL,10)。也就是我們輸入的字符串應該是10進制數,它會被轉
換成一個長整形C緊隨其后有一條判斷
8048f62:8d40fflea-Ox1(%eax),%eax
8048f65:83c410add$0xl0,%esp
8048f68:3de8030000cmp$0x3e8,%eax
8048f6d:7735ja8048fa4<secret_phase+0x5d
判斷(%eax-l)>0x3e8時觸發爆炸,限制了我們的輸入范圍。
之后是fun7的調用,參數分別為我們的輸入和$Ox8O4cOaO,查看內容可知為24.
(gdb)X/UJX0x804c0a0
0x804c0a0<nl>:0x00000024
執行fun7(0x804c0a0,input),后面可以看到如果返|叫直為3就完成本關。
查看fun7函數,通讀可知是一個if-elseif-else語句。
8048efa:8b5508mov0x8(%ebp),%edx
8048efd:8b4d0cmovOxc(%ebp),%ecx
8048f0
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年食品與飲料行業食品行業食品安全監管效果評估報告
- 2025高三復習計劃與健康管理
- 文化娛樂行業消費者行為分析報告:2025年市場細分與消費者行為數據挖掘與分析
- 2025年遠程醫療技術對偏遠地區醫療服務質量的影響報告
- 2025年廣播影視行業融合發展中的行業市場細分市場布局策略研究報告
- 2025年工業機器人在柔性制造系統中的應用與人工智能技術融合報告
- 2025年礦山智能化開采中無人作業技術智能化設備研發與創新戰略實施研究報告
- 人工智能賦能2025年智能投顧平臺合規運營風險管理與合規體系建設報告
- 醫療器械注冊審批制度改革2025:對中小型企業的生存與發展影響報告
- 中國橡膠奶頭項目投資計劃書
- 2022國家電網企業文化、電力與能源戰略題庫(答案)
- 完整的策劃書模板
- 土木工程材料期末考試試題庫
- 旅游定制師培訓課件
- 中國青光眼指南
- 智慧礦山行業洞察研究報告 2023
- 《體態與健康》課件
- 《國有企業采購操作規范》【2023修訂版】
- 熱水供水系統運營維護服務投標方案(技術標)
- 軸承安裝施工方案
- 職業生涯規劃與求職就業指導智慧樹知到課后章節答案2023年下中南大學
評論
0/150
提交評論