---
tags: 工作用, Pentest, 滲透測試, CPENT
---
# CPENT iLab筆記 - Appendix B - Fuzzing (Expected Duration 55 Minutes)
Fuzzing(模糊測試)和IoT逆向工程是兩種在目的和方法上有顯著差異的技術。以下是它們的主要不同點:
**Fuzzing(模糊測試)**
Fuzzing 是一種自動化的軟體測試技術,主要用於發現軟體中的安全漏洞和錯誤。這種方法通過向軟體系統輸入大量隨機或異常數據來試圖引發錯誤、程序崩潰或潛在的安全漏洞,從而檢測程序的健壯性。Fuzzing 通常不需要對目標軟體的內部結構有深入了解。
**IoT逆向工程**
IoT逆向工程是指分析IoT(物聯網)設備的硬體和軟體組件,目的是瞭解其運作原理和設計細節。這通常涉及對設備的韌體或軟體進行解碼和分析,以獲取原始代碼或其他關鍵信息。逆向工程可以用於設計兼容產品、增強設備功能、或發現安全漏洞。這種技術要求很高的技術知識,包括對硬體結構和軟體語言的理解。
**主要區別**
目的不同:Fuzzing 主要用於檢測和改進軟體的安全性和穩定性,而IoT逆向工程則更多用於理解產品的運作原理和改進技術。
方法不同:Fuzzing 依賴於自動化生成數據並觀察軟體對異常數據的反應,不需深入了解軟體的具體實現;逆向工程則涉及深入分析和理解設備的內部結構和代碼。
技術要求:逆向工程通常要求更專業的技術知識,包括硬體架構和軟體編程語言的熟悉度。
關於工具zzuf,推薦這個簡報教學更容易了解:
https://archive.fosdem.org/2007/slides/lightningtalks/Zzuf.pdf





## Exercise 1: Fuzzing with zzuf
Lab Objective:
In this lab, we will explore the process of fuzzing.
Lab Tasks:
1. Log in to the Ub20 Fuzzing machine using studentpassword as Password.

2. Ensure that your Address Space Layout Randomization (ASLR) is disabled. Type: **sudo sysctl kernel.randomize_va_space=0** and press Enter.
確保您的地址空間佈局隨機化 (ASLR) 已停用。 輸入:**sudo sysctl kernel.randomize_va_space=0** 並按 Enter。
```bash=
$sudo sysctl kernel.randomize_va_space=0
```

3. We will currently not address binary analysis and exploitation since we have a dedicated module for this.
我們目前不會解決二進制分析和利用問題,因為我們有一個專用模組。
4. Open a terminal, and navigate to the folder **/home/student/Downloads/fuzzing/zzuf**.
開啟終端,然後導覽至資料夾 /home/student/Downloads/fuzzing/zzuf。
```bash=
$cd /home/student/Downloads/fuzzing/zzuf
```
5. Once you are in the folder, type: man zzuf and read more about the tool. An example of the output is shown in the following screenshot.
進入該資料夾後,輸入:man zzuf 並閱讀有關該工具的更多資訊。 以下螢幕截圖顯示了輸出範例。
```bash=
$man zzuf
```

Note: Take a few minutes, and review the data in the main page.
6. Next, to create a file, enter: hd -vn 32 /dev/zero. The results of this command are shown in the following screenshot.
接下來,要建立文件,請輸入:hd -vn 32 /dev/zero。該命令的結果如下面的螢幕截圖所示。
```bash=
$hd -vn 32 /dev/zero
```

-------------
這個指令在Unix或Linux環境下被使用,目的是要讀取`/dev/zero`(一個特殊文件,讀取它會產生無限的零(0x00)字節)的前32個字節,然後通過`hd`(hex dump的縮寫,但在某些系統中可能需要使用`hexdump`)命令以十六進制格式顯示這些字節。
- `hd`:是一個工具,用於將二進制數據轉換成十六進制格式顯示。這對於分析和調試二進制文件非常有用。
- `-vn 32`:這個選項和參數組合用於指定`hd`命令的行為。`-v`表示使輸出中包括重複行(儘管在這個情況下可能不太相關),而`-n 32`限制輸出到前32個字節。
- `/dev/zero`:是一個特殊的設備文件,對它的讀取操作將連續產生零字節。
總結來說,`hd -vn 32 /dev/zero`這個指令將會輸出`/dev/zero`的前32個字節(都是0x00)的十六進制表示,這是一種展示如何使用`hd`命令來查看二進制數據的十六進制格式的簡單例子。
-------------
7. Next, we want to use the zzuf tool to fuzz the cat command. Open a new terminal and type: zzuf cat /dev/zero | hd -vn 32 and press Enter. An example of this is shown in the following screenshot.
接下來,我們要使用 zzuf 工具對 cat 指令進行模糊測試。 開啟一個新終端機並輸入: zzuf cat /dev/zero | hd -vn 32,然後按 Enter。 以下螢幕截圖顯示了這樣的範例。
```bash=
$zzuf cat /dev/zero | hd -vn 32
```

-------------
這個指令是在Unix或Linux環境下使用的,包含了幾個不同的命令和工具,我們來逐一解釋。
1. `$zzuf`:`zzuf`是一個應用程序故障注入器,它可以用來查找程序在處理不同輸入數據時的錯誤。它通過隨機改變程序的輸入數據(例如文件、網絡流量等)來工作。在這個命令中,`zzuf`可能是作為一個前置工具來改變後續命令的輸入。
2. `cat /dev/zero`:`cat`命令用於連接文件並打印到標準輸出裝置上。`/dev/zero`是一個特殊的文件,讀取它會產生無限的零(0x00)字節。
3. `|`:這是一個管道符號,它用於將一個命令的輸出作為另一個命令的輸入。
4. `hd`:`hd`是hex dump的縮寫,用於將二進制數據轉換成十六進制格式顯示。不過,在一些系統中,你可能需要使用`hexdump`命令來達到相同的效果。
5. `-vn 32`:這個選項和參數組合指定了`hd`命令的行為。`-v`選項使`hd`在輸出中包括重複行,`-n 32`限制輸出到前32個字節。
綜合來看,這個命令序列的作用是使用`zzuf`來改變從`/dev/zero`讀取的無限零字節流的一部分,然後通過`hd`以十六進制格式輸出改變後的前32個字節。這個命令可能用於測試或演示`zzuf`對數據的改變效果,或者用於檢測`hd`命令對特定數據模式的顯示行為。
--------------
8. As the image shows, the zzuf tool has fuzzed two bytes in the binary, and if you run it again, it will repeat this. Therefore, it exhibits reproducible behavior.
如圖所示,zzuf 工具已模糊二進位檔案中的兩個位元組,如果再次執行它,它將重複此操作。 因此,它表現出可重現的行為。
9. Next, let us try to do the same thing but dump it in octal, which is in base 8. In the terminal window, type: zzuf cat /dev/zero | od -vN 32 and press Enter. An example of the output of the command is shown in the following screenshot.
接下來,讓我們嘗試做同樣的事情,但將其轉儲為八進制,即以 步驟 8 為基礎。在終端機視窗中,鍵入: zzuf cat /dev/zero | od -vN 32 並按 Enter 鍵。 以下螢幕截圖顯示了該命令的輸出範例。
```bash=
$zzuf cat /dev/zero | od -vN 32
```

10. You will notice that the output is the same, so this is another advantage . Regardless of the fuzzed application, the data are fuzzed in the same way.
您會注意到輸出是相同的,因此這是另一個優點。 無論模糊應用程式如何,資料都以相同的方式進行模糊處理。
11. The fuzzing ratio is the proportion of bits that zzuf changes. It can be specified using the -r flag. By default, the ratio is 0.004, which translates to fuzzing 0.4% of the number of bits being fuzzed.
模糊比率是zzuf改變的位元的比例。 可以使用 -r 標誌指定它。 預設情況下,該比率為 0.004,這表示模糊測試位數的 0.4%。
12. Next, we will try and fuzz more bits using the -r flag. Type: zzuf -r 0.05 cat /dev/zero | hd -vn 32 and press Enter. An example of the output of this command is shown in the following screenshot.
接下來,我們將嘗試使用 -r 標誌來模糊更多位。 輸入 zzuf -r 0.05 cat /dev/zero | hd -vn 32,然後按 Enter。 以下螢幕截圖顯示了此命令的輸出範例。
```bash=
$zzuf -r 0.05 cat /dev/zero | hd -vn 32
```

13. The behavior of zzuf is reproducible, but we may need to fuzz in different ways. We do this by changing the random seed with the -s flag. The initial value of the random generator is random , and the default seed is 0. We can change the seed, and type: zzuf -s 10 cat /dev/zero | hd -vn 32 and press Enter. An example of the output is shown in the following screenshot:
zzuf 的行為是可重現的,但我們可能需要以不同的方式進行模糊測試。 我們透過使用 -s 標誌更改隨機種子來做到這一點。 隨機產生器的初始值為 random ,預設種子為 0。我們可以更改種子,輸入: zzuf -s 10 cat /dev/zero | hd -vn 32,然後按 Enter。 以下螢幕截圖顯示了輸出範例:
```bash=
$zzuf -s 10 cat /dev/zero | hd -vn 32
```

