ARM 汇编基础教程番外篇 ——配置实验环境

ARM 汇编基础教程番外篇 ——配置实验环境_第1张图片

这篇教程中有一些示例程序,可以动手调试来加深理解。要调试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镜像下载地址:https://www.raspberrypi.org/downloads/raspbian/

树莓派内核下载地址:https://github.com/dhruvvyas90/qemu-rpi-kernel

Raspbian的镜像有两个版本,一个带图形界面的完整版和一个没有图形界面的lite版本,对于我们的实验而言lite版本就足够了。内核文件有多个,选择内核版本最新的那个就可以了。下载完上述文件后,创建一个“arm_vm”目录,将上述文件一起放置在该目录下。然后执行如下命令:

$ unzip .zip

$ fdisk –l

你应该可以看到,类似如下内容:

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.img2942083621911 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 bash

qemu-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 [email protected] -p 5022

我们可以使用scp命令通过ssh,将上一节编译的hello程序上传到虚拟机中执行:

scp -P 5022 hello [email protected]:/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各版本的源码:http://ftp.gnu.org/gnu/gdb/。

下载解压后进入“gdb-/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 hello

Process hello created; pid = 702

Listening on port 2333

至此,我们的远程调试环境搭建完毕,下一节,我们将引入gef增强脚本。

III. gef增强脚本

gef是一个支持多种硬件体系结构的gdb增强脚本,非常适合IoT安全领域应对多变的硬件平台。你可以参考github主页(https://github.com/hugsy/gef)的README,进行安装配置。不过需要注意的是,gef依赖的第三方模块keystone-engine需要手动安装,因为pip源提供的安装是无效的。建议先通过pip安装,如果安装后gef的部分功能仍无法使用,可以卸载通过pip安装的第三方模块,在github上(https://github.com/keystone-engine/keystone)下载最新源码,手动编译安装(参见:http://www.keystone-engine.org/docs/)。

安装完成后开启gdb调试,你将看到类似如下的界面:

ARM 汇编基础教程番外篇 ——配置实验环境_第2张图片

首先设置目标硬件体系架构为arm:

gef> set architecture arm

我们使用gef-remote命令连接gdbserver,如果使用gdb自带的“target remote”命令会出现一些非预期的问题(参见:https://github.com/hugsy/gef/issues/7)。

gef> gef-remote –q 127.0.0.1:2333

你应该能看到类似如下的输出:

ARM 汇编基础教程番外篇 ——配置实验环境_第3张图片

至此,我们的调试环境配置完毕了。

扩展阅读

[1] gef官方文档,http://gef.readthedocs.io/en/master/

[2] gdb调试利器,http://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/gdb.html

[3] gdb中应该知道的几个调试方法,https://coolshell.cn/articles/3643.html

本文由看雪翻译小组 ljcnaix 原创  转载请注明来自看雪社区

你可能感兴趣的:(ARM 汇编基础教程番外篇 ——配置实验环境)