2011-12-14 5 views
10

ho il seguente programma di esempio:execve ("/ bin/sh", 0, 0); in un tubo

#include <stdio.h> 

int 
main(int argc, char ** argv){ 
    char buf[100]; 

    printf("Please enter your name: "); 
    fflush(stdout); 
    gets(buf); 
    printf("Hello \"%s\"\n", buf); 

    execve("/bin/sh", 0, 0); 
} 

I e quando corro senza tubo funziona come dovrebbe e restituisce una sh promt:

bash$ ./a.out 
Please enter your name: warning: this program uses gets() which is unsafe. 
testName 
Hello "testName" 
$ exit 
bash$ 

Ma questo non funziona in una pipe, penso di sapere perché, ma non riesco a capire una soluzione. Esempio di esecuzione sotto.

bash$ echo -e "testName\npwd" | ./a.out 
Please enter your name: warning: this program uses gets() which is unsafe. 
Hello "testName" 
bash$ 

Immagino che questo ha qualcosa a che fare con il fatto che gets svuota stdin in modo tale che /bin/sh riceve un EOF e promtly si chiude senza un messaggio di errore.

Ma come posso aggirare questo (senza modificare il programma, se possibile, e non rimuovere gets, se non lo è) in modo che ottenga un promt anche se fornisco l'input attraverso una pipe?

P.S. Lo sto eseguendo su un dispositivo FreeBSD (4.8) DS

+6

*** MAI *** usare 'ottiene'. ** sempre ** apre un buco di sicurezza del buffer overflow. – ThiefMaster

+5

Lo so;) ...questo fa parte di un tentativo di buffer overflow su un computer presso il laboratorio di sicurezza della mia università. Puramente accademico. = D –

risposta

10

È possibile eseguire il programma senza alcuna modifica di questo tipo:

(echo -e 'testName\n'; cat) | ./a.out 

In questo modo si garantisce che lo standard input del vostro programma non finisce dopo quello che echo uscite. Invece, cat continua a fornire input al tuo programma. La fonte di quell'ingresso successivo è il terminale poiché questo è il punto da cui legge cat.

Ecco una sessione di esempio:

bash-3.2$ cc stdin_shell.c 
bash-3.2$ (echo -e 'testName\n'; cat) | ./a.out 
Please enter your name: warning: this program uses gets(), which is unsafe. 
Hello "testName" 
pwd 
/home/user/stackoverflow/stdin_shell_question 
ls -l 
total 32 
-rwxr-xr-x 1 user group 9024 Dec 14 18:53 a.out 
-rw-r--r-- 1 user group 216 Dec 14 18:52 stdin_shell.c 
ps -p $$ 
    PID TTY   TIME CMD 
93759 ttys000 0:00.01 (sh) 
exit 

bash-3.2$ 

noti che poiché standard input del guscio non è collegato ad un terminale, sh pensa che non viene eseguito in modo interattivo e quindi non visualizzare la richiesta. Puoi comunque digitare i tuoi comandi normalmente.

+0

Ah .. sì, hai ragione, (sono riuscito a trovare questa soluzione prima di aver visto il tuo post, ma grazie per averlo messo qui). –

1

Non sicuro al 100% di questo (la shell precisa utilizzata e il sistema operativo potrebbe lanciare un po 'queste risposte: credo che FreeBSD utilizzi GNU bash come predefinito /bin/sh?), ma

  • sh potrebbe rilevare che il suo input non è un tty.

o

  • La versione di sh potrebbe andare in modalità non interattiva del genere anche se chiamato come sh, aspettandosi login sarà anteporre una - su argv[0] per esso. L'impostazione di execve ("/bin/sh", { "-sh", NULL}, NULL) potrebbe convincere che è stata eseguita come shell di login.
3

L'utilizzo di execve("/bin/sh", 0, 0); è una punizione crudele e inusuale per il guscio. Non fornisce alcun argomento o ambiente - nemmeno il suo nome di programma, né nemmeno variabili di ambiente obbligatorie come PATH o HOME.

+2

beh ... sì, sono completamente d'accordo, ma questo è semplicemente usato come un esperimento. Non lo userei mai in qualcosa di simile a un programma utilizzabile. –

Problemi correlati