// Titolo: Stack in azione v0.2
// Autore: Saio
// Data: Marzo 2005

////////////
// PAG.04 //
////////////


----------------------------------
INDICE PAG.01 PAG.02 PAG.03 PAG.04
----------------------------------

///////////////ECCEZIONI///////////////////
////PROPRIETA' DI LEGAMENTO LEG1 E LEG2////
///////////APPOGGIO A DESTRA APDX//////////


// L'obiettivo e' capire quando andremo in S.F. in base ai buffer[] che abbiamo.
//
// Ad esclusione di buffer[1], buffer[2], buffer[4], buffer[8] (che si
// definiscono percio'
ECCEZIONI) vale la regola per cui sullo stack si crea
// uno spazio pari ad:
/////////////////////////////////////////////////////////////////////////////
// S = (8) + [16,32,48,...] + [16,32,48,...] + [16,32,48,...] + [16,32,48,...] + ....
/////////////////////////////////////////////////////////////////////////////
// In questa regola generale si considera che lo spazio viene allocato
// di 16 byte in 16 byte con l'aggiunta di (8) byte nella parte adiacente al SFP.
// Una volta riempito lo spazio S si andra’ in S.F. con l’aggiunta di un carattere.
// Si ha S.F. quando si alloca un carattere in SFP.
// Verifichiamo qui un esempio della regola generale in cui NON compaiono eccezioni:

-----------bof-ex1.c---------
#include <stdio.h>
int main() {
char buff5[13];
char buff4[41];
char buff3[25];
char buff2[23];
char buff1[42];
gets(buff1);
}
// Utilizziamo la regola generale:
// buff5[13] occupa 16 byte
// buff4[41] occupa 48 byte
// buff3[25] occupa 32 byte
// buff2[23] occupa 32 byte
// buff1[42] occupa 48 byte
// Questi buffer, nello stack, si allocano da indirizzi maggiori a indirizzi minori,
// cioe' prima buff5, poi buff4, poi buff3, poi buff2, poi buff1.
// => S = [48]+[32]+[32]+[48]+[16]+(8)=176 = 0xb8 in esadecimale
// In questo caso, visto che non ci sono eccezioni possiamo verificare che
[root@localhost saio]# ./bof-ex1
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaxxxxxx
// dopo 176 caratteri non si va in S.F.
[root@localhost saio]# ./bof-ex1
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaxxxxxxx
// dopo 177 si va in S.F.
Segmentation fault (core dumped)

// Inoltre, in assenza di eccezioni, S lo ritroviamo pari pari nel disassemblato
[root@localhost saio]# gdb bof-ex1
(gdb) disassemble main
Dump of assembler code for function main:
0x80481e0 <main>: push %ebp
0x80481e1 <main+1>: mov %esp,%ebp
0x80481e3 <main+3>: sub $0xb8,%esp
<------- S
0x80481e9 <main+9>: sub $0xc,%esp
0x80481ec <main+12>: lea 0xffffff48(%ebp),%eax
0x80481f2 <main+18>: push %eax
0x80481f3 <main+19>: call 0x80486b0 <_IO_gets>
0x80481f8 <main+24>: add $0x10,%esp
0x80481fb <main+27>: mov %ebp,%esp
0x80481fd <main+29>: pop %ebp
0x80481fe <main+30>: ret
0x80481ff <main+31>: nop
End of assembler dump.
(gdb) q
[root@localhost saio]#

////////////////////// ECCEZIONI ://///////////////////
// Valutiamo ora le eccezioni

-----------bof-p1.c---------
#include <stdio.h>
int main() {
char buff1[1];
gets(buff1);
}
[root@localhost saio]# ./bof-p1
a
[root@localhost saio]# ./bof-p1
aa
Segmentation fault (core dumped)
// =>buff1[1] ‘singolarmente’ occupa 1 byte

-----------bof-p2.c---------
#include <stdio.h>
int main() {
char buff1[2];
gets(buff1);
}
[root@localhost saio]# ./bof-p2
aa
[root@localhost saio]# ./bof-p2
aaa
Segmentation fault (core dumped)
// =>buff1[2] ‘singolarmente’ occupa 2 byte

-----------bof-p3.c---------
#include <stdio.h>
int main() {
char buff1[3];
gets(buff1);

}
[root@localhost saio]# ./bof-p3
wwwwwwwwwwdddddfffffrrrr
[root@localhost saio]# ./bof-p3
rrrrrrrrrrrrrrrrrrrrrrrrg
Segmentation fault (core dumped)
// =>buff1[3] occupa 16 byte, cioe’ un char buffer[3] NON E’ UNA ECCEZIONE,
// un char buffer[3] occupa lo STESSO SPAZIO di un char buffer[16]
// Quindi rientra nella regola generale per cui
// S = [16]+(8)=24 => si va in S.F. al 25 carattere