-------
這個指令結合了幾個不同的命令,用於在Unix或Linux環境下執行。我們來逐步解釋這個指令的各個部分:
- `$zzuf -s 10`:`zzuf`是一個錯誤注入工具,用於測試程序處理各種輸入時的穩健性。`-s 10`選項指定了隨機種子為10,這決定了`zzuf`隨機改變輸入的方式。這樣做可以保證,使用相同的種子值時,`zzuf`的行為是可重現的。
- `cat /dev/zero`:這個命令讀取`/dev/zero`特殊文件,該文件提供了一個無限的零(0x00)字節流。
- `|`:管道符號,將前一個命令的輸出作為後一個命令的輸入。
- `hd -vn 32`:`hd`命令用於將二進制數據以十六進制格式輸出。在這裡,`-v`選項通常用於顯示所有輸出(包括重複行),而`-n 32`限制輸出的數據量為前32個字節。
整體而言,`$zzuf -s 10 cat /dev/zero | hd -vn 32`這條指令的作用是使用`zzuf`工具和種子10來隨機改變從`/dev/zero`讀取的零字節流,然後用`hd`命令將改變後的前32個字節以十六進制格式輸出。這可以用於演示`zzuf`如何改變數據流,以及如何使用`hd`命令來查看二進制數據的十六進制表示。
隨機種子(Random Seed)是一種在生成偽隨機數(pseudo-random numbers)時使用的初始值。在計算機科學和數學中,由於計算機無法產生真正的隨機數,因此會使用特定的算法來生成一系列看起來隨機的數字,這些被稱為偽隨機數。隨機種子的作用就是作為這個算法的起始點。
使用相同的隨機種子,配合同一個偽隨機數生成算法,將會產生完全相同的隨機數序列。這個特性使得隨機數生成在需要可重現性的應用中非常有用,比如科學研究、遊戲、安全性測試等領域。
在不同的應用場景中,隨機種子可以是任意的數字,或者是基於某些變化的數據(如當前時間)。設置隨機種子後,隨機數生成器將從這個種子出發,按照其內置的算法產生一系列的隨機數。
總之,隨機種子對於控制偽隨機數列的生成具有關鍵作用,它確保了在相同種子和算法的情況下,生成的隨機數序列是可預測和可重現的。
-------
14. Another method to use the tool is to fuzz files directly. Type: cat /dev/zero | zzuf | hd -vn 32 and press Enter. An example of the output of the command is shown in the following screenshot.
使用該工具的另一種方法是直接模糊(fuzz)文件。 輸入:cat /dev/zero | zzuf | hd -vn 32,然後按 Enter。 以下螢幕截圖顯示了該命令的輸出範例。
```bash=
$cat /dev/zero | zzuf | hd -vn 32
```

15. We can also use the tool to create files. Type: dd if=/dev/zero bs=1 count=32 | zzuf > output.file and press Enter. An example of the output is shown in the following screenshot.
我們也可以使用該工具來建立文件。 輸入: dd if=/dev/zero bs=1 count=32 | zzuf > output.file 並按 Enter 鍵。 以下螢幕截圖顯示了輸出範例
```bash=
$dd if=/dev/zero bs=1 count=32 | zzuf > output.file
```

-----
這條命令在Unix或Linux系統中使用了幾個不同的工具和概念,下面是對其的逐步解釋:
- `dd`:`dd`是一個用於轉換和複製文件的命令,它可以按照指定的塊大小讀取和寫入數據。
- `if=/dev/zero`:這指定了輸入文件(`if`)為`/dev/zero`,這是一個特殊文件,讀取它將不斷產生零(0x00)字節。
- `bs=1`:設置塊大小(`bs`)為1字節。
- `count=32`:指示`dd`命令只讀取32塊數據,因為塊大小設為1字節,所以這意味著讀取32字節。
- `|`:管道符號,用於將前一個命令的輸出作為後一個命令的輸入。
- `zzuf`:`zzuf`是一個錯誤注入工具,常用於軟件測試中,以模擬數據錯誤的情況。在這裡,它沒有顯示指定任何選項,所以將使用默認設置來處理從`dd`命令接收的數據。
- `>`:重定向符號,用於將命令的輸出寫入到文件中。
- `output.file`:這是將要被創建或覆蓋,並接收處理後數據的文件名。
總的來說,這條命令的功能是從`/dev/zero`讀取32字節的數據,然後通過`zzuf`對這些數據進行可能的錯誤注入處理,最後將處理後的數據寫入到`output.file`文件中。這可以用於測試或演示`zzuf`如何處理和修改輸入的數據。
-----
16. Next, to view the file, type: hd -v output.file and press Enter. The output is shown in the following screenshot:
接下來,要查看該文件,請輸入 hd -v output.file 並按 Enter。 輸出如下圖所示:
```bash=
$hd -v output.file
```

17. We can use zzuf as a batch testing tool as well as a debugging tool. In the terminal window, type **zzuf file /bin/ls** and press Enter. An error appears, because zzuf tries to fuzz the ls file. This is not expected since the file is a special file. The error message is not very helpful but it allows to change our option to add the debug option. Enter **zzuf -d file /bin/ls**. An example of the output from this command is shown in the following screenshot.
我們可以使用zzuf作為批次測試工具以及調試工具。 在終端機視窗中,輸入 zzuf file /bin/ls 並按 Enter。 出現錯誤,因為 zzuf 嘗試模糊測試 ls 檔案。 這是不期望的,因為該文件是一個特殊文件。 該錯誤訊息不是很有幫助,但它允許更改我們的選項以添加偵錯選項。 輸入zzuf -d file /bin/ls。 以下螢幕截圖顯示了此命令的輸出範例
```bash=
$zzuf file /bin/ls
$zzuf -d file /bin/ls
```

18. We see that the file opens /etc/magic and the two /usr/share files. We can use the -E flag to ensure that the tool excludes files. This tells the tool to not fuzz any files that match the given regular expression. Add the -E flag to the previous command. In the terminal window, type zzuf -d -E /etc/ -E /usr/share/ file /bin/ls and press Enter. An example of the output of the command is shown in the following screenshot:
我們看到該檔案開啟了 /etc/magic 和兩個 /usr/share 檔案。 我們可以使用 -E 標誌來確保工具排除檔案。 這告訴工具不要模糊任何與給定正規表示式相符的檔案。 將 -E 標誌加入上一個指令。 在終端機視窗中,輸入 zzuf -d -E /etc/ -E /usr/share/ file /bin/ls 並按 Enter。 以下螢幕截圖顯示了該命令的輸出範例:
```bash=
$zzuf -d -E /etc/ -E /usr/share/ file /bin/ls
```

19. Another way to avoid the issue is to use the include option using the -i flag.
避免此問題的另一種方法是使用包含選項 -i flag
20. We can also use the -c flag to ensure zzuf to only files that appear on the fuzzed applications command line. Type zzuf -d -c file /bin/ls and press Enter. An example of the output of the command is shown in the following screenshot.
我們也可以使用 -c 標誌來確保 zzuf 僅適用於出現在模糊應用程式命令列上的檔案。 輸入 zzuf -d -c file /bin/ls 並按 Enter。 以下螢幕截圖顯示了該命令的輸出範例。
```bash=
$zzuf -d -c file /bin/ls
```

21. Ensure that you are in the /home/student/examples/samplecode. Type: for i in {1000..3000}; do for f in example.* ; do zzuf -r 0.01 -s $i < "$f" > "$i-$f"; done; done and press Enter.
確保您位於 /home/student/examples/samplecode 中。 輸入:for i in {1000..3000}; do for f in example.* ; do zzuf -r 0.01 -s $i < "$f" > "$i-$f"; done;done 完成並按 Enter 鍵。
```bash=
$cd /home/student/examples/samplecode
$for i in {1000..3000}; do for f in example.*; do zzuf -r 0.01 -s $i < "$f" > "$i-$f"; done; done
```
22. Thus, for every example file, we create 2000 malformed variants, all named in the form [number]-example.[extension]. The -r parameter for zzuf is the amount of change you want in a file. 0.01 means that 1% of the file gets changed randomly. The -s parameter is the seed. For every different s value, we get a different output. You can certainly adapt the number of variants but judging from experience, 2000 is a reasonable number to start with . Type ls and press Enter. An example of the output is shown in the following screenshot.
因此,對於每個範例文件,我們建立 2000 個格式錯誤的變體,全部以 [number]-example.[extension] 形式命名。 zzuf 的 -r 參數是您想要在檔案中進行的變更量。 0.01 表示文件的 1% 被隨機更改。 -s 參數是種子。 對於每個不同的 s 值,我們都會得到不同的輸出。 您當然可以調整變體的數量,但從經驗來看,2000 個是一個合理的起始數字。 輸入 ls 並按 Enter 鍵。 以下螢幕截圖顯示了輸出範例。

23. As the image shows, the for loop created a lot of files for us to work with.
如圖所示,for 迴圈創建了許多文件供我們使用。
24. From here, we could input the files into a program as follows:
LC_ALL=C; LANG=C; for f in -example.; do timeout 3 convert -resize 2 "$f" /tmp/test.png; echo $f; done &> fuzzing.log
```bash=
$LC_ALL=C; LANG=C; for f in -example.; do timeout 3 convert -resize 2 "$f" /tmp/test.png; echo $f; done &> fuzzing.log
```

