Forum: PC-Programmierung Zeiger im lokalen Adressraum


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,
auf einem einfachen µC kann ich ja einen beliebigen Integer-Wert als 
Zeiger behandeln, und so denn in des µCs virtuellem Adressraum an dieser 
Stelle etwas sinnvolles steht innerhalb des Programms anzeigen lassen. 
So kann ich z.B. die gesamte SRAM-Belegung auf einem LCD darstellen, um 
die Speicherbelegung auf einen Blick überprüfen zu können.

Auf dem PC ist das Ganze ja nicht mehr so einfach: Dort hat jedes 
Programm seinen eigenen virtuellen Adressraum. Irgendeinen Zeiger zu 
erzeugen und auf dieser Adresse lesen sollte zuverlässig zu einer 
Schutzverletzung führen.

Angenommen, ich wollte mir den virtuellen Adressraum eines 
selbstgeschriebenen Programms von innerhalb des Programms ansehen -
 - wo erstreckt sich der Adressraum meines Programms?
 - Kann ich die Adressen herausfinden und lesen?
 - Ist dieser Adressraum zusammenhängend?

Viele Grüße
W.T.

von Neumann (Gast)


Lesenswert?

Walter Tarpan schrieb:
> einen beliebigen Integer-Wert als
> Zeiger behandeln, und so denn in des µCs virtuellem Adressraum an dieser
> Stelle etwas sinnvolles steht innerhalb des Programms anzeigen lassen

Der Zeiger muss zum Adressraum passen. Ein 16-Bit Pointer kann nur 64k 
adressieren.

Bei einem Harvard erreicht man nur den RAM Bereich.

Auf dem PC hindert dich dein Betriebssytem. Sonst geht das problemlos.
Unter DOS hat man direkt in den Speicher der Grafikkarte geschrieben, 
der in den CPU Adressraum eingeblendet wurde. :-)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Walter Tarpan schrieb:
> Irgendeinen Zeiger zu erzeugen und auf dieser Adresse lesen sollte
> zuverlässig zu einer Schutzverletzung führen.

Das tut es nur dann, wenn auf der Adresse kein Speicher eingeblendet 
ist. Irgendwo aber ist immer Speicher eingeblendet, sowohl der, in dem 
das Binary Deines Programmes liegt, als auch der, in dem Dein Programm 
seine Daten und Stack(s) unterbringt.
Von "Zuverlässig" kann also nicht die Rede sein. "Zufällig" und 
"Wahrscheinlich", das ja.

Deine restlichen Fragen beantwortet das Programmierhandbuch des von Dir 
ungenannt bleibenden Betriebssystems, Abschnitt 
Speicherverwaltung/"Memory Management".

von (prx) A. K. (prx)


Lesenswert?

Walter Tarpan schrieb:
> - Ist dieser Adressraum zusammenhängend?

Nicht wenn dein Betriebssystem shared memory oder shared libraries 
(DLLs) unterstützt. Zudem kann je nach OS der Systemadressraum mit 
eingeblendet sein.

von Noch einer (Gast)


Lesenswert?

Dein Programm kann die Schutzverletzung selbst bearbeiten bzw. 
ignorieren. Alle Adressen abklappern geht auch auf dem PC. Bleibt nur 
noch die Frage - wie lange dauert das bei einem 64Bit Adressraum?

von Rolf M. (rmagnus)


Lesenswert?

Walter Tarpan schrieb:
> auf einem einfachen µC kann ich ja einen beliebigen Integer-Wert als
> Zeiger behandeln, und so denn in des µCs virtuellem Adressraum an dieser
> Stelle etwas sinnvolles steht innerhalb des Programms anzeigen lassen.

... Sofern der µC Speichervirtualisierung betreibt.

> So kann ich z.B. die gesamte SRAM-Belegung auf einem LCD darstellen, um
> die Speicherbelegung auf einen Blick überprüfen zu können.

Das wäre dann ohne Speichervirtualisierung.

> Auf dem PC ist das Ganze ja nicht mehr so einfach: Dort hat jedes
> Programm seinen eigenen virtuellen Adressraum.

Also wieder mit Speichervirtualisierung...

