[C/asm] SIGSEGV solo senza gdb

Stato
Discussione chiusa ad ulteriori risposte.

imported_BlackOrWhite

Utente Silver
12 Giugno 2010
2
0
0
53
Non capisco perchè il codice seguente funziona solo sotto gdb.... mi sta sfuggendo qualcosa....
sono su un kernel 2.6.32,

il codice:
Codice:
#include <stdio.h>
#include <stdlib.h>

char string[]="/bin/sh;";

void main(void)
{
	asm(
			"push %0;"		 // string address
			"push $0x41414141;"	 // dummy
			"push $0x00167100;"	 // system address in libc
			"ret;"			 // call system()
			:
			:"r"(string)
	);
	exit(0);
}

quindi con gdb ho SIGSEGV dopo essere uscito dalla shell, che è quello che mi aspetto:

Codice:
matteo@Unix:~/Documenti/RetOriented-Exploit$ gdb a.out -q
Reading symbols from /home/matteo/Documenti/RetOriented-Exploit/a.out...done.
(gdb) run
Starting program: /home/matteo/Documenti/RetOriented-Exploit/a.out 
$ exit

Program received signal SIGSEGV, Segmentation fault.
0x00166eb6 in ?? () from /lib/tls/i686/cmov/libc.so.6

mentre se lo eseguo senza gdb... mi da subito SIGSEGV.... ma non dovrebe comunque eseguire system("/bin/sh") prima???

Codice:
matteo@Unix:~/Documenti/RetOriented-Exploit$ ./a.out
Segmentation fault

mi sono un attimo perso.... mi date una mano?

EDIT:
stesso problema anche con qualsiasi altra funzione della libc.... ad esempio ho provato con puts....
per ricavare l'indirizzo ho usato "print system" durante il debugging.

Forse succede perchè ho scritto tutto all'interno di una inline?? ma non credo.....
 
l'istruzione ret posta li, carica nel registro EIP ciò che è puntato da ESP al momento della sua esecuzione.
Quindi dato che ho "pushato" nello stack in quel dato ordine quelle WORD, esegue system().
(Tale indirizzo cambia a seconda della versione di libc e distribuzione che usi, se vuoi provare devi ricalcolarlo con gdb)

Ciò che non capisco è perchè senza gdb mi da picche. invece prima di andare in crash dovrebbe aprirmi la shell......

doveva essere un semplice test e ci ho perso già un giorno...... forse non è giornata..... :huh:
 
(quello lo avevo capito)non riesco a capire perchè hai fatto così.... quando la funzione di sistema eseguirà la ret andrà in segmentation fault (che però è quello che vuoi)...

vabbè comunque sei sicuro che la libreria sia statica e non dinamica, o meglio sei sicuro che non ci sia rilocazioni degli indirizzi delle funzioni? può darsi che senza gdb gli indirizzi siano diversi
 
Whivel ha detto:
(quello lo avevo capito)non riesco a capire perchè hai fatto così.... quando la funzione di sistema eseguirà la ret andrà in segmentation fault (che però è quello che vuoi)...

ok andrà in crash ma prima mi deve aprire la shell...

vabbè comunque sei sicuro che la libreria sia statica e non dinamica, o meglio sei sicuro che non ci sia rilocazioni degli indirizzi delle funzioni? può darsi che senza gdb gli indirizzi siano diversi

perchè con gdb dovrebbero cambiare le cose? Che io sappia dovrebbe essere uguale.
Nel senso, se io metto sotto debug un processo... quindi lo posso fare con ptrace() ad esempio... questa non credo andrà a cambiarmi strutture così importanti.... sbaglio?

come vedi:
from /lib/tls/i686/cmov/libc.so.6
le librerie sono dinamiche, posso provare a rifare con le librerie statiche più tardi.

grazie per l'aiuto.
 
il fatto è che forse, ma non sono sicuro, caricandolo con gdb (essendo un debugger a livello utente e non kernel), le librerie potrebbero essere caricate ad indirizzi diversi....

ripeto non sono sicuro
 
ok, ci sono.
ritornando alla questione, linkando staticamente non risolvo nulla se non che system viene inclusa nell'eseguibile...

quello che io intendo fare è riprodurre esattamente ciò che avviene in un ret-to-libc... tra l'altro questo esempio è molto semplice perchè c'è una sola chiamata.... ma non ho capito perchè ho quell'errore....
ho ripreso in mano anche alcuni libri.. ma la procedura che seguo è giusta dunque non sono ancora impazzito :matto:
 
(ret-to-libc, mi dovrò informare prima o poi)
se non sbaglio lanciandolo da gdb il segmentation fault viene intercettato e mostrato a video e il processo non termina, mentre se lo esegui normalmente questo termina subito.

detto questo non potrebbe essere che in entrambi i casi il codice viene eseguito, ma fai in tempo a vederlo solo sotto gdb perchè terminando il processo termina anche la shell?
 
