At this moment, we need to unzip the zip file and use binwalk to analyze the .trx file. Using the option "-e" we can extract all the files from the .trx file.
We can see the firmware uses little-endian, and this is probably a sign that it is using a 3x ARM version or minor.
Why not emulation your router firmware instead of getting a physical device? 🤓
Backing to the extracted folder from the .trx file (firmware itself), we have a file called 1C we need to analyze. We got some precious information, such as:
We can confirm some details by using the Linux strings utility:
In fact, we should check everytime the device configuration available on the vendor page to learn about it, and get the device datasheet in order to confirm some details.
Per-process emulation is useful when only one binary needs to be emulated. To this that, next install full dependencies:
The user-mode emulation can be made by using the following command:
The -L option is important for when the binary links to external dependencies such as uCLibc or encryption libraries. It tells the dynamic linker to look for dependencies with the provided prefix.
We can get the following error:
qemu-arm: Could not open '/lib/ld-uClibc.so.0': No such file or directory
By inspecting the /lib/ folder, we can see the following:
The file "ld-uClibc.so.0" is present, so we need to just add the current dir to the qemu-arm execution. Otherwise, if the UClibc.so file has another name, we could resolve that by doing a symbolic link, e.g.: squashfs-root/lib/ld-uClibc-0.9.29.so to squashfs-root/lib/ld-uClic.so.
So, the final qemu command is the following:
Using qemu-user-static approach
Another way to emulate the process is to perform a cross-architectural chroot with QEMU.
You can also download the target qemu-user static file pre-compiled from GitHub 😼
Next, we copy the qemu-arm-static binary to the rootFS directory of the firmware. We then chroot into the firmware root and obtain a working shell:
This is possible due to QEMU registering with the kernel during installation to handle binaries with certain magic bytes via the binfmt_misc mechanism.
We can try to run the httpd service, getting some errors - of course, because the /etc/ folder is not mounted, NVRAM system is not present - but we will just workaround this later! 😎
This is the best method to test a single binary or feature in a short period of time without losing a lot of hours configuring and preparing the environment.
Next, we can start e.g., telnetd service inside our emulated environment ;)
Emulation NVRAM
In the previous user emulation scenarios, we found problems to emulate correctly the NVRAM. In this way, we can use hooks in a simple library to intercept calls to libnvram using LD_PRELOAD.
You can simply access this project on GitHub, compiling the C files with the target arch (ARM) or just download the arm version from releases.
You can also compile the nvram file using a cross-compiler for ARM architectures.
It works 😋
Hook functions
If we need to hook any function, LD_PRELOAD is our best friend.
For example, the next hook will emulate the native open file call from gclib.
We can compile it onto ARM using a cross compiler:
Even though we don't have the /etc/rc.d or /etc/init.d to run the appropriate RC script to kick off the userland services, we were able to execute single binaries, which can give us some input about the device operation, or even finding vulnerabilities at this level.
Firmware full emulation
To do this, we can use Buildroot 2012.02 to create your rootFS and compile kernel version 2.6.36.
or accessing: output/build/linux-2.6.36.4/arch/arm/configs
To start the compilation process: make all or using a specific GCC version: make HOSTCC=gcc-4
Fixing kernel crashes or dependencies
"gets" undeclared here
Fix
textinfo incompatibilities with GCC documentation
This is frustrating me too, I cannot install texinfo, because texinfo is compatible with the tex documentation for this version of the compiler I have to use, which is what's breaking the documentation in the first place.
Instead of editing files, when I run make I pass the argument MAKEINFO.
One minor point about this. I think it should be pointed out what this does. It basically overrides the MAKEINFO variable predefined by GNU make, which normally points to the program to call in order to get makeinfo invoked. So by setting it to true you are effectively replacing calls to makeinfo by calls to /bin/true (can be seen with make -npf /dev/null |grep ^MAKEINFO).
Fix
Can't use 'defined(@array)'
Fix
Can’t use ‘defined(@array)’ (Maybe you should just omit the defined()?) at kernel/timeconst.pl line 373has prompted where is the delicate error message, open timeconst.pl to see (under the kerner directory).
Compiling everything is a long journey, you can also test more recent kernel versions and so on to avoid some errors when you are building your environment for emulation.
At the end, you will get something like this on your output/images folder:
Now, it's time to start your qemu emulator:
Finally, merge the rootfs (host + router), and exploit it like a baws 😉
Using docker containers and relax to emulate your firmware 👾
Other options instead of using qemu are docker containers.
cd _RT-AC5300_3.0.0.4_380_2356-g34e8f6b.trx.extracted
ls -la
ls -la squashfs-root
ls squashfs-root/www
//CPIO file with the /dev and rootFS
139264 0x22000 ASCII cpio archive (SVR4 with no CRC), file name: "/dev", file name length: "0x00000005", file size: "0x00000000"
139380 0x22074 ASCII cpio archive (SVR4 with no CRC), file name: "/dev/console", file name length: "0x0000000D", file size: "0x00000000"
139504 0x220F0 ASCII cpio archive (SVR4 with no CRC), file name: "/root", file name length: "0x00000006", file size: "0x00000000"
139620 0x22164 ASCII cpio archive (SVR4 with no CRC), file name: "TRAILER!!!", file name length: "0x0000000B", file size: "0x00000000"
//Linux kernel version - it's important to full emulation
3163712 0x304640 Linux kernel version 2.6.36
//UNIX path - cool for searching related files/content on web
3735664 0x390070 Unix path: /home/yau/asuswrt/release/src-rt-7.14.114.x/src/linux/linux-2.6.36/arch/arm/include/asm/dma-mapping.h
which qemu-arm-static 130 ⨯
/usr/bin/qemu-arm-static
cp /usr/bin/qemu-arm-static squashfs-root/
cd squashfs-root/
sudo chroot . ./qemu-arm-static /bin/sh
---inside chroot FS----
/usr/sbin # telnetd
called setup()
/usr/sbin #
---Guest machine---
└─$ netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp6 0 0 :::23 :::* LISTEN -
In file included from clean-temp.h:22:0,
from clean-temp.c:23:
./stdio.h:477:1: error: 'gets' undeclared here (not in a function)
_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
^
find . -name stdio.in.h
./output/build/host-m4-1.4.16/lib/stdio.in.h
sed -i -e '/gets is a/d' lib/stdio.in.h
/home/ubuntu/buildroot-2012.02/output/toolchain/gcc-4.5.3/gcc/doc/service.texi:6: warning: node prev `Service' in menu `Trouble' and in sectioning `Bugs' differ
/home/ubuntu/buildroot-2012.02/output/toolchain/gcc-4.5.3/gcc/doc/service.texi:6: warning: node up `Service' in menu `Bugs' and in sectioning `Top' differ
Makefile:4052: recipe for target 'doc/gcc.info' failed
make[2]: *** [doc/gcc.info] Error 1
make[2]: Leaving directory '/home/ubuntu/buildroot-2012.02/output/toolchain/gcc-4.5.3-initial/gcc'
Makefile:5027: recipe for target 'all-gcc' failed
make[1]: *** [all-gcc] Error 2
make[1]: Leaving directory '/home/ubuntu/buildroot-2012.02/output/toolchain/gcc-4.5.3-initial'
make MAKEINFO=true
Can't use 'defined(@array)' (Maybe you should just omit the defined()?) at kernel/timeconst.pl line 373.
/home/ubuntu/buildroot-2012.02/output/build/linux-3.2.6/kernel/Makefile:141: recipe for target 'kernel/timeconst.h' failed
make[2]: *** [kernel/timeconst.h] Error 255
Makefile:945: recipe for target 'kernel' failed
make[1]: *** [kernel] Error 2
make[1]: *** Waiting for unfinished jobs....
make[1]: Leaving directory '/home/ubuntu/buildroot-2012.02/output/build/linux-3.2.6'
package/Makefile.package.in:393: recipe for target '/home/ubuntu/buildroot-2012.02/output/build/linux-3.2.6/.stamp_built' failed
make: *** [/home/ubuntu/buildroot-2012.02/output/build/linux-3.2.6/.stamp_built] Error 2
cd output/build/linux-3.2.6/kernel/
vim timeconst.pl
/!defined(@val))
change this (line 373):
372 @val = @{$canned_values{$hz}};
373 if (!defined(@val)) {
374 @val = compute_values($hz);
375 }
376 output($hz, @val);
by:
372 @val = @{$canned_values{$hz}};
373 if (!@val) {
374 @val = compute_values($hz);
375 }
376 output($hz, @val);
make
-rw-r--r-- 1 kali kali 62914560 Jul 27 18:30 rootfs.ext2
-rw-r--r-- 1 kali kali 1437696 Jul 27 18:30 rootfs.squashfs
-rw-r--r-- 1 kali kali 4085760 Jul 27 18:30 rootfs.tar
-rwxr-xr-x 1 kali kali 446 Jul 27 18:30 start-qemu.sh
-rwxr-xr-x 1 kali kali 8880 Jul 27 18:27 versatile-pb.dtb
-rw-r--r-- 1 kali kali 2871872 Jul 27 18:27 zImage