GNU/Linux >> Linux Esercitazione >  >> Linux

Nascondi argomenti per programmare senza codice sorgente

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.


  1. 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.

  2. Se fallisce, invia una segnalazione di bug contro l'applicazione sulla base del fatto che non esiste un modo sicuro per fornirle un segreto.

  3. 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:

  1. Questo non è sicuro, dal momento che esponi ancora gli argomenti del tuo programma inizialmente prima di cambiarli
  2. 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.


Linux
  1. Come installare phpMyAdmin in Linux usando il codice sorgente

  2. Ottieni il codice sorgente per qualsiasi comando Linux

  3. Esempi di C argc e argv per analizzare gli argomenti della riga di comando

  4. Dove posso trovare il codice sorgente della chiamata di sistema?

  5. Come passare argomenti a uno script richiamato dal comando source?

Introduzione a differenze e patch

Come installare un programma da Source su Linux

Nozioni di base sulla compilazione di software dal codice sorgente in Linux

Ohcount - Il contatore e l'analizzatore di linee di codice sorgente

Rimuovere il codice sorgente Ppa?

Aggiornamenti del kernel senza riavviare