DLL-Programmierung: Speicherüberlauf - was ist das? Verhindern?

philippo

Mitglied
Hallo,

vorneweg: ich bin leider noch Anfänger was C++ angeht. Ich arbeite gerade an einer DLL, die eine Lizenzprüfung enthält. Darin enthalten sind einige Funktionen, die bestimmte Übergabewerte erhalten.
Was kann denn ein Angreifer damit tun, wenn er ungültige Übergabewerte übergibt um Speicherüberläufe zu provozieren?
Muss ich mich dagegen absichern und wenn ja wie?

Philipp
 
Hi

Was das ist:
Dir ist sicher klar, dass der Compiler ein Programm zu (für Menschen ziemlich unlesbare) Bytefolgen macht, die die einzelnen Anweisungen darstellen. Angenommen, du hast ein Programm mit einem char[200]-Array (also 200 Byte), und dazu halt irgendeinen Code.

Nach dem Kompilieren beim tatsächlichen Starten des Programms werden dann die Codebytes in den Arbeitsspeicher geladen, um von dort ausgeführt zu werden. Irgendwo dazwischen gibts dann auch 200 Byte ohne Code, die für den Inhalt deines Arrays reserviert sind.

Wenn jetzt in deinem Programm eine Schleife vorkommt, die dem Array von Element 0 bis 205 Werte zuweist (obwohl es ja nur von 0 bis 199 geht), wird zuerst der Arrayspeicher vollgeschrieben...
und die restlichen 6 Byte kommen auf den Platz der nächsten 6 Byte hinter dem Array im Speicher, unabhängig, was da vorher drin war.

Wenn da andere Variablen waren, bekommen sie eben neue Werte (und später sucht man lang, weil das Programm mit anderen Werten unter Umstanden andere Sachen macht und man sich das nicht erklären kann.

Wenn da aber Code drin war...
Ein Prozessorbefehl (die alle durchnummeriert sind) besteht grundsätzlich zuerst aus der Nummer des Befehls und je nach Befehl ggf. noch weitere Byte, die den betroffenen Platz im Arbeitsspeicher angeben etc..
Wenn in den 6 byte also Code war, wird das erste von den sechs als Befehlsnummer hergenommen usw.
Das Programm macht dann ziemlich sicher nicht mehr das, was man will.
Nur oft merkt man es nicht sofort, weil der überschriebene Codeteil nicht zwingend sofort ausgeführt wird.
Könnte ja zu einem if gehören, in das man bei dem Programmdurchlauf nie reinkommt etc. etc.

Das Betriebssystem überprüft sowas nicht.
Was Windows angeht, wird nur reagiert, wenn man seinen Speicher so weit überdehnt, dass nicht nur über das Array sondern über zugeteilten Speicher des gesamten Programms hinausgeschrieben wird.
So muss man sich wenigstens keine Sorgen machen, dass ein anderes fehlerhaftes Programm sein eigenes stört bzw. man selber kann nicht versehentlich andere Programme zerschießen.

In so einem Fall wird dein Programm mit einer netten Absturzmeldung plattgemacht.
Ist sicher jedem C-Lerndenden schon passiert, wenn er einen Fehler bei Pointersachen gemacht hat:D

//@Rest: Ich weiss, ein modernes OS vergibt nichtdirekt RAM-Adressen etc...das Ganze ist komplizierter
//als hier beschrieben, aber vom Prinzip her richtig und nur zum Erklären.

Vor allem Benutzereingaben müssen geprüft werden, wenn mehr geschrieben wird als man in seinem char-Array etc. Platz hat.

Die ganze Geschichte kann auch mutwillig ausgenutzt werden, wenn man zB extra irgendwas in Überlänge eingibt und in den überstehenden Teil gültige Prozessorbefehle reingibt...

Deshalb immer prüfen, ob die Maximallänge eingehalten wird und nicht einfach blind vertrauend die Daten weiterverarbeiten

(Die Leute, die das Programm haben und Starten können, kommen auch so an den RAM-Inhalt...aber man muss es ihnen ja nicht so einfach machen. Ich weiß, der Satz macht einen nicht fröhlicher.)

Puuh...das ist wieder einmal ein langer Beitrag :)

Bevor ich noch eine Stunde weiterschreibe, lies das bitte einmal und frag, was unklar ist.

Gruß
 
Muss ich mich dagegen absichern und wenn ja wie?Philipp
Ja. Kurz und knapp: Die übergebenen Werte vor der Weiterverarbeitung prüfen, wie etwa den Wertebereich oder die Größe des Datenblocks. Insbesondere Strings sind gefährlich, wenn man nicht darauf achtet, die Länge (entsprechend des reservierten Speicherplatzes) zu begrenzen und das auch zu prüfen!

Gruß
MCoder
 
Vielen Dank für die ausführlichen Erklärungen!

Aber muss ich mir in meinem Fall überhaupt diese Mühe machen? Da ich die DLL ja sowieso "aus der Hand gebe", kann ja jeder einfach mit WinHex bei sich in den RAM schauen. Der Assembler-Code lässt sich ja auch wiedergewinnen. Wenn man genügend Freizeit hat, lässt sich somit jeder in einer DLL abgelegte Code wiederherstellen. Also bringen mir diese Absicherungen wirklich mehr Sicherheit?

Und dann noch ein paar konkrete Fragen: Ich muss eigentlich nur int's doubles und double-Arrays übergeben, keine Strings. Wie genau fange ich dann solche Angriffsversuche sauber ab?
Reicht das hier?
Code:
if (ÜbergabeParameterInt>999) return(-1);
Wie mache ich das bei Doubles und wie bei Arrays?
 
Bei einzelnen Werten kannst du keinen Speicherüberlauf bekommen.
Je nachdem, was du damit machen willst, prüfst du ggf. eben die Werte, so wie in deiner Codezeile.

Bei int- und double-Arrays kannst du ja nicht mit strlen etc die Länge herausfinden und musst sowieso die Länge mitübergeben. Was da eventuell noch zu machen wäre, lässt sich pauschal schwer sagen.
Kommt drauf an, was du mit den Arrays vorhast.
 
Zuletzt bearbeitet:
Zurück