25. LC_ALL=C; LANG=C; ensures that we set our output to the English language. We do this because we now want to grep for error messages. The timeout command ensures that we stop when a single file takes too long. This will miss endless loop bugs. The workaround is outside the scope of this introduction tutorial. Additionally, after every call of convert, we output the name of the current file. This should be quite obvious — we want to know later which file caused a crash when we found one.
LC_ALL=C; LANG=C;確保我們將輸出設為英語。 我們這樣做是因為我們現在想要 grep 來尋找錯誤訊息。 超時命令確保我們在單一文件花費太長時間時停止。 這會錯過無限循環錯誤。 此解決方法超出了本介紹教程的範圍。 此外,每次呼叫 Convert 後,我們都會輸出目前檔案的名稱。 這應該是非常明顯的——當我們發現一個文件時,我們想知道是哪個文件導致了崩潰。
26. This can take quite some time. Depending on how many inputs you use, the output file may become quite large. Therefore, ensure that you place it somewhere with some gigabytes of space.
這可能需要相當長的時間。 根據您使用的輸入數量,輸出檔案可能會變得相當大。 因此,請確保將其放置在具有幾 GB 空間的位置。
27. Next, we check if we found something. We look for Segmentation faults in our logfile, type grep -C2 "Segmentation fault" fuzzing.log and press Enter.
接下來,我們檢查是否可以發現一些東西。 我們在日誌檔案中尋找分段錯誤,輸入 grep -C2 "Segmentation failure" fuzzing.log 並按 Enter。

28. In this case, we do not show any crashes , but the process is the most important thing. You can change the numbers and work with them to modify and make changes.
在這種情況下,我們不會顯示任何崩潰,但過程是最重要的。 您可以更改數字並與它們一起修改和進行更改。
29. We have another method of using the zzuf, which is using it directly. In this example, we will use the tool with the objdump command. Ensure that you are in the samplecode folder, and type: **zzuf -s 0:1000000 -c -C 0 -q -T 3 objdump -x win9x.exe** and press Enter. In this example, we are using an EXE file that is part of the binutils resources. It is an older Windows executable, but here, we are demonstrating the process.
我們還有另一種使用zzuf的方法,那就是直接使用它。 在此範例中,我們將使用該工具與 objdump 命令。 確保您位於範例程式碼資料夾中,然後鍵入:zzuf -s 0:1000000 -c -C 0 -q -T 3 objdump -x win9x.exe 並按 Enter。 在此範例中,我們使用的 EXE 檔案是 binutils 資源的一部分。 它是一個較舊的 Windows 可執行文件,但在這裡,我們正在演示該過程。
```bash=
$zzuf -s 0:1000000 -c -C 0 -q -T 3 objdump -x win9x.exe
```

30. -s means that we will try one million seed values. -c means zzuf should only fuzz the files given on the command line. This is useful because otherwise, the tools might throw error messages from reading config files or other things. Therefore, they will not really get to our fuzzed input. -C 0 means that zzuf should not stop after the first crash is found. -q suppresses the output of our fuzzed command. -T 3 sets a timeout of three seconds, so zzuf won’t hang if we run into an endless loop. We are trying to see if we can crash the program. An example of the output from the command is shown in the following screenshot.
-s 表示我們將嘗試一百萬個種子值。 -c 表示 zzuf 應該只模糊命令列上給出的檔案。 這非常有用,因為否則工具可能會因讀取設定檔或其他內容而拋出錯誤訊息。 因此,他們不會真正獲得我們的模糊輸入。 -C 0 表示 zzuf 在發現第一次崩潰後不應停止。 -q 抑制模糊指令的輸出。 -T 3 設定三秒的逾時,因此如果我們遇到無限循環,zzuf 不會掛起。 我們正在嘗試看看是否可以使程式崩潰。 以下螢幕截圖顯示了該命令的輸出範例。


31. We see in the image that we have a SIGSEGV. This is our segmentation fault, and whenever we have one, it is indicated by signal 11. Now we have the data we need to query that specific instance. In the terminal window, enter the details from the crash, which in our example here, is s=16915. Therefore, we type zzuf -r 0.004 -s 16915 < win9x.exe > crash.exe and press Enter.
我們在圖像中看到有一個 SIGSEGV。 這是我們的分段錯誤,每當出現分段錯誤時,都會由訊號 11 指示。現在我們有了查詢該特定實例所需的資料。 在終端視窗中,輸入崩潰的詳細信息,在我們的範例中為 s=16915。 因此,我們輸入zzuf -r 0.004 -s 16915 < win9x.exe > crash.exe,然後回車。
```bash=
$zzuf -r 0.004 -s 16915 < win9x.exe > crash.exe
```

32. Next, we have a fuzzed file that generates a crash in our application. We can send these to the application author. Please note that if you fuzzed one of the example applications mentioned, a large number of issues have already been reported there and the authors are busy fixing them. If you want to report anything, ensure that you test the crashes with their latest upstream git/svn code.
接下來,我們有一個模糊文件,它會在我們的應用程式中產生崩潰。 我們可以將這些發送給應用程式作者。 請注意,如果您對提到的範例應用程式之一進行模糊測試,則那裡已經報告了大量問題,作者正在忙於修復它們。 如果您想報告任何內容,請確保使用最新的上游 git/svn 程式碼測試崩潰。
33. We can also analyze them further. One handy tool is valgrind. Simply run valgrind -q in front of your crashing command (-q suppresses some unnecessary output). Enter: **valgrind -q objdump -x crash.exe**. An example of the output from the command is shown in the following screenshot.
我們還可以進一步分析它們。 valgrind 是一款方便的工具。 只需在崩潰命令前面執行 valgrind -q (-q 會抑制一些不必要的輸出)。 輸入 valgrind -q objdump -x crash.exe。 以下螢幕截圖顯示了該命令的輸出範例。
```bash=
$valgrind -q objdump -x crash.exe
```

34. As the image shows, we have obtained quite a bit of information about the crashed program. You are now familiar with the process for crashing a program.
如圖所示,我們已經獲得了有關崩潰程序的大量資訊。 您現在已經熟悉了程式崩潰的過程。
35. The lab objectives have been achieved.
## Exercise 2: Address Sanitizer
Lab Objective:
In this lab, we will explore the process of using the tool Address Sanitizer that will provide us more capabilities.
Lab Tasks
1. Log in to the Ub20 Fuzzing machine using studentpassword as Password.
2. The first thing we need to do is create a simple main function. Enter the following into your favorite editor, and save it as test.c.
我們需要做的第一件事是建立一個簡單的 main 函數。 在您喜歡的編輯器中輸入以下內容,並將其另存為 test.c。
```c=
int main() {
int a[2] = {1,0};
int b=a[2];
}
```

3. As a reminder, this is a classic off-by-one-error. An array “a” with two elements is defined. The elements of an array are accessed with indices starting with 0, so this array consists of the elements a[0] and a[1]. The code then sets b to the value a[2]. However, a[2] is an invalid value, as it is not part of the array. The variable b will end up containing an arbitrary value. It just reads “some” memory from the stack, and it is undefined what that memory contains. However, unlike other memory access bugs, this does not crash. Even valgrind will not be able to indicate that something is wrong
提醒一下,這是一個典型的逐一錯誤。 定義了一個包含兩個元素的陣列「a」。 數組的元素是透過從 0 開始的索引來存取的,因此該數組由元素 a[0] 和 a[1] 組成。 然後程式碼將 b 設定為值 a[2]。 但是,a[2] 是無效值,因為它不是陣列的一部分。 變數 b 最終將包含任意值。 它只是從堆疊中讀取“一些”內存,並且該內存包含的內容是未定義的。 然而,與其他記憶體存取錯誤不同,這不會崩潰。 即使 valgrind 也無法表明出現問題
4. Recent versions of the compilers llvm and gcc have received a powerful tool to spot such memory access bugs, which is Address Sanitizer. We can enable it at compile time. To use Address Sanitizer, we need to add the parameter -fsanitize=address to our compiler flags. To make debugging easier, we will also add **-ggdb**.
最新版本的編譯器 llvm 和 gcc 已經獲得了一個強大的工具來發現此類記憶體存取錯誤,這就是 Address Sanitizer。 我們可以在編譯時啟用它。 要使用 Address Sanitizer,我們需要將參數 -fsanitize=address 新增到編譯器標誌。 為了使調試更容易,我們還將添加-ggdb。(在下個步驟執行)
5. In the terminal window, type: gcc -fsanitize=address -ggdb -o test test.c and press Enter.
在終端機視窗中,鍵入:gcc -fsanitize=address -ggdb -o test test.c 並按 Enter。
```bash=
$ggc -fsanitize=address -ggdb -o test test.c
```
6. Now that the code has been compiled with Address Sanitizer, we obtain more feedback when it is run. Type ./test and press Enter. An example of the output of the command is shown in the following screenshot.
現在程式碼已經使用 Address Sanitizer 進行了編譯,我們在運行時可以獲得更多回饋。 輸入 ./test 並按 Enter 鍵。 以下螢幕截圖顯示了該命令的輸出範例。
```bash=
$./test
```

7. The tool is reporting that we have a stack-buffer-overflow as shown in the following screenshot. It even references the line with the problem.
該工具報告我們有堆疊緩衝區溢出,如以下螢幕截圖所示。 它甚至引用了有問題的行。

