Sovrascrivere un indirizzo di memoria

tranquillo, significa che sono interessato al topic, e quindi mi ritrovero' le risposte automaticamente in alto a destra, sezione Replies.
Del topic in se non so nulla :slight_smile:

DarkCoffee:
Sto lavorando ad un progetto all'università.
L'idea è di attaccare il codice sulla board in modo da gestire il flusso di memoria.

More informations please

Credo che ci sia alla base un concetto errato.
Un conto è far girare un programma su un computer con un sistema operativo che sovrintende al controllo degli accessi alla memoria, un conto è far girare un programma su un microcontrollore dove non c'è sistema operativo e dove il controllo sulla memoria lo deve fare l'utente stesso in fase di stesura di codice.

Se tu su un computer crei un array e poi cerchi di andare fuori dai suoi limiti credo (ma non lo so con certezza non essendo un sistemista) che sia lo stesso sistema operativo che vede accedere ad un'area di memoria non assegnata a quel programma a bloccare il software, e poi quindi generare l'errore di overflow.
Su un microcontrollore, invece, puoi benissimo accedere al di fuori di un array. Non riceverai nessun tipo di errore perché non c'è nessuno a dirti che hai fatto una cosa che non potevi fare. Te ne potresti accorgere, però, per via di effetti indesiderati che la tua azione potrebbe provocare. Tu sai che un microcontrollore come l'Atmel Atmega328P lavora con architettura Harvard, quindi ha la memoria del programma (Flash) separata dalla memoria dei dati (SRAM). In questa ultima memoria il micro crea le variabili del programma, tiene l'heap per l'allocazione dinamica delle risorse e crea lo stack. Accedendo al di fuori dei limiti di un array potresti semplicemente andare a leggere/scrivere in un'area di SRAM inutilizzata che però contiene dati precedentemente salvati lì. Scrivendoci sopra non avresti nessun problema, leggendoci potresti tirare fuori informazioni senza senso che potrebbero alterare il tuo programma. Oppure potresti anche andare a scrivere su parti usate dal resto del programma oppure dalla stessa CPU, ad esempio potresti scrivere su una porzione dello stack! Pensa se in quel momento il chip avesse salvato i registri per una chiamata ad una ISR, tu andresti ad alterare lo stato salvato del micro. Al ripristino, le conseguenze potrebbero essere qualunque, anche un improvviso blocco e reset.

A me è capitato l'altro giorno. Lavoravo ad un progetto molto complesso e leggevo/scrivere diverse decine di dati dalla EEPROM . Mi sono accorto che all'avvio il progetto funzionanva come doveva, mentre al successivo reset perdevo l'uso di una fila di pulsantini di una tastierina 4x4 collegata :wink: Alla fine ho capito che al primo avvio scrivevo le info sulla EEPROM e contemporaneamente caricavo i dati in un array, mentre al reset seguente andavo a caricare i dati in un array al di fuori dei suoi limiti, ed il chip si comportava nel modo che ti ho descritto :wink:

Grazie per l'aiuto!

Il progetto su cui sto lavorando è far un attacco sulla board (precisamente una atmega2560), utilizzando proprio il buffer overflow.
Quello che devo fare è sovrascrivere lo stack fino al raggiungimento del return address e quindi sovrascriverlo con un puntatore.
Secondo te è possibile farlo?
Il return address dovrebbe essere salvato nello stack, come i dati del buffer che vado a scrivere, giusto?

ma vista la struttura della ram basta scrivere uno sketch che la riempie ed hai il tuo bel crash :slight_smile: perche' va a sovrascrivere lo stack

perchè quando sovrascrivo il return address con un puntatore ad un altro punto della memoria posso far partire una parte del programma che non era previsto.

ok, alzo le mani allora, non e' il mio campo, Leo di certo sapra' risponderti
ma e' a titolo di studio ? credo stiamo parlando di una specie di virus ? integri nello sketch un qualcosa e solo tu poi saprai come arrivare a farlo partire ?

Si si è a titolo di studio, esattamente per la tesi =(
Comunque grazie per cercarmi di aiutare!

Uhm.. non credo che tu possa fare quello che vuoi. Non sono un esperto come mi dipinge Testato, però nell'Atmega le variabili statiche sono salvate nella prima parte della SRAM mentre lo stack è creato a partire dall'ultima locazione di SRAM a crescere verso il basso.
In mezzo c'è l'heap e l'area che raccoglie le variabili non inizializzate del programma. E la memoria libera.

sram.jpeg

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: