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

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

本文接 深入理解計算機系統(CSAPP)課程實驗bomb程式炸彈實驗日誌(phase_3)繼續寫,phase_4部分在昨天已經完成了,日誌在今天才開始寫。個人認為這個部分是整個bomb程式炸彈最難破解的部分,在破解的過程中發現這是一個遞迴函式,體現在組合語言中就顯得特徵不是那麼明顯,所以採用了一種將彙編轉化成與之等價的C語言語句,這樣有助於更好的看清程式的運作過程。下面是我的探索過程。

在Notepad++中查詢到函式phase_4,程式碼如下:

08048e2e <phase_4>:
 8048e2e:	55                   	push   %ebp
 8048e2f:	89 e5                	mov    %esp,%ebp
 8048e31:	83 ec 28             	sub    $0x28,%esp
 8048e34:	8d 45 f0             	lea    -0x10(%ebp),%eax
 8048e37:	89 44 24 0c          	mov    %eax,0xc(%esp)
 8048e3b:	8d 45 f4             	lea    -0xc(%ebp),%eax
 8048e3e:	89 44 24 08          	mov    %eax,0x8(%esp)
 8048e42:	c7 44 24 04 3e a2 04 	movl   $0x804a23e,0x4(%esp)
 8048e49:	08 
 8048e4a:	8b 45 08             	mov    0x8(%ebp),%eax
 8048e4d:	89 04 24             	mov    %eax,(%esp)
 8048e50:	e8 eb f9 ff ff       	call   8048840 <
[email protected]
> 8048e55: 83 f8 02 cmp $0x2,%eax 8048e58: 75 0c jne 8048e66 <phase_4+0x38> 8048e5a: 8b 45 f4 mov -0xc(%ebp),%eax 8048e5d: 85 c0 test %eax,%eax 8048e5f: 78 05 js 8048e66 <phase_4+0x38> 8048e61: 83 f8 0e cmp $0xe,%eax 8048e64: 7e 05 jle 8048e6b <phase_4+0x3d> 8048e66: e8 66 02 00 00 call 80490d1 <explode_bomb> 8048e6b: c7 44 24 08 0e 00 00 movl $0xe,0x8(%esp) 8048e72: 00 8048e73: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp) 8048e7a: 00 8048e7b: 8b 45 f4 mov -0xc(%ebp),%eax 8048e7e: 89 04 24 mov %eax,(%esp) 8048e81: e8 da fc ff ff call 8048b60 <func4> 8048e86: 83 f8 01 cmp $0x1,%eax 8048e89: 75 06 jne 8048e91 <phase_4+0x63> 8048e8b: 83 7d f0 01 cmpl $0x1,-0x10(%ebp) 8048e8f: 74 0c je 8048e9d <phase_4+0x6f> 8048e91: 8d b4 26 00 00 00 00 lea 0x0(%esi,%eiz,1),%esi 8048e98: e8 34 02 00 00 call 80490d1 <explode_bomb> 8048e9d: c9 leave 8048e9e: 66 90 xchg %ax,%ax 8048ea0: c3 ret

同樣,從函式開始的部分到0x8048e4d位置都是在做新空間的開闢和引數的傳遞工作。依然設-0xc(%ebp)位置的引數為val1,-0x10(%ebp)位置的引數為val2,接著0x8048e50位置就是資料讀入,0x8048e55位置eax中的資料應該是讀入資料的個數,若eax中的值不等於2,跳轉到0x8048e66位置,引爆炸彈。所以這一關的要求是輸入兩個數字,且兩個引數之間必定會滿足某種關係。

接下來是0x8048e5a位置的一條mov指令,將引數1放入暫存器eax中。0x8048e5d開始的test和js指令,將eax和eax自身進行與操作,當符號位位1時發生跳轉,引爆炸彈。這說明eax中存的數必須滿足符號位不為1,也就是必須是一個正數,這樣我們獲得了引數1的第一個範圍限制。

繼續往下讀,0x8048e5a位置開始又是一個比較加跳轉指令,將引數1的值和十六進位制的e,也就是十進位制的14進行比較,若eax<=14,則跳轉到0x8048e6b位置,否則下一步就是引爆炸彈。所以,引數1必須小於等於14,這樣得到了引數1的第二個範圍限制。

然後將執行0x8048e6b位置和0x8048e73位置的兩個movl指令,0x8048e7b開始再將eax中的值設為phase_4的返回值。

再往下看,0x8048e81位置呼叫了func4函式,這又是另外一個函式,也是phase_4這個部分最關鍵的地方,先跳過它繼續往下獲取資訊。

0x8048e86位置開始是一個比較加跳轉指令,在將func4函式執行後的返回值和1做比較,若不等則引爆炸彈。說明此函式的返回值必須為1。