8. The software we want to fuzz usually does not come as a simple .c file, so we have to add the Address Sanitizer to the compiler flags. For a software using normal configure scripts, this can be performed using the following commands:
我們想要模糊測試的軟體通常不是一個簡單的 .c 文件,因此我們必須將 Address Sanitizer 添加到編譯器標誌中。 對於使用普通設定腳本的軟體,可以使用以下命令執行此操作:
a. ./configure --disable-shared CFLAGS="-fsanitize=address -ggdb" CXXFLAGS="-fsanitize=address -ggdb" LDFLAGS="-fsanitize=address"
b. make
```bash=
$./configure --disable-shared CFLAGS="-fsanitize=address -ggdb" CXXFLAGS="-fsanitize=address -ggdb" LDFLAGS="-fsanitize=address"
$make
```
9. Again, we add -ggdb for more debugging information. If possible, we disable shared libraries and set the flags for both the C and the C++ compiler.
再次,我們新增 -ggdb 以獲取更多偵錯資訊。 如果可能,我們禁用共享庫並為 C 和 C++ 編譯器設定標誌。
10. We can now run our software against malformed inputs similar to how we did in the previous lab.
我們現在可以針對格式錯誤的輸入來運行我們的軟體,就像我們在前一個lab中所做的那樣。
11. When redirecting the output to a log file, we must consider that we cannot grep for Segmentation Fault anymore. Instead, we need to grep for Address Sanitizer’s messages using grep AddressSanitizer fuzzing.log
將輸出重新導向到日誌檔案時,我們必須考慮到我們無法再 grep 查找分段錯誤。 相反,我們需要使用 grep AddressSanitizer fuzzing.log 來尋找 Address Sanitizer 的訊息。
12. Note the following when using Address Sanitizer. If it finds a memory access violation, it does not automatically crash the application. This is a problem when using automated fuzzing tools because they usually try to detect segfaults by checking the return code. We can, however, force the tool to crash the software when an error occurs. To do this, we use the environment variable ASAN_OPTIONS by entering export ASAN_OPTIONS='abort_on_error=1'.
使用 Address Sanitizer 時請注意以下事項。 如果它發現記憶體存取衝突,它不會自動使應用程式崩潰。 使用自動模糊測試工具時這是一個問題,因為它們通常會嘗試透過檢查回傳程式碼來偵測段錯誤。 但是,我們可以在發生錯誤時強制該工具使軟體崩潰。 為此,我們透過輸入 export ASAN_OPTIONS='abort_on_error=1' 來使用環境變數 ASAN_OPTIONS。
13. Another problem is that the tool can take a large amount of memory.
另一個問題是該工具可能佔用大量記憶體。
14. A fuzzed sample may cause an application to allocate vast amounts of memory, which in turn may cause your system to become unstable and other applications to crash. Therefore, do not do anything important on a system while running a fuzzer without a memory limit on the same system.
模糊樣本可能會導致應用程式分配大量內存,進而可能導致您的系統變得不穩定並且其他應用程式崩潰。 因此,在同一系統上執行沒有記憶體限制的模糊器時,請勿在系統上執行任何重要操作。
15. As you have seen, you can do several things with this tool. Remember that it is only one suite of sanitizers. As such, you are encouraged to explore this tool as well as others.
如您所見,您可以使用這個工具執行多種操作。請記住,這只是一套清潔工具中的一部分。因此,我們鼓勵您探索這個工具以及其他工具。
16. The lab objectives have been achieved.
## Exercise 3: Fuzzing with AFL
Lab Objective:
In this lab, we will explore the process of fuzzing using the tool American Fuzzy Lop (AFL).
在本實驗中,我們將探索使用 American Fuzzy Lop (AFL) 工具進行模糊測試的過程。
Lab Tasks
1. Log in to the 口Ub20 Fuzzing machine using **studentpassword** as Password.

2. Ensure that your Address Space Layout Randomization (ASLR) is disabled, open a terminal and type: **sudo sysctl kernel.randomize_va_space=0**. This is not required for our fuzzing. However, often, when you have to build code repeatedly, you might forget that the ASLR is not disabled and waste time troubleshooting. Other aspects related to fuzzing need troubleshooting as well.
確保停用位址空間佈局隨機化 (ASLR),開啟終端機並鍵入:sudo sysctl kernel.randomize_va_space=0。 這對於我們的模糊測試來說不是必需的。 然而,通常,當您必須重複建置程式碼時,您可能會忘記 ASLR 沒有被停用,浪費時間進行故障排除。 與模糊測試相關的其他方面也需要進行故障排除。
```bash=
$sudo sysctl kernel.randomize_va_space=0
```
3. We will currently not address binary analysis and exploitation since we have a dedicated module for this.
我們目前不會解決二進制分析和利用問題,因為我們有一個專用模組。
4. Once you are logged in, open a terminal window.
登入後,打開終端機視窗。
5. We want to create a program to work with. In your favorite editor, enter the following program:
我們想要創建一個可以使用的程式。 在您最喜歡的編輯器中,輸入以下程序:
```c=
#include <stdio.h>
#include <string.h>
int main(void)
{
char login[32];
char passwd[32];
printf("Login: \n");
gets(login);
printf("Password: \n");
gets(passwd);
if (strcmp(login, "root") == 0) {
if (strcmp(passwd, "1qazxsw2") == 0) {
printf("Access Granted.\n");
return 0;
}
}
printf("Access Denied.\n");
return 1;
}
```
6. Save the program as **aflfirsttest.c**.
將程式儲存為 aflfirsttest.c
7. The program uses two character buffers of 32 characters: one to hold the username and the other to hold a password. To manage user input, we used the well-known insecure gets() function, which fails to check buffer boundaries and leads to buffer overflows.
此程式使用兩個 32 個字元的字元緩衝區:一個用於保存使用者名,另一個用於保存密碼。 為了管理使用者輸入,我們使用了眾所周知的不安全的 gets() 函數,該函數無法檢查緩衝區邊界並導致緩衝區溢位。
8. Once executed, the program first asks for a username and a password. The inputs are stored in the login and passwd variables. Their values are then compared with the expected value using strcmp(). If the credentials entered are “**root**” and “**1qazxsw2**”, then an “**Access Granted**.” message is printed out to the console. Otherwise, “Access Denied.” is displayed to the user, and the program exits.
執行後,程式首先要求輸入使用者名稱和密碼。 輸入儲存在 login 和 passwd 變數中。 然後使用 strcmp() 將它們的值與預期值進行比較。 如果輸入的憑證是“root”和“1qazxsw2”,則顯示“已授予存取權限”。 訊息被印到控制台。 否則,「訪問被拒絕」。 顯示給用戶,然後程式退出。
9. We will compile this program with absolutely no memory protection, i.e. **NX** will be disabled and no stack canary. **NX** is usually enabled to prevent code from being executed directly from the stack, which there is no need for other than exploitation purposes. As for stack canaries, they can detect stack overflows by adding an extra value to the software stack. If this value is not found when the function returns, an exception is thrown to prevent further execution. Nowadays, these protection schemes are enabled in a vast majority of cases, but we adopt simplicity rather than realism for this post . These protection mechanisms can be disabled using the following GCC command:
我們將使用完全沒有記憶體保護的方式編譯這個程式,也就是說,**NX** 將被禁用,並且不使用堆疊金絲雀。通常啟用 **NX** 是為了防止直接從堆疊執行代碼,除了利用目的之外,沒有其他需要。至於堆疊金絲雀,它們通過在軟件堆疊中添加一個額外的值來檢測堆疊溢出。如果在函數返回時找不到這個值,就會拋出異常以防止進一步執行。如今,這些保護機制在大多數情況下都是啟用的,但在這篇文章中,我們選擇簡單而非現實。這些保護機制可以使用以下 GCC 命令來禁用:
(堆疊金絲雀(Stack Canary)是一種用於增強軟體安全性的技術,旨在防止堆疊溢出攻擊。這種技術通過在函數的堆疊框架上放置一個稱為“金絲雀”的隨機生成的值,作為一種保護機制。當函數執行並返回之前,系統會檢查這個金絲雀值是否被更改。如果發現金絲雀值被覆蓋或更改,這通常表示有堆疊溢出攻擊的嘗試,系統會立即採取行動(如終止程序),以防止潛在的安全漏洞被利用。這種方法能有效地增加攻擊者利用軟體漏洞的難度,從而提高了軟體的安全性。)
```bash=
$gcc -fno-stack-protector -z execstack aflfirsttest.c -o aflfirsttest-gcc
```


10. The **-fno-stack-protector** will disable the stack canaries while the -z execstack makes both the heap and stack executable. To verify that these options have not been included, we can use a powerful tool called checksec, which is included with pwntools that we have installed on the machine. Enter checksec aflfirsttest-gcc. An example of this is shown in the following screenshot.
使用 -fno-stack-protector 會禁用堆疊看門狗,而 -z execstack 則使堆積和堆疊都可執行。為了驗證這些選項沒有被包含,我們可以使用一個強大的工具叫做 checksec,它是隨 pwntools 一起安裝在機器上的。輸入 checksec aflfirsttest-gcc。以下截圖顯示了這個例子。
```bash=
$checksec aflfirsttest-gcc
```

