Hintergrund

Hintergrund

Für die Zwecke dieser Frage nehmen wir an, dass es /path/to/fileim Dateisystem eine Datei () mit einem bestimmten Inhalt wie diesem gibt:

$> cat /path/to/file
this is the content of the
file /path/to/file 

Ich bin zufrieden damit, dass fast alle Prozesse laufen (und Lesezugriff auf diese Datei haben) und diesen Inhalt lesen.
Es sollte jedoch (und das ist der Kern der Frage) ein bestimmter Prozess sein, welcher beim Lesen /path/to/filemit unterschiedlichen Dateiinhalten versorgt werden soll.

$> cat /path/to/file
this is the DIFFERNT content of the
file /path/to/file 

Wie kann ich den Dateiinhalt für einen bestimmten Prozess irgendwie fälschen?

Einige meiner Vermutungen, welchen Weg man einschlagen sollte, hängen mit Folgendem zusammen:

  • Symlink-Trick
  • (Linux) Namespaces (Dateisystem-Namespace) Trick
  • chrootTrick
  • $LD_PRELOADHakentrick
  • Überlagerungen

Meine Plattform ist GNU/Linux, aber wenn es eine POSIX-Möglichkeit gäbe, dies zu erreichen, wäre das noch besser :)

Aktualisieren

Was wäre eine gute Lösung/Antwort?

Ein Kriterium für eine gute Lösung/Antwort wäre, dass es möglich ist, „unterschiedliche Dateiinhalte für bestimmte Prozesse“ zu erreichen, ohne dass eine Interaktion des Root-Benutzers erforderlich ist, obwohl die gefälschte Datei im Idealfall von vornherein nicht vom Benutzer beschreibbar sein sollte.

Ein weiteres gutes Kriterium wäre, dass die dem Prozess angezeigte Änderung des Dateiprozesses spezifisch ist und im Idealfall ohne eine Art Race-Condition erfolgt.

Hintergrund

Mozilla Firefox verwendet zwei Zip-Archive /usr/lib/firefox/omni.jaund /usr/lib/firefox/browser/omni.ja, die einen Großteil des Firefox-Codes enthalten (hauptsächlich das in Javascript geschriebene Zeug). Durch das Fälschen der Datei könnte ich meine Version von Firefox ändern (einige Funktionen einbauen, die ich nicht mehr als Erweiterung implementieren kann, vorausgesetzt, die XPCOM-Unterstützung wurde eingestellt und die Add-On-Signierungserzwingung wird nicht mehr gemocht).

Antwort1

Ja, das Einbinden von Namespaces ist ein Ansatz:

$ cat file
foo
$ cat other-file
bar
$ sudo unshare -m zsh -c 'mount --bind other-file file; USERNAME=$SUDO_USER; cat file'
bar
$ cat file
foo

Oben wird zshdie UID/GID des ursprünglichen Benutzers für den entführten Cat-Befehl verwendet.

Antwort2

Hier ist eine Möglichkeit, dies zu tun mitVorladenum Code zwischen dem Programm und der Systembibliothek einzufügen, und zwar durch ein kleines Stück Code. Dies setzt voraus, dass das Programm eine dynamisch verknüpfte Binärdatei oder ein Skript ist, das von einer dynamisch verknüpften Binärdatei ausgeführt wird (d. h. es ist nicht statisch verknüpft). Schreiben Sie den folgenden Code in eine Datei override_fopen.c:

#include <dlfcn.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#ifndef FROM
#error "Define FROM to the path to override in double quotes, e.g. -DFROM='\"/bad\"'"
#endif
#ifndef TO
#error "Define TO to the path to use instead in double quotes, e.g. -DFROM='\"/good\"'"
#endif
FILE *fopen(const char *path, const char *mode) {
    void *(*original_fopen)(const char *, const char *) = dlsym(RTLD_NEXT, "fopen");
    if (!strcmp(path, FROM)) {
        path = TO;
    }
    return original_fopen(path, mode);
}
int open(const char *path, int oflag, ...) {
    int (*original_open)(const char *, int, ...) = dlsym(RTLD_NEXT, "open");
    int ret;
    va_list args;
    if (!strcmp(path, FROM)) {
        path = TO;
    }
    va_start(args, oflag);
    if (oflag & O_CREAT) {
        ret = original_open(path, oflag, (mode_t)va_arg(args, mode_t));
    } else {
        ret = original_open(path, oflag);
    }
    va_end(args);
    return ret;
}

Kompilieren Sie mit dem folgenden Befehl (das ist für Linux, andere Unix-Varianten erfordern möglicherweise andere Optionen). Beachten Sie die Anführungszeichen um den Pfad, den Sie überschreiben möchten.

gcc -DFROM='"/path/to/file"' -DTO='"/path/to/alternate/content"' -D_GNU_SOURCE -O -Wall -fPIC -shared -o override_fopen.so override_fopen.c -ldl

Führen Sie das Programm wie folgt aus (unter OSX verwenden Sie DYLD_PRELOADanstelle von LD_PRELOAD):

LD_PRELOAD=./override_fopen.so ./myexe

fopenDies funktioniert nur, wenn das Programm die Bibliotheksfunktion oder aufruft open. Wenn es eine andere Funktion aufruft, müssen Sie diese überschreiben. Sie können verwendenltraceum zu sehen, welche Bibliotheksaufrufe das Programm macht.

verwandte Informationen