User CPFAQMembers ListCalendarToday's PostsSearch




Go Back   Foonews.Net > Newsgroups de.* > de.comp.* > de.comp.lang.assembler.x86

Prova Gratis 30gg l'hosting fooweb
Reply
 
LinkBack Thread Tools Display Modes
 
Old 05-07-06, 06:25 PM
Stefan Reuther
 
Posts: n/a
Default Re: Sichere Stringoperationen z.B. fuer Socket-Anwendungen - Danke.

Heinz Saathoff wrote:
> Auf heutigen moderneren Architekturen, und dazu zähle ich auch die Intel
> ab '386, sollte sowas doch aufgrund von Speicherschutzmechanismen nicht
> möglich sein. Das Datensegment ist zwar les- und schreibbar, aber nicht
> ausführbar. Dafür ist das Codesegment nur les- und ausführbar, aber
> nicht schreibbar.


Das gilt für 286er-Betriebssysteme. OS/2 2.x oder Windows 3.0. Aktuelle
Betriebssysteme nutzen einen flachen Adressraum, in dem erstmal alle
Bytes gleich sind. Das "No-Execute"-Bit in der Pagetabelle ist auf x86
erst eine neuere Erfindung.

Hilft alles nicht dagegen, dass jemand einfach die Rücksprungadresse
tauscht ("return-to-libc-Attacke").

> Ich habe mal folgendes kleine C-Programm als WIN-
> Consolanwendung übersetzt. Beim Start bekomme ich einen Absturz
> (privilegierte Anweisung). Unter DOS funktioniert es und ich ich erhalte
> 2 mal die Ausgabe von Func.


Das liegt aber nicht daran, dass die Kopie von func() nicht ausführbar
(im Sinne von Speicherschutz wäre). Vielmehr wird der Aufruf von
printf() über einen IP-relativen call aufgelöst. Wenn du den Code um
1000 Bytes nach hinten verschiebst, landet also auch der 'call printf'
1000 Bytes weiter hinten, irgendwo im Nirvana. Unter DOS hast du
vermutlich in einem Speichermodell compiliert, das den 'call printf' als
absoluten far-call ausführt, der unabhängig von der Stelle, wo er
ausgeführt wird, immer an die gleiche Stelle springt.

> void Func() {
> printf("Func is here\n");
> }


Ersetze das durch
void Func() {
int (*volatile p)(const char*, ...) = printf;
p("Func is here\n");
}
und schon "funktioniert" auch die Kopie. Zur Initialisierung von
Zeigervariablen werden wieder absolute Adressen benutzt.

xp&fup Assemblerprogrammierer.


Stefan

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
 
Old 05-07-06, 08:09 PM
Jan Bruns
 
Posts: n/a
Default Re: Sichere Stringoperationen z.B. fuer Socket-Anwendungen - Danke.


"Stefan Reuther":
> Heinz Saathoff wrote:
>> Auf heutigen moderneren Architekturen, und dazu zähle ich auch die Intel
>> ab '386, sollte sowas doch aufgrund von Speicherschutzmechanismen nicht
>> möglich sein. Das Datensegment ist zwar les- und schreibbar, aber nicht
>> ausführbar. Dafür ist das Codesegment nur les- und ausführbar, aber
>> nicht schreibbar.


> Das gilt für 286er-Betriebssysteme. OS/2 2.x oder Windows 3.0. Aktuelle
> Betriebssysteme nutzen einen flachen Adressraum, in dem erstmal alle
> Bytes gleich sind. Das "No-Execute"-Bit in der Pagetabelle ist auf x86
> erst eine neuere Erfindung.


Trotzdem hat Heinz ja recht: Es sollte nicht möglich sein,
ist es aber, weil man (bzw. die Betriebsystementwickler) auf die
konsequente Anwendung von Segmentierung verzichtet hat.