11. Checksec reports on two additional security mechanisms other than the stack canaries and No-eXecute bit. Although these concepts are outside the scope of this lab, we will explain them briefly.
Checksec 報告了除堆疊金絲雀和 No-eXecute 位元之外的兩種附加安全機制。 儘管這些概念超出了本實驗的範圍,但我們將對其進行簡要解釋
12. Relocation Read-Only (RELRO) is a technique used to relocate the sections of an ELF executable in order to prevent the Global Offset Table (GOT) from being overwritten due to an exploitable vulnerability.
只讀重定位 (RELRO) 是一種用於重定位 ELF 可執行檔案部分的技術,以防止全域偏移表 (GOT) 由於可利用的漏洞而被覆蓋。
13. Even though it is within the gdb, we will explain it here. PIE stands for Position Independent Executable and causes the program to be allocated at different memory locations on each execution, making it difficult to exploit it reliably. PIE is an implementation of the ASLR concept.
即使它在 gdb 中,我們也會在這裡解釋它。 PIE 代表位置獨立可執行文件,導致程式在每次執行時分配到不同的記憶體位置,難以可靠地利用它。 PIE 是 ASLR 概念的實作。
14. Now that our target has been created, we are ready to start fuzzing it to uncover the buffer overflow that it contains.
現在我們的目標已經創建,我們準備開始對其進行模糊測試以發現它包含的緩衝區溢位。
15. We will use AFL, which is a popular open-source and free fuzzer.
我們將使用 AFL,這是一種流行的開源免費模糊器。
16. AFL has been leveraged to discover vulnerabilities in a large set of applications and libraries. Before starting AFL, we need to instrumentalize our target using the afl-gcc compiler. The AFL compiler will add code around the source in order to maximize coverage. To compile the source code with AFL, use the same command that was used earlier to compile aflfirsttest.c using afl-gcc instead of gcc, or use the associated Makefile.
AFL 已被用來發現大量應用程式和庫中的漏洞。 在開始 AFL 之前,我們需要使用 afl-gcc 編譯器來工具化我們的目標。 AFL 編譯器將在原始程式碼周圍添加程式碼以最大化覆蓋範圍。 若要使用 AFL 編譯原始程式碼,請使用先前使用 afl-gcc 而不是 gcc 來編譯 aflfirsttest.c 時使用的相同命令,或使用關聯的 Makefile。
17. In the terminal window, type: **afl-gcc -fno-stack-protector -z execstack aflfirsttest.c -o aflfirsttest-afl** and press Enter. An example of the output from the command is shown in the following screenshot.
在終端視窗中,鍵入: **afl-gcc -fno-stack-protector -z execstack aflfirsttest.c -o aflfirsttest-afl** 並按 Enter。 以下螢幕截圖顯示了該命令的輸出範例。
```bash=
$afl-ggc -fno-stack-protector -z execstack aflfirsttest.c -o aflfirsttest-afl
```

18. Warnings are displayed as shown in the above screenshot, but we know that because it is deliberately written for testing and will work for our purposes .
如上面的螢幕截圖所示顯示警告,但我們知道這是因為它是故意為測試而編寫的並將用於我們的目的。
19. The resulting binary is the one that will be used with AFL.
產生的二進位檔案將與 AFL 一起使用。
20. A critical aspect of fuzzing is crafting meaningful test cases, e.g. inputs that will maximize code coverage by exploring all potential paths of the targeted program. Our example program has the following three possible paths for input:
a. Username is invalid
b. Username is valid, but password is invalid
c. Username and password are valid
模糊測試的一個關鍵方面是製作有意義的測試案例,例如 透過探索目標程式的所有潛在路徑來最大化程式碼覆蓋率的輸入。 我們的範例程式有以下三種可能的輸入路徑:
a. 無效的使用者名稱
b. 使用者名稱有效,但密碼無效
c. 使用者名稱和密碼有效
21. Therefore, to reach these three possible paths, the method is to design each test case with its own file.
因此,要達到這三個可能的路徑,方法是用自己的檔案設計每個測試案例。
22. The first file will have two lines, none of which will contain appropriate credentials. The second file will have the right username, but an invalid password. The third file will have both correct credentials. AFL will read the contents of each file and feed each line to the stdin of Vuln1. Create a directory called testcases, and in it, create three files representing these cases. The names of the files do not matter. The data for each file are shown in the following table.
第一個文件將有兩行,其中沒有一行包含適當的憑證。 第二個檔案將具有正確的用戶名,但密碼無效。 第三個文件將有兩個正確的憑證。 AFL 將讀取每個檔案的內容並將每一行提供給 Vuln1 的標準輸入。 建立一個名為 testcases 的目錄,並在其中建立代表這些案例的三個檔案。 文件的名稱並不重要。 每個文件的資料如下表所示。

23. Once you have created the files, create another directory for the results. You can simply call it results.
建立檔案後,為結果建立另一個目錄。 您可以簡單地將其稱為結果。
24. Create another directory for your three test cases called testcases files, and move them there.
為您的三個測試案例建立另一個目錄,稱為 testcases 文件,並將它們移到那裡
25. Once you have moved the files, type: ls -lart testcases and verify that the output matches what is shown in the following screenshot.
移動檔案後,輸入:ls -lart testcases 並驗證輸出是否與以下螢幕截圖中顯示的內容相符
```bash=
$ls -lart testcasesll
```

26. At this point, we are ready to start the fuzz. Type: **afl-fuzz -i ./testcases -o ./results ./aflfirsttest-afl** and press Enter. An example of the output of this command is shown in the following screenshot. This often occurs when you first run the program.
至此,我們已經準備好開始模糊測試了。 輸入: **afl-fuzz -i ./testcases -o ./results ./aflfirsttest-afl** 並按 Enter。 以下螢幕截圖顯示了此命令的輸出範例。 當您第一次運行程式時,通常會發生這種情況。
```bash=
$afl-fuzz -i ./testcases -o ./results ./aflfirsttest-afl
```

27. All we have to do is follow the steps in the error message, open another window, and type: **sudo -i**. Then type: **echo core > /proc/sys/kernel/core_pattern**.
我們要做的就是按照錯誤訊息中的步驟操作,打開另一個窗口,然後輸入:**sudo -i**。 然後輸入:**echo core > /proc/sys/kernel/core_pattern**。
```bash=
$sudo -i
$echo core > /proc/sys/kernel/core_pattern
```

28. We should now be able to again run our command in the original terminal window. You might have to go to an expanded screen if you get an error message. An example of this is shown in the following screenshot.
我們現在應該能夠在原始終端機視窗中再次運行我們的命令。 如果收到錯誤訊息,您可能必須轉到擴充畫面。 以下螢幕截圖顯示了這樣的範例。

29. Upon reviewing the image, you will see that there is quite a bit of data that you can review. We will not cover many of these due to time constraints . You are encouraged to research them. An excellent reference is the README file located at **/home/student/afl-2.52b**. An example of the beginning of the file is shown in the following screenshot.
查看圖像後,您會發現有相當多的數據可供查看。 由於時間限制,我們不會討論其中的許多內容。 我們鼓勵您研究它們。 位於 **/home/student/afl-2.52b** 的自述文件是一個很好的參考。 以下螢幕截圖顯示了檔案開頭的範例。

30. The output that you are looking at when the fuzzing tool is running has two sections that are of interest for us in this lab:
a. Total paths
b. Unique crashes
模糊測試工具運行時您看到的輸出有兩個部分是我們在本實驗中感興趣的:
a. 總路徑數
b. 獨特的崩潰
31. Each of these is shown in the following screenshots:
以下螢幕截圖顯示了其中的每一個:

32. Since the total paths are listed as 3, and we have identified from the start of the lab that we have three paths of input, we can test and this is what we are showing currently. We have completed the three paths, so we can break the run by hitting +C.
由於總路徑列出為 3,並且我們從實驗一開始就確定了我們有 3 個輸入路徑,因此我們可以進行測試,這就是我們目前所展示的內容。 我們已經完成了三個路徑,因此我們可以透過按 +C 來中斷運行。
33. For our example here, we only have three input paths that we created, and as such, we have this advantage. This advantage will not be available in a normal situation, but for our training here, this suffices and the process is the same. Before we start investigating, unique crashes, we must look at two more things, namely the CPU and the exec speed. Both of these are shown in the following screenshot:
對於我們這裡的範例,我們只有創建的三個輸入路徑,因此,我們有這個優勢。 這個優勢在正常情況下是不會有的,但是對於我們這裡的訓練來說,這就足夠了,而且過程也是一樣的。 在我們開始調查獨特的崩潰之前,我們必須考慮另外兩個因素,即 CPU 和執行速度。 這兩個都顯示在下面的螢幕截圖中:

34. Regarding the CPU, since we are running on a virtual machine and it has been configured for two CPUs with two cores each, we have a reasonable CPU load. When testing with only one processor and one core, the results showed 300% CPU load. Please note that this is something you will have to consider when you are fuzzing, as it takes extensive memory and resources.
關於CPU,由於我們在虛擬機器上運行,並且已配置為兩個CPU,每個CPU有兩個核心,因此我們有一個合理的CPU負載。 僅使用 1 個處理器和 1 個核心進行測試時,結果顯示 CPU 負載為 300%。 請注意,這是您在模糊測試時必須考慮的事情,因為它需要大量的記憶體和資源。
35. Regarding the exec speed, here we are at 8290/sec. This is something to which you must pay close attention, since it can also lead to problems in fuzzing.
關於執行速度,這裡是 8290/秒。 這是您必須密切注意的事情,因為它也可能導致模糊測試出現問題。
36. To look at these two unique crashes, type: **ls -lart results/crashes** and press Enter. The output of this command is shown in the following screenshot.
要查看這兩個獨特的崩潰,請輸入: **ls -lart results/crashes** 並按 Enter。 此指令的輸出如以下螢幕截圖所示。
```bash=
$ls -lart results/crashes
```

37. Each file contains a crash. Since it is signal 11, this means the crash caused a segmentation fault. This lab does not explore exploitation in detail since there is a dedicated module on this , but we will work through the process with the AFL tool.
每個文件都包含一個崩潰。 由於它是訊號 11,這意味著崩潰導致了分段錯誤。 本實驗不會詳細探討漏洞利用,因為有一個專門的模組,但我們將使用 AFL 工具完成該過程。
38. We need to take the crash data as an input and pipe it into our program. Change directory to ./results/crashes. In the terminal window, enter: **cat id\:000000\,sig\:11\,src\:000000\,op\:havoc\,rep\:128 | ../../aflfirsttest-gcc**. Note that “\” is required. Without it, the file will not be found it. An example of the output from the command is shown in the following screenshot.
我們需要將崩潰資料作為輸入並將其傳輸到我們的程式中。 將目錄改為 ./results/crashes。 在終端機視窗中,輸入: **cat id\:000000\,sig\:11\,src\:000000\,op\:havoc\,rep\:128 | ../../aflfirsttest-gcc**。 請注意,“\”是必需的。 沒有它,將找不到該文件。 以下螢幕截圖顯示了該命令的輸出範例。
```bash=
$cat id\:000000\,sig\:11\,src\:000000\,op\:havoc\,rep\:128 | ../../aflfirsttest-gcc
```