0x8048e8b位置同樣是一個比較加跳轉,將引數2的值和1進行比較,若相等則函式執行結束,否則引爆炸彈。說明引數2的值必須為1。

接下來分析最關鍵的函式func4部分,它是一個遞迴結構,通過逐條將彙編指令轉化成對應的C語言程式碼,將函式的功能清楚地顯示出來。

在Notepad++中搜索函式func4,程式碼如下:

08048b60 <func4>:
 8048b60:	55                   	push   %ebp
 8048b61:	89 e5                	mov    %esp,%ebp
 8048b63:	83 ec 18             	sub    $0x18,%esp
 8048b66:	89 5d f8             	mov    %ebx,-0x8(%ebp)
 8048b69:	89 75 fc             	mov    %esi,-0x4(%ebp)
 8048b6c:	8b 55 08             	mov    0x8(%ebp),%edx
 8048b6f:	8b 45 0c             	mov    0xc(%ebp),%eax
 8048b72:	8b 5d 10             	mov    0x10(%ebp),%ebx
 8048b75:	89 d9                	mov    %ebx,%ecx
 8048b77:	29 c1                	sub    %eax,%ecx
 8048b79:	89 ce                	mov    %ecx,%esi
 8048b7b:	c1 ee 1f             	shr    $0x1f,%esi
 8048b7e:	8d 0c 0e             	lea    (%esi,%ecx,1),%ecx
 8048b81:	d1 f9                	sar    %ecx
 8048b83:	01 c1                	add    %eax,%ecx
 8048b85:	39 d1                	cmp    %edx,%ecx
 8048b87:	7e 17                	jle    8048ba0 <func4+0x40>
 8048b89:	83 e9 01             	sub    $0x1,%ecx
 8048b8c:	89 4c 24 08          	mov    %ecx,0x8(%esp)
 8048b90:	89 44 24 04          	mov    %eax,0x4(%esp)
 8048b94:	89 14 24             	mov    %edx,(%esp)
 8048b97:	e8 c4 ff ff ff       	call   8048b60 <func4>
 8048b9c:	01 c0                	add    %eax,%eax
 8048b9e:	eb 20                	jmp    8048bc0 <func4+0x60>
 8048ba0:	b8 00 00 00 00       	mov    $0x0,%eax
 8048ba5:	39 d1                	cmp    %edx,%ecx
 8048ba7:	7d 17                	jge    8048bc0 <func4+0x60>
 8048ba9:	89 5c 24 08          	mov    %ebx,0x8(%esp)
 8048bad:	83 c1 01             	add    $0x1,%ecx
 8048bb0:	89 4c 24 04          	mov    %ecx,0x4(%esp)
 8048bb4:	89 14 24             	mov    %edx,(%esp)
 8048bb7:	e8 a4 ff ff ff       	call   8048b60 <func4>
 8048bbc:	8d 44 00 01          	lea    0x1(%eax,%eax,1),%eax
 8048bc0:	8b 5d f8             	mov    -0x8(%ebp),%ebx
 8048bc3:	8b 75 fc             	mov    -0x4(%ebp),%esi
 8048bc6:	89 ec                	mov    %ebp,%esp
 8048bc8:	5d                   	pop    %ebp
 8048bc9:	c3                   	ret    

以下是在棧中模擬func4函式操作並將彙編指令轉化為C語言程式碼的過程示意:



將轉化的C語言程式碼整合成完整的func4在編譯器中執行,註釋為對應的彙編程式碼:

