GNU/Linux >> Tutoriales Linux >  >> Linux

Ocultar argumentos para programar sin código fuente

Como se explica aquí, Linux coloca los argumentos de un programa en el espacio de datos del programa y mantiene un puntero al inicio de esta área. Esto es lo que usa ps y así sucesivamente para encontrar y mostrar los argumentos del programa.

Dado que los datos están en el espacio del programa, puede manipularlos. Hacer esto sin cambiar el programa implica cargar un shim con un main() función que será llamada antes del main real del programa. Esta corrección puede copiar los argumentos reales en un nuevo espacio y luego sobrescribir los argumentos originales para que ps solo verá nulos.

El siguiente código C hace esto.

/* https://unix.stackexchange.com/a/403918/119298
 * capture calls to a routine and replace with your code
 * gcc -Wall -O2 -fpic -shared -ldl -o shim_main.so shim_main.c
 * LD_PRELOAD=/.../shim_main.so theprogram theargs...
 */
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <dlfcn.h>

typedef int (*pfi)(int, char **, char **);
static pfi real_main;

/* copy argv to new location */
char **copyargs(int argc, char** argv){
    char **newargv = malloc((argc+1)*sizeof(*argv));
    char *from,*to;
    int i,len;

    for(i = 0; i<argc; i++){
        from = argv[i];
        len = strlen(from)+1;
        to = malloc(len);
        memcpy(to,from,len);
        memset(from,'\0',len);    /* zap old argv space */
        newargv[i] = to;
        argv[i] = 0;
    }
    newargv[argc] = 0;
    return newargv;
}

static int mymain(int argc, char** argv, char** env) {
    fprintf(stderr, "main argc %d\n", argc);
    return real_main(argc, copyargs(argc,argv), env);
}

int __libc_start_main(pfi main, int argc,
                      char **ubp_av, void (*init) (void),
                      void (*fini)(void),
                      void (*rtld_fini)(void), void (*stack_end)){
    static int (*real___libc_start_main)() = NULL;

    if (!real___libc_start_main) {
        char *error;
        real___libc_start_main = dlsym(RTLD_NEXT, "__libc_start_main");
        if ((error = dlerror()) != NULL) {
            fprintf(stderr, "%s\n", error);
            exit(1);
        }
    }
    real_main = main;
    return real___libc_start_main(mymain, argc, ubp_av, init, fini,
            rtld_fini, stack_end);
}

No es posible intervenir en main() , pero puede intervenir en la función de biblioteca C estándar __libc_start_main , que pasa a llamar a main. Compile este archivo shim_main.c como se indica en el comentario al principio, y ejecútelo como se muestra. He dejado un printf en el código para que verifique que realmente se está llamando. Por ejemplo, ejecute

LD_PRELOAD=/tmp/shim_main.so /bin/sleep 100

luego haz un ps y verá un comando en blanco y argumentos que se muestran.

Todavía hay una pequeña cantidad de tiempo en que los argumentos del comando pueden estar visibles. Para evitar esto, podría, por ejemplo, cambiar el shim para leer su secreto de un archivo y agregarlo a los argumentos pasados ​​al programa.


  1. Lea la documentación de la interfaz de línea de comandos de la aplicación en cuestión. Bien puede haber una opción para proporcionar el secreto de un archivo en lugar de un argumento directamente.

  2. Si eso falla, presente un informe de error contra la aplicación con el argumento de que no existe una forma segura de proporcionarle un secreto.

  3. Siempre puedes adaptar cuidadosamente (!) la solución en la respuesta de meuh a tus necesidades específicas. Preste especial atención al comentario de Stéphane y sus seguimientos.


Si necesita pasar argumentos al programa para que funcione, no tendrá suerte sin importar lo que haga si no puede usar hidepid en procfs.

Como mencionó que se trata de un script bash, ya debería tener el código fuente disponible, ya que bash no es un lenguaje compilado.

En su defecto, puede ser capaz de reescribir la línea de cmd del proceso usando gdb o similar y jugando con argc /argv una vez que ya ha comenzado, pero:

  1. Esto no es seguro, ya que aún expone los argumentos de su programa inicialmente antes de cambiarlos
  2. Esto es bastante complicado, incluso si pudieras hacerlo funcionar, no recomendaría confiar en él

Realmente recomendaría obtener el código fuente o hablar con el proveedor para modificar el código. Proporcionar secretos en la línea de comandos en un sistema operativo POSIX es incompatible con la operación segura.


Linux
  1. ¿Código fuente de Netstat?

  2. Ejemplos de C argc y argv para analizar argumentos de línea de comandos

  3. ¿Dónde está el código del programador de Linux CFS?

  4. ¿Cómo pasar argumentos a un script invocado por el comando fuente?

  5. ¿Números de línea de origen en el gráfico de llamadas de rendimiento?

Una introducción a los diferenciales y parches

Cómo instalar un programa desde la fuente en Linux

Conceptos básicos de la compilación de software a partir del código fuente en Linux

Ohcount:el contador y analizador de líneas de código fuente

¿Eliminar el código fuente de Ppa?

¿Dónde puedo encontrar el código fuente de la llamada al sistema?