39. As you can see, our crash and the segmentation fault from the crash are displayed.
如您所見,顯示了我們的崩潰和崩潰導致的分段錯誤
40. The next step would be to analyze the data. We know that we have a weak program since we created it.
下一步是分析數據。 我們知道自從我們創建它以來我們的程式就很弱
41. The lab objectives have been achieved.
實驗室目標已達到
## Exercise 4: Fuzzing with AFL and capstone
Lab Objective:
In this lab, we will continue to explore the process of fuzzing using the tool American Fuzzy Lop (AFL).
Lab Tasks
1. Go to 口Ub20 Fuzzing-CAP machine and login using studentpassword as Password.

2. We will work and fuzz with the tool capstone. Capstone is an open-source disassembly engine widely used in exploitation frameworks, disassemblers, debugging aids, and other projects.
我們將使用工具 capstone 進行工作和模糊測試。 Capstone 是一個開源反彙編引擎,廣泛應用於開發框架、反彙編器、調試輔助工具和其他專案。
3. The code we are going to work with has been created for you. It is in the home directory and called captest.c. The code is shown in the following screenshot.
我們將要使用的程式碼已為您建立。 它位於主目錄中,名為 captest.c。 程式碼如下面的螢幕截圖所示。

4. This is only a small file that we are using for a base. There really is nothing special here, but it is enough to give us another example of the process to use this tool .
這只是我們用作基礎的小文件。 這裡確實沒有什麼特別的,但是給我們另一個使用這個工具的過程的例子就足夠了
5. You do not have to type the commands in the following screenshot. We are including them here in case you want to do this on a machine you build.
您不必鍵入以下螢幕截圖中的命令。 我們將它們包含在這裡,以防您想在自己建造的機器上執行此操作。
```bash=
$git clone https://github.com/aquynh/capstone.git
$cd capstone
$CC=afl-clang-fast ./make.sh
```

6. We have included the binaries here since afl-clang-fast does not work the same on Ubuntu 20, but the process is key. In your environment, you would build this on your own platform. The 18.04 version of Ubuntu works well with this.
我們在這裡包含了二進位文件,因為 afl-clang-fast 在 Ubuntu 20 上的工作方式不同,但過程是關鍵。 在您的環境中,您可以在自己的平台上建立它。 Ubuntu 18.04 版本可以很好地運作這個實驗。
7. The compilation steps are for reference only, just the executables and perform the fuzzing. You only need to execute the highlighted steps; the remaining are for reference.
編譯步驟僅供參考,只是可執行檔並執行模糊測試。 您只需執行強調的步驟即可; 剩下的僅供參考。
8. We are now ready to compile and link our test code using capstone. Type: **afl-clang-fast -static captest.c capstone/libcapstone.a -o captest** and press Enter. The output of the command is shown in the following screenshot.
我們現在準備好使用 capstone 編譯和連結我們的測試程式碼。 輸入: **afl-clang-fast -static captest.c capstone/libcapstone.a -o captest** 並按 Enter。 此指令的輸出如以下螢幕截圖所示。
```bash=
$afl-clang-fast -static captest.c capstone/libcapstone.a -o captest
```

9. As the above screenshot shows, some warnings are displayed. This is to be expected when we use this type of code and moreover functions.
如上面的螢幕截圖所示,會顯示一些警告。 當我們使用這種類型的程式碼和函數時,這是可以預料到的。
10. Next, we generate our inputs. Type: **mkdir inputs** and press Enter.
接下來,我們產生輸入。 鍵入:**mkdir 輸入**並按 Enter。
```bash=
$mkdir inputs
```
11. We will use the dd command to create some data. Type: **dd if=/dev/urandom of=inputs/rand bs=64 count=1** and press Enter. The output of the command is shown in the following screenshot.
我們將使用 dd 命令創建一些資料。 輸入:**dd if=/dev/urandom of=inputs/rand bs=64 count=1** 並按 Enter。 該命令的輸出如下圖所示
```bash=
$dd if=/dev/urandom of=inputs/rand bs=64 count=1
```

12. Now that the input is created, we are ready to run our fuzzing tool. However, before we do that, we want to ensure that the core is not pointing to an external source. Open another shell, and enter: **sudo -i** to get root privileges (we cannot sudo the command; we have to achieve root first). Then type: **echo > /proc/sys/kernel/core_pattern**.
現在輸入已創建,我們準備好運行我們的模糊測試工具。 然而,在這樣做之前,我們要確保核心沒有指向外部來源。 開啟另一個 shell,然後輸入: **sudo -i** 以獲得 root 權限(我們不能 sudo 該指令;我們必須先取得 root 權限)。 然後輸入:**echo > /proc/sys/kernel/core_pattern**。
```bash=
$sudo -i
$echo > /proc/sys/kernel/core_pattern
```

13. Now we are ready. Type: **afl-fuzz -i inputs -o findings ./captest** and press Enter. An example of the output of the command is shown in the following screenshot.
現在我們準備好了。 輸入: **afl-fuzz -i input -o discovery ./captest** 並按 Enter。 以下螢幕截圖顯示了該命令的輸出範例。
```bash=
$afl-fuzz -i inputs -o findings ./captest
```

14. Our exec speed is over 2K per second, so this is not as good as the earlier speed. However, we can still try to improve the speed.
我們的執行速度超過每秒 2K,所以這不如早期的速度。 不過,我們仍然可以嘗試提高速度。
15. A variety of tricks can be used to speed up the processing. The method we will use here is AFL in-process fuzzing. We will not restart the process each time we get a new input string. We can achieve this by using a loop. We are doing this on the program captest2.c. An example of the code is shown in the following screenshot.
可以使用多種技巧來加快處理速度。 我們在這裡使用的方法是 AFL 進程內模糊測試。 每次獲得新的輸入字串時,我們都不會重新啟動該過程。 我們可以透過使用循環來實現這一點。 我們正在程式 captest2.c 上執行此操作。 以下螢幕截圖顯示了程式碼範例。
```c=
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include "capstone/include/capstone/capstone.h"
#include <inttypes.h>
int main(int argc, char** argv){
csh handle;
cs_insn *insn;
size_t count;
uint8_t buf[128]
ssize_t read_bytes;
while (__AFL_LOOP(1000)){
// (re-) initialize the library and read new input
read_bytes = -1;
memset(buf, 0, 128);
read_bytes = read(STDIN_FILENO, buf, 128);
if(cs_open(CS_ARCH_X86, CS_MODE_64, &handle) == CS_ERR_OK){
// disassemble the bytes we just read using capstone
count = cs_disasm(handle, buf, read_bytes, 0x1000, 0, &insn);
// Dont leak memory. This is especially important in persistent mode,
// because we reuse the process a significant number of times
cs_free(insn, count);
}
cs_close(&handle);
}
return 0;
}
```

16. This code now contains a macro of __AFL_LOOP that detects whether the program is running under AFL. If it is, then 1000 different inputs will be fed to the tool. Every 1000 iterations, the process tears down and restarts. This ensures that we replace the process to avoid memory leaks.
這段程式碼現在包含一個__AFL_LOOP宏,用於偵測程式是否在AFL下運作。 如果是,那麼 1000 個不同的輸入將提供給該工具。 每 1000 次迭代,該過程就會終止並重新啟動。 這確保我們替換進程以避免記憶體洩漏。
17. Please also note that if the program is launched outside AFL, then the loop code only runs once. This allows for testing cases from the command line and allows us to use other tools such as gdb or automated tools to inspect crashes.
另請注意,如果程式在 AFL 之外啟動,則循環程式碼只會執行一次。 這允許從命令列測試用例,並允許我們使用其他工具(例如 gdb 或自動化工具)來檢查崩潰。
18. On a new terminal, type: **afl-clang-fast -static captest2.c capstone/libcapstone.a -o captest2** and press Enter.
```bash=
$afl-clang-fast -static captest2.c capstone/libcapstone.a -o captest2
```

19. Next, once the code is compiled, we are ready to run the fuzzer again. Type: **afl-fuzz -i inputs -o findings ./captest2** and press Enter. An example of the output of this command is shown in the following screenshot.
接下來,編譯程式碼後,我們就準備再次執行模糊器。 輸入: **afl-fuzz -i input -o discovery ./captest2** 並按 Enter。 以下螢幕截圖顯示了此命令的輸出範例。
```bash=
$afl-fuzz -i inputs -o findings ./captest2
```

