目錄
實驗目的與要求
實驗原理與內容
實驗設備與軟件環境
實驗過程與結果(可貼圖)
操作異常問題與解決方案
實驗總結
實驗目的與要求
1. 增強學生對于程序的機器級表示、匯編語言、調試器和逆向工程等方面原理與技能的掌握。
2. 掌握使用gdb調試器和objdump來反匯編炸彈的可執行文件,并單步跟蹤調試每一階段的機器代碼,從中理解每一匯編語言代碼的行為或作用,進而設法“推斷”出拆除炸彈所需的目標字符串。
3. 需要拆除盡可能多的炸彈。
實驗原理與內容
一個“binary bombs”(二進制炸彈,下文將簡稱為炸彈)是一個Linux可執行C程序,包含了7個階段(phase1~phase6和一個隱藏階段)。炸彈運行的每個階段要求學生輸入一個特定的字符串,若的輸入符合程序預期的輸入,該階段的炸彈就被“拆除”,否則炸彈“爆炸”并打印輸出 "BOOM!!!"字樣。實驗的目標是拆除盡可能多的炸彈層次。
每個炸彈階段考察了機器級語言程序的一個不同方面,難度逐級遞增:
階段1:字符串比較
階段2:for循環
階段3:switch分支
階段4:遞歸函數
階段5:數組元素按序訪問
階段6:鏈表
隱藏階段:只有在階段4的拆解字符串后再附加一特定字符串后才會出現(作為最后一個階段)
為了完成二進制炸彈拆除任務,需要使用gdb調試器和objdump來反匯編炸彈的可執行文件,并單步跟蹤調試每一階段的機器代碼,從中理解每一匯編語言代碼的行為或作用,進而設法“推斷”出拆除炸彈所需的目標字符串。這可能需要在每一階段的開始代碼前和引爆炸彈的函數前設置斷點,以便于調試。
拆彈密碼的輸入分文兩種模式。
模式1:正常手動輸入,每次程序運行到某一階段會停下來要求用戶輸入數據。這種方式比較原始,不推薦使用。如果使用這種做法,在程序調試到后期時,每次為了進入后期的斷點位置都需要在之前的每一個階段進行手動輸入,極其浪費時間。
模式2:采用輸入重定向。首先將答案文本寫至一個.txt文本中,每個階段的拆彈密碼占一行。
實驗設備與軟件環境
1.Linux操作系統—64位 Ubuntu 18.04
2. C編譯環境(gcc)
3. 計算機
實驗過程與結果(可貼圖)
在Linux中,以下是幾個常見的命令:
"cd"命令用于更改當前工作目錄。通過輸入"cd"命令,然后加上要更改到的目錄路徑,就可以進入該目錄。
"ls"命令用于列出目錄中的文件和子目錄。如果不指定參數,它將顯示當前目錄中的所有文件和子目錄。
"vi"命令是一種文本編輯器,用于創建和編輯文本文件。它允許用戶以不同的模式瀏覽和編輯文件,包括插入模式、命令行模式和普通模式。
"cat"命令可以用于查看文件內容。它將打印文件的內容到終端上。
"objdump"是一個強大的調試工具,它可以用于分析可執行文件和目標文件的二進制代碼。objdump可以顯示程序的匯編代碼、符號表、重定位表等信息,幫助開發人員進行調試和優化。
objdump的語法如下:
objdump [選項] 文件名
其中,文件名參數可以是可執行文件、目標文件或共享庫文件。常用的選項包括:
-d 顯示匯編代碼
-t 顯示符號表
-r 顯示重定位表
-S 顯示源代碼和匯編代碼
例如,要顯示可執行文件"hello"的匯編代碼,可以使用以下命令:
objdump -d hello
本次實驗主要是要學會運用gdb調式器來查看匯編代碼和寄存器。
常用的指令:
break (b)設置斷點,接函數名或者*地址
x 查看地址中的數據,后面可以接/c(數據為字符串),/d(數據為數字)
也可以直接x/s
disas 查看當前函數的匯編代碼
i r 查看寄存器的值
stepi n 運行n步(會進入別的函數)
nexti n 運行n部(跳過別的函數,只在當前函數)
phase_1
首先gdb啟動bomb
這時候再使用run指令,讓bomb跑起來
這個時候我們就到了第一階段的答題部分
輸入正確的答案就會提示闖關成功
是否進入下一關
否則就會使炸彈爆炸,顯示bomb字樣
我們可以知道,第一關是讓我們輸入一個特定的字符串
如果字符串的某個字符和比較的字符串不相等,都會引發炸彈爆炸
這個時候我們可以disas phase_1
查看一階段的匯編代碼
首先給了8個字節的空間給rsp
然后加載了一個字符串使得與輸入的字符串進行比較
這個時候我們可以先看一下這個圈中的地址里面的字符串
這是我們要比較的字符串
我們可以看到,這個顯示的字符串會和我們輸入的字符串進行比較
那么也就是說
只要我們輸入的字符串是這個字符串
就會闖關成功
??? 我們來試試看
輸入run使得bomb運行
輸入剛剛我們查看到的指令
And they have no disregard for human life.
可以看到,
也就是說我們第一關已經通過了
Phase_2
來到第二關,第二關是一個for循環的關卡
在解答之前
我們可以把上一關的答案放到一個文本文件中,可以新建也可以放在自己有的空白文本文件中。
這樣做的好處是我們不用每一關都手動輸入前面關卡的答案
只需要運行這個文本文件就可以直接解答下一關。
我們先看一下這個循環的匯編代碼
在這之前
我們可以先打上一個斷點,這樣即使我們的答案有誤
炸彈也不會被引爆
第一個圈是提供這個程序所需的空間,fs是一個防止棧溢出的操作
這個關卡讓我們輸入六個數字,我們可以看到,我們的第一位會和一
進行比較
如果不相等,就會引發45行的bomb指令,發生爆炸
所以我們基本可以確定,第一個數字是1
再往下看63行,這里是將eax的值再加上一個eax也就是
說eax的值乘以兩倍
在六次循環里,eax每次都會以它的二倍進行儲值
到了這一步,我們基本可以確定
六個數字分別為
1 2 4 8 16 32
運行一下我們剛剛保存的文本文件,看看答案是否正確
通過顯示的字符
我們可以確定
答案是正確的
Phase_3
第三關是一個switch循環
我們把上一關的斷點刪除,用delete指令
然后重新打上斷點
我們輸入的第一個字符
會和0-7進行判斷
如果大于7
那么就會引發炸彈
所以我們可以確定這個switch循環有7或8個case語句
再往下看,可以看到有很多的mov和cmpl指令
我這里選擇的是0x6f和0x150
既然我們有7個case語句
我這里用0進入查看case0是否是答案之一
我們用x/s查看這個地址要我們輸入什么
一個整形,一個字符,一個整形
我們可以確定第一個整形是0
第二個應該是0x6f
第三個是0x150
我們用p指令將它們換算成相對應的值
到這里,我們可以知道第三位是336,
那么第二位這個字符是什么呢
這個時候我們借助ascll表進行查看
可以看到111對應的是英語字母o
我們試著輸入一下看看
0 o 336
可以看到顯示闖關成功
那么為了驗證我們的思路沒有問題
我們試著將case1也進行解答
那么case1對應的就是下一段mov和cmpl
0x77和0x12d
119對應的是w
由此我們可以斷定
解題思路是正確的
將答案寫入文本文件中。
Phase_4
先給b打上斷點,然后disas查看匯編代碼
可以看到四階段有重復調用自身代碼的操作,基本可以判斷是
遞歸函數
Mov 0xe
16進制中e是14
也就是說第一位答案應該是在0-14之間
我們接著看一下
0x555555556aaf
里面的要求
要求我們輸入兩個整形
第一個可以確定為0-14
第二個我們可以看
Eax是第一個值存儲在一個臨時變量里面
Rsp此時存的是我們輸入的第二個值
當這個值不等于0x23
也就是16x2+3時
就會發生爆炸
這個時候我們只需要進行不斷的輸入判斷
就可以知道正確答案
這里1不是我們的正確答案
那么經過我們的逐個判斷
最后確定8 35
是正確答案
將答案保存在文本文件中之后。
關閉terminal
關閉虛擬機。
操作異常問題與解決方案
無
實驗總結
通過這次實驗,我初步了解了可以通過反匯編指令獲得反匯編代碼。在本次拆彈實驗,對于匯編代碼的查看可以先找到炸彈語句,反推出避免爆炸條件。可以根據函數名初步確定函數功能,再到具體代碼進行詳細分析。根據輸入函數的格式可以初步確定思路內容方向。由跳轉表語句或者數組語句可確定相關結構方向。內存數據可以通過gdb查看。Gdb還可查看跳轉表,數組,鏈表等相關結構。可靈活運用gdb的斷點調試功能確定猜測以及函數功能。了解了匯編代碼在實際一個小工程的運行流程。進一步加深了相關知識點的理解。如內存數據的存取,函數的調用,參數寄存器的設置,棧幀中關于寄存器的保護、臨時變量、數組創建的實現的理解。同時也加深了關于gdb工具的學習使用,受益良多。
學習是循序漸進的,生活中有許多未知的事情等著我們去探索,這個bomb實驗還是挺好玩的,做了一個就想會第二個,學習就是如此,加油吧!騷年!