> Irgendeinen Zeiger zu erzeugen und auf dieser Adresse lesen sollte
> zuverlässig zu einer Schutzverletzung führen.
>
> Angenommen, ich wollte mir den virtuellen Adressraum eines
> selbstgeschriebenen Programms von innerhalb des Programms ansehen -
>  - wo erstreckt sich der Adressraum meines Programms?

Was meinst du mit "wo"? Wo die Daten phyisch liegen? Das regelt das 
Betriebssystem.

>  - Kann ich die Adressen herausfinden und lesen?

Wenn das geheime Betriebssystem dafür eine Möglichkeit bietet, ja. Wenn 
es einen Bug hat, über den man trotzdem rankommt, ja. Sonst nein.

>  - Ist dieser Adressraum zusammenhängend?

Meinst du den virtuellen Adressraum oder den physischen Bereich im 
Speicher?

von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,
ich betrachte das Ganze rein aus der Sicht des Anwendungsprogramms.

Bei meinem µC ohne Speichervirtualisierung kann mein Anwendungsprogramm 
auf jede Speicherstelle, wo auch etwas ist, zugreifen. Zum Glück stehen 
diese Speicherstellen im Datenblatt, so daß ich sinnvolle Adressbereiche 
zum Auslesen (z.B. Flash, SRAM, EEPROM) und irgendwelche Sonderbefehle, 
die dazu notwendig sind leicht herausfinden kann.

Ich gehe jetzt auf den PC. Daß von Betriebssystemseite der 
Speicherbereich eines Anwendungsprogramms nicht zusammenhängend sein 
muß, ist klar - aber was sieht das Anwendungsprogramm davon? Lese ich 
(aus Sicht des Anwendungsprogramms) von der Addresse 0, also im 
C-Quelltext:
1
uint32_t address, temp;
2
address=0;
3
printf("Jetzt aber:");
4
printf("address=%i",&address);
5
temp = *(uint32_t *) address;
6
printf("i=%i",temp);
so schafft mein Programm es noch, ein "Jetzt aber:address=2293316" auf 
der Konsole auszugeben und stürzt dann ab. Da hat der Speicherschutz 
vermutlich alles richtig gemacht und ich weiß zumindest, daß der 
Adressraum aus Sicht des Anwendungsprogramms nicht bei Null anfängt.

Die Adresse, die angezeigt wird, ist auch viel zu hoch, als daß das 
Anwendungsprogramm einen Addressraum von 0 bis 2293316 brauchen würde. 
Aber kennt das Anwendungsprogramm irgendwie die Speicheradressen, auf 
die es zugreifen kann?

Ich habe die Frage bewußt betriebtsystemunabhängig gestellt. Ich nutze 
Windows 7 und Debian 7, aber ehrlich gesagt interessiert mich mehr die 
Sicht des Anwendungsprogramms.

Viele Grüße
W.T.

von Noch einer (Gast)


Lesenswert?

Die Entwickler der Betriebssysteme und des Compilers haben viel Mühe 
aufgewendet, damit du als Anwendungsprogrammierer diese ganze 
Komplexität unterschiedlicher Multitasking-betriebssysteme ignorieren 
kannst.

Die stellen halt alles richtig zusammen und gehen davon aus, der 
Anwendungsprogrammierer will es gar nicht wissen.

Betriebtsystemunabhängig geht da nichts. Unter Windows gibt es kein 
/proc Verzeichnis. Betriebtsystemabhängig gibt es ja verschiedene 
Open-Source Tools - 'einfach' mal schauen, auf welchen Wegen diese 
Programme die Infos zusammenstellen.

von Georg (Gast)


Lesenswert?

Noch einer schrieb:
> Die stellen halt alles richtig zusammen

Die Betriebssysteme, die einen virtuellen Speicher verwalten - grob 
gesagt "richtige" Computer wie PCs oder Workstations usw, nicht Embedded 
Systeme - stellen einem korrekten Programm Speicher an den Adressen zur 
Verfügung, wo das Programm ihn haben möchte, sofern noch einer verfügbar 
ist. Mehr muss und kann das Programm nicht wissen, wo der Speicher 
(-Block) physikalisch liegt ist völlig irrelevant.

