ARM 彙編基礎教程番外篇——配置實驗環境

這篇教程中有一些示常式序,可以動手調試來加深理解。要調試ARM程序,我們需要能運行ARM程序的運行環境和支持ARM架構的調試器。本篇教程將基於x86平台的Ubuntu 16.04,介紹如何搭建ARM的交叉編譯、運行和調試環境。

交叉編譯環境

Ubuntu 16.04的源中提供了多個arm-gcc的軟體包,以gcc 5為例可以通過「apt

search」命令找到「gcc-5-arm-linux-gnueabi」和「gcc-5-arm-linux-gnueabihf」兩個軟體包。這兩個軟體包安裝的編譯工具是一樣的,只是與浮點數相關的默認編譯選項不同。由於我們虛擬的環境沒有FPU,只需要安裝「gcc-5-arm-linux-gnueabi」就可以了。

安裝完成後可以在「/usr/bin/arm-linux-gnueabi-*」找到相關的編譯工具鏈,包含常用的gcc、as和ld等。只要使用如下兩條命令,就可以實現對ARM彙編的編譯:

$ arm-linux-gnueabi-as [source file] –o [object file]$ arm-linux-gnueabi-ld [object file] –o [executable file]

可以使用如下命令編譯經典的「hello world」程序,用於後續章節的實驗:

$ arm-linux-gnueabi-gcc-5 hello.c –g –o hello -static

運行環境

I. qemu-user-static

最簡單的運行環境是使用qemu-user-static模擬運行靜態編譯的可執行程序。我們可以使用如下命令模擬運行上一節創建的hello程序:

# 首先安裝qemu-user-static,若已安裝可以忽略這一步$ sudo apt install qemu-user-static# 直接執行hello程序$ qemu-arm-static hello# 啟動gdbserver等待gdb連接$ qemu-arm-static –g [gdbserver port] hello

上述命令運行後會啟動一個qemu自帶的gdbserver,監聽你通過「-g」選項指定的埠。可以在另一個窗口中啟動gdb進行遠程調試(遠程調試的細節,將在第三章介紹)。

II. 虛擬Raspberry

qemu-user-static的方式比較簡單,但功能也很局限,Azeria-labs的教程中介紹了另一種方法,使用qemu創建一台虛擬樹莓派。首先你需要安裝qemu-system:

$ sudo apt install qemu-system

為了虛擬一台樹莓派,你還需要下載專為樹莓派定製的debian鏡像(raspbian)和支持樹莓派的內核文件。

raspbian鏡像下載地址:raspberrypi.org/downloa

樹莓派內核下載地址:github.com/dhruvvyas90/

Raspbian的鏡像有兩個版本,一個帶圖形界面的完整版和一個沒有圖形界面的lite版本,對於我們的實驗而言lite版本就足夠了。內核文件有多個,選擇內核版本最新的那個就可以了。下載完上述文件後,創建一個「arm_vm」目錄,將上述文件一起放置在該目錄下。然後執行如下命令:

$ unzip <image-file>.zip$ fdisk –l <image-file>

你應該可以看到,類似如下內容:

Disk 2017-08-16-raspbian-stretch-lite.img: 1.7 GiB, 1854418944 bytes, 3621912 sectors

Units: sectors of 1 * 512 = 512 bytes

Sector size (logical/physical): 512 bytes / 512 bytes

I/O size (minimum/optimal): 512 bytes / 512 bytes

Disklabel type: dos

Disk identifier: 0xee397c53

Device Boot Start End Sectors Size Id Type

2017-08-16-raspbian-stretch-lite.img1 8192 93813 85622 41.8M c W95 FAT32 (LBA)

2017-08-16-raspbian-stretch-lite.img2 94208 3621911 3527704 1.7G 83 Linux

注意標紅的部分,可以看到文件系統從94208扇區開始。我們將這個值乘以512,本例中為「94208 * 512=48234496」,這就是文件系統其實位置的偏移位元組數,在下面的命令中我們會用到:

$ sudo mkdir /mnt/raspbian$ sudo mount -v -o offset=48234496 -t ext4 [path-of-your-img-file.img] /mnt/raspbian$ sudo vi /mnt/raspbian/etc/ld.so.preload將上述文件中的所有內容用「#」注釋掉,保存修改並退出。$ sudo vi /mnt/raspbian/etc/fstab

如果fstab文件中有出現mmcblk0字元串,那麼將「/dev/mmcblk0p1」替換為「/dev/sda1」,將「/dev/mmcblk0p2」替換為「/dev/sda2」,保存後退出。至此,系統配置的修改完成,可以將「/mnt/raspbian」卸載掉。

$ sudo umount /mnt/raspbian

你可以進入「arm_vm」目錄,使用如下腳本啟動虛擬機:

#!/usr/bin/env bashqemu-system-arm -kernel kernel-qemu-4.4.34-jessie -cpu arm1176 -m 256 -M versatilepb -serial stdio -append "root=/dev/sda2 rootfstype=ext4 rw" -drive format=raw,file=2017-08-16-raspbian-stretch-lite.img -redir tcp:5022::22 # 為ssh預留-redir tcp:3011::3011 # 為gdbserver預留,用於遠程調試-no-reboot 1> /dev/null 2>&1 &