Im Prinzip völlig unnötig. So furchtbar kompliziert
ist die Unterscheidung von near und far Zeigern ja nicht.

Wär' nur ein klein wenig unschön, die meisten Speicherzugriffe
ausgerechnet im Stack-Segment, und nicht im Datensegment zu haben.

Wie war das noch gleich? Kann man nicht das Stacksegment auch als
"readonly" setzen, mit der Auswrikung, daß nur mit PUSH und so
geschrieben werden kann, oder so ähnlich?

Dann hätte man manuell einen "Daten/Parameterstapel" im DS verwalten
können, und hätte nur für "dynamisch allozierten Speicher" far-pointer
verwenden müssen, und schwubs, schon hätten wir den grösseren Anteil
aller Speicheroperationen (globale und lokale Variablen) über
near-pointer bezogen auf DS, im SS nur readonly Flusskontrolle,
dann bspw. im ES den Heap, dessen pointer Verwaltungstechnisch ebenfalls
near-pointer sein könnten.
Der Hochsprachenprogrammierer müsste lediglich zwischen
"eigenen" Zeigern und Systempointern unterscheiden, der Compiler
zusätzlich zwischen Variablen- und Heapzugriffen (und folglich
im Zweifel far-pointer verwenden).

Hab' ich was übersehen?

Gruss

Jan Bruns

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Try the foonews Toolbar!!!
 
Old 05-07-06, 09:04 PM
Stefan Reuther
 
Posts: n/a
Default Re: Sichere Stringoperationen z.B. fuer Socket-Anwendungen - Danke.

Jan Bruns wrote:
> "Stefan Reuther":
>> Heinz Saathoff wrote:
>>> Auf heutigen moderneren Architekturen, und dazu zähle ich auch die Intel
>>> ab '386, sollte sowas doch aufgrund von Speicherschutzmechanismen nicht
>>> möglich sein. Das Datensegment ist zwar les- und schreibbar, aber nicht
>>> ausführbar. Dafür ist das Codesegment nur les- und ausführbar, aber
>>> nicht schreibbar.

>
>> Das gilt für 286er-Betriebssysteme. OS/2 2.x oder Windows 3.0. Aktuelle
>> Betriebssysteme nutzen einen flachen Adressraum, in dem erstmal alle
>> Bytes gleich sind. Das "No-Execute"-Bit in der Pagetabelle ist auf x86
>> erst eine neuere Erfindung.

>
> Trotzdem hat Heinz ja recht: Es sollte nicht möglich sein,
> ist es aber, weil man (bzw. die Betriebsystementwickler) auf die
> konsequente Anwendung von Segmentierung verzichtet hat.
>
> Im Prinzip völlig unnötig. So furchtbar kompliziert
> ist die Unterscheidung von near und far Zeigern ja nicht.


Dummerweise sind far-Zeiger lahm (das Neuladen der Deskriptoren kostet.
Du hast nur 3 frei verwendbare Segmentregister, obwohl die 6 GPRs
bereits als knapp gelten) und inkompatibel zu real existierenden
C-Programmieren (passt nicht in einen Integertyp).

> Wie war das noch gleich? Kann man nicht das Stacksegment auch als
> "readonly" setzen, mit der Auswrikung, daß nur mit PUSH und so
> geschrieben werden kann, oder so ähnlich?


Nein, das geht nicht.

Du kannst aber das Segmentlimit von CS einfach auf die maximal mögliche
Code-Adresse setzen und das vom SS auf die minimal mögliche Stackadresse
(nebst gesetztem expand-down-Bit). Dann sind Code- und Stackbereich
disjunkt. WIMRE macht OpenBSD das.

Bringt aber Probleme mit beispielsweise Trampolinen.

> Der Hochsprachenprogrammierer müsste lediglich zwischen
> "eigenen" Zeigern und Systempointern unterscheiden, der Compiler
> zusätzlich zwischen Variablen- und Heapzugriffen (und folglich
> im Zweifel far-pointer verwenden).


Der Hochsprachenprogrammierer müsste einfach nur ein korrektes Programm
abliefern, dann ist das alles egal.

Und da neuere Prozessoren ein No-Execute-Bit haben und im 64-bit-Modus
die Segmentierung eh ignorieren, ist es erst recht egal :-)


Stefan

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
 
Old 05-07-06, 10:38 PM
Jan Bruns
 
Posts: n/a
Default Re: Sichere Stringoperationen z.B. fuer Socket-Anwendungen - Danke.


"Stefan Reuther":
> Jan Bruns wrote:
>> "Stefan Reuther":


>> Wie war das noch gleich? Kann man nicht das Stacksegment auch als
>> "readonly" setzen, mit der Auswrikung, daß nur mit PUSH und so
>> geschrieben werden kann, oder so ähnlich?


> Nein, das geht nicht.


Ja, scheinst recht zu haben.

Keine Ahnung, wo ich das herhabe.

> Du kannst aber das Segmentlimit von CS einfach auf die maximal mögliche
> Code-Adresse setzen und das vom SS auf die minimal mögliche Stackadresse
> (nebst gesetztem expand-down-Bit). Dann sind Code- und Stackbereich
> disjunkt. WIMRE macht OpenBSD das.


Naja, aber das hilft ja bspw. nicht gegen Buffer-Overflows auf dem Stack,
mit der Rücksprungadressenproblematik.

Andererseits könnten compiler ja von sich aus darauf verzichten,
Schreibzugriffe über/im SS zu verwenden (s. mein voriges Posting).

