Sovrascrivere un indirizzo di memoria

Ma se creo una funzione mettiamo caso in c, senza pensare all'arduino language, in questo modo:

getInput(){
  char buff[8];
  getc(buff);
  putc(buff);
}

int main(){
  getInput();
  return 0;
}

la memoria sarà buff(8 byte), indirizzo del fp(2 byte), return address(2 byte). Quindi se sovrascrivo il buff mettendo 10caratteri da tastiera dovrei arrivare al return address, giusto?
Ora, vorrei applicarlo usando l'arduino language o comunque il c dentro un programmino arduino per la mia atmega2560.

Solo una precisazione, non esiste un "Arduino language".
In uno sketch Arduino si scrive in C o C++ in quanto il tutto viene compilato dal avr-gcc (compilatore gnu c per gli avr).
Arduino ha dietro un framework chiamato Wire, un insieme di librerie e un main che "nasconde" la solita struttura main() di un qualsiasi programma C e che richiama una volta la setup() e in un ciclo infinito la loop().
I sorgenti di questi codici sono nelle cartelle dell'IDE (....\arduino-IDE\hardware\arduino\cores\arduino). Ci troverai anche un bel main.c

#include <Arduino.h>
int main(void)
{  init();
#if defined(USBCON)
	USBDevice.attach();
#endif
	setup();
   	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}
	return 0;
}

Hai partecipato a questa discussione (vedo un Darkcoffee)?

Sembra l'unica cosa che si trovi in internet sull'argomento

E poi mi sembra che il grande @Gammon del forum ti ha trovato la soluzione :
http://forum.arduino.cc/index.php?topic=182559.msg1356108#msg1356108

Però quel che non mi è chiaro è la motivazione su un Atmel. Il codice che viene iniettato è comunque nel tuo sketch.
Di solito un attacco del genere su PC viene fatto da un codice sul codice di un altro programma.
Al limite mi viene in mente un attacco del genere ad un Arduino su cui gira un server (Ethernet library) e attraverso http gli passi richieste anomale.

nid69ita:
Solo una precisazione, non esiste un "Arduino language".
In uno sketch Arduino si scrive in C o C++ in quanto il tutto viene compilato dal avr-gcc (compilatore gnu c per gli avr).
Arduino ha dietro un framework chiamato Wire, un insieme di librerie e un main che "nasconde" la solita struttura main() di un qualsiasi programma C e che richiama una volta la setup() e in un ciclo infinito la loop().
I sorgenti di questi codici sono nelle cartelle dell'IDE (....\arduino-IDE\hardware\arduino\cores\arduino). Ci troverai anche un bel main.c

#include <Arduino.h>