20. As the above screenshot shows, we are now almost at 13k per second, which is a significant increase! All from adding three lines of code ! You can also run one AFL session per each core, so you could open additional windows and run the commands as a master and slave setup.
如上面的螢幕截圖所示,我們現在幾乎達到每秒 13k,這是一個顯著的成長! 全部來自新增三行程式碼! 您還可以為每個核心運行一個 AFL 會話,這樣您就可以打開其他視窗並作為主從設定運行命令
21. As the screenshot shows, total execs is now 1.75M, which is a significant increase.
如螢幕截圖所示,執行人員總數現在為 175 萬,這是一個顯著的增長
22. The lab objectives have been achieved.
## Exercise 5: Additional Capabilities of Address Sanitizer
Lab Objective:
In this lab, we will explore the Address Sanitizer tool and look at some of the functions that are not enabled by default.
Lab Tasks
1. We saw some of the advantages of the Address Sanitizer tool earlier. Next, we will expand more on them.
我們之前看到了 Address Sanitizer 工具的一些優點。 接下來,我們將對它們進行更多擴展。
2. Go to 口Ub20 Fuzzing-AFL-ADV machine and login using studentpassword as Password.

3. Use after return: The Address Sanitizer warns when a variable is used after it ceases to be within the scope of a function. However, it does not warn when the variable is used after the function return. This can, however, be enabled by **adding detect_stack_use_after_return=1** to the ASAN_OPTIONS environment variable.
傳回後使用:當變數不再位於函數作用域內後使用時,Address Sanitizer 會發出警告。 但是,在函數返回後使用該變數時,它不會發出警告。 不過,可以透過 **將 detector_stack_use_after_return=1** 新增至 ASAN_OPTIONS 環境變數來啟用此功能。
4. Similar to the earlier instance , we will start with a sample program. In the home folder, you will see a file named **file.c**. The contents of the file are shown in the following screenshot.
與前面的實例類似,我們將從範例程式開始。 在主資料夾中,您將看到一個名為 **file.c** 的檔案。 該文件的內容如以下螢幕截圖所示。
```c=
int *ptr;
__attribute__((noinline))
void foo(void)
{
int a;
ptr = &a;
}
int main(void)
{
foo();
return *ptr; //Error
}
```

5. Now that we have a sample to work with, let us compile it. Type: gcc -O -fsanitize=address file.c -o file and press Enter.
現在我們有了一個可以使用的範例,讓我們編譯它。 鍵入:gcc -O -fsanitize=位址 file.c -o 文件,然後按 Enter。
```bash=
$gcc -O -fsanitize=address file.c -o file
```

6. Next, we can add **detect_stack_use_after_return=1** to the **ASAN_OPTIONS** environment variable before running the program by entering **env ASAN_OPTIONS="detect_stack_use_after_return=1" ./file**.
接下來,我們可以在執行程式之前將 **detect_stack_use_after_return=1** 加入到 **ASAN_OPTIONS** 環境變數中,方法是輸入 **env ASAN_OPTIONS="detect_stack_use_after_return=1" ./file**。

7. As the above screenshot shows, without setting use after return, this bug would have not been caught.
如上圖所示,如果不設定返回後使用,這個bug就不會被捕獲。
8. We have demonstrated one of the additional functions of the Address Sanitizer tool. So we can add the additional options to help us detect even more bugs!
我們示範了 Address Sanitizer 工具的附加功能之一。 因此我們可以添加額外的選項來幫助我們檢測更多的錯誤!
9. The lab objectives have been achieved.
## Exercise 6: Fuzzing with Peach
Lab Tasks
1. In this lab, we will explore the Peach fuzzer tool. The Peach framework can be used on Windows, Linux, and OS X OSes. On Linux and OS X, a cross-platform .NET development framework called Mono is required to run Peach. In this section, we use the 64-bit version of Windows Server 2016. Your steps and outputs may vary slightly from those in this lab if you use a different platform.
在本實驗中,我們將探索 Peach 模糊器工具。 Peach 框架可在 Windows、Linux 和 OS X 作業系統上使用。 在 Linux 和 OS X 上,需要一個名為 Mono 的跨平台 .NET 開發框架才能執行 Peach。 在本部分中,我們使用 64 位元版本的 Windows Server 2016。如果您使用不同的平台,您的步驟和輸出可能與本實驗室中的步驟和輸出略有不同。
2. You will notice that the community edition is not as up-to-date as the commercial tool, but it is free and will serve our purpose. We will now explore the concept of mutation fuzzing.
您會注意到社群版不像商業工具那麼最新,但它是免費的並將服務於我們的目的。 我們現在將探討突變模糊測試的概念。
3. To start fuzzing with Peach, you have to create a file called Pit. Peach Pit files are XML documents that contain the entire configuration for the fuzzing session. Here is some typical information contained in a Pit file that is shown in the following table.
要開始使用 Peach 進行模糊測試,您必須建立一個名為 Pit.txt 的檔案。 Peach Pit 文件是 XML 文檔,包含模糊測試會話的整個配置。 以下是 Pit 檔案中包含的一些典型信息,如下表所示。

4. Mutation Pits are fairly easy to create, and Peach provides several templates that can be examined and modified to suit different scenarios. Pit configurations can be created and modified using any text editor.
突變坑相當容易創建,Peach 提供了多個模板,可以檢查和修改這些模板以適應不同的場景。 可以使用任何文字編輯器建立和修改坑配置。
5. Since the files are in XML, any XML editor will work as well. An example of one of the XML files is shown in the following screenshot. Take a few minutes, and review the data contained within the image.
由於文件採用 XML 格式,任何 XML 編輯器都可以工作。 以下螢幕截圖顯示了其中一個 XML 檔案的範例。 花幾分鐘時間,查看圖像中包含的數據

6. We will only use the default templates at first. Click 口Server2016-Fuzzing and click Ctrl+Alt+Delete to login.
我們一開始只會使用預設模板。 點選口Server2016-Fuzzing,然後點選Ctrl+Alt+Delete登入。

7. By default Administrator profile is selected type: `Pa$$w0rd` and press Enter.
預設情況下,選擇管理員設定文件,鍵入:`Pa$$w0rd`,然後按 Enter。

8. Open File Explorer and navigate to C drive. Now, shift + right-click on **Peach** folder and click **Open command window here** from the context menu as shown in the screenshot.
開啟檔案總管並導航至 C 碟。 現在,按住 Shift 鍵並右鍵單擊 **Peach** 資料夾,然後從上下文功能表中按 **在此處開啟命令視窗**,如螢幕截圖所示。

9. In the terminal type: peach -t samples\HelloWorld.xml and press Enter. This will validate the file.
在終端機中輸入:peach -t樣本\HelloWorld.xml並按Enter鍵。 這將驗證該文件。
```bash=
$peach -t samples\HelloWorld.xml
```

10. Now that we have validated the file, we can begin the process to start a session with the file. Type: **peach samples\HelloWorld.xml Default** and press Enter. This will start the fuzzing process.
現在我們已經驗證了該文件,我們可以開始使用該文件啟動會話的過程。 鍵入:**peach Samples\HelloWorld.xml Default** 並按 Enter。 這將開始模糊測試過程。
```bash=
>peach samples\HelloWorld.xml Default
```
11. As shown in the screenshot, this is a powerful tool. In fact, it can **crash** the machine it is running on as well. Therefore, at times, you may have to stop it to perform maintenance.
如螢幕截圖所示,這是一個功能強大的工具。 事實上,它也可能導致運行它的機器**崩潰**。 因此,有時您可能必須停止它才能進行維護。
12. To exit the fuzz, press **Ctrl+c**.
若要退出模糊,請按 **Ctrl+c**。


13. You will notice is that it does not take long for the iterations to increase rapidly. Note the requirement for the installation of **WinDbg **and the correction of the path in the XML files. An example of this is shown in the screenshot.
你會注意到,不需要很長時間,迭代次數就會迅速增加。 請注意安裝 **WinDbg ** 的要求以及 XML 檔案中路徑的更正。 螢幕截圖中顯示了這樣的範例。

14. There is always a possibility that you might have to correct the paths for the other files as well.
您始終有可能也必須更正其他文件的路徑。
15. The results of a terminated session can be examined in the session folder under the **Peach "logs"** directory. Folders in the logs directory use a naming scheme in which a timestamp with the current time at the moment of directory creation is appended to the filename of the Pit XML configuration used for fuzzing.
可以在 **Peach“logs”** 目錄下的會話資料夾中檢查終止會話的結果。 日誌目錄中的資料夾使用一種命名方案,其中包含建立目錄時的當前時間的時間戳記被附加到用於模糊測試的 Pit XML 配置的檔案名稱中。
16. If the session had been successful, an additional folder named Faults would exist in the session folder. The **Faults** directory contains a separate folder for each class of crash detected. Each of these crash clusters contain one or more test cases that include the following information:
- The mutated test case that triggered the crash
- A debugging report collected about the program state at the time of the crash. This report includes information about the state and values of the processor register, a portion of stack content, and information gathered from the WinDbg plug-in !exploitable, which provides automated crash analysis and security risk assessment
- The original test case name that was mutated to create this specific mutation
如果會話成功,則會話資料夾中將存在一個名為「Faults」的附加資料夾。 **Faults** 目錄包含針對偵測到的每種類型的當機的單獨資料夾。 每個崩潰叢集都包含一個或多個測試案例,其中包含以下資訊:
- 觸發崩潰的變異測試用例
- 收集有關崩潰時程式狀態的偵錯報告。 該報告包括有關處理器暫存器的狀態和值、堆疊內容的一部分以及從 WinDbg 插件 !exploitable 收集的信息,該插件提供自動崩潰分析和安全風險評估
- 為創建此特定突變而進行突變的原始測試案例名稱
17. The session can be resumed by skipping the test that has already been performed. Information about which test case was performed last by the fuzzer can be seen in the Logs folder under the session name in file **status.txt**. An example of this is shown in the screenshot.
可以透過跳過已執行的測試來恢復會話。 有關模糊器最後執行的測試案例的資訊可以在檔案 **status.txt** 中會話名稱下的 Logs 資料夾中看到。 螢幕截圖中顯示了這樣的範例。

