Nur aus Neugier frage ich mich, ob es möglich ist, einen Teil des Codes während der Laufzeit des Programms zu verschieben. der Ausführung eines Programms zu verschieben. Ich habe zum Beispiel eine Funktion und diese Funktion soll jedes Mal im Speicher ersetzt werden, nachdem sie ausgeführt worden ist. Eine Idee, die uns in den Sinn kam ist die Verwendung von selbstmodifizierendem Code für diesen Zweck. Einigen Online-Ressourcen zufolge kann selbstmodifizierender Code unter Linux ausgeführt werden, aber ich bin mir immer noch nicht sicher, ob eine solche dynamische Verschiebung möglich ist. Hat jemand Erfahrung damit?
Antworten
Zu viele Anzeigen?Ja, eine dynamische Verlagerung ist durchaus möglich. Sie müssen jedoch sicherstellen, dass der Code vollständig in sich geschlossen ist oder dass er auf globale/externe Funktionen über absolute Referenzen zugreift. Wenn Ihr Code völlig positionsunabhängig sein kann, d. h. die einzigen Verweise, die er macht, sind relativ zu ihm selbst, sind Sie bereit. Andernfalls müssen Sie die Korrekturen zum Zeitpunkt des Ladens selbst vornehmen.
Mit GCC können Sie -fpic
um positionsunabhängigen Code zu erzeugen. Übergabe -q
o --emit-relocs
an den Linker, damit dieser Informationen über den Standortwechsel ausgibt. Die ELF-Spezifikation (PDF-Link) enthält Informationen darüber, wie diese Umzugsinformationen verwendet werden können; wenn Sie nicht ELF verwenden, müssen Sie die entsprechende Dokumentation für Ihr Format finden.
Wie Carl sagt, ist es möglich, aber Sie öffnen damit ein Wespennest. In der Praxis sind die einzigen Leute, die sich die Mühe machen, dies zu tun, Akademiker oder Malware-Autoren (die jetzt meinen flammensicheren Mantel anziehen).
Sie können etwas Code in einen malloc'd Heap-Bereich kopieren und ihn dann über Funktionszeiger aufrufen, aber je nach Betriebssystem müssen Sie möglicherweise die Ausführung in dem Segment aktivieren. Sie können versuchen, etwas Code in das Codesegment zu kopieren (wobei Sie darauf achten müssen, dass Sie die folgende Funktion nicht überschreiben), aber das Betriebssystem hat dieses Segment wahrscheinlich schreibgeschützt gemacht. Schauen Sie sich den Linux-Kernel an, um zu sehen, wie er seine Module lädt.
Wenn all diese verschiedenen Funktionen zur Kompilierzeit existieren, könnten Sie einfach einen Funktionszeiger verwenden, um die nächste aufzurufende Funktion zu verfolgen. Wenn Sie die Funktion unbedingt zur Laufzeit ändern müssen und diese Änderung nicht an Ort und Stelle vorgenommen werden kann, könnten Sie auch einen Funktionszeiger verwenden, der mit der Adresse der neuen Funktion aktualisiert wird, wenn diese erstellt/geladen wird. Der Rest Ihres Systems würde dann die sich selbst modifizierende Funktion über den Funktionszeiger aufrufen und müsste daher den sich selbst modifizierenden Code nicht kennen oder sich darum kümmern, und Sie müssten die Korrektur nur an einer Stelle vornehmen.