-------------bof-p4.c-----------

#include <stdio.h>
int main() {
char buff1[4];
gets(buff1);
}
[root@localhost saio]# ./bof-p4
wwww
[root@localhost saio]# ./bof-p4
rrrrr
Segmentation fault (core dumped)
// =>buff1[4] occupa ‘singolarmente’ 4 byte

-------------bof-p8.c-----------
#include <stdio.h>
int main() {
char buff1[8];
gets(buff1);
}
[root@localhost saio]# ./bof-p8
wwwwwwww
[root@localhost saio]# ./bof-p8
rrrrrrrrr
Segmentation fault (core dumped)
// =>buff1[8] occupa ‘singolarmente’ 8 byte
// continuando otteniamo la seguente tabella riassuntiva
//
/////////////////////////////////////////////////////////
///////////////////TABELLA RIASSUNTIVA///////////////////
/////////////////////////////////////////////////////////
/////////////////////////...Validita'..//////////////////
/////////////////////////....regola....//////////////////
/////////////////////////////////////////////////////////
buff1[1] occupa .1 byte .......NO......
buff1[2] occupa .2 byte .......NO......
buff1[3] occupa 16 byte ............... => s=[16]+(8)=24 => S.F. al 25 carat.
buff1[4] occupa .4 byte .......NO......
buff1[5] occupa 16 byte ............... => s=[16]+(8)=24 => S.F. al 25 carat.
buff1[6] occupa 16 byte ............... => s=[16]+(8)=24 => S.F. al 25 carat.
buff1[7] occupa 16 byte ............... => s=[16]+(8)=24 => S.F. al 25 carat.
buff1[8] occupa .8 byte .......NO......
buff1[9] occupa 16 byte ............... => s=[16]+(8)=24 => S.F. al 25 carat.
buff1[10] occupa 16 byte .............. => s=[16]+(8)=24 => S.F. al 25 carat.
buff1[11] occupa 16 byte .............. => s=[16]+(8)=24 => S.F. al 25 carat.
buff1[12] occupa 16 byte .............. => s=[16]+(8)=24 => S.F. al 25 carat.
buff1[13] occupa 16 byte .............. => s=[16]+(8)=24 => S.F. al 25 carat.
buff1[14] occupa 16 byte .............. => s=[16]+(8)=24 => S.F. al 25 carat.
buff1[15] occupa 16 byte .............. => s=[16]+(8)=24 => S.F. al 25 carat.
buff1[16] occupa 16 byte .............. => s=[16]+(8)=24 => S.F. al 25 carat.
buff1[17] occupa 32 byte .............. => s=[32]+(8)=40 => S.F. al 41 carat.
....................................... => s=[32]+(8)=40 => S.F. al 41 carat.
buff1[32] occupa 32 byte .............. => s=[32]+(8)=40 => S.F. al 41 carat.
buff1[33] occupa 48 byte .............. => s=[48]+(8)=56 => S.F. al 57 carat.
....................................... => s=[48]+(8)=56 => S.F. al 57 carat.
buff1[48] occupa 48 byte .............. => s=[48]+(8)=56 => S.F. al 57 carat.
buff1[49] occupa 64 byte .............. => s=[64]+(8)=72 => S.F. al 73 carat.
....................................... => s=[64]+(8)=72 => S.F. al 73 carat.
buff1[64] occupa 64 byte .............. => s=[64]+(8)=72 => S.F. al 73 carat.

////// PROPRIETA DI LEGAMENTO (LEG1, LEG2) E SPOSTAMENTO A DESTRA (SPDX) ///////

//
// Analizziamo cosa accade mischiando eccezioni e non eccezioni:
// Se utilizziamo buffer[1] insieme a buffer[3] osserviamo che il buffer[1]
// occupa 16 byte comunque, infatti esso NON e' accoppiato con nessun'altra
// eccezione, per cui se si utilizza una eccezione singola in mezzo ad altri
// buffer che non lo sono, l'eccezione occupa sempre 16 byte.
-------------bof-w1.c-----------
#include <stdio.h>
int main() {
char buff3[3];
char buff2[1];
char buff1[3];
gets(buff1);
}
[root@localhost saio]# ./bof-w1
wwwwwwwwwwxxxxxxxxxxcccccccccceeeeeeeeeevvvvvvvvvvssssss
[root@localhost saio]# ./bof-w1
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrre
Segmentation fault (core dumped)