虛擬機啟動後默認的登錄密碼是「raspberry」。為了更方便的使用虛擬機,我們需要開啟ssh服務,並設置開機啟動。

$ sudo service ssh start$ sudo update-rc.d ssh enable

此時,你應該已經可以使用如下命令,通過ssh訪問虛擬機了:

$ ssh pi@127.0.0.1 -p 5022

我們可以使用scp命令通過ssh,將上一節編譯的hello程序上傳到虛擬機中執行:

scp -P 5022 hello pi@127.0.0.1:/tmp

進入虛擬機的tmp目錄,可以看到我們上傳的hello程序嘗試執行,應該會輸出久違的「hello world!」,說明我們的交叉編譯環境搭建是正確的。至此我們的虛擬樹莓派環境搭建完畢。

調試環境

調試環境的搭建是最重要的也是坑最多的。為了模擬真實IoT安全實戰中遠程調試的場景,我們將介紹如何交叉編譯gdbserver並上傳至虛擬機進行遠程調試。為了獲得類似pwndbg那樣強大的調試效果,我們將介紹如何安裝使用專為IoT安全設計的gef增強腳本。

I. gdb-multiarch

在使用gdb進行調試之前,我們需要先安裝gdb-multiarch。顧名思義,它是gdb支持多中硬體體系架構的版本。之所以要安裝gdb-multiarch,是因為Ubuntu默認安裝的gdb只支持x86/x64架構,你可以啟動gdb然後輸入命令「set

architecture arm」查看,gdb會提示錯誤。

# 安裝gdb-multiarch$ sudo apt install gdb-multiarch# 啟動gdb-multiarch$ gdb-multiarch

II. 編譯gdbserver

在分析IoT設備的安全性時,我們往往需要上傳gdbserver進行遠程調試。在我們的實驗環境中(事實上我們的Raspbian系統自帶gdb),我們也可以模擬搭建一個遠程調試環境。首先,我們需要獲取gdb的源碼(包含了gdb源碼和gdbserver源碼),版本需要與我們本地的gdb版本一致,因為gdbserver需要與gdb版本保持一致,否則容易出現非預期的問題。你可以在這個地址,找到gdb各版本的源碼:ftp.gnu.org/gnu/gdb/

下載解壓後進入「gdb-<version>/gdb/gdbserver」目錄,使用如下命令編譯安裝:

$CC="arm-linux-gnueabi-gcc-5" CXX="arm-linux-gnueabi-g++-5" ./configure --target=arm-linux-gnueabi --host="arm-linux-gnueabi" --prefix="setup-directory"$ make install

然後,在你通過「--prefix」選項指定的路徑下,就可以找到編譯完成的gdbserver了。使用file命令查看,應該可以看到類似如下輸出:

$ file arm-linux-gnueabi-gdbserver arm-linux-gnueabi-gdbserver: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=32ad2025951ee428276ac2fbadb199bfd39e2278, not stripped

使用scp將gdbserver上傳到我們的虛擬樹莓派中並啟動:

$ ln -s arm-linux-gnueabi-gdbserver gdbserver$ gdbserver 0.0.0.0:2333 helloProcess hello created; pid = 702Listening on port 2333

至此,我們的遠程調試環境搭建完畢,下一節,我們將引入gef增強腳本。

III. gef增強腳本

gef是一個支持多種硬體體系結構的gdb增強腳本,非常適合IoT安全領域應對多變的硬體平台。你可以參考github主頁(github.com/hugsy/gef)的README,進行安裝配置。不過需要注意的是,gef依賴的第三方模塊keystone-engine需要手動安裝,因為pip源提供的安裝是無效的。建議先通過pip安裝,如果安裝後gef的部分功能仍無法使用,可以卸載通過pip安裝的第三方模塊,在github上(github.com/keystone-eng)下載最新源碼,手動編譯安裝(參見:keystone-engine.org/doc)。

安裝完成後開啟gdb調試,你將看到類似如下的界面:

首先設置目標硬體體系架構為arm:

gef> set architecture arm

我們使用gef-remote命令連接gdbserver,如果使用gdb自帶的「target remote」命令會出現一些非預期的問題(參見:github.com/hugsy/gef/is)。

gef> gef-remote –q 127.0.0.1:2333

你應該能看到類似如下的輸出:

至此,我們的調試環境配置完畢了。

擴展閱讀

[1] gef官方文檔,gef.readthedocs.io/en/m

[2] gdb調試利器,linuxtools-rst.readthedocs.io

[3] gdb中應該知道的幾個調試方法,coolshell.cn/articles/3

本文由看雪翻譯小組 ljcnaix 原創 轉載請註明來自看雪社區


推薦閱讀:

64位Windows10系統彙編調試
assembly notes
Visual Studio2017彙編環境教程

TAG:ARM | 彙編語言 | ARM架構 |