Speicher an physikalischen Adressen ansprechen muss man nur, wenn man 
einen Speichertest durchführen und den kaputten Riegel indentifizieren 
will.

Georg

von Noch einer (Gast)


Lesenswert?

> wo der Speicher (-Block) physikalisch liegt ist völlig irrelevant.

Linux legt immer noch ein swap Device an. Damals, als es noch benutzt 
wurde, und nach jedem Mausklick die Platte 10 Sekunden klapperte, war 
das schon relevant :-)

von Konrad S. (maybee)


Lesenswert?

Walter Tarpan schrieb:
> Lese ich
> (aus Sicht des Anwendungsprogramms) von der Addresse 0,

Normalerweise gibt es bei Adresse 0 kein Mapping, je nach System einige 
kBytes bis MBytes groß. Dadurch können dereferenzierte NULL-Pointer per 
Hardware erkannt werden.
Üblicherweise kommt nach diesem "Schutzbereich" erstmal der 
Programmcode. Danach können DLLs/Shared Objects liegen. Anschließend 
kommt der Heap. Ganz "oben" im nutzbaren Adressraum der Prozesses liegt 
der Stack. Der unbenutzte Adressraum zwischen Heap und Stack kann bei 
Bedarf zur dynamischen Vergrößerung der beiden Bereiche genutzt werden: 
der Heap wächst nach "oben", der Stack wächst nach "unten". Treffen sich 
Heap und Stack, dann hat der Prozess ein Problem und wird gekillt.

Noch einer schrieb:
> Linux legt immer noch ein swap Device an.

Swap ist schon seit langer Zeit optional.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Walter Tarpan schrieb:
> Ich habe die Frage bewußt betriebtsystemunabhängig gestellt.

Das ist aber nicht betriebssystemunabhängig. Welche Adressen Deinem 
Programm für welche Teile zur Verfügung gestellt werden, hängt vom 
Betriebssystem ab.

Und wie Dein Programm herausfinden kann, welcher Adressbereich (und 
folglich wieviel Speicher) ihm zur Verfügung steht, hängt auch vom 
Betriebssystem ab.

von (prx) A. K. (prx)


Lesenswert?

Walter Tarpan schrieb:
> Ich habe die Frage bewußt betriebtsystemunabhängig gestellt. Ich nutze
> Windows 7 und Debian 7, aber ehrlich gesagt interessiert mich mehr die
> Sicht des Anwendungsprogramms.

Das ist nichts, was ein Anwenderprogramm wissen muss - ganz im 
Gegenteil. Folglich haben Betriebssysteme dabei viel Freiheit und es 
gibt keine Regel, die betriebssystemübergreifend gültig wäre.

Es gab Zeiten, insbesondere als shared libs / DLLs noch nicht en vogue 
waren, in denen der virtuelle Adressraum denkbar einfach strukturiert 
war. Code unten, statische Daten dahinter, gefolgt vom Heap. Nur die 
Lage vom Stack war weniger klar. Grad so wie bei µCs, nur eben virtuell.

Diese Zeiten sind vorbei. Um Schadcode das Leben zu erschweren wird das 
mittlerweile ausgewürfelt. Also viel Spass bei der Suche nach einer 
Regel: https://en.wikipedia.org/wiki/Address_space_layout_randomization

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Konrad S. schrieb:
> Noch einer schrieb:
>> Linux legt immer noch ein swap Device an.
>
> Swap ist schon seit langer Zeit optional.

Es war schon immer optional.

von Yalu X. (yalu) (Moderator)


Lesenswert?

In Linux kannst du dir die Belegung des virtuellen Adressraums eines
Prozesses mit

1
cat /proc/<Prozess-ID>/maps

anzeigen lassen. Hier findest du eine Erläuterung der angezeigten
Informationen:

  http://stackoverflow.com/questions/1401359/understanding-linux-proc-id-maps

Wenn du dir jetzt in einem Programm die Adresse einer automatischen
Variable (automatisch = nichtstatisch lokal) ausgeben lässt, sollte
diese in dem Bereich liegen, der in maps als [stack] gekennzeichnet ist.
Du kannst dir in deinem Programm auch die Inhalte von absoluten Adressen
ausgeben lassen, wenn diese Adressen innerhalb der in maps aufgelisteten
Bereiche liegen.

Du kannst damit bei einem laufenden Programm auch schön sehen, wie Stack
und Heap bei entsprechendem Bedarf dynamisch wachsen.

In Windows gibt es kein proc-Filesystem und wahrscheinlich auch kein
mitgeliefertes Tool, um die gewünschten Informationen anzuzeigen. Du
kannst dir dazu aber dieses hier

  https://technet.microsoft.com/en-us/library/dd535533.aspx

herunterladen.

von Noch einer (Gast)


Lesenswert?

Mal eine ganz dumme Frage.

Was für einen Nutzen hat eigentlich ASLR, wenn der Trojaner 
/proc/self/maps lesen kann?

von Peter II (Gast)


Lesenswert?

Noch einer schrieb:
> Was für einen Nutzen hat eigentlich ASLR, wenn der Trojaner
> /proc/self/maps lesen kann?

der Trojaner muss ja erst mal ausgeführt werden. Wenn es schon auf dem 
System ist braucht man auch kein ASLR mehr.

Bei der Infizierung eines System ist ja das Problem, das man code zur 
Ausführung bringen muss.

von (prx) A. K. (prx)


Lesenswert?

Noch einer schrieb:
> Was für einen Nutzen hat eigentlich ASLR, wenn der Trojaner
> /proc/self/maps lesen kann?

Üblicherweise geht es um das Layout anderer Prozesse auf dem gleichen 
oder einem anderen System, um deren Verletzbarkeiten auszuforschen und 
deren weitergehenden Rechte auszunutzen. Nicht um die Rechte, die man 
sowieso schon hat. Auf fremde Maps besteht kein Zugriff.

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Walter Tarpan schrieb:

> ich betrachte das Ganze rein aus der Sicht des Anwendungsprogramms.
>
> Bei meinem µC ohne Speichervirtualisierung kann mein Anwendungsprogramm
> auf jede Speicherstelle, wo auch etwas ist, zugreifen.

Das Lustige ist: Das ist bei virtualisiertem Speicher ganz genauso.

> Zum Glück stehen
> diese Speicherstellen im Datenblatt

Ja, das ist der entscheidende Unterschied, denn genau das ist bei 
virtualisiertem Speicher nur eingeschränkt der Fall, je größer die 
Beschränkung, desto sicherer ist das System.

> Ich gehe jetzt auf den PC. Daß von Betriebssystemseite der
> Speicherbereich eines Anwendungsprogramms nicht zusammenhängend sein
> muß, ist klar - aber was sieht das Anwendungsprogramm davon?

Im Idealfall: garnix. Ein Anwendung sieht immer nur ihre eigene 
virtuelle Umgebung und hat auch keine Möglichkeit, auf etwas anderes 
zuzugreifen, außer unter Mithilfe genau definierter und im Idealfall 
vollständig die Paremeter prüfender Schnittstellen zu Code, der mit 
höheren Rechten läuft. Alles andere ist (mindestens potentiell) eine 
Sicherheitslücke. Selbst die erlaubten Schnittstellen stellen bei 
genauerer Betrachtung oftmals eine Sicherheitslücke dar, zumindest unter 
dem Aspekt, daß sie das Auffinden "echter" Sicherheitslücken erleichtern 
oder deren zielgerichtete Ausnutzung überhaupt erst möglich machen.

> Aber kennt das Anwendungsprogramm irgendwie die Speicheradressen, auf
> die es zugreifen kann?

Natürlich. Sie kann den eigenen Codespace erfragen, den eigenen Stack 
und für den Heap ist sie ja sowieso selbst verantwortlich, weil sie ihn 
vor der Benutzung erstmal vom OS anfordern muß.

> Ich habe die Frage bewußt betriebtsystemunabhängig gestellt.

Naja, immerhin hast du wohl das begriffen: bei allen modernen OS wird 
prinzipiell mit genau dem gleichen Wasser gekocht. Auch wenn natürlich 
die jeweiligen Fanboys das mit tiefster Entrüstung weit von sich weisen 
würden...

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.