Problem schreiben:
ich eine neue (einzelne Seite) Textsegment im Speicher zugeordnet werden soll, und führen Sie es ohne viel Montage zu schreiben, aus einem C-Programm. Um dies zu tun, bin ich eine C-Funktion des Programms selbst zu duplizieren, und ich setze ein Flag, also wenn ich zu ihm springen einen anderen Pfad in der Funktion aufgerufen wird. Sie können es als dumm denken, aber es ist das gleiche, was wir tun, wenn wir zum Beispiel fork()
einen Prozess.C: Führen Sie eine manuell mmaped Textsegment ohne viel Montage
Warum
ich eine minimale Erfassung und Wiedergabe-Mechanismus auf Android implementiert haben, link. Derzeit verwende ich eine nicht so elegante Möglichkeit, echte Android-Apps wiederzugeben, die ASLR deaktiviert, und abgesehen von Sicherheitslücken (die jetzt einfach ignoriert werden können), verursacht es uns einige andere Probleme. Also von einem reinen C-Prozess möchte ich einen Übergang machen und eine Android-Funktion wiedergeben. Wenn ich den folgenden Ansatz zur Arbeit mache, wird es viel besser sein, dass der aktuelle, der auf die erste Android-Funktion eingreift, die aufgerufen wird und zum Hauptthread gehört, und .. bla bla ..!
Ansatz:
In einem C-Programm I ein Textsegment am abbildet, die im Grunde eine Kopie einer C-Funktion des Programms selbst ist. Um dies zu tun, rufe ich eine Funktion namens entrypoint
einmal, bekomme ich den Programmzähler, setzen Sie ein Flag und zurück. Dann mmap ich eine Seite im Speicher (die Code-Größe der Einstiegspunkt-Funktion sollte nicht größer sein, dass dies) sagen wir bei 0xabc000
, und ich kopiere darin eine Seite von dem PC aus, die ich habe. Das bedeutet, dass die Seite abc
ein Duplikat des Textes/Codes vom PC bis mindestens zum Ende der Einstiegspunktfunktion enthalten sollte (eine Seite, die grundsätzlich von pc ausgeht) Ich setze die Berechtigungen der Seite abc
auf ausführbar, und ich springe zu es.
Und ich bekomme eine Segmentierung Verletzung. Aber ich möchte wissen, WARUM?
Beispielcode:
bool entered_ = false;
void *pc_ = 0x0;
void entrypoint() {
if(!entered_){
entered = 1;
pc_ = GET_PROGRAM_COUNTER();
return;
}
// ..
// SPECIAL CODE
// ..
}
int main(..) {
entrypoint();
// map a new rdwr private page (4096)
newtextseg = mmap(..args..);
// copy 1 page of text from this application's text segment,
// starting from the point where I got the pc
memcpy(newtextseg, pc, PAGE_SIZE);
// give exec permissions to newtextseg
mprotect(..args);
// Jump to the code, and expect the
// SPECIAL CODE to run
JUMP(newtextseg);
}
Zusätzliche Informationen
Die C-Bibliothek ist statisch mit meiner Anwendung verknüpft. Ich führe dies auf einem Android-Gerät mit Arm-Architektur. Leider gibt das Betriebssystem keine Informationen über die Segmentierung, da es sich um einen reinen C-Prozess handelt, der statisch mit libc verknüpft ist. Es gibt nichts, was Android dort betrifft. Nicht einmal llog
.
Annahmen
Montagevorgänge korrekt sind (für immer und PC Springen). Auch die Ergebnisse der Aufrufe von mmap und mprotect werden überprüft, und ich überprüfe die Datei proc/self/maps
.
Zufällige Gedanken:
Da ich statisch mit libc verbunden bin, und ich bin einige printf
‚s zum entrypoint
für Debugging-Zwecke zu tun, könnte es der Fall sein, dass die Zeiger auf die Funktionen von Offset einige behoben haben der Anfang des ursprünglichen Code-Segments (das, das ich entrypoint
von kopiert habe), also, wenn ich versuche, aus einem anderen Offset Dinge zu brechen brechen?
Sie sollten zumindest als Position unabhängigen Code kompilieren. Um den PC zu bekommen, können Sie einfach den Namen der Funktion verwenden. Wenn Sie einen segfault erhalten, müssen Sie einen Debugger verwenden und uns zeigen, wo der Fehler liegt. – Jester
@Jester Leider lief ich dies auf einem Android-Gerät und kein Ereignis wird vom Betriebssystem für die 'SEGV' generiert. Nicht einmal ein "Tombstone" wird erstellt, was passiert, wenn ein Prozess unter Android abstürzt. – Paschalis
Ich denke, dass ich es auf x86 mit dem richtigen Debuggen testen und dann auf Arm übertragen muss. – Paschalis