Forum: Mikrocontroller und Digitale Elektronik Was tun wenn der Stack überschrieben wird?


von Lernwilliger (Gast)


Lesenswert?

Guten Morgen,

folgende Situation: innerhalb einer mehrfach verschachtelten
Aufrufhierachie wird ein memcpy (innerhalb von Funktion7) aufgerufen.
Es handelt sich dabei um eine Socket-Funktion. In den Einstellungen
des GCC habe ich -fstack-protector-all übergeben. Der Stackframe ist
zunächst wie folgt:

-000|Funktion7
-001|Funktion6
-002|Funktion5
-003|Funktion4
-004|Funktion3
-005|Funktion2
-006|Funktion1
-007|Funktion1
 ---|end of frame

Nach dem Aufruf der memcpy-Funktion sind nur noch die Einträge von
Funktion7 und Funktion6 im Debugger sichtbar. Nach dem return in der
Funktion6 schlägt wie zu erwarten die vorher Stack-Protection des GCC 
zu.

Meine Frage ist jetzt: wie geht man generell an solche Probleme ran? Ich
kann genau sehen an welcher Stelle das memcpy schief geht weil ich den 
RAM
mit einem bestimmten pattern vorinitialisiere.

Für ein paar Anregungen wäre ich sehr dankbar.

Schönen Gruß!

von Lernwilliger (Gast)


Lesenswert?

Als kleine Ergänzung: Unter [1] ist die Beschreibung des Stack 
Protectors. Das Ganze spielt sich auf einem Cortex A9 ab.

[1] http://wiki.osdev.org/Stack_Smashing_Protector

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

Moegliche Abhilfen:
- mehr Stack vorsehen
- kein grossen Variaben in Funktionen definieren
- keine rekursiven Funktionen
- mehr Speicher vorsehen
- das ganze Konzept ueberdenken

von Oliver S. (oliverso)


Lesenswert?

Du solltest allerdings schon klären, ob das ein Programmierfehler 
deinerseits ist, oder der Stack einfach zu klein ist.

Oliver

von Christian B. (casandro)


Lesenswert?

Da gibts einen schönen Artikel der das alles erklärt und Ideen gibt:
http://insecure.org/stf/smashstack.html

"Smashing The Stack For Fun And Profit"

Man kann damit relativ viele schöne Sachen machen. Idealerweise 
überschreibst Du Deinen Stack mit Benutzereingaben, das macht mehr Spaß.

von fop (Gast)


Lesenswert?

Hm, überprüfe doch mal Zieladresse und Länge, die Du an memcpy 
übergibst. Entweder hast Du zu viel auf den Stack gelegt, so dass er in 
den Bereich einer Variablen gelaufen ist, die Du mit memcpy beschreibst, 
oder Du schreibst an eine völlig falsche Adresse bzw. fängst an der 
richtigen Adresse an, aber schreibst mehr als das was dort hin passt.
Ein weiterer Klassiker fällt in die Rubrik "use after free" : Du hast 
eine lokale Variable und einen Zeiger, der auf sie zeigt. Nachdem die 
Variable längst Geschichte ist, weil die Funktion, zu der sie gehört 
beendet ist, greifst Du über den Zeiger auf ihren Ex-Speicherbereich zu.
Compiler legen meist lokale Variablen auf dem Stack an, deshalb liegt 
die Vermutung nahe, dass in deren Zusammenhang etwas schief läuft.

von Volle (Gast)


Lesenswert?

eine mögliches Fehreszenario:

deine memcpy  Zielvariabel liegt vermutlich auf dem Stack
-> nicht gut
+
die Bytegröße von memcpy stimmt nicht mit dem Ziel überein
-> echter  tödlicher Fehler

von Markus F. (mfro)


Lesenswert?

Lernwilliger schrieb:
> Nach dem Aufruf der memcpy-Funktion sind nur noch die Einträge von
> Funktion7 und Funktion6 im Debugger sichtbar.

Dann ist das kein Stacküberlauf.

