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.
-
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.
-
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.
-
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:
- Esto no es seguro, ya que aún expone los argumentos de su programa inicialmente antes de cambiarlos
- 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.