1. 程式人生 > >CMU-CSAPP-Lab2拆解二進位制炸彈

CMU-CSAPP-Lab2拆解二進位制炸彈

一、 實驗目的

1.理解C語言程式的機器級表示。
2.初步掌握GDB偵錯程式的用法。
3.閱讀C編譯器生成的x86-64機器程式碼,理解不同控制結構生成的基本指令模式,過程的實現。

二、實驗工具

  1. SecureCRT
  2. Linux
  3. Objdump命令反彙編
  4. GDB除錯工具

三、實驗內容

登入bupt1伺服器,在home目錄下可以找到Evil博士專門為你量身定製的一個bomb,當執行時,它會要求你輸入一個字串,如果正確,則進入下一關,繼續要求你輸入下一個字串;否則,炸彈就會爆炸,輸出一行提示資訊並向計分伺服器提交扣分資訊。因此,本實驗要求你必須通過反彙編和逆向工程對bomb執行檔案進行分析,找到正確的字串來解除這個的炸彈。

本實驗通過要求使用課程所學知識拆除一個“binary bombs”來增強對程式的機器級表示、組合語言、偵錯程式和逆向工程等方面原理與技能的掌握。 “binary bombs”是一個Linux可執行程式,包含了5個階段(或關卡)。炸彈執行的每個階段要求你輸入一個特定字串,你的輸入符合程式預期的輸入,該階段的炸彈就被拆除引信;否則炸彈“爆炸”,列印輸出 “BOOM!!!”。炸彈的每個階段考察了機器級程式語言的一個不同方面,難度逐級遞增。 

為完成二進位制炸彈拆除任務,需要使用gdb偵錯程式和objdump來反彙編bomb檔案,可以單步跟蹤除錯每一階段的機器程式碼,也可以閱讀反彙編程式碼,從中理解每一組合語言程式碼的行為或作用,進而設法推斷拆除炸彈所需的目標字串。實驗2的具體內容見實驗2說明。

四、實驗步驟及實驗分析

1、反彙編並利用SSH Secure Shell Client工具下載反彙編程式碼

通過ls指令顯示當前目錄下的檔案,找到壓縮包bomb115.tar,即目標炸彈。通過tar xvf bomb115.tar解壓此壓縮包,然後再通過ls顯示解壓出的檔案:bomb、bomb.c和README。

通過objdump –d bomb > bomb.txt將炸彈程式反彙編並重定向到bomb.txt,通過ls顯示反彙編出的程式碼檔案bomb.txt。

開啟SSH Secure Shell Client工具,登入到遠端主機,將遠端主機上的檔案下載到本機上,便於檢視。

 

2、檢視目標檔案並做好除錯準備

檔案介紹:

bomb.txt:反彙編得到的程式碼檔案,也是主要研究的目標檔案。

bomb.c:主函式,通過呼叫每一關的函式實現,未顯示每關的具體程式碼。

bomb:炸彈程式,當除錯得出每一關的密碼後開啟程式執行來拆炸彈。

通過gdb bomb指令進入gdb除錯環境。

大致瀏覽反彙編程式碼,可以觀察到整個程式一共有六關,分別為phase_1到phase_6,並有一關隱藏關secret_phase,每次輸入錯誤時會呼叫引爆函式explode_bomb,因此為避免除錯時引爆炸彈,需要首先在引爆函式前設定斷點,即b explode_bomb。

 

3、拆除炸彈 

1、 第一個炸彈

 

 

程式流程:

  1. 取記憶體地址0x4024b0處的內容;
  2. 取使用者輸入的內容(即密碼);
  3. 比較兩者的值,相等則%eax置為0,進入下一關,不相等則呼叫引爆程式引爆炸彈。

破解思路:

通過x/s 0x4024b0指令取出該地址的字串,得到:Only you can give me that feeling.

則密碼為:Only you can give me that feeling.

通過 !

 

 

 

 

 

2、 第二個炸彈

 

程式流程:

  1. 讀取使用者輸入內容(為6個數字);
  2. 判斷輸入的第一個值是否為1,不是則引爆炸彈;
  3. 做一個6次迴圈,判斷後一個數是否等於前一個數加上之前迴圈變數,不是則引爆炸彈;
  4. 六個數字判斷相等結束後,進入下一關

破解思路:

設輸入內容為一個數組Key[6],則可知Key[0]=1,Key[i+1]=Key[i]+i。

因此第二關的密碼是:1 2 6 24 120 720

 

3、 第三個炸彈

程式流程:

  1. 讀取輸入引數1和引數2,呼叫scanf函式傳入兩個引數;
  2. 比較引數1與7的大小,小於等於7繼續,大於7引爆;
  3. 根據引數1的值來搜尋跳轉地址,計算得到最終的%eax;
  4. 比較引數1與5的大小,小於等於5繼續,大於5引爆;
  5. 比較引數2與計算得到的%eax是否相等,相等則進入下一關,不相等則引爆。

 

重點在於引數1的選擇決定了switch的跳轉,該實驗地址為(設引數1為x):

0x402510+x*8

其中存在一個Switch函式表,這個炸彈我選擇引數1為2,則跳轉地址為0x00400f33

Switch跳轉到改地址開始計算eax%,最終結果為0x328-0xf7=0x231=561。

輸入 2 561。

成功 !

 

4、 第四個炸彈

 

主程式流程:

  1. 讀取2個引數,呼叫scanf函式傳入引數;
  2. 比較輸入引數與2的大小,小於則引爆;比較輸入引數與4的大小,大於則引爆。
  3. 把輸入引數傳入函式func4,並呼叫函式func4;
  4. 若函式func4返回值等於%rsp+0x8,則返回,進入下一關,否則引爆炸彈。

 

func4函式流程:

1.  比較傳入引數是否大於1,大於1則繼續,小於1則返回0,等於1則返回%rax;

2.  迴圈%edi=%edi-1,並遞迴呼叫函式func4,直到引數小於等於1;

3.  迴圈變數%edi=edi-2,並傳入%esp繼續遞迴呼叫函式func4;

4.  函式返回的所得值加到%eax;

 

設b=%edi,a=%esi,則f(a,b)=f(a,b-1)+f(a,b-2)+a;

第二個引數小於1則返回0,等於1則返回%rax(即a)。

炸彈中預設b=8,我們輸入a=2,經過上述式子計算得f(8)=561.

輸入108 2 或者162 3。

成功 !

 

5、 第五個炸彈

 

程式流程:

  1. 輸入字串
  2. 呼叫string_length的字串長度函式,測得的長度若不為6則引爆;
  3. 做一個6次的迴圈,迴圈變數%eax從1到6,;
  4. 我們要使得 string_not_equal返回值為0 ,也就是%ebp處的值和0x4024fe處的值相等,檢視0x4024fe處的值,發現為bruins
  5. 迴圈賦giant了, 依次改變以%ebp為開始位置的char的陣列的值 那麼b,r,u,I,n,s就存在於該字串,尋找改變字串值的語句。
  6. 取得 (0x8[%ebp]+0xc(%ebp)) &0xf的值,作為下標取得0x402550中的值,檢視 0x402550處的記憶體為 maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?
  7. bruins分別對應 13 6 3 4 8 7 所以要取得13 6 3 4 8 7
  8. 我們輸入的內容寫成 ASCII碼應該是xd x6 x3 x4 x8 x7。x表示任取,隨便取得 3d 36 33 34 38 37,對應ASCII碼為=63487。輸入
  9. 成功 !