Der Stack "wächst" normalerweise vom Speicherende hin zu niedrigeren 
Adressen - ein Stacküberlauf wäre dann der Fall, wenn er in die .bss- 
oder .data-Section hineinwachsen und dort Unsinn anstellen würde.

Nachdem hier aber offensichtlich der Stack "von oben her" überschrieben 
wird, hast Du mit ziemlicher Sicherheit einen simplen Programmierfehler 
(ein "&" z.B., wo keins hingehört).

von Lernwilliger (Gast)


Lesenswert?

Vielen Dank schonmal für die ganzen Denkanstöße!

Uwe B. schrieb:
> - mehr Stack vorsehen
> - kein grossen Variaben in Funktionen definieren
> - keine rekursiven Funktionen
> - mehr Speicher vorsehen
> - das ganze Konzept ueberdenken
Ich arbeite mit einem Echtzeitsystem. Die Stacks für die Threads sind 
alle zu maximal 25% ausgelastet. Due Funktion ist eine 
Netzwerk-Socket-Funktion eines anderen Anbieters die in anderen 
Situationen auch schon funktionierte.

Oliver S. schrieb:
> Du solltest allerdings schon klären, ob das ein Programmierfehler
> deinerseits ist, oder der Stack einfach zu klein ist.
Klar! Mir fehlt nur einfach die Routine wie man an sowas strukturiert 
und zielführend rangeht...

Christian B. schrieb:
> Da gibts einen schönen Artikel der das alles erklärt und Ideen gibt:
> http://insecure.org/stf/smashstack.html
Danke, werde ich mir durchlesen.

fop schrieb:
> Hm, überprüfe doch mal Zieladresse und Länge, die Du an memcpy
> übergibst.
Volle schrieb:
> die Bytegröße von memcpy stimmt nicht mit dem Ziel überein
Wenn ich den Speicher der Zieladresse ansehe, dann sehe ich vier Byte 0 
und danach das MagicPattern. Die übergebene Länge, ermittelt mit sizeof 
ist 132... Autsch. Ich befürchte es gibt konkurrierende Definitionen der 
Struktur die ich kopieren möchtes (fd_set), einmal vom Netzwerkstack und 
einmal vom Betriebssystem.

Volle schrieb:
> deine memcpy  Zielvariabel liegt vermutlich auf dem Stack
> -> nicht gut
Wie genau kann ich das denn feststellen?

Vielen Dank nochmal!

von Lernwilliger (Gast)


Lesenswert?

Markus F. schrieb:
> Dann ist das kein Stacküberlauf.
Stack-Überlauf habe ich es deswegen genannt, weil eben der Stack 
Protector zuschlägt. Ich kann auch im Debugger sehen, dass das Magic 
Pattern überschrieben wird...

von Kirsch (Gast)


Lesenswert?

Dann ist es eher ein BufferOverflow eines auf dem Stack abgelegten 
Array, oder ein use after free eine Stackvariable

von Hans-Georg L. (h-g-l)


Lesenswert?

Lernwilliger schrieb:
> Due Funktion ist eine
> Netzwerk-Socket-Funktion eines anderen Anbieters die in anderen
> Situationen auch schon funktionierte.
>
...
>Die übergebene Länge, ermittelt mit sizeof
> ist 132... Autsch. Ich befürchte es gibt konkurrierende Definitionen der
> Struktur die ich kopieren möchtes (fd_set), einmal vom Netzwerkstack und
> einmal vom Betriebssystem.
>

Oder die Struktur ist bei dem anderen Anbieter mit einem anderen 
Alignment wie bei dir compiliert.

von Carl D. (jcw2)


Lesenswert?

Mit was wurden das memcpy() gefüttert?
Ist die Zieladresse vielleicht eine lokale Pointervariable, von der dann 
versehentlich die Adresse statt dem Inhalt übergeben wurde. So wäre dann 
der Stack das Ziel und damit kaputt sobald die Kopierlänge > 
sizeof(void*).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.