In this exercise we will run the latest Android Oreo (8.1.0) x86_64 under KVM accelerated Qemu and forward all internet traffic from the Android through Burp Suite running on our Linux x86_64 host. We will be using the following software :
- Linux Mint 19.1 (x86_64) as our host system (With KVM support built into the kernel)
- Latest Qemu from git ( https://github.com/qemu/qemu )
- Android 8.1.0 from ( https://www.fosshub.com/Android-x86.html )
- Burp Suite community ( https://portswigger.net/burp/communitydownload )
I usually build Qemu from source, so once we download the sources via git following is sufficient to build the complete emulator.
$ mkdir build $ cd build $ ../configure $ make # make install
In order to be able to intercept SSL traffic from the Android we will need to add our self generated certificate to the system cacert store which will be covered here later on.
I am using the following network scripts for all my qemu simulations, so please feel free to change them according to your needs if desired.
On our Linux x86_64 host we will need the following
/etc/qemu-ifup
#! /bin/sh # Script to bring a network (tap) device for qemu up. # The idea is to add the tap device to the same bridge # as we have default routing to. # in order to be able to find brctl PATH=$PATH:/sbin:/usr/sbin ip=$(which ip) if [ -n "$ip" ]; then ip link set "$1" up else brctl=$(which brctl) if [ ! "$ip" -o ! "$brctl" ]; then echo "W: $0: not doing any bridge processing: neither ip nor brctl utility not found" >&2 exit 0 fi ifconfig "$1" 0.0.0.0 up fi switch=$(ip route ls | awk '/^default / { for(i=0;i<NF;i++) { if ($i == "dev") { print $(i+1); next; } } }' ) switch=br0 # only add the interface to default-route bridge if we # have such interface (with default route) and if that # interface is actually a bridge. # It is possible to have several default routes too for br in $switch; do if [ -d /sys/class/net/$br/bridge/. ]; then if [ -n "$ip" ]; then ip link set "$1" master "$br" else brctl addif $br "$1" fi exit # exit with status of the previous command fi done echo "W: $0: no bridge for guest interface found" >&2
And the network sharing script (must be started before the qemu simulator and requires root privs) (On Debian/Ubuntu just run sudo apt–get install uml-utilities bridge-utils to get tunctl and brctl commands)
tunctl -t tap0 -u user ifconfig tap0 up brctl addbr br0 brctl setfd br0 0 ifconfig br0 10.0.2.2 netmask 255.255.255.0 broadcast 10.0.2.255 up brctl addif br0 tap0 ifconfig tap0 0.0.0.0 sysctl net.ipv4.ip_forward=1 iptables --table nat -A POSTROUTING --out-interface wlan0 -j MASQUERADE
Once we have all this ready we can move on to install latest Android (x86_64) and run it.
We will be working in a directory called $ANDROID-QEMU (you can call it whatever you want, Im just assigning it a dummy variable name here) and create a virtual disk.img of 10 Gigs size. Also make sure you move your Android iso to this directory
$ mkdir $ANDROID-QEMU $ qemu-img create -f qcow disk.img 10G
Next we shall run the installer with the following loader script
qemu-system-x86_64 -enable-kvm -boot d -cpu host -m 2048 -hda disk.img -cdrom android-x86_64-8.1-r2.iso -net nic -net tap
The installer is pretty straight forward. What we need to make sure is that we setup the WiFi as follows :
- SSID: VirtWifi (Define as maual)
- no DHCP – Static IP – 10.0.2.12
- Gateway 10.0.2.2
- DNS 8.8.8.8
We update the system, test the network etc. Now we are ready for the next stage. That is installing a custom CA into the Android system cacert directory so we can intercept the outgoing/incoming HTTPS traffic in Burp Suite. The only way that I know which works is to add the custom certificate to the root filesystem in /system/etc/security/cacert
Lets shut down the emulator (ACPI shutdown from Qemu will trigger a shutdown menu from Android)
lets first mount the Qemu qcow2 image from the host Linux
# apt-get install libguestfs-tools # cd $ANDROID-QEMU # mkdir img # guestmount -a disk.img -m /dev/sda1 img/ # cd img # cd android-8.1-r2/ # ls -la total 867056 drwxr-xr-x 3 root root 4096 Jul 7 22:11 . drwxr-xr-x 5 root root 4096 Jul 7 22:11 .. drwxrwx--x. 34 user user 4096 Jul 7 22:12 data -rw-r--r-- 1 root root 1358699 Jul 7 22:11 initrd.img -rw-r--r-- 1 root root 7437056 Jul 7 22:11 kernel -rw-r--r-- 1 root root 1424814 Jul 7 22:11 ramdisk.img -rw-r--r-- 1 root root 877621248 Jul 7 22:11 system.sfs
We are interested in the system.sfs file – since this will contain the system cacert files we need
# cp system.sfs ../.. // we are copying the system.sfs away # cd ../.. # umount img # mkdir SYS # mv system.sfs SYS # cd SYS # unsquashfs system.sfs // extracting the system.sfs # cd squashfs-root # ls -la total 2066844 drwxrwxrwx 3 user user 4096 Jul 8 21:42 . drwxr-xr-x 3 root root 4096 Jul 8 21:40 .. -rw-r--r-- 1 user user 2318401536 Jul 8 21:43 system.img $ANDROID-QEMU/SYS/squashfs-root# file system.img system.img: Linux rev 1.0 ext4 filesystem data, UUID=da594c53-9beb-f85c-85c5-cedf76546f7a, volume name "system" (needs journal recovery) (extents) (large files)
Great another nested FS to work with … lets create a new mount dir here called img
# mkdir img # mount -o loop system.img img # cd img # ls -la total 180 drwxr-xr-x. 17 root root 4096 Jan 1 1970 . drwxrwxrwx 3 user user 4096 Jul 8 21:42 .. drwxr-xr-x. 43 root root 4096 Jun 12 21:33 app drwxr-xr-x. 3 root 2000 8192 Jun 12 21:33 bin -rw-------. 1 root root 3116 Jun 12 18:56 build.prop -rw-r--r--. 1 root root 74747 Jun 12 19:24 compatibility_matrix.xml drwxr-xr-x. 11 root root 4096 Jun 13 11:10 etc drwxr-xr-x. 2 root root 4096 Jun 13 06:10 fake-libs drwxr-xr-x. 2 root root 4096 Jun 13 06:10 fake-libs64 drwxr-xr-x. 2 root root 8192 Jun 12 18:36 fonts drwxr-xr-x. 5 root root 4096 Jun 13 06:12 framework drwxr-xr-x. 7 root root 12288 Jun 13 10:35 lib drwxr-xr-x. 5 root root 12288 Jun 13 06:10 lib64 drwx------. 2 root root 4096 Jan 1 1970 lost+found -rw-r--r--. 1 root root 2946 Jun 12 19:24 manifest.xml drwxr-xr-x. 3 root root 4096 Jun 12 18:56 media drwxr-xr-x. 52 root root 4096 Jun 12 21:38 priv-app drwxr-xr-x. 8 root root 4096 Jun 12 18:56 usr drwxr-xr-x. 7 root 2000 4096 Jun 12 21:25 vendor drwxr-xr-x. 2 root 2000 8192 Jun 12 21:32 xbin
Now we are finally in the Android rootfs, lets add the custom certificate now
We will create a custom certificate via OpenSSL and import it to Burp as well as place it to Andriod
$ cd $CERTIFICATE-LOCATION //lets create some dummy cert directory $ openssl req -x509 -days 730 -nodes -newkey rsa:2048 -outform der -keyout server.key -out ca.der -extensions v3_ca $ openssl rsa -in server.key -inform pem -out server.key.der -outform der $ openssl pkcs8 -topk8 -in server.key.der -inform der -out server.key.pkcs8.der -outform der -nocrypt $ openssl x509 -inform der -in ca.der -out ca.pem $ openssl x509 -inform PEM -subject_hash_old -in ca.pem | head -1 Check the hash value and change accordingly $ cp ca.pem abcdefg1.0 $ openssl x509 -inform PEM -text -in ca.pem -out /dev/null>> abcdefg1.0 And move to the extracted image on Android # mv abcdefg1.0 $ANDROID-QEMU/SYS/squashfs-root/img/etc/security/cacerts
Now lets pack all these things back together
Unmount the system.img first
# cd $ANDROID-QEMU/SYS/squashfs.root/ # umount img # rm -rf img # cd .. # mkdir BACKUP # mv system.sfs BACKUP/ // backup the original system.sfs # mksquashfs squashfs-root system.sfs -b 131072 // pack everything back up
Lets mount the qemu2 image agin # cd $ANDROID-QEMU/ # guestmount -a disk.img -m /dev/sda1 img/ # cd img # cd android-8.1-r2 # rm system.sfs // remove the original system.sfs # cp ../../SYS/system.sfs . // copy over the new modified one # cd ../.. # umount img
So now we are almost ready now, lets first prepare a loader script for the Android
qemu-system-x86_64 -enable-kvm -boot c -cpu host -m 2048 -hda disk.img -cdrom android-x86_64-8.1-r2.iso -net nic -net tap
Now we can verify the modified Android boots up by executing the above (save it as a shell script for future) If all went fine you should see the normal Android screen
Now lets start up Burp Suite on our Linux machine and import the custom generated SSL certificates as follows
Once we have these loaded, we setup Burp Suite to listen on the br0 interface @ 10.0.2.2
Next we need to tell Android to use the Proxy address and port for the WiFi connection, so we simply re-configure the networking (this is a bit clumsy in Android, and took me a while to figure out were the proxy setting was hidden in Oreo)
So it must look like the above.
With the above we can finally intercept all traffic via Burp Suite on the emulated Android !
Acknowledgement : Thanks to Awakened for his approach https://awakened1712.github.io/hacking/hacking-install-ca-android/
P.S you can try add the CA certificate via the inbuilt Terminal Emulator; elevate to root via su
But you will get a nice message about the system being read-only
Im unsure how to remount with RW tags on the live system
Also one can install the adb tools on the Linux host
sudo apt-get install android-tools-adb android-tools-fastboot
Then if we nmap the remote Android (IP assigned was 10.0.2.12)
# nmap -sS -sV -vv 10.0.2.12 Starting Nmap 7.70SVN ( https://nmap.org ) at 2019-07-09 22:44 CEST NSE: Loaded 44 scripts for scanning. Initiating ARP Ping Scan at 22:44 Scanning 10.0.2.12 [1 port] Completed ARP Ping Scan at 22:44, 0.24s elapsed (1 total hosts) Initiating Parallel DNS resolution of 1 host. at 22:44 Completed Parallel DNS resolution of 1 host. at 22:44, 0.00s elapsed Initiating SYN Stealth Scan at 22:44 Scanning 10.0.2.12 [1000 ports] Discovered open port 5555/tcp on 10.0.2.12 Completed SYN Stealth Scan at 22:44, 1.27s elapsed (1000 total ports) Initiating Service scan at 22:44 Scanning 1 service on 10.0.2.12 Completed Service scan at 22:44, 11.02s elapsed (1 service on 1 host) NSE: Script scanning 10.0.2.12. NSE: Starting runlevel 1 (of 2) scan. Initiating NSE at 22:44 Completed NSE at 22:44, 0.00s elapsed NSE: Starting runlevel 2 (of 2) scan. Initiating NSE at 22:44 Completed NSE at 22:44, 0.00s elapsed Nmap scan report for 10.0.2.12 Host is up, received arp-response (0.0010s latency). Scanned at 2019-07-09 22:44:40 CEST for 13s Not shown: 999 closed ports Reason: 999 resets PORT STATE SERVICE REASON VERSION 5555/tcp open adb syn-ack ttl 64 Android Debug Bridge device (name: android_x86_64; model: Standard PC (i440FX + PIIX, 1996); device: x86_64; features: cmd,stat_v2,shell_v2) MAC Address: 52:54:00:12:34:56 (QEMU virtual NIC) Service Info: OS: Android; CPE: cpe:/o:linux:linux_kernel Read data files from: /usr/local/bin/../share/nmap Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 13.01 seconds Raw packets sent: 1002 (44.072KB) | Rcvd: 1002 (40.072KB)
We can then initiate the adb to the remote system as follows:
$ adb connect 10.0.2.12 $ adb shell x86_64:/ $ id uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid) context=u:r:shell:s0 x86_64:/ $ su x86_64:/ # id uid=0(root) gid=0(root) groups=0(root) context=u:r:su:s0 x86_64:/ # uname -a Linux localhost 4.19.50-android-x86_64-geeb7e76e5df5 #1 SMP PREEMPT Thu Jun 13 12:10:59 CST 2019 x86_64
But we are still stuck with the RO filesystem
x86_64:/ # uname -a Linux localhost 4.19.50-android-x86_64-geeb7e76e5df5 #1 SMP PREEMPT Thu Jun 13 12:10:59 CST 2019 x86_64 x86_64:/ # df Filesystem 1K-blocks Used Available Use% Mounted on tmpfs 1020176 3372 1016804 1% / /dev/loop1 2193072 2078004 115068 95% /system /dev/block/sda1 10186756 1785628 8401128 18% /data tmpfs 1020176 460 1019716 1% /dev tmpfs 1020176 0 1020176 0% /mnt none 1020176 0 1020176 0% /cache /data/media 10186756 1785628 8401128 18% /mnt/runtime/default/emulated /dev/block/vold/public:11,0 878742 878742 0 100% /mnt/media_rw/Android-x86_LiveCD x86_64:/ # x86_64:/ # x86_64:/ # mount -o rw,remount /system '/dev/loop1' is read-only x86_64:/ #