#include <stdio.h>
//val1:%edx,y:%eax,z:%ebx,k:%ecx,t:%esi;
int func4(int val1,int y,int z)
{
	int k,t;	//
	k = z;	//8048b75:	89 d9                	mov    %ebx,%ecx
	k = k-y;	//8048b77:	29 c1                	sub    %eax,%ecx
	t = k;	//8048b79:	89 ce                	mov    %ecx,%esi
	t = t>>31;	//8048b7b:	c1 ee 1f             	shr    $0x1f,%esi
	k = k+t;	//8048b7e:	8d 0c 0e             	lea    (%esi,%ecx,1),%ecx
	k = k/2;	//8048b81:	d1 f9                	sar    %ecx
	k = k+y;	//8048b83:	01 c1                	add    %eax,%ecx
	if(k<=val1)	//8048b85:	39 d1                	cmp    %edx,%ecx
 				//8048b87:	7e 17                	jle    8048ba0 <func4+0x40>
	{
		y = 0;	//8048ba0:	b8 00 00 00 00       	mov    $0x0,%eax
		if(k>=val1)	//8048ba5:	39 d1                	cmp    %edx,%ecx
 					//8048ba7:	7d 17                	jge    8048bc0 <func4+0x60>
		{
			return y;	//8048bc0:	8b 5d f8             	mov    -0x8(%ebp),%ebx
 						//8048bc3:	8b 75 fc             	mov    -0x4(%ebp),%esi
 						//8048bc6:	89 ec                	mov    %ebp,%esp
 						//8048bc8:	5d                   	pop    %ebp
 						//8048bc9:	c3                   	ret    
		}
		else
		{
			k = k+1;	//8048bad:	83 c1 01             	add    $0x1,%ecx
			y = func4(val1,k,z);	//8048ba9:	89 5c 24 08          	mov    %ebx,0x8(%esp)
									//8048bb0:	89 4c 24 04          	mov    %ecx,0x4(%esp)
									//8048bb4:	89 14 24             	mov    %edx,(%esp)
			y = y+y+1;	//8048bbc:	8d 44 00 01          	lea    0x1(%eax,%eax,1),%eax
			return y;	//8048bc0:	8b 5d f8             	mov    -0x8(%ebp),%ebx
 						//8048bc3:	8b 75 fc             	mov    -0x4(%ebp),%esi
 						//8048bc6:	89 ec                	mov    %ebp,%esp
 						//8048bc8:	5d                   	pop    %ebp
 						//8048bc9:	c3                   	ret    
		}
	}
	else
	{
		k = k-1;	//8048b89:	83 e9 01             	sub    $0x1,%ecx
		y = func4(val1,y,k);	//8048b8c:	89 4c 24 08          	mov    %ecx,0x8(%esp)
 								//8048b90:	89 44 24 04          	mov    %eax,0x4(%esp)
 								//8048b94:	89 14 24             	mov    %edx,(%esp)
		y = y+y;	//8048b9c:	01 c0                	add    %eax,%eax
		return y;	//8048b9e:	eb 20                	jmp    8048bc0 <func4+0x60>
	}
}

int main()
{
	int val1,val2;
	for(val1=0;val1<=14;val1++)
	{
		val2 = func4(val1,0,14);
		if(val2 == 1)
		{
			printf("%d\n",val1);
		}
	}
	return 0;
}

執行後的結果如下:


說明滿足條件的答案有3個,分別是:

8,1

9,1

11,1

輸入任意一個進行驗證:


相關推薦

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

本文接 深入理解計算機系統(CSAPP)課程實驗bomb程式炸彈實驗日誌(phase_3)繼續寫,phase_4部分在昨天已經完成了,日誌在今天才開始寫。個人認為這個部分是整個bomb程式炸彈最難破解的部分,在破解的過程中發現這是一個遞迴函式,體現在組合語言中就顯得特徵不是

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

找到phase_6的程式碼,比前面幾關都要長很多: 08048c89 <phase_6>: 8048c89: 55 push %ebp 8048c8a: 89 e5 mov %

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

在Notepad++編輯器中找到函式phase_3,程式碼如下: 08048ea1 <phase_3>: 8048ea1: 55 push %ebp 8048ea2: 89 e5

深入理解計算機系統》讀書筆記 —— 第三章 程式的機器級表示

>本章主要介紹了計算機中的機器程式碼——組合語言。當我們使用高階語言(C、Java等)程式設計時,程式碼會遮蔽機器級的細節,我們無法瞭解到機器級的程式碼實現。既然有了高階語言,我們為什麼還需要學習組合語言呢?學習程式的機器級實現,可以幫助我們理解編譯器的優化能力,可以讓我們瞭解程式是如何執行的,哪些部分是可以

CSAPP 深入理解計算機系統課程實驗 bomb實驗 反向編譯 彙編4

隱藏關卡。Secretphase 這個隱藏關卡還是很難發現的,自己帶的班上的學生中,僅有3個學生髮現並解除了炸彈。中間也出現了一些小小問題,在給他們驗收的時候也有意識的去引導他們發現一些小問題,並討論解決。 首先是隱藏關卡的發現,其實在彙編程式碼中就有一個secret_ph

CSAPP 深入理解計算機系統 Buflab實驗,緩衝區溢位攻擊實驗1

由於實驗太長所以還是採用分開 其實感覺之前做過那個bomb實驗以後,這個實驗相對來說還是很容易的,主要是要搞懂緩衝區溢位原理,以及堆疊的過程,函式呼叫的實現過程,做完這個實驗如果認認真真的做完,對於堆疊的過程,還有快取溢位攻擊的原理就會掌握的比較清楚的。個人感覺實驗設計的

深入理解計算機系統序章------談程序員為什麽要懂底層計算機結構

人類 是你 驅動 計算機世界 執行過程 鍵盤 二進制 java虛擬機 調優   萬丈高樓平地起,計算機系統就像程序員金字塔的地基。理解了計算機系統的構造原理,在寫程序的道路上才能越走越遠。道理LZ很早就懂了,可是一直沒下定決心好好鉆研,或許是覺得日常工作中根本用不到這些,又

