Virtualizing ARM-Based Firmware Part - 1
Hello everyone, this blog demonstrates how to simulate/virtualize the ARM-based firmware in your system. This blog is for the people who are interested in IoT security and love playing with firmware. This is a custom approach to simulate firmware. Using a virtual machine will make the task easy. Commands in blog pertain to Linux, to be more specific Ubuntu. The blog will be divided into 2 parts.
- Part 1: Preparing ARM Machine
- Part 2: Booting up ARM Firmware
Part 1: Preparing ARM Machine
Let’s start preparing a machine(ARM) on which ARM based firmware will be simulated. Steps are as below:
- Setup QEMU
- Compile Linux kernel for ARM
- Download and prepare the ARM file system
- Setup network
- Boot up ARM file system using compiled kernel
QEMU is an open-source machine emulator and virtualizer. As this blog focus on preparing/virtualizing the ARM machine, QEMU is not covered in depth. More details and documentation can be found on QEMU
Install QEMU and other utilities
sudo apt-get install qemu qemu-system qemu-user-static
Compiling Linux Kernel for ARM
Here, the kernel will be customized and compiled for ARM using the Ubuntu machine. Compiling an executable code for a platform other than the compiler is running on, is known as cross compilation. Cross Compilers of ARM like gcc, g++ will be used to fulfill task. Follow the steps mentioned below.
- Installing cross compilation tools
sudo apt-get install gcc-arm-*
- Installing dependencies and other tools
sudo apt-get install build-essential ncurses-dev flex bison
- Download and extract kernel from The Linux Kernel Archives. For demo, linux kernel version 5.2.6 is used. Explore the folders after extraction. Different architectures can be found under
<kernel path>/arch/directory. Go into architecture directory and explore more. Check for
<kernel path>/arch/arm/configs/. This directory contains many default configuration files used while compiling kernel.
- Kernel Root Directory
- ”./arch” Directory
- ”./arch/arm” Directory
- ”./arch/arm/config” Directory
- Copy any config file (as per requirement) from
<kernel path>/.config. For demo, let’s use vexpress_defconfig config file to compile the kernel.
- Customize the kernel configuration (as per requirement) using interactive GUI way:
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- menuconfig
- Alternatively, traditional console based configuration can be used:
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- oldconfig
- Being GUI, menuconfig is easier way to go ahead. Don’t forget to save the configuration before exiting.
- Start compilation. This process may take a while depending on your CPU and threads.
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- -k
- Compiled kernel files (Image, zImage, etc.) can be found under
The end result for this step is customized kernel files which will be used along with virtualization software to bootup the file system.
Download and prepare ARM file system
Here, file system (ARM) will be prepared using Ubuntu ARM file system which will be used to start ARM-based firmware. This will be booted along with compiled kernel using QEMU.
Terms: (Below terms are used for demo purpose. Replace it accordingly)
- armfs - is a directory used to mount the partition
- /dev/sdb1 - is a harddisk partition
- TestARM - is hostname used for ARM system
Follow the steps mentioned below:
- Download the appropriate file system from Ubuntu Base. Extract it. Here, for demo purpose ubuntu 18.04.1 ARMHF file system is used.
- Create a formatted hard disk partition with size 5 GB or more. In case of virtual machine, add a hard disk.
- Create folder in base machine where newly created partition can be mounted. For e.g.
- Mount the partition
sudo mount <drivepath> <foldername>.
- Copy the extract file system to
~/armfs. The folder should look like
~/armfs/etc, ~/armfs/var, etc...
- Copy qemu-arm-static to armfs
sudo cp -av /usr/bin/qemu-arm-static ~/armfs/usr/bin/
- Copy resolv.conf to armfs
sudo cp -av /run/systemd/resolve/stub-resolv.conf ~/armfs/etc/resolv.conf.
- Change root to armfs
sudo chroot armfs. Now root filesystem is changed to ARM file system.
- Add user
useradd -G sudo -m -s /bin/bash <username>.
- Change password
echo <username>:<password> | chpasswd.
useradd -G sudo -m -s /bin/bash test
echo demo:demopass | chpasswd
- Change password of root user
- Setup hostname and hosts file. Follow commands as below:
echo <hostname> > /etc/hostname echo 127.0.0.1 localhost > /etc/hosts echo 127.0.1.1 <hostname> >> /etc/hosts
apt-get update && apt-get upgrade
- Install basic tools
apt-get install locales dialog perl sudo ifupdown net-tools ethtool udev wireless-tools iputils-ping resolvconf wget apt-utils wpasupplicant nano systemd openssh-server
- Exit from chroot
- Unmount the file system
sudo umount armfs
The end result of these steps will be an ARM-based Ubuntu file system which can be booted with some kernel using virtualization software.
Setup network for ARM system
Network setup is required to share a base network interface in QEMU. Follow Setting up Qemu with a tap interface · GitHub to create bridge interface in the host operating system and use it with QEMU. To make task simple create a shell script for the same. In addition to the above steps, /etc/network/interfaces file needs to be created/modified for the ARM file system. Changes can be made in both the ways, while setting up file system or after booting file system. Add the below lines in the ARM file system’s interfaces file. i.e ~/armfs/etc/network/interfaces
auto eth0 iface eth0 inet dhcp
By this step setting up the ARM machine is completed. Let’s boot up and check if things are working fine.
Boot up ARM system with compiled kernel
Let’s boot up ARM system using previously compiled kernel and file system. Below is the command to boot up the ARM system.
sudo qemu-system-arm -M virt -cpu cortex-a15 -kernel <kernel path>/arch/arm/boot/zImage -nographic -append "-noinitrd root=/dev/sda rw init=/sbin/init" -device virtio-scsi-device,id=scsi -device scsi-hd,drive=hd -drive if=none,id=hd,file=<device path. In my case /dev/sdb1> -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -device virtio-net-device,netdev=net0,mac=52:55:00:d1:55:01
Note: Make sure to change directory paths accordingly. After system is booted, system will prompt for credentials. Provide the credentials that was set while preparing ARM file system. If something fails make sure to go through all the above steps properly.
Bingo!!! ARM system is up and running. Now its time to boot up ARM-based firmware (router, IP Camera, etc.)…