> Dummerweise sind far-Zeiger lahm (das Neuladen der Deskriptoren kostet.


Code ( muss nichtmal lesbar sein )
Stack ( enthält freiwillig nur Rücksprungadressen, so daß gar keine
Codeschnipsel existieren, die Daten über SS schreiben )
Daten ( rw, enthält "manuell" verwalteten Datenstapel )
System( rw, Zugriffkontrolle/Gestaltung per paging; OS hat die Option,
Systemdaten ins DS der Anwendung zu blenden )

Da müssten gar keine Selektoren neugeladen werden,
hatte ich falsch gesehen.

Aber irgendwer, ob nun Betriebsystem, Compiler, oder Programmierer müsste
immer noch zwischen Daten bzw. Systempointer unterscheiden.

Gruss

Jan Bruns

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
 
Old 06-07-06, 02:39 AM
Sebastian Biallas
 
Posts: n/a
Default Re: Sichere Stringoperationen z.B. fuer Socket-Anwendungen - Danke.

Jan Bruns wrote:
> Trotzdem hat Heinz ja recht: Es sollte nicht möglich sein,
> ist es aber, weil man (bzw. die Betriebsystementwickler) auf die
> konsequente Anwendung von Segmentierung verzichtet hat.


Da die Segmentierung seit 32 Bit Betriebssystemen fast völlig
vernachlässigt wurde, ist die inzwischen auch in den Prozessoren "am
aussterben". Im Longmode gibt es sie nicht mehr wirklich und im 32 Bit
Modus empfiehlt AMD die CS-Basis immer auf 0 zu setzen, sonst gibts
irgendeine extra mistaken-branch-penalty.

Gibts eigentlich ein halbwegs aktuelles Bestriebssystem, dass noch
Segmentierung mit unterschiedlichen Basisadressen benutzt? Irgendein
Microkernel?

--
Gruß,
Sebastian
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
 
Old 06-07-06, 08:35 AM
Heinz Saathoff
 
Posts: n/a
Default Re: Sichere Stringoperationen z.B. fuer Socket-Anwendungen - Danke.

Moin,

[wg. F'Up: es geht um die Möglichkeit, per Pufferüberlauf die Return-
Adresse auf dem Stack zu ändern und damit im Datenpuffer eingeschleusten
Schadcode ausführen zu können]

Stefan Reuther schrieb...
> > Auf heutigen moderneren Architekturen, und dazu zähle ich auch die Intel
> > ab '386, sollte sowas doch aufgrund von Speicherschutzmechanismen nicht
> > möglich sein. Das Datensegment ist zwar les- und schreibbar, aber nicht
> > ausführbar. Dafür ist das Codesegment nur les- und ausführbar, aber
> > nicht schreibbar.

>
> Das gilt für 286er-Betriebssysteme. OS/2 2.x oder Windows 3.0. Aktuelle
> Betriebssysteme nutzen einen flachen Adressraum, in dem erstmal alle
> Bytes gleich sind. Das "No-Execute"-Bit in der Pagetabelle ist auf x86
> erst eine neuere Erfindung.


Flache Adressierung schließt aber das Segmentieren nicht aus, was man
spätestens dann merkt, wenn man mal eins der Segmentregister willkürlich
setzt. Soweit ich weiß, werden die Selektoren so initialisiert, daß sie
den gleichen logischen Adressraum abbilden, der dann durch die
Pagingunit auf den wirklichen physischen Speicher gemapped wird. Bitte
korregieren, falls ich da falsch liege. Ist schon eine Weile her, daß
ich das Prozessorhandbuch es '386 gelesen habe.


> Hilft alles nicht dagegen, dass jemand einfach die Rücksprungadresse
> tauscht ("return-to-libc-Attacke").


Gut, ein Rücksprung an eine beliebige Stelle im Code ist natürlich so
mörglich, aber es läßt sich kein Fremdcode einschleusen.


> > Ich habe mal folgendes kleine C-Programm als WIN-
> > Consolanwendung übersetzt. Beim Start bekomme ich einen Absturz
> > (privilegierte Anweisung). Unter DOS funktioniert es und ich ich erhalte
> > 2 mal die Ausgabe von Func.

>
> Das liegt aber nicht daran, dass die Kopie von func() nicht ausführbar
> (im Sinne von Speicherschutz wäre). Vielmehr wird der Aufruf von
> printf() über einen IP-relativen call aufgelöst. Wenn du den Code um
> 1000 Bytes nach hinten verschiebst, landet also auch der 'call printf'
> 1000 Bytes weiter hinten, irgendwo im Nirvana. Unter DOS hast du
> vermutlich in einem Speichermodell compiliert, das den 'call printf' als
> absoluten far-call ausführt, der unabhängig von der Stelle, wo er
> ausgeführt wird, immer an die gleiche Stelle springt.
>
> > void Func() {
> > printf("Func is here\n");
> > }

>
> Ersetze das durch
> void Func() {
> int (*volatile p)(const char*, ...) = printf;
> p("Func is here\n");
> }
> und schon "funktioniert" auch die Kopie. Zur Initialisierung von
> Zeigervariablen werden wieder absolute Adressen benutzt.


Hast recht. Funktioniert tatsächlich, auch unter Windows.
Ich dachte immer, daß für call absolute Adressen genutzt würden, da ja
der Code immer bei logischer Adresse 0 beginnt. Somit könnte der Linker
einfach die absolute Adresse eintragen.

Jetzt wird mir auch klar, warum der Schutz per CS-Register nicht wirken
kann, denn wenn die Selektoren für DS un CS gleiche Startadresse und
Länge aufweisen, dann kann der Datenpuffer sowohl bezuglich CS als auch
DS adressiert werden.

Unter DOS hat mein Progrämmchen nur funktioniert, weils im FAR-Modell
ein Inter-Segment-Call war und dort wieder absolute Adressen genutzt
werden.


- Heinz
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
 
Old 06-07-06, 07:07 PM
Stefan Reuther
 
Posts: n/a
Default Re: Sichere Stringoperationen z.B. fuer Socket-Anwendungen - Danke.

Hallo,

Jan Bruns wrote:
> "Stefan Reuther":
>> Dummerweise sind far-Zeiger lahm (das Neuladen der Deskriptoren kostet.

>
> Code ( muss nichtmal lesbar sein )
> Stack ( enthält freiwillig nur Rücksprungadressen, so daß gar keine
> Codeschnipsel existieren, die Daten über SS schreiben )
> Daten ( rw, enthält "manuell" verwalteten Datenstapel )


Auch nicht so prall, da du damit weitere Register und/oder Performance
opferst (nehmen wir EBP als Datenstackpointer, müssen wir immer ein
DS:-Prefix verwenden. Nehmen wir EBX o.ä., haben wir ein weiteres
Register verloren).

Und dann überschreibe ich dir eben statt der Rückkehradressen vtbl-Pointer.

Ich bin ja immer noch dafür, einfach Programme ohne Buffer Overflows zu
schreiben :-)


Stefan

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
 
Old 06-07-06, 11:42 PM
Jan Bruns
 
Posts: n/a
Default Re: Sichere Stringoperationen z.B. fuer Socket-Anwendungen - Danke.


"Stefan Reuther":
> Jan Bruns wrote:
>> "Stefan Reuther":


>>> Dummerweise sind far-Zeiger lahm (das Neuladen der Deskriptoren kostet.

>>
>> Code ( muss nichtmal lesbar sein )
>> Stack ( enthält freiwillig nur Rücksprungadressen, so daß gar keine
>> Codeschnipsel existieren, die Daten über SS schreiben )
>> Daten ( rw, enthält "manuell" verwalteten Datenstapel )


> Auch nicht so prall, da du damit weitere Register und/oder Performance
> opferst (nehmen wir EBP als Datenstackpointer, müssen wir immer ein
> DS:-Prefix verwenden. Nehmen wir EBX o.ä., haben wir ein weiteres
> Register verloren).


So? Hat denn Intel bei der Auflistung der 32-Bit Adressierungen
die Fussnote vergessen, die darauf hinweist? Diese fussnote findet
sich nämlich nur an der Auflistung der 16-bit Adressierungen.

> Und dann überschreibe ich dir eben statt der Rückkehradressen
> vtbl-Pointer.


Was ist ein vtbl-pointer?

> Ich bin ja immer noch dafür, einfach Programme ohne Buffer
> Overflows zu schreiben :-)


Besser wär's.

Gruss

Jan Bruns


Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
 
Old 07-07-06, 06:20 PM
Stefan Reuther
 
Posts: n/a
Default Re: Sichere Stringoperationen z.B. fuer Socket-Anwendungen - Danke.

Jan Bruns wrote:
> "Stefan Reuther":
>>> Code ( muss nichtmal lesbar sein )
>>> Stack ( enthält freiwillig nur Rücksprungadressen, so daß gar keine
>>> Codeschnipsel existieren, die Daten über SS schreiben )
>>> Daten ( rw, enthält "manuell" verwalteten Datenstapel )

>
>> Auch nicht so prall, da du damit weitere Register und/oder Performance
>> opferst (nehmen wir EBP als Datenstackpointer, müssen wir immer ein
>> DS:-Prefix verwenden. Nehmen wir EBX o.ä., haben wir ein weiteres
>> Register verloren).

>
> So? Hat denn Intel bei der Auflistung der 32-Bit Adressierungen
> die Fussnote vergessen, die darauf hinweist? Diese fussnote findet
> sich nämlich nur an der Auflistung der 16-bit Adressierungen.


386intel.txt, Zeile 1737ff:
# When EBP is used as the base register in an offset calculation, the
# offset is calculated automatically in the current stack segment (i.e.,
# the segment currently selected by SS). Because SS does not have to be
# explicitly specified, instruction encoding in such cases is more
# efficient.

>> Und dann überschreibe ich dir eben statt der Rückkehradressen
>> vtbl-Pointer.

>
> Was ist ein vtbl-pointer?


Tabelle für virtuelle Funktionen, auch als VMT bekannt. Objekt-
orientierte Programme sind voll von indirekten Funktionsaufrufen über
Tabellen. Die Tabelle ist im allgemeinen schreibgeschützt, aber der
Zeiger auf die Tabelle liegt mitten im RAM, innerhalb des Objekts. Eine
prima Gelegenheit, eigene Zeiger einzuführen.


Stefan

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
 
Old 08-07-06, 11:20 PM
Jan Bruns
 
Posts: n/a
Default Re: Sichere Stringoperationen z.B. fuer Socket-Anwendungen - Danke.


"Stefan Reuther":
> Jan Bruns wrote:
>> "Stefan Reuther":
>>>> Code ( muss nichtmal lesbar sein )
>>>> Stack ( enthält freiwillig nur Rücksprungadressen, so daß gar keine
>>>> Codeschnipsel existieren, die Daten über SS schreiben )
>>>> Daten ( rw, enthält "manuell" verwalteten Datenstapel )

>>
>>> Auch nicht so prall, da du damit weitere Register und/oder Performance
>>> opferst (nehmen wir EBP als Datenstackpointer, müssen wir immer ein
>>> DS:-Prefix verwenden. Nehmen wir EBX o.ä., haben wir ein weiteres
>>> Register verloren).


Naja, aber "verloren" ist ja auch nicht ganz richtig.

Dann wäre EBP ja frei (bspw. anstelle von EBX) benutzbar.
So furchtbar oft habe ich EBX nun auch wieder nicht zur
Adressierung verwendet, als daß ein zusätzliches Präfix
ernsthaft problematisch wäre.

Klar, macht marginal mehr "Registerdruck", und ist auch neinfach
nicht so schön, wenn eines der "freien Register" anders
funktioniert, als die anderen.

>> So? Hat denn Intel bei der Auflistung der 32-Bit Adressierungen
>> die Fussnote vergessen, die darauf hinweist? Diese fussnote findet
>> sich nämlich nur an der Auflistung der 16-bit Adressierungen.

>
> 386intel.txt, Zeile 1737ff:
> # When EBP is used as the base register in an offset calculation, the
> # offset is calculated automatically in the current stack segment (i.e.,
> # the segment currently selected by SS). Because SS does not have to be
> # explicitly specified, instruction encoding in such cases is more
> # efficient.


Ja, selbst nochmal in aktuellerer Dou nachgelesen.
Hast recht.

>>> Und dann überschreibe ich dir eben statt der Rückkehradressen
>>> vtbl-Pointer.

>>
>> Was ist ein vtbl-pointer?

>
> Tabelle für virtuelle Funktionen, auch als VMT bekannt.


Ja, die kenne ich allerdings.

Aber da liesse sich doch ganz wunderbar mit verschiedenen
Segmenten arbeiten:

Stapelobjekte:

VMT einschl. Datenzeiger im SS, Daten auf dem manuell
verwalteten DS-Stack


Globalobjekte und dynamische Objekte:

VMT + Datenzeiger im SS, oberhalb des gültigen
Stapeladressraumes, verwaltet durch zusätzlichen
Heap-manager,
Daten weiterhin im DS


Also, ich will das Problem ja auch gar nicht schönreden,
soweit dem Programmierer Zeiger zur freien Verfügung stehen,
kann er sich natürlich immer so einiges kaputt machen.

Aber ob man nun als Programmierer unbedingt gleichzeitig
frei belegbare Methoden-Zeiger, frei überschreibbare
Rüclsprungadressen sowie u.U. sogar frei überschreibbaren
Code benötigt?

Gruss

Jan Bruns

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



 RSS Feeds - Archive - Top




All times are GMT +1. The time now is 11:54 PM. Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.1.0 Forum style by ForumMonkeys.com.