深入理解計算機系統1.2------存儲設備

高速 計算 想法 知識 1-1 運用 文件 字符 設備   上一章我們講解了hello world 程序在計算機系統中是如何運行的。 hello 程序的機器指令最初是存放在磁盤上的,當程序加載時,他們被復制到主存;當處理器運行程序的時候,指令又從主存復制到處理器。相似的,數

3.2《深入理解計算機系統》筆記內存和高速緩存的原理【插圖】

img sram 本質 text ddr rate too 是我 很大的 《深入計算機系統》筆記(一)主要是講解程序的構成、執行和控制。接下來就是運行了。我跳過了“處理器體系結構”和“優化程序性能”,這兩章的筆記繼續往後延遲! 《深入計算機系統》的一個很大的用處

深入理解計算機系統2.4------整數的表示無符號編碼和補碼編碼

class 映射 們的 c語言 正數 裏的 小例子 負數 類型   上一篇博客我們主要介紹了布爾代數和C語言當中的幾個運算符。那麽這一篇博客我們主要介紹在計算機中整數是如何表示的,諸如我們在編碼過程中遇到的對數據類型進行強制轉換可能會得到意想不到的結果在這篇博客裏你會得到解

深入理解計算機系統3.1------匯編語言和機器語言

找到 生產 有著 shu 符號 ces pc機 高效率 機器語言   《深入理解計算機系統》第三章——程序的機器級表示。作者首先講解了匯編代碼和機器代碼的關系,闡述了匯編承上啟下的作用;接著從機器語言IA32著手,分別講述了如何存儲數據、如何訪問數據

深入理解計算機系統3.3------操作數指示符和數據傳送指令

邏輯操作 無效 系統 get 訪問 www. 執行 十六 title   在上一篇博客 程序編碼以及數據格式 中我們給出了一個簡單的C程序,然後編譯成了匯編代碼。大家看不懂沒關系,後面的博客我們將逐漸揭開一些匯編指令的神秘面紗。本篇博客我們將對操作數指示符和數據傳送指令進行

深入理解計算機系統3.8------數組分配和訪問

2個 說明 add 如果 c++編譯 類型 操作 http 程序   上一篇博客我們講解了匯編語言中過程(函數)的調用實現。理解數據如何在調用者和被調用者之間傳遞,以及在被調用者當中局部變量內存的分配以及釋放是最重要的。那麽這篇博客我們將講解數組的分配和訪問。 1、

速讀《深入理解計算機系統第三版》問題及解決

情況 csdn 第六章 填充 以及 函數 順序 時鐘 管理所 第一章 計算機漫遊 P13:用戶棧和運行時堆有什麽區別?數據結構中經常說堆棧,這裏的堆和棧一樣嗎?和操作系統的堆、棧有什麽區別? 參考:堆和棧的區別(內存和數據結構) 操作系統: 棧:由操作系統自動分配釋放

深入理解計算機系統_3e 第四章家庭作業部分 CS:APP3e chapter 4 homework

ray design sed copy default ror this 處理 implement 4.52以後的題目中的代碼大多是書上的,如需使用請聯系 [email protected] 流水線部分只寫了偶數題號的,這幾天太浮躁,落下了好多課。。。 4.

20179215《深入理解計算機系統第三版》第三章

imu 組成 不但 圖片 想是 運行 href com 語言 《深入理解計算機系統》第三章 程序的機器級表示學習 讀書筆記 一、這章主要任務: ? 二、程序編碼 ?計算機系統使用了多種不同形式的抽象,利用更簡單的抽象模型來隱藏實現的細節。對於機器級編程來說,其中兩種抽

深入理解計算機系統》閱讀筆記--程序的機器級表示

還要 所有 執行文件 命令 不同的 指向 local 變量 section 一、為什麽要學習和了解匯編 編譯器基於編程語言的規則,目標機器的指令集和操作系統遵循的慣例,經過一系列的階段生成機器代碼。GCC c語言編譯器以匯編代碼的形式產生輸出,匯編代碼是機器代碼的文

深入理解計算機系統》——讀書筆記

img 可執行 即將 簡單的 world std 加載 完整 .exe   這本書從一個簡單的C語言的HelloWorld程序講起...   這是這個小程序的生命周期的一個部分:   HellOWorld程序,從被創建(文本格式),到被執行(在屏幕上打印出來)。   其

第1章 計算機系統漫遊深入理解計算機系統

printf 保存 並運行 用戶 數據 ogr 語句 亂碼 hello 1 #include <stdio.h> 2 3 int main() 4 { 5 printf("hello, world\n"); 6 } 1.1 信息就是位+上下文 h