1. 程式人生 > >深入理解計算機系統(CSAPP)課程實驗bomb程式炸彈實驗日誌(phase_6)

深入理解計算機系統(CSAPP)課程實驗bomb程式炸彈實驗日誌(phase_6)

找到phase_6的程式碼,比前面幾關都要長很多:

08048c89 <phase_6>:
 8048c89:	55                   	push   %ebp
 8048c8a:	89 e5                	mov    %esp,%ebp
 8048c8c:	57                   	push   %edi
 8048c8d:	56                   	push   %esi
 8048c8e:	53                   	push   %ebx
 8048c8f:	83 ec 5c             	sub    $0x5c,%esp
 8048c92:	8d 45 d0             	lea    -0x30(%ebp),%eax
 8048c95:	89 44 24 04          	mov    %eax,0x4(%esp)
 8048c99:	8b 45 08             	mov    0x8(%ebp),%eax
 8048c9c:	89 04 24             	mov    %eax,(%esp)
 8048c9f:	e8 67 04 00 00       	call   804910b <read_six_numbers>
 8048ca4:	be 00 00 00 00       	mov    $0x0,%esi
 8048ca9:	8d 7d d0             	lea    -0x30(%ebp),%edi
 8048cac:	8b 04 b7             	mov    (%edi,%esi,4),%eax
 8048caf:	83 e8 01             	sub    $0x1,%eax
 8048cb2:	83 f8 05             	cmp    $0x5,%eax
 8048cb5:	76 05                	jbe    8048cbc <phase_6+0x33>
 8048cb7:	e8 15 04 00 00       	call   80490d1 <explode_bomb>
 8048cbc:	83 c6 01             	add    $0x1,%esi
 8048cbf:	83 fe 06             	cmp    $0x6,%esi
 8048cc2:	74 22                	je     8048ce6 <phase_6+0x5d>
 8048cc4:	8d 1c b7             	lea    (%edi,%esi,4),%ebx
 8048cc7:	89 75 b4             	mov    %esi,-0x4c(%ebp)
 8048cca:	8b 44 b7 fc          	mov    -0x4(%edi,%esi,4),%eax
 8048cce:	3b 03                	cmp    (%ebx),%eax
 8048cd0:	75 05                	jne    8048cd7 <phase_6+0x4e>
 8048cd2:	e8 fa 03 00 00       	call   80490d1 <explode_bomb>
 8048cd7:	83 45 b4 01          	addl   $0x1,-0x4c(%ebp)
 8048cdb:	83 c3 04             	add    $0x4,%ebx
 8048cde:	83 7d b4 05          	cmpl   $0x5,-0x4c(%ebp)
 8048ce2:	7e e6                	jle    8048cca <phase_6+0x41>
 8048ce4:	eb c6                	jmp    8048cac <phase_6+0x23>
 8048ce6:	bb 00 00 00 00       	mov    $0x0,%ebx
 8048ceb:	8d 7d d0             	lea    -0x30(%ebp),%edi
 8048cee:	eb 16                	jmp    8048d06 <phase_6+0x7d>
 
 8048cf0:	8b 52 08             	mov    0x8(%edx),%edx
 8048cf3:	83 c0 01             	add    $0x1,%eax
 8048cf6:	39 c8                	cmp    %ecx,%eax
 8048cf8:	75 f6                	jne    8048cf0 <phase_6+0x67>
 
 8048cfa:	89 54 b5 b8          	mov    %edx,-0x48(%ebp,%esi,4)
 8048cfe:	83 c3 01             	add    $0x1,%ebx
 8048d01:	83 fb 06             	cmp    $0x6,%ebx
 8048d04:	74 16                	je     8048d1c <phase_6+0x93>
 
 8048d06:	89 de                	mov    %ebx,%esi
 8048d08:	8b 0c 9f             	mov    (%edi,%ebx,4),%ecx
 8048d0b:	ba c4 c0 04 08       	mov    $0x804c0c4,%edx
 8048d10:	b8 01 00 00 00       	mov    $0x1,%eax
 8048d15:	83 f9 01             	cmp    $0x1,%ecx
 8048d18:	7f d6                	jg     8048cf0 <phase_6+0x67>
 8048d1a:	eb de                	jmp    8048cfa <phase_6+0x71>
 
 8048d1c:	8b 5d b8             	mov    -0x48(%ebp),%ebx
 8048d1f:	8b 45 bc             	mov    -0x44(%ebp),%eax
 8048d22:	89 43 08             	mov    %eax,0x8(%ebx)
 8048d25:	8b 55 c0             	mov    -0x40(%ebp),%edx
 8048d28:	89 50 08             	mov    %edx,0x8(%eax)
 8048d2b:	8b 45 c4             	mov    -0x3c(%ebp),%eax
 8048d2e:	89 42 08             	mov    %eax,0x8(%edx)
 8048d31:	8b 55 c8             	mov    -0x38(%ebp),%edx
 8048d34:	89 50 08             	mov    %edx,0x8(%eax)
 8048d37:	8b 45 cc             	mov    -0x34(%ebp),%eax
 8048d3a:	89 42 08             	mov    %eax,0x8(%edx)
 8048d3d:	c7 40 08 00 00 00 00 	movl   $0x0,0x8(%eax)
 8048d44:	be 00 00 00 00       	mov    $0x0,%esi
 8048d49:	8b 43 08             	mov    0x8(%ebx),%eax
 8048d4c:	8b 13                	mov    (%ebx),%edx
 8048d4e:	3b 10                	cmp    (%eax),%edx
 8048d50:	7d 05                	jge    8048d57 <phase_6+0xce>
 8048d52:	e8 7a 03 00 00       	call   80490d1 <explode_bomb>
 8048d57:	8b 5b 08             	mov    0x8(%ebx),%ebx
 8048d5a:	83 c6 01             	add    $0x1,%esi
 8048d5d:	83 fe 05             	cmp    $0x5,%esi
 8048d60:	75 e7                	jne    8048d49 <phase_6+0xc0>
 8048d62:	83 c4 5c             	add    $0x5c,%esp
 8048d65:	5b                   	pop    %ebx
 8048d66:	5e                   	pop    %esi
 8048d67:	5f                   	pop    %edi
 8048d68:	5d                   	pop    %ebp
 8048d69:	c3                   	ret    

