CSAPP lab2 二進制拆彈 binary bombs phase_2


 

給出對應於7個階段的7篇博客

phase_1  https://www.cnblogs.com/wkfvawl/p/10632044.html
phase_2  https://www.cnblogs.com/wkfvawl/p/10636214.html
phase_3  https://www.cnblogs.com/wkfvawl/p/10651205.html
phase_4  https://www.cnblogs.com/wkfvawl/p/10672680.html
phase_5  https://www.cnblogs.com/wkfvawl/p/10703941.html
phase_6  https://www.cnblogs.com/wkfvawl/p/10742405.html
secret_phase  https://www.cnblogs.com/wkfvawl/p/10745307.html

 phase_2

phase_2要求輸入包含6個整數的字符串。phase_2函數從中讀取6個整數,並判斷其正確性,如果不正確,則炸彈爆炸。phase_2主要考察學生對C語言循環的機器級表示的掌握程度。

觀察框架源文件bomb.c:

從上可以看出:

1、首先調用了read_line()函數,用於輸入炸彈秘鑰,輸入放置在char* input中。

2、調用phase_2函數,輸入參數即為input,可以初步判斷,phase_2函數將輸入的input字符串作為參數。

因此下一步的主要任務是從asm.txt中查找在哪個地方調用了readline函數以及phase_2函數。

1.1 尋找並分析調用phase_2函數的代碼

打開asm.txt,尋找phase_2函數。

 

 

phase_1類似分析:

1、當前棧的位置存放的是read_line函數讀入的一串輸入;

2、phase_2的函數入口地址為0x8048c24

此時的函數棧為:

 

1.2 phase_2函數分析

尋找8048c24,或者繼續尋找phase_2,可以尋找到phase_2函數,如下圖所示:

 

分析上面的代碼:

1390 ~ 392行:進行一些壓棧,並擴展了函數棧幀。

2、第394-395行:lea 0x18(%esp) %eaxmov %eax 4(%esp),將esp + 18指向的棧的內容的地址放置到esp+4指向的地方。簡單的說,當前esp + 4指針指向的空間的內容為esp + 18。(實際上,根據后面的分析,可以知道esp + 4的內容,放的是num[0]的地址esp + 18

3、第396行:將0x40(%esp)的內容放置到esp指向的棧。0x40(%esp)里面的內容實際上就是input字符串首地址。

4、第397行:調用了read_six_numbers函數(顧名思義,從字符串中解析出六個整數),可以猜測實際上第394行到第396行,是在為read_six_numbers函數准備參數。

5、在調用read_six_numbers之前,函數棧幀為:

 

 

7、上圖所示的函數棧幀中,從esp + 18 ~ esp+2c,共6個棧空間,標記為保存6個整數,實際上從當前的地方並不能完全看出來,可以有些猜測,到后來閱讀read_six_numbers時,證實了當前的猜測是正確的。

8、依據以上的分析,read_six_numbers函數的定義:void read_six_numbers(char* input, num);其中第二個參數,是num數組的地址。在后面,會剖析read_six_numbers函數,來證實以上的猜測,下面的分析以以上的棧幀圖為基礎。

9、第399行:cmp $0x1, 0x18(%esp)0x18(%esp)中是num[0],該語句判斷num[0]是否應等於1,如果等,則跳轉到phase_2 + 0x3e(第400行),如果不等,則call explode_bomb(第401行),從此處,可以猜測:num[0]  = 1

10、第412行(8048c62phase_2 + 0x3e)),將0x1c + esp --> ebx寄存器,即將num[1]的地址送入到ebx寄存器,第413行,將0x30 + esp -->esi0x30(%esp)num[5]上面的棧空間,將該棧空間的地址送入到esi

11、第415行:跳轉到8048c4b(即第403行)。

12、第403行:將-0x4%ebx)的內容送入到eax-0x4%ebx)的內容實際上指的是0x18(%esp),也即num[0]送入到eax

13、第404行:eax = eax + eax,即: 2 * num[0];

14、第405行:比較ebx所指的地址的內容和eax的內容,據前面分析,當前ebx的內容即為num[1]的地址。

15、第406行:如果相等,則跳轉到8048c59

16、第408行(8048c59):ebx += 4,當前ebxnum[1]的地址,加4之后,正好是num[2]的地址。

17、第409行:ebxesinum[5]之上的地址)比較,如果不等則跳轉到8048c4b(第403行),繼續從前面第11繼續開始。如果相等,則跳轉到8048c6c(第415行),退出函數。實際上如果ebxesi相等,說明前面已經處理完了num[5],也即處理完了第6個數。如果不等,則說明num[5]沒有處理,繼續循環。

18、總結前面的分析,以上顯然是一個循環表示的機器級表示的處理過程,從上面的分析來看:

1num[0] = 1;

2num[i] = 2 * num[i-1]。(i > 0

因此,phase_2炸彈秘鑰應該是:1 2 4 8 16 32。

 

以上所有的分析是建立在六個輸入數字是放置在esp + 0x18開始的地址中的前提下的。為確認這一個問題,下面對read_six_numbers函數進行詳細分析。

 

 

1.3 read_six_numbers分析

 

根據前面分析,read_six_numbers的入口地址為80493da,如下圖所示:

 

1、第996行:擴展棧幀,增加了44

 2、第997行:將0x34%esp)的內容送到eax0x34%esp)的內容正好是num[0]的地址,也即num的首地址,也即eax內容為num[0]的地址。(參見后面的棧幀圖)

3、第998行:將eax + 0x14地址(即為eax + 0x14送到edxeax+0x14正好是num[5]的地址。(參見后面棧幀圖)

4、第999行:將edx的內容送到esp + 0x1c的地方,即將num[5]的地址送到esp+0x1c的地方;

5、第1000~1008行:

1num[4]地址,送到esp + 0x18

2num[3]地址,送到esp + 0x14

3num[2]地址,送到esp + 0x10

4num[1]地址,送到esp + 0xc

6、第1009行:num[0]地址,送到esp + 8

7、第1010行:0x804a725送入到esp + 4的地方

8、第1011/1012行:0x30%esp)內容送入到esp0x30%esp)內容為input輸入首地址。

9、第1013行:調用scanf函數,用於從input中讀入6個整數。可以認為前面都是在為scanf函數調用准備參數,包括第1009行,0x804a67d實際上是指向一個字符串的首地址,這個字符串為“%d %d %d %d %d %d”(這點將在后面分析),因此,我們可以判斷scanf的函數定義/使用為:scanf(input, "%d %d %d %d %d %d", &num[0],  &num[1], &num[2], &num[3], &num[4], &num[5],); 返回的是讀取的整數的個數。

10、此時的棧幀為:

 

11、第1014行:eax的值與5比較,eax應該是scanf函數返回的輸入數字的個數;

12、第1015行:如果大於5,則函數正確返回;

13、第1016行:如果小於等於5,則引爆炸彈。

14.為了查看0x804a67d地址的內容,可以使用objdump --start-address= 0x804a67d -s  bomb命令查看,如下圖所示:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM