硬件安全 · 2021年7月13日 0

ZC706 DMA攻击环境搭建

基于 Xilinx ZC706 开发板的DMA攻击工具环境搭建过程。

实现与主机PCIe总线的TLP数据包收发、解析、物理内存读取等功能。

项目地址

Vivado安装

在ubuntu下安装Vivado 2019.2

image-20210714145336758

解压安装包文件,运行sudo ./xsetup进行安装。

选择Vivado HL. Design Edition版本,安装目录选择默认的,最好不要更改。

在Vivado License Manager中选load License导入证书文件: LICENSE FOR ISE VIVADO.lic

安装Petalinux

安装依赖库:

$ sudo apt-get install tofrodos gawk xvfb git libncurses5-dev tftpd zlib1g-dev zlib1g-dev:i386 libssl-dev flex bison chrpath socat autoconf libtool texinfo gcc-multilib libsdl1.2-dev libglib2.0-dev screen pax xterm diffstat build-essential

下载Petalinux

配置安装目录及权限:

$ sudo -s
$ mkdir -p /opt/pkg/petalinux
$ chown edvison /opt/pkg/
$ chgrp edvison /opt/pkg/
$ chgrp edvison /opt/pkg/petalinux/
$ chown edvison /opt/pkg/petalinux/
$ exit

安装petalinux:

$ sudo chmod +x petalinux-v2019.2-final-installer.run
$ ./petalinux-v2019.2-final-installer.run /opt/pkg/petalinux/

设置环境变量:

$ export PATH=$PATH:/opt/pkg/petalinux/tools/xsct/bin/

Xilinx Zynq DMA攻击项目准备

获取项目:

$ git clone https://github.com/Cr4sh/zc_pcie_dma

进入vivado安装目录,配置环境变量:

$ cd /tools/Xilinx/Vivado/2019.2
$ source settings64.sh
  1. 进入zc_pcie_dma项目目录下,运行make projectzx_pcie_dma.tcl模板创建Vivado项目。
image-20210714160103911
  1. 运行vivadoOpen project >,打开~/zc_pcie_dma/zc_pcie_dma/zc_pcie_dma.xpr,执行Run Synthesis,等待右上角的后台运行完成后,执行Run implementation,完成后执行generate the bitstream。点File --> Export --> Export Hardware..导出到zc_pcie_dma.xsa文件中。
  2. 运行make binimage-20210714170031442
  3. 运行:
$ git submodule init && git submodule update
$ cd devicetree/my_dtg/
$ git clone https://github.com/Xilinx/device-tree-xlnx
$ cd device-tree-xlnx
$ git checkout xilinx-v2019.2
$ git clone git://git.kernel.org/pub/scm/utils/dtc/dtc.git
$ sudo apt install flex bison
$ cd dtc
$ make
$ export PATH=$PATH:$(pwd)
  1. 运行make dts_gen生成设备树源码
  2. 打开devicetree/my_dts/pl.dtsi文件,把所有的compatible = "xlnx,axi-dma-7.1", "xlnx,axi-dma-1.00.a"compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a"都替换成compatible = "generic-uio"
  3. 运行make dts_build,生成设备树二进制文件。

Buildroot构建环境

使用 Buildroot 来交叉编译 Linux 内核和 uBoot 引导加载程序。

安装Buildroot:

$ wget https://buildroot.org/downloads/buildroot-2021.02.tar.gz
$ tar -xpvf buildroot-2021.02.tar.gz
$ cd ~/buildroot-2021.02

安装依赖:

$ sudo apt-get install libncurses-dev

使用ZC706开发板的标准配置文件初始化构建环境:

$ make zynq_zc706_defconfig
$ echo “BR2_PACKAGE_ZC_DMA_MEM=y” >> .config

配置linux内核:

$ make linux-menuconfig

开启下面的选项:

Device Drivers-->
GPIO Support-->
Memory mapped GPIO drivers-->
[*]Xilinx GPIO support
[*]Xilinx Zynq GPIO support
Device Drivers-->
Userspace I/O drivers
kernel hacking-->
[*] Filter access to /dev/mem
[*] Filter I/O access to /dev/mem
Enable loadable module support-->
[*] Forced module loading
[*] Module unloading [*] Forced module unloading [*] Module versioning support

设置br2外部树zc_dma_mem

$ make BR2_EXTERNAL="~/zc_pcie_dma/kernel/zc_dma_mem" menuconfig

开启选项External options -> zc_dma_mem

设置hostname,root密码:

System configuration -->
System hostname
System banner
Root password
image-20210727141613598

编译内核、bootloder、zc_dma_mem.ko内核模块和文件系统:

$ make

如报错cannot stat 'package/busybox/S02sysctl': No such file or directory,添加软链接:

$ ln -s S02sysctl ../procps-ng/S02sysctl

生成zc_dma_mem.ko位于:

~/buildroot-2021.02/output/build/zc_dma_mem-1.0
~/buildroot-2021.02/output/target/lib/modules/4.9.0-xilinx/extra

更改内核版本方法

安装buildroot 2020.02版本:

$ wget https://buildroot.org/downloads/buildroot-2020.02.tar.gz
$ tar -xpvf buildroot-2020.02.tar.gz
$ cd ~/buildroot-2020.02

安装gcc5,g++5

这里 可查找所需的内核包。

要把内核版本改为4.0,则需要linux-xilinx-v2015.4.tar.gz版本的包,内核版本号可在包里的Makefile中查看:

image-20210729105135408

找到需要的内核包后,运行make menuconfig,更改下面的选项:

Toolchain -->
Custom kernel headers series (4.0.x) --->
GCC compiler Version (gcc 5.x) --->
kernel -->
($(call github,Xilinx,linux-xlnx,xilinx-v2015.4)/linux-xilinx-v2015.4.tar.gz) URL of custom kernel tarball

再次运行make linux-menuconfig,即可下载并配置更改的内核版本。

设置Fat32分区引导SD卡

复制需要的文件到SD目录下:

$ mkdir -p output/images/sd
$ cp output/images/boot.bin output/images/sd
$ cp output/images/uImage output/images/sd
$ cp output/images/u-boot.img output/images/sd/u-boot.img
$ cp output/images/rootfs.cpio.uboot output/images/sd/uramdisk.image.gz
$ cp ~/zc_pcie_dma/devicetree.dtb output/images/sd
$ cp ~/zc_pcie_dma/zc_pcie_dma.bit output/images/sd

创建uEnv.txt文件:

$ gedit uEnv.txt
bootargs=console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=fat rootwait devtmpfs.mount=0 mem=992M uio_pdrv_genirq.of_id=generic-uio
load_fpga=fatload mmc 0 0x4000000 zc_pcie_dma.bit && fpga loadb 0 0x4000000 13321511
load_image=fatload mmc 0 ${kernel_load_address} ${kernel_image} && fatload mmc 0 ${devicetree_load_address} devicetree.dtb
uenvcmd=echo Copying Linux from SD to RAM... && mmcinfo && run load_fpga && run load_image && bootm ${kernel_load_address} - ${devicetree_load_address}

格式化SD卡,类型为FAT:

image-20210727142435335

将sd目录下所有文件复制到sd卡:

$ cd ~/buildroot-2021.02/output/images/sd
$ sudo cp -a * /media/edvison/boot

弹出SD卡:

$ sudo eject /dev/sdc

sd卡插回zc706,连接USB串口调试线,SW11设置为00110(SD卡引导模式):

image-20210727151447201

主机开始监听:

$ sudo pip install pyserial
$ sudo miniterm.py --eol LF --raw /dev/ttyUSB0 115200
image-20210727143032050

———————————————-分界线———————————————————–

设置ext4分区引导SD卡

下面是构建ubuntu文件系统方法

安装qemu用户空间模拟:

$ sudo apt install qemu-user-static
$ sudo apt install qemu-user-binfmt

检查ARM用户空间模拟配置:

$ cat /proc/sys/fs/binfmt_misc/qemu-arm
enabled
interpreter /usr/bin/qemu-arm-static
flags: OC
offset 0
magic 7f454c4601010100000000000000000002002800
mask ffffffffffffff00fffffffffffffffffeffffff

依赖包安装:

$ sudo apt-get install gawk wget git git-core diffstat unzip texinfo gcc-multilib build-essential \
chrpath socat cpio python python3 python3-pip python3-pexpect \
xz-utils debianutils iputils-ping libsdl1.2-dev xterm \
language-pack-en coreutils texi2html file docbook-utils \
python-pysqlite2 help2man desktop-file-utils \
libgl1-mesa-dev libglu1-mesa-dev mercurial autoconf automake \
groff curl lzop asciidoc u-boot-tools libreoffice-writer \
sshpass ssh-askpass zip xz-utils kpartx vim screen bison flex \
debootstrap qemu-system-arm qemu-user-static libssl-dev

交叉编译器安装:

$ sudo apt-get install gcc-arm-linux-gnueabi

使用debootstrap获取ubuntu 20.04文件系统:

$ sudo apt install debootstrap
$ sudo debootstrap --arch armhf --verbose --foreign focal ~/debootstrap_focal_armhf

准备chroot环境:

$ sudo cp /usr/bin/qemu-arm-static debootstrap_focal_armhf/usr/bin
$ sudo chroot debootstrap_focal_armhf /bin/bash

运行第二阶段

$ /debootstrap/debootstrap --second-stage

基本配置,创建/etc/fstab

$ echo "/dev/mmcblk0p1 /boot vfat umask=0077 0 1" >> /etc/fstab
$ echo "/dev/mmcblk0p2 /ext4 relatime,errors=remount-ro 0 1" >> /etc/fstab

配置主机名:

$ cat /etc/hostname
zc706
$ cat /etc/hosts
127.0.0.1 localhost zc706
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

设置root密码:

$ passwd

创建非root用户添加到sudo组中

$ adduser edvison
$ adduser edvison sudo

添加apt下载源:

$ cat /etc/apt/sources.list
deb http://ports.ubuntu.com/ubuntu-ports focal main

安装vim:

$ sudo apt install vim

配置网络:

$ sudo apt install network-manager network-manager-pptp network-manager-gnome network-manager-pptp-gnome
$ sudo apt install net-tools

报错解决:

Ubuntu下locale命令路径无法找到问题解决方法:Cannot set LC_CTYPE to default locale: No such file or directory

退出chroot环境:

$ exit

擦除SD卡内容:

$ dd if=/dev/zero of=/dev/sdc bs=1024

运行fdisk创建两个分区,256MB的引导分区和存放根文件系统的分区:

$ sudo fdisk /dev/sdc
欢迎使用 fdisk (util-linux 2.32)。
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。

设备不包含可识别的分区表。
创建了一个磁盘标识符为 0x7f900099 的新 DOS 磁盘标签。

命令(输入 m 获取帮助): p
Disk /dev/sdc:14.9 GiB,16005464064 字节,31260672 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x7f900099

命令(输入 m 获取帮助): n
分区类型
p 主分区 (0个主分区,0个扩展分区,4空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p): p
分区号 (1-4, 默认 1): 1
第一个扇区 (2048-31260671, 默认 2048): 2048
上个扇区,+sectors  +size{K,M,G,T,P} (2048-31260671, 默认 31260671): +256M

创建了一个新分区 1,类型为“Linux”,大小为 256 MiB。

命令(输入 m 获取帮助): t
已选择分区 1
Hex 代码(输入 L 列出所有代码) c
已将分区“Linux”的类型更改为“W95 FAT32 (LBA)”。

命令(输入 m 获取帮助): n
分区类型
p 主分区 (1个主分区,0个扩展分区,3空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p): p
分区号 (2-4, 默认 2): 2
第一个扇区 (526336-31260671, 默认 526336): 526336
上个扇区,+sectors  +size{K,M,G,T,P} (526336-31260671, 默认 31260671): 31116287

创建了一个新分区 2,类型为“Linux”,大小为 14.6 GiB。

命令(输入 m 获取帮助): w
分区表已调整。

The kernel still uses the old partitions. The new table will be used at the next reboot.
正在同步磁盘。

给引导分区创建FAT32文件系统:

$ sudo mkfs.vfat -F 32 -n BOOT /dev/sdc1
mkfs.fat 4.1 (2017-01-24)

给根分区创建ext4文件系统:

$ sudo mkfs.ext4 /dev/sdc2
mke2fs 1.44.4 (18-Aug-2018)
创建含有 3823744 个块(每块 4k)和 956592 个inode的文件系统
文件系统UUID:a02929a4-bc1b-4591-999b-7d4812b95edc
超级块的备份存储于下列块:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208

正在分配组表: 完成
正在写入inode表: 完成
创建日志(16384 个块) 完成
写入超级块和文件系统账户统计信息:已完成

挂载引导分区并复制文件:

$ sudo mkdir /mnt/tmp
$ sudo mount /dev/sdc1 /mnt/tmp
$ sudo cp ~/buildroot-2021.02/output/images/boot.bin /mnt/tmp
$ sudo cp ~/buildroot-2021.02/output/images/u-boot.img /mnt/tmp
$ sudo cp ~/buildroot-2021.02/output/images/uImage /mnt/tmp
$ sudo cp ~/zc_pcie_dma/uEnv.txt /mnt/tmp
$ sudo cp ~/zc_pcie_dma/devicetree.dtb /mnt/tmp
$ sudo cp ~/zc_pcie_dma/zc_pcie_dma.bit /mnt/tmp
$ sudo umount /mnt/tmp

挂载根分区,复制根文件系统和内核模块:

$ sudo mount /dev/sdc2 /mnt/tmp
$ sudo cp -a ~/debootstrap_focal_armhf/. /mnt/tmp
$ sudo cp -a ~/buildroot-2021.02/output/target/lib/modules /mnt/tmp/lib
$ sudo umount /mnt/tmp

弹出SD卡:

$ sudo eject /dev/sdc

sd卡插回zc706,连接USB串口调试线,SW11设置为00110(SD卡引导模式),插上网线。

主机开始监听

$ sudo miniterm.py --eol LF --raw /dev/ttyUSB0 115200

自动加载内核失败,进入u-boot命令行,手动加载内核:

zynq> run load_image
zynq> bootm ${kernel_load_address} - ${devicetree_load_address}

成功加载ubuntu 20.04:

image-20210727174608785

zc706 ubuntu环境配置

配置网络:

$ sudo ifconfig eth0 up
$ sudo dhclient eth0
$ sudo service network-manager restart

安装python2.7和相关依赖库:

$ sudo apt install software-properties-common
$ sudo add-apt-repository universe
$ sudo apt install python2
$ sudo apt install python-dev python-setuptools libssl-dev

安装pip:

$ sudo apt install curl
$ curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py
$ sudo python2 get-pip.py

安装gcc:

$ sudo apt install gcc-9 gcc-9-multilib

安装numpy包:

$ sudo pip install numpy

获取s6_pcie_microblaze项目:

$ git clone https://github.com/Cr4sh/s6_pcie_microblaze.git