依然是從新空間的開闢開始做。0x8048c9f位置讀入6個引數,0x8048ca4~0x8048cac執行的是與phase_5相似的陣列型別的操作,偏移量以4的倍數增長。

8048caf到8048cb7的程式碼說明,第一個數的值要小於等於6。否則將引爆炸彈。

從0x8048cbc開始,%esi的值開始從1往6遞增,直到等於6時才跳轉到0x8048ce6,否則將執行8048cc4。這裡應該是雙層迴圈的外層。

8048cc4將當前元素的地址傳入暫存器ebx儲存,並將當前的偏移量(陣列的下標)儲存到-0x4c(%ebp)位置暫存起來,這裡應該是內層迴圈的起點。再把陣列的下一個元素,也就是-0x4(%edi,%esi,4)位置的元素放入暫存器eax並將兩者比較,如果不相等則跳轉到0x8048cd7位置,否則將引爆炸彈。即第一個數不能和第二個數相等。

再看0x8048cd7位置,將前面暫存在-0x4c(%ebp)位置的值取出並加1,然後%ebx加4,指向陣列的下一個元素。

0x8048cde位置,將5和-0x4c(%ebp)位置的數,也就是內層迴圈的控制條件進行比較,當小於等於5時,說明內層迴圈還未結束,跳轉至0x8048cca繼續比較當前元素和下一個元素,需要滿足的條件同樣是兩個元素不相等,直到內層迴圈結束,0x8048ce4跳轉至0x8048cac處,重新開始外層迴圈。

至此可以分析出第一部分程式碼的意思是要求輸入的6個數據彼此都不能相等。所以這6個數據應該是大於0而小於等於6的。

當0x8048cc2處的跳轉條件滿足時,將結束整個迴圈,跳轉至0x8048ce6處。

0x8048ce6開始執行一個新的操作,將暫存器ebx的值清零,同樣將地址-0x30(%ebp)傳給%edi,然後直接跳轉至0x8048d06處。

0x8048d06開始先是將%ebx(也就是0)賦給%esi,使%esi獲得初始值0,再將(%edi,%ebx,4)位置的數取出,存入%ecx中,將立即數0x804c0c4存入暫存器%edx中。

0x8048d10開始將%eax的值變為1,將%ecx中的值(也就是記憶體中(%edi,%ebx,4)位置的數)和1做比較,如果大於1,則跳轉至0x8048cf0,否則跳轉至0x8048cfa。

轉向8048cf0位置,從8048cf0到8048cf8是一個迴圈,每迴圈一次,就更新一次%edx中的值,更新為記憶體地址為0x8(%edx)中的值,從這樣的操作可以發現,地址的下一個元素還是地址,由此可以聯想到的結構就是連結串列。直到%eax中的值和%ecx中的值相等為止。如果相等,就來到0x8048cfa位置。

0x8048cfa處開始是一個mov指令,將前面那個迴圈產生的最終的%edx中的值存入-0x48(%ebp,%esi,4)位置,若為第一輪操作,就是-0x48(%ebp),若為第二輪,就是-0x44(%ebp),依此次序每次向上遞增4個單元。(因為%esi,%ebx的值是變化的)

隨後%ebx加1,再和6做比較,不相等則繼續從0x8048d06重新開始,若相等,也就是6輪迴圈結束,則跳轉至0x8048d1c位置。

可以發現,這個6輪的迴圈總是會執行0x8048cfa開始的這一小部分程式碼,也就是說會有6組不同的%edx被傳入記憶體-0x48(%ebp)開始向後的6個空間。

接下來對0x8048ce6開始的這部分程式碼進行除錯,可以清楚地看到,暫存器%ecx中的值經歷了6個不同的值。而這6個值正是我們在除錯的時候輸入的。

並且,按不同的順序輸入6個數,每次存入對應記憶體位置的地址也不相同。

六輪迴圈結束後,跳轉至8048d1c位置。

與前面的程式碼實現的功能做一個類比可以發現,這裡一連串的mov指令應該是將連結串列中的元素做一個新的賦值對映。

同時,0x8048d44開始的比較+迴圈結構實現的功能是判斷連結串列元素是否是一個遞增的序列。

再次進入gdb除錯,檢視地址0x804c0c4(%edx)中的內容。

然後每次將%edx偏移0x8,檢視後會發現,首先edx中是內容,然後edx+0x8內的內容是一個地址,然後再檢視這個地址,地址內的內容是一個內容,然後在將這個地址偏移0x8得到的地址內的內容又是一個地址,可以看出來,這是一個典型的連結串列結構。連結串列就是不同的node節點,每個node節點在記憶體中存在不同的位置,不連續的位置中。每個node由內容和next指標構成,每個next指標內的值是一個指向下一個node節點的地址,最後一個node的next指向null。

這樣結合前面的分析就可以知道,我們輸入的6個數實際上就是不同的node節點數,根據我輸入的節點號,把節點內的內容重新進行排序,排成遞增序列。



將節點值按遞增順序排列,則節點號的順序應該為:

5,6,1,4,3,2

測試一下這個答案:


提示炸彈已解除。