Come spiegato qui, Linux inserisce gli argomenti di un programma nello spazio dati del programma e mantiene un puntatore all'inizio di quest'area. Questo è ciò che viene utilizzato da ps
e così via per trovare e mostrare gli argomenti del programma.
Poiché i dati si trovano nello spazio del programma, può manipolarli. Fare questo senza cambiare il programma stesso comporta il caricamento di uno shim con un main()
funzione che verrà chiamata prima del vero main del programma. Questo shim può copiare gli argomenti reali in un nuovo spazio, quindi sovrascrivere gli argomenti originali in modo che ps
vedrà solo nuls.
Il seguente codice C fa questo.
/* 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);
}
Non è possibile intervenire su main()
, ma puoi intervenire sulla funzione della libreria C standard __libc_start_main
, che continua a chiamare main. Compila questo file shim_main.c
come notato nel commento all'inizio, ed eseguilo come mostrato. Ho lasciato un printf
nel codice in modo da verificare che sia effettivamente chiamato. Ad esempio, esegui
LD_PRELOAD=/tmp/shim_main.so /bin/sleep 100
poi fai un ps
e vedrai un comando vuoto e argomenti visualizzati.
C'è ancora un po' di tempo prima che il comando args possa essere visibile. Per evitare ciò, potresti, ad esempio, modificare lo shim in modo che legga il tuo segreto da un file e aggiungerlo agli argomenti passati al programma.
-
Leggi la documentazione dell'interfaccia della riga di comando dell'applicazione in questione. Potrebbe esserci un'opzione per fornire il segreto da un file anziché direttamente come argomento.
-
Se fallisce, invia una segnalazione di bug contro l'applicazione sulla base del fatto che non esiste un modo sicuro per fornirle un segreto.
-
Puoi sempre adattare con attenzione (!) la soluzione nella risposta di meuh alle tue esigenze specifiche. Presta particolare attenzione al commento di Stéphane e ai suoi follow-up.
Se hai bisogno di passare argomenti al programma per farlo funzionare, sarai sfortunato qualunque cosa tu faccia se non puoi usare hidepid
su procfs.
Dato che hai detto che si tratta di uno script bash, dovresti già avere il codice sorgente disponibile, dato che bash non è un linguaggio compilato.
In caso contrario, puoi essere in grado di riscrivere la riga di comando del processo utilizzando gdb
o simili e giocare con argc
/argv
una volta che è già avviato, ma:
- Questo non è sicuro, dal momento che esponi ancora gli argomenti del tuo programma inizialmente prima di cambiarli
- Questo è piuttosto confuso, anche se potessi farlo funzionare non consiglierei di fare affidamento su di esso
Consiglierei davvero solo di ottenere il codice sorgente o di parlare con il fornitore per modificare il codice. Fornire segreti sulla riga di comando in un sistema operativo POSIX è incompatibile con operazioni sicure.