Stefan Reuther
2006-07-05 16:25:55 UTC
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. Aktuelleab '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.
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ührbarConsolanwendung übersetzt. Beim Start bekomme ich einen Absturz
(privilegierte Anweisung). Unter DOS funktioniert es und ich ich erhalte
2 mal die Ausgabe von Func.
(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 durchprintf("Func is here\n");
}
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