Whivel ha detto:
(ret-to-libc, mi dovrò informare prima o poi)
se non sbaglio lanciandolo da gdb il segmentation fault viene intercettato e mostrato a video e il processo non termina, mentre se lo esegui normalmente questo termina subito.
detto questo non potrebbe essere che in entrambi i casi il codice viene eseguito, ma fai in tempo a vederlo solo sotto gdb perchè terminando il processo termina anche la shell?

ma la shell che chiamo è interattiva, il sistema si accorgerà di andare in SIGSEGV solo dopo aver eseguito la shell e avermela fatta usare.

cmq aspetta sono io che sono fuso ... dopo mangiato si ragiona meglio.... :)

su un kernel precedente (2.6.30) questi indirizzi cambiano ad ogni esecuzione quindi non funzionerà mai.... infatti nemmeno con gdb funziona.
sul kernel 2.6.32 non ho capito perchè questo non avviene, cmq anche qui sono random...
già perchè non ci ho pensato... :dodgy: ... bo....
resta un pò un mistro il perchè con gdb funziona.... ma ora lascio un attimo da parte questo problema....
funziona bene solo usando la entry di system nella sezione .plt,
ma perchè questa sia presente la funzione system deve essere usata all'interno del mio programma, in modo che venga linkata. A questo punto è molto facile perchè ci pensa una tabella a fare tutto...

naturalmente però il programma cambia:

Codice:
#include <stdio.h>
#include <stdlib.h>

void func() {
system("/bin/sh");
}

char string[]="/bin/sh";

int main(int argc, char**argv) {

	if(argc > 2) func();

	asm(
		"push %0;"
		"push $0x41414141;"
		"push $0x804830c;"
		"ret"
		:
		:"r"(string));
}

nota che non viene chiamata func(), io non passerò argomenti, è solo per avere system() nella sezione .plt ($0x804830c è la mia entry system@plt )
quindi:

Codice:
matteo@Moon:~/RETOR$ ./a.out
$ exit
Segmentation fault

però questo non è quello che voglio...
Sulle nuove distribuzioni credo sia necessario ricavare l'indirizzo di system() a runtime. Però per questo ci devo pensare un attimino, non è proprio semplice semplice...... :shocked:

a meno che qualcuno non abbia suggerimenti....un ret-to-libc non se po fa dal kernel 2.6.xx non ricordo esattamente..... infatti...
(http://www.phrack.org/issues.html?issue=59&id=9)

detto questo verifico la mia tesi,

Codice:
root@Moon:~/RETOR# echo 0 > /proc/sys/kernel/randomize_va_space

e infatti torna..... torniamo al mio programma:

Codice:
matteo@Moon:~/RETOR$ vim verfytest.c
#include <stdio.h>

char string[]="/bin/sh";

void main(void)
{
	asm(
		"push %0;"
		"push $0x41414141;"
		"push $0x00167100;"
                        "ret;"
		:
		:"r"(string)
	);
}
matteo@Moon:~/RETOR$ gcc verfytest.c -g
matteo@Moon:~/RETOR$ ./a.out
$ exit
Segmentation fault

scusa la perdita di tempo... certe volte il mio cervello mi fa gli scherzi...
detto questo c'è comunque il modo di calcolarlo a runtime, occorre usare un'altra tecnica... che è poi quella che stavo studiando... mizze se mi sono intortato.....

quello che ho notato è dal kernel 2.6.32 la rilcazione delle libc in modo casuale non è intuibile dalla analisi che si fa con gdb, infatti è per questo che sono stato tratto in inganno e mi sono dimenticato della randomizzazione delle libc.... infatti l'indirizzo sembra sempre essere (sul mio sistema) 0x00167100, mentre non era così. Cosa che sul 2.6.30 era visibile.
Comunque l'importante è che ci siamo arrivati, anche se lo sapevo già :blush:..
quindi obiettivo: "calcolare &system a runtime".... eh eh eh ....

se non altro questa discussione può essere stata comunque interessante e utile per rendere pubblica la mia bravura a inoltrarmi in problemi che non esistono.....
 
tra l'altro è una spiegazione simile a quella che avevo dato io al secondo post....

su windows esiste l'api GetProcAddress che si trova in kernel32.dll.
credo che su linux esista una cosa simile, ma se fosse randomizzata pure quello, allora sarebbe più complicato.

Di più non posso dire, perchè non conosco il formato elf e quindi nemmeno come funziona la rilocazione del codice
 
già GetProcAddress() ritorna l'indirizzo della funzione, quindi riferisce al segmento .text della libreria o programma che sia.
Su Windows le cosa sono un pò diverse, non conosco windows quanto linux ma sul primo quello che viene rilocato in posizioni random sono solo le DLL. Questo però ad ogni riavvio del sistema.
 
avevo dimenticato il post....
tanto per completezza nel mio ambiente system calcolata a runtime:

Codice:
#include <stdio.h>

char string[]="/bin/sh";

void main(void)
{
        asm(
                "push %0;"
                "push $0x41414141;"
                "movl $0x8049ffc, %%edi;"
                "movl (%%edi), %%eax;"
                "subl $0x14b5c0, %%eax;"
                "push %%eax;"
                "ret;"
                :
                :"r"(string)
        );
}
 
Stato
Discussione chiusa ad ulteriori risposte.