int main(void)
{  init();
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
  for (;:wink: {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}

mmm, sono un po' confusa.
Dalla pagina di arduino, ho letto questo

Can I program the Arduino board in C?
In fact, you already are; the Arduino language is merely a set of C/C++ functions that can be called from your code. Your sketch undergoes minor changes (e.g. automatic generation of function prototypes) and then is passed directly to a C/C++ compiler (avr-g++). All standard C and C++ constructs supported by avr-g++ should work in Arduino. For more details, see the page on the Arduino build process.

Mentre qui c'è una serie di funzioni, strutture e variabili: Arduino - Home
Inoltre quando ho voluto usere printf e scanf ho dovuto configurare l'uart e aprire stdout e stdin.

nid69ita:
Hai partecipato a questa discussione (vedo un Darkcoffee)?
atmega - Exploiting stack buffer overflows on an Arduino - Electrical Engineering Stack Exchange
Sembra l'unica cosa che si trovi in internet sull'argomento

E poi mi sembra che il grande @Gammon del forum ti ha trovato la soluzione :
Handle memory - #39 by nickgammon - Programming Questions - Arduino Forum

Però quel che non mi è chiaro è la motivazione su un Atmel. Il codice che viene iniettato è comunque nel tuo sketch.
Di solito un attacco del genere su PC viene fatto da un codice sul codice di un altro programma.
Al limite mi viene in mente un attacco del genere ad un Arduino su cui gira un server (Ethernet library) e attraverso http gli passi richieste anomale.

Si, la discussione su electronics.stackexchange l'ho aperta io. Le risposte sono stati interessanti, il paper che mi ha proposto Warren Young l'avevo già letto. Il problema è che ho bisogno di trovare la strada giusta, perchè non riesco, in modo pratico, ad andare avanti.
E' vero, Gammon mi sta aiutando, è molto bravo e spiega bene.
Spero che con questo forum, molto preparato, riesco ad uscire da questo problema.

Inizialmente sto creando io la vulnerabilità, dopo che questo primo esperimento è stato fatto, dovrei cercarlo di applicarlo ad un programma che mi hanno dato loro. Ed infatti, proprio in questo programma c'è l'invio di messaggi tramite tcp. Quindi l'idea è quella di mandare un pacchetto con una grandezza giusta e con il giusto payload.

ho provato anche io per curiosita' il codice di Gammon, ed anche a me non funziona sulla mega, probabilmente funziona solo sul 328P ?

qualcuno mi spiega come funziona il codice di Gammon ? :cold_sweat:

unsigned int * stack = (unsigned int *) SP;
  stack [1] = (unsigned int) bar;

grazie

@Testato: da quel che dice @gammon SP è un variabile che ritorna indirizzo dello stack (messo a disposizione non sò da chi, forse il compilatore). Assegna questo valore a variabile stack. Poi con stack[1] va a scrivere oltre al puntatore di una cella. e ci scrive indirizzo della funzione bar. In teoria all'uscita della funzione loop() non dovrebbe tornare al chiamante (la main) ma alla bar() stampando il msg e fermandosi (non siamo più nella main)
Invece di usare array uoi anche scrivere:

*(stack+1) = (unsigned int) bar;

A me funziona su Arduino Uno R3 con IDE 1.0.5.
NON funziona su Mega :frowning:

Come dice alla prima pagina, è C++. Poi alla reference si "parla" di linguaggio Arduino per semplicità , secondo me.

DarkCoffee:
Mentre qui c'è una serie di funzioni, strutture e variabili: Arduino - Home
Inoltre quando ho voluto usere printf e scanf ho dovuto configurare l'uart e aprire stdout e stdin.

Ma tu non usi l'IDE Arduino ma Atmel Studio. Arduino IDE magicamente mette insieme le librerie e il core senza doverle includere nel progetto. Se usi il IDE Arduino e metti il verbose vedi tutti le cose automatiche che fa di sotto Arduino. Mi sembra che alcune librerie le capisce da quali include tu metti. Credo che l'IDE analizzi anche il sorgente per capire quali librerie includere.

In realtà ho iniziato ad usare Atmel Studio perchè volevo fare il debugging per capire l'indirizzi di memoria. Ho dovuto settarlo aggiuggendoci tutte le librerie di Arduino per linkarle in compilazione. In più ho aggiunto anche il core di arduino.
Ma alla fine, se riesco a capire come sovrascrivere il return address senza Atmel Studio, per me va bene lo stesso.

A me l'esempio funziona. Se togli il while() dalla funzione bar() non capisco perchè ma su Monitor Seriale vedi solo una y con puntini sopra
(non funziona su Mega!!!)

Ho provato a anche a pacioccare un pò ma funziona ancora:

void setup ()
{ delay(2000);
  Serial.begin(9600);
}  // end of setup

void bar ()
{ Serial.println ("hacked!");
  while (true);  
}

void mybar()
{ bar();
  while (true);  
}
  
void foo ()
{ Serial.println ("in foo.");
  // corrupt return address
  unsigned int * stack = (unsigned int *) SP;
  *(stack+1) = (unsigned int) mybar;
}
  
void loop ()
{ foo ();
}  // end of loop

Ci sono alcune costanti predefinite in alcuni file della toolchain che il compilatore, quando le trova, le sostituisce con determinati indirizzi. Ad esempio SP è lo Stack Pointer. Ci sono valori generici per tutti i chip ed altri specifici per singolo micro. Aprite la cartella della toolchain in /avr/avr/include/avr.
Common.h ad esempio contiene gli indirizzi dello stack SP, poi c'è iom328p.h che contiene le cose specifiche dell'Atmega328P e iom2560.h che contiene quelle dell'ATmega2560.

Grazie per le info @Leo :slight_smile:

Una domanda, dato che non ho la Mega.
Cos'è che fa, esattamente, lo sketch di Gammon su questa scheda? Che output da?

leo72:
Una domanda, dato che non ho la Mega.
Cos'è che fa, esattamente, lo sketch di Gammon su questa scheda? Che output da?

in foo.
hacked!

Il codice di gammon a me funziona solo su Uno. non su Mega.

Appunto chiedevo l'output della Mega :sweat_smile: :sweat_smile:

leo72:
Una domanda, dato che non ho la Mega.
Cos'è che fa, esattamente, lo sketch di Gammon su questa scheda? Che output da?

:stuck_out_tongue_closed_eyes:

sulla mega stampa questo all'infinito

in foo.
in foo.

ma probabilmente e' solo diverso il comando SP, forse e' presente nei file che hai suggerito

x nid, grazie della spiegazione, quindi con l'asterisco stiamo dicendo che vogliamo lavorare con i puntatori, e gli indirizzi delle celle di memoria li si assegnano come normali variabili. mai usati e mai li usero' credo, a prima vista pensavo fosse una moltiplicazione :slight_smile:

a conferma che si sta pasticciando, almeno sulla mega, quando apro la seriale si blocca il micro, devo resettare per vederla partire a scrivere (ho la rxtx modificata, quella che non resetta all'apertura del serial monitor, chi usa la normale non si accorge di nulla)

Forse ciò dipende dal fatto che per indirizzare 128 o più kB di Flash si deve usare un terzo byte, se non ricordo male.
Forse manipolare lo stack cambiando solo il valore del PC (Program Counter) lì memorizzato non è sufficiente. Forse (continuo con le ipotesi) il compilatore salva anche questo terzo byte, che andrebbe manipolato. O forse si va a cambiare lui e non il PC. Chissà.
Andrebbe disassemblato un programma per capire cosa viene salvato durante il alto ad una subroutine.

nid69ita:
Poi con stack[1] va a scrivere oltre al puntatore di una cella. e ci scrive indirizzo della funzione bar.

spetta pero' dimmi se ho capito, dopo l'istruzione

unsigned int * stack = (unsigned int *) SP;

il micro va sempre a leggere la cella di memoria successiva ? e' questo il discorso del Return di cui si parla ? ad ogni istruzione
c'e' un return (un enter diciamo) che non si vede da codice ?
perche' il succo della questione e' proprio "Chi" e "Quando" va a leggere ed eseguire l'istruzione che c'e' in stack[1] ?

Ho trovato conferma nel datasheet. Il PC dell'Atmega2560 è di 3 byte (è scritto chiaramente al cap. 7.8.1 pag. 20):

the Program Counter (three bytes)

Provate a giocare con l'istruzione:

*(stack+1) = (unsigned int) mybar;

Prova a sommare 2.

mettendo il 2 stampa sempre solo in foo. pero' con una differenza, con 1 stampa una volta al secondo, come se ci fosse un delay, mentre con 2 stampa velocissimo