// Proprieta' di legamento LEG1:
// in questo caso l'eccezione non e' LEGATA a nessun altra eccezione,
// per cui occupa 16 byte come un buffer[5], un buffer[13] o buffer[16].
// Vediamo altri esempi che comprendono eccezioni NON LEGATE, per cui
// in tal caso tutte le eccezioni occupano 16 byte come le non eccezioni.
// Quando si parla di LEG1 si intende la proprieta' delle eccezioni
// a non comportarsi come tali se NON LEGATE ad altre eccezioni.
// Vediamo un tipico esempio in cui si applica LEG1:

-------------bof-01leg1.c-----------
#include <stdio.h>
int main() {
char buff6[345];
char buff5[1];
char buff4[34];
char buff3[1];
char buff2[39];
char buff1[123];
gets(buff1);
}


//Verifichiamo disassemblando:
[root@localhost saio]# gdb bof-01leg1
GNU gdb 5.1.1
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-mandrake-linux"...
(gdb) disassemble main
Dump of assembler code for function main:
0x80481e0 <main>: push %ebp
0x80481e1 <main+1>: mov %esp,%ebp
0x80481e3 <main+3>: sub $0x
268 ,%esp <---------- COME VOLEVAMO DIMOSTRARE
0x80481e9 <main+9>: sub $0xc,%esp
0x80481ec <main+12>: lea 0xfffffd98(%ebp),%eax
0x80481f2 <main+18>: push %eax
0x80481f3 <main+19>: call 0x80486b0 <_IO_gets>
0x80481f8 <main+24>: add $0x10,%esp
0x80481fb <main+27>: mov %ebp,%esp
0x80481fd <main+29>: pop %ebp
0x80481fe <main+30>: ret
0x80481ff <main+31>: nop
End of asembler dump.
(gdb)

// Proprieta' di legamento LEG2:
// Quando due eccezioni sono contigue, si accoppiano fra loro sfruttando la stessa
// porzione di spazio sullo stack: questa e' la proprieta' di legamento LEG2.

-------------bof-02leg2.c-----------
#include <stdio.h>
int main() {
char buff6[345];
char buff5[1];
char buff4[1];
char buff3[34];
char buff2[39];
char buff1[123];
gets(buff1);
}


// visto che ormai siamo abituati alla schematizzazione grafica per semplicita'
// utilizzeremo principalmente quella.


// Per fare un po' di pratica ho messo altri quattro esempi:


// Osservando attentamente tutti gli esempi riportati precedentemente,
// si e' evitato accuratamente di inserire delle eccezioni in cima
// allo stack (a sinistra negli schemi).
// Analizziamo il caso in cui in cima allo stack c'e' l'eccezione [1]:
// in questo caso si ha uno spostamento a destra durante l'inserimento dei
// buffer (proprieta' SPDX) in presenza di varie eccezioni [1].
// In questo caso prima viene applicata APDX a tutte le eccezioni.
// Vediamo alcuni esempi:


/////////////////////////////////////////////
///////////////CONCLUSIONI///////////////////
/////////////////////////////////////////////


// Quando ci sono in cima allo stack le eccezini [2], [4] e [8] si ha sempre
// uno spostamento a destra, il quale pero' muta se vi sono piu' eccezioni affiancate.
// A rendere ancora meno chiara la situazione si segnala che in presenza di sole
// eccezioni le cose si complicano ulteriormente, per cui la linea da seguire e'
// la seguente: Evitare di inserire eccezioni, in questo caso infatti la
// regola generale varra' SEMPRE.
// Inoltre compilando con l'opzione -mpreferred-stack-boundary=2 abbiamo addirittura
// l'assenza della costante +(8) che affianca il SFP.
// In conclusione con quest'ultimo accorgimento sapremo prevedere ad occhio quando
// andremo in Segmentation Fault.
//
////////////////////////////////////////////////////////////////////////////
//
// S = [16,32,48,...] + [16,32,48,...] + [16,32,48,...] + [16,32,48,...] + .
//
////////////////////////////////////////////////////////////////////////////
//..........................................................................
// S.F. si ha per S + 1 carattere ........ => S.F. = S + 1 .................
//..........................................................................
////////////////////////////////////////////////////////////////////////////

// Saluti
// Saio


----------------------------------
INDICE PAG.01 PAG.02 PAG.03 PAG.04
----------------------------------