18. Another way to see the progress and number of iterations performed by Peach is in the command-line output during fuzzing, which will show in the first entry of a list iteration number. Scroll upward direction in the terminal. An example of this is shown in the screenshot.
另一種查看 Peach 執行的進度和迭代次數的方法是在模糊測試期間的命令列輸出中,該輸出將顯示在清單迭代次數的第一個條目中。 在終端機中向上滾動。 螢幕截圖中顯示了這樣的範例。
19. One thing to note is that resuming the fuzzing session only has real value if the fuzzing strategy chosen is deterministic. If you use the "random" strategy, resuming the previous session does not make much difference.
需要注意的一件事是,只有選擇的模糊測試策略是確定性的,恢復模糊測試會話才具有真正的價值。 如果您使用「隨機」策略,恢復上一個會話並沒有太大差異。

20. Peach comes by default with 27 different mutators, depending on the element type (numeric, array, text string, or blob). These mutators perform substitutions of the defined and / or cracked values in the model in order to cause an exception in the application when parsing the data (casting and data conversion exceptions, array out of bounds, null pointer access, or buffer/integer Overflow). Some of the most interesting mutators are as follows:
- **ArrayNumericalEdgeCasesMutator**: Transforms arrays by adding or subtracting members to increase or decrease their length according to minOccurs and/or maxOccurs attribute values
- **BlobMutator**: Performs different transformations on a blob element (enlarge, shrink, or fill with zeros)
- **DataElementDuplicateMutator**: Duplicates elements
- **DataElementRemoveMutator**: Deletes elements
- **DataElementSwapNearNodesMutator**: Switches the order of adjacent nodes
- **NumericalEdgeCaseMutator**: Produces a range of numbers around extreme cases based on the size of a number element, including negative numbers. With the hint NumericalString, it can also be applied to string elements.
- **NumericalEdgeCaseMutator**: Produces a range of numbers around extreme cases based on the size of a number element, including negative numbers. With the hint NumericalString, it can also be applied to string elements.
- **ValidValuesMutator**: This mutator will mutate between the values of a supplied list separated by a semicolon.
Peach 預設帶有 27 個不同的修改器,具體取決於元素類型(數字、陣列、文字字串或 blob)。 這些變異器執行模型中定義和/或破解值的替換,以便在解析資料時在應用程式中引起異常(轉換和資料轉換異常、陣列越界、空指標存取或緩衝區/整數溢位) 。 一些最有趣的變種器如下:
- **ArrayNumericalEdgeCasesMutator**:透過增加或減去成員來轉換數組,以根據 minOccurs 和/或 maxOccurs 屬性值增加或減少其長度
- **BlobMutator**:對 blob 元素執行不同的轉換(放大、縮小或用零填充)
- **DataElementDuplicateMutator**:重複元素
- **DataElementRemoveMutator**:刪除元素
- **DataElementSwapNearNodesMutator**:切換鄰近節點的順序
- **NumericalEdgeCaseMutator**:根據數字元素的大小(包括負數)產生極端情況周圍的一系列數字。 透過提示 NumericalString,它也可以應用於字串元素。
- **NumericalEdgeCaseMutator**:根據數字元素的大小(包括負數)產生極端情況周圍的一系列數字。 透過提示 NumericalString,它也可以應用於字串元素。
- **ValidValuesMutator**:此變異器將在以分號分隔的提供清單的值之間變異。
21. Some mutators allow to pass information to configure them for each element by adding hints. An example of this is shown in the following screenshot.
一些修改器允許傳遞訊息,透過添加提示來為每個元素配置它們。 以下螢幕截圖顯示了這樣的範例。

22. Virtually, all mutators are active by default for all elements. They will only be disabled for an element if the element’s data type is not the one required by the mutator or its mutable attribute is set to false. An example of this is shown in the following screenshot.
實際上,預設情況下,所有元素的所有修改器都是活動的。 只有當元素的資料類型不是變元所需的資料類型或其可變屬性設為 false 時,才會對元素停用它們。 以下螢幕截圖顯示了這樣的範例。

23. We must take into account that despite setting the mutable attribute of an element to false, if the element is inside a container block (**Choice**, **Block** or **DataModel**), it will be mutated anyway, unless the mutable attribute in the container is set to false as well. The default behavior of Peach is to mutate all elements in our model with all mutators available. We must note that this could easily generate hundreds of thousands or even millions of iterations of our fuzzer. As mentioned in the beginning, the concept of fuzzing continues to grow.
我們必須考慮到,儘管將元素的 mutable 屬性設為 false,但如果該元素位於容器區塊(**Choice**、**Block** 或 **DataModel**)內,它無論如何都會發生變異,除非容器中的可變屬性也設定為false。 Peach 的預設行為是使用所有可用的變異器來變異模型中的所有元素。 我們必須注意,這可以輕鬆地產生我們的模糊器數十萬甚至數百萬次迭代。 正如一開始提到的,模糊測試的概念不斷在發展。
24. As you have seen, the Peach tool is a very capable mutation fuzzer. Therefore, now we will cover the concept of generation fuzzing. For this, we will use the vulnserver program that was created by Stephen Bradshaw and is often used for testing located at **Desktop**.
正如您所看到的,Peach 工具是一個非常強大的變異模糊器。 因此,現在我們將介紹生成模糊測試的概念。 為此,我們將使用由 Stephen Bradshaw 創建的 vulnserver 程序,該程序通常用於位於**桌面**的測試。

25. To run the machine, press shift + right-click on **Peach** folder and click **Open command window here** from the context menu as shown in the screenshot.
若要執行機器,請按 Shift + 右鍵單擊 **Peach** 資料夾,然後從上下文功能表中按一下 **在此處開啟命令視窗**,如螢幕截圖所示。

26. In the terminal type **vulnserver.exe** and press Enter.
在終端機中輸入 **vulnserver.exe** 並按 Enter。
```cmd=
>vulnserver.exe
```

27. To verify that the program is running and has opened a port, open another terminal and type: **netstat -abno | findstr 9999** and press Enter. Here you need to note down the process ID i.e., 1672. This will differ in your case.
若要驗證程式是否正在運行並已開啟端口,請打開另一個終端並鍵入:**netstat -abno | 找到str 9999**並按下Enter鍵。 在這裡,您需要記下進程 ID,即 1672。這將根據您的情況而有所不同。
```cmd=
>netstat -abno | findstr 9999
```

28. To verify that this process ID is the one that has opened the port, type: tasklist /svc | findstr [PID] and press Enter.
若要驗證此進程 ID 是否為已開啟連接埠的進程 ID,請鍵入:tasklist /svc | findstr [PID]並按 Enter 鍵。
```cmd=
>tasklist /svc | findstr [PID]
```

29. Now that we know that the code is running and a server is listening on port **9999**, it is time to connect to it and verify that we can access it. The machine has **netcat** on it, in the terminal type: **cd Desktop\netcat** and press Enter.
現在我們知道程式碼正在運行並且伺服器正在偵聽連接埠 **9999**,是時候連接到它並驗證我們是否可以存取它了。 機器上有**netcat**,在終端機中輸入:**cd Desktop\netcat** 並按 Enter。
```cmd=
>cd Desktop\netcat
```

30. Now, type: **nc localhost 9999** and press Enter. As soon as get connected to server type: **HELP** and press Enter.
現在,輸入:**nc localhost 9999** 並按 Enter。 連接到伺服器後,立即輸入:**HELP** 並按 Enter。
```cmd=
>nc localhost 9999
出現"Welcome to Vulnerable Server! Enter HELP for help"
>HELP
```

31. Open File Explorer and navigate to C: drive. Now, shift + right-click on Peach folder and click **Open command window here **from the context menu. In the terminal type: **peach -a tcp** and press Enter. Leave the window running.
開啟檔案總管並導航至 C: 磁碟機。 現在,按住 Shift 鍵並右鍵單擊 Peach 資料夾,然後從上下文功能表中按 **在此處打開命令視窗 **。 在終端機中輸入:**peach -a tcp** 並按 Enter。 讓視窗保持運作。
```cmd=
>peach -a tcp
```

32. Switch to the other **Peach** terminal, type: **peach fuzz_TRUN.xml TestTRUN** and press Enter.
切換到另一個 **Peach** 終端,輸入:**peach fuzz_TRUN.xml TestTRUN** 並按 Enter。
```bash=
$peach fuzz_TURN.xml TestRUN
```


自己測試的截圖


33. To get an idea of what is occurring, in another command prompt, type: **netstat -atn | findstr 9999** and press Enter.
若要了解正在發生的情況,請在另一個命令提示字元中鍵入: **netstat -atn | 找到str 9999**並按下Enter鍵。
```bash=
$netstat -atn | findstr 9999
```


34. You may see warnings, or the vulnerable server may crash and you may need to restart testing again. Depending on how lucky (or unlucky) you are, you may need to generate many test cases—even as many as a thousand to get a reliable crash to debug. The key is the process of reviewing the **Logs** folder.
您可能會看到警告,或者易受攻擊的伺服器可能會崩潰,您可能需要再次重新啟動測試。 根據您的幸運(或不幸)程度,您可能需要產生許多測試用例 - 甚至多達一千個測試用例才能獲得可靠的崩潰來調試。 關鍵是查看**Logs**資料夾的過程。

35. Close all the windows that were opened. The lab objectives have been achieved
關閉所有開啟的視窗。 實驗室目標已達到