Python-Ctypes und Funktionsaufrufe

7

Mein Freund hat einen kleinen Proof-of-Concept-Assembler erstellt, der auf x86 funktioniert. Ich entschied mich, es auch für x86_64 zu portieren, aber ich traf sofort ein Problem.

Ich habe ein kleines Stück Programm in C geschrieben, dann den Code kompiliert und objdumped. Danach habe ich es in mein Python-Skript eingefügt, daher ist der x86_64-Code korrekt:

%Vor%

Nun, warum macht dieses Skript immer Segmentierungsfehler, wenn ich es ausführe?

Ich habe noch eine Frage über mprotect und kein Ausführungsflag. Es wird gesagt, dass es gegen die meisten grundlegenden Sicherheitsexplosionen wie Pufferüberläufe schützt. Aber was ist der wahre Grund dafür? Du könntest einfach weiterschreiben, bis du auf den .text triffst, dann sprichst du deine Anweisungen in einen schönen PROT_EXEC-Bereich. Es sei denn natürlich, Sie verwenden einen Schreibschutz in .text

Aber warum sollte PROT_EXEC dann überall sein? Wäre es nicht nur enorm hilfreich, wenn Ihr .text-Bereich schreibgeschützt ist?

    
Cheery 08.11.2008, 21:11
quelle

5 Antworten

8

Als vincent erwähnt, liegt dies daran, dass die zugeordnete Seite markiert ist als nicht ausführbar. Neuere Prozessoren unterstützen diese -Funktionalität und werden von Betriebssystemen, die sie unterstützen, als zusätzliche Sicherheitsebene verwendet. Die Idee ist, sich vor bestimmten Pufferüberlaufangriffen zu schützen. Z.B. Ein üblicher Angriff besteht darin, eine Stapelvariable zu überfließen, indem die Rücksprungadresse so umgeschrieben wird, dass sie auf den Code zeigt, den Sie eingefügt haben. Bei einem nicht ausführbaren Stack erzeugt dies jetzt nur einen segfault und nicht die Kontrolle über den Prozess. Ähnliche Angriffe gibt es auch für Heap-Speicher.

Um es zu umgehen, müssen Sie den Schutz ändern. Dies kann nur mit seitenausgerichtetem Speicher ausgeführt werden. Daher müssen Sie Ihren Code wahrscheinlich wie folgt ändern:

%Vor%

Hinweis: Es kann eine gute Idee sein, das ausführbare Flag vor dem Freigeben der Seite zu deaktivieren. Die meisten C-Bibliotheken geben den Arbeitsspeicher nicht wirklich an das Betriebssystem zurück, wenn sie ausgeführt werden, behalten ihn jedoch in ihrem eigenen Pool. Dies könnte bedeuten, dass sie die Seite an anderer Stelle wiederverwenden, ohne das EXEC-Bit zu löschen, wodurch der Sicherheitsvorteil umgangen wird.

Beachten Sie auch, dass dies nicht tragbar ist. Ich habe es auf Linux getestet, aber nicht auf anderen Betriebssystemen. Es funktioniert nicht auf Windows, kaufen Sie möglicherweise auf andere Unixe (BSD, OsX?).

    
Brian 09.11.2008, 01:06
quelle
7

Habe mit meinem Freund geforscht und herausgefunden, dass dies ein plattformspezifisches Problem ist. Wir vermuten, dass auf einigen Plattformen malloc mmaps Speicher ohne PROT_EXEC und auf anderen Plattformen es tut.

Daher muss die Schutzstufe mit mprotect nachträglich geändert werden.

Lame Ding, dauerte eine Weile, um herauszufinden, was zu tun ist.

%Vor%     
Cheery 09.11.2008 00:29
quelle
4

Ich denke, Sie können keinen zugewiesenen Speicher frei ausführen, ohne ihn vorher als ausführbar zu definieren. Ich habe es nie selbst versucht, aber vielleicht möchtest du die Unix-Funktion mprotect :

überprüfen

Ссылка

VirtualProtect scheint dasselbe bei Windows zu tun:

Ссылка

    
vincent 08.11.2008 22:51
quelle
0

Erlaubt Python sogar eine solche Verwendung? Ich sollte es dann lernen ...

Ich denke, der Interpreter erwartet nicht, dass irgendein Register geändert wird. Versuchen Sie, die Register zu speichern, die Sie in der Funktion verwenden, wenn Sie Ihre Assembler-Ausgabe so verwenden möchten.

Übrigens unterscheidet sich die Aufrufkonvention von x86_64 von regulären x86. Sie können Probleme haben, wenn Sie die Stapelzeigerausrichtung verlieren und externe Objekte mischen, die mit anderen Werkzeugen erstellt wurden.

    
artificialidiot 08.11.2008 22:21
quelle
0

Es gibt einen einfacheren Ansatz, den ich nur vorgestellt habe, aber in letzter Zeit ist mprotect noch nicht in Benutzung. Einfach den ausführbaren Speicherplatz für das Programm direkt angeben. Heutzutage hat Python ein Modul, um genau das zu tun, obwohl ich keine Möglichkeit gefunden habe, die Adresse des Codes zu bekommen. Kurz gesagt, Sie würden Speicher zuordnen, der mmap aufruft, anstatt Zeichenfolgenpuffer zu verwenden und das Ausführungs-Flag indirekt zu setzen. Dies ist einfacher und sicherer, Sie können sicher sein, dass nur Ihr Code jetzt ausgeführt werden kann.

    
Cheery 28.11.2009 13:22
quelle

Tags und Links