Running Raspbian OS on QUEMU to learn ARM assembly Jan 19 2020

If you want to get into mobile security or reverse engineering, you’ll get to a point when you would like to have access to an ARM processor. There are many devices you could use, but one very cheap (in price not in quality) is the Raspberry pi. You can get one for about 35$, which opens up the doors to a lot of learning. But sometimes you don’t want to carry an additional device, so what to do? Well, you can run a virtual machine that is ARM-based. That is what we are going to explore in this short post, how to install Raspbian OS using QUEMU so you can create your own ARM lab.

We need to download the OS image that might be big, so depending on your Internet speed, you might wish to start downloading them before we start.

Raspbian latest OS - download Raspbian Buster lite

Ok, let’s begin.

QEMU

We want to have access to a machine that has an ARM processor, so we are going to use QEMU to emulate that machine. I’ll assume you are using Ubuntu, but the installation of QEMU through your package manager should be easy. You can check the download specific instructions for your OS here.

1
2
#Ubuntu
$ sudo apt-get install qemu-system-arm

That should install all the required packages for QEMU.

Now we need to figure out which machine we are going to be emulating. You can list all the machines supported by QEMU using the -M help command:

1
$ qemu-system-arm -M help

You can see many types of machine that can be emulated. We are going to be using versatilepb. We’ll choose this machine because there is a handy repository dhruvvyas90/qemu-rpi-kernel that already contains QEMU kernels that can be used to emulate a Raspberry Pi. We could go the hard way and build the kernel ourselves and also create the DTB (Device Tree Blob, that describes the machine and the supported devices), but I still need to learn more so I can comfortably write about it. So in the meantime, we’ll take advantage of the knowledge shared by the authors of qemu-rpi-kernel.

Let’s start by getting all the necessary files.

Get the sources

First, let’s create a directory where we are going to be doing all our work. You can name it whatever you want. I’ll call it raspbian_vm:

1
2
$ mkdir raspian_vm
$ cd raspbian_vm

Now, let’s clone the qemu-rpi-kernel repo so we can have access to the kernel and dtb files:

1
$ git clone https://github.com/dhruvvyas90/qemu-rpi-kernel.git

We are going to download the Raspbian OS image. I will be using Buster Lite. We don’t need a GUI if most of our work will be on the terminal while doing reverse engineering.

1
2
3
4
5
6
7
8
9
10
11
12
$ curl -JLO https://downloads.raspberrypi.org/raspbian_lite_latest
# In theory it should follow the link and use the correct file name
# but if not to check the filename use this command:
$ curl -sI https://downloads.raspberrypi.org/raspbian_lite_lates
# In my case
HTTP/1.1 302 Found
Date: Sun, 19 Jan 2020 12:06:54 GMT
Server: Apache/2.4.10 (Debian)
Location: https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-09-30/2019-09-26-raspbian-buster-lite.zip
Content-Type: text/html; charset=iso-8859-1
# so I renamed raspbian_lite_latest to 2019-09-26-raspbian-buster-lite.zip
$ mv raspbian_lite_latest 2019-09-26-raspbian-buster-lite.zip

I’m don’t know of an easier way to use curl to follow the redirect and use the name of the file. If you know, please let me know. If you want to get funky, you could use something like the following instruction, but that seems to mee a little convoluted:

1
2
3
4
5
# we are obtaining the name from the curl command inside the backticks
# then asking curl to download from that URL and use the name of the file
# I'm not sure this is easier, it seems too much, but there you have
# it. Do with that knowledge what you want.
$ curl -O `curl https://downloads.raspberrypi.org/raspbian_lite_latest -s -L -I -o /dev/null -w '%{url_effective}'`

Anyways, you should have the image on your folder. Extract the image:

1
2
#In my case the file is 2019-09-26-raspbian-buster-lite.zip
$ unzip 2019-09-26-raspbian-buster-lite.zip

Now we have everything we need to boot up our machine. You should have something similar to this directory structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
raspbian_vm/
├── 2019-09-26-raspbian-buster-lite.img
├── 2019-09-26-raspbian-buster-lite.zip
└── qemu-rpi-kernel
  ├── kernel-qemu-3.10.25-wheezy
  ├── kernel-qemu-4.14.79-stretch
  ├── kernel-qemu-4.19.50-buster
  ├── kernel-qemu-4.4.34-jessie
  ├── README.md
  ├── tools
  │  ├── build-kernel-qemu
  │  ├── build-kernel-qemu.conf-4.14.79
  │  ├── config_file
  │  ├── config_file_3.10.25
  │  ├── config_file_4.19.50
  │  ├── config_file_4.4.34
  │  ├── config_ip_tables
  │  ├── config_loopdev
  │  ├── config_webcam
  │  ├── linux-arm-4.4.34.patch
  │  ├── linux-arm.patch
  │  ├── qemu_choose_vm.sh
  │  └── README.md
  └── versatile-pb.dtb

2 directories, 21 files

We are ready to boot up our VM.

Booting up our Raspbian OS image

Now that we have all the missing pieces, we can put them together on one command, don’t run it just yet.

1
2
3
4
5
6
7
8
9
10
11
12
$ qemu-system-arm \
  -M versatilepb \
  -cpu arm1176 \
  -m 256 \
  -hda ./2019-09-26-raspbian-buster-lite.img \
  -net nic, \
  -net user,hostfwd=tcp::5022-:22 \
  -dtb ./qemu-rpi-kernel/versatile-pb.dtb \
  -kernel ./qemu-rpi-kernel/kernel-qemu-4.19.50-buster \
  -append 'root=/dev/sda2 panic=1' \
  -no-reboot \
  -nographic

Let’s break it apart and understand what we are doing (some options are self-explanatory):

We could run that command every time, but it’s a long command, and if we want to tweak something, it becomes messy. So let’s create a small bash script to bring our VM up. Create a file called startBusterVM.sh and add the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash

set -e

qemu-system-arm \
 -M versatilepb \
 -cpu arm1176 \
 -m 256 \
 -hda ./2019-09-26-raspbian-buster-lite.img \
 -net nic, \
 -net user,hostfwd=tcp::5022-:22 \
 -dtb ./qemu-rpi-kernel/versatile-pb.dtb \
 -kernel ./qemu-rpi-kernel/kernel-qemu-4.19.50-buster \
 -append 'root=/dev/sda2 panic=1' \
 -no-reboot \
 -nographic

Add execution permissions and run it:

1
2
$ chmod u+x startBusterVM.sh
$ ./startBusterVM.sh

Now you can log in to your new machine! (Default user is pi password: raspberry, make sure to change it after login).

And that’s it. You have a VM you can use for your ARM explorations.

SSH configuration

Before we are entirely done with the machine, we would like to enable ssh to login into the VM.

While logged in the VM, let’s activate the SSH server, it’s off by default.

1
2
3
4
5
$ sudo raspi-config
# 1. Navigate to Interfacing Options
# 2. SSH (Option number two in my case)
# 3. Select Yes when prompted to enable ssh.
# You'll get a message that it was enabled, and now you can exit (Finish).

If you haven’t changed your default password, do it now, else you might get refused to login because your user has the default password. To change the password, use the passwd command:

1
2
$ passwd
# Change your password

Let’s restart the VM:

1
2
3
4
# Shutdown "halt" the computer
$ sudo shutdown -h now
#You can use our script to run the VM again
$ ./startBusterVM.sh

I prefer to log in from another terminal via ssh, so I get a nice colour terminal instead of the default vt220.

You can log in from your computer via ssh using the port we configured:

1
$ ssh pi@localhost -p5022

You’ll be prompted for the user password. You can keep writing the password like a barbarian, or you could change to using key pairs. If you don’t know how to do this, check the post I wrote about Understanding SSH Keys and using Keychain to manage passphrase on macOS. The process is the same except you don’t have the Keychain in Linux, but everything else applies. You would remove the line UseKeychain yes from your ~/.ssh/config.

Only one more small configuration left (that you can skip).

Change the prompt colour

I want to make it clear for me when I’m inside the VM, so I usually change the colour of the shell’s prompt. This step is optional, but I find it useful. Let’s edit your .bashrc. Search for PS1. This variable contains the format of your prompt.

1
2
3
4
5
6
7
#change
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w \$\[\033[00m\] '
# you see the Ansi sequence [\033[01;32m\]\u
# [01;32m] is colour green
# let's change it to red [\033[01;31m\]\u
# Your PS1 should look like this:
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;31m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w \$\[\033[00m\] '

Save and exit. Now, reload the bashrc.

1
$ source ~/.bashrc

Your prompt should be displayed in red and will make you realise that you are in the raspberry VM.

Ok, that’s it, enjoy playing with your VM.

Final thoughts

Virtualisation is such a handy technology. We don’t have to carry around a lot of devices we can have a powerful computer and emulate the rest.

Keep in mind that sometimes the VM won’t behave the same way as the real computer. Virtualisation is useful for some scenarios, but if you want to develop for ARM or any other architecture, make sure you test it on that architecture and not only on a VM.

As you saw the instructions in this post were specific to one distribution and one architecture. Still, I tried to explain the details so you can understand the steps you’ll need for emulating a different architecture. You now know that you’ll need a kernel, an Image, and a Device Tree Blob, you can now search the specifics for the flavour you desire.

I hope this was helpful, as always, feedback is welcomed.

Related topics/notes of interest


** If you want to check what else I'm currently doing be sure to follow me on twitter @rderik or subscribe to the newsletter. If you want to send me a direct message you can send it to derik@rderik.com.