Snapshot eines laufenden Prozesses erstellen



  • Hallo,

    mich plagt gerade eine verrückte Idee: nämlich die Möglichkeit, von einem laufenden Prozeß einen "Snapshot" zu erstellen, also eine Momentaufnahme eines Zustandes, in den man ihn später zurückversetzen könnte.

    Meine anfängliche Überlegung war:

    • Die Sache wird natürlich vollkommen verunmöglicht, wenn externe Ressourcen mit hineinspielen, also nehmen wir an, ich hätte volle Kontrolle über den Austausch meines Prozesses mit der Außenwelt.
    • Zunächst, wie VMMap (http://technet.microsoft.com/en-us/sysinternals/dd535533.aspx) es macht, alle Speicherseiten des Prozesses zu enumerieren, und wann immer Schreibzugriff besteht, diesen zu entfernen. Wird dann in die Seite geschrieben, so tritt eine Zugriffsverletzung auf, die ich mit einem Exception-Filter abfangen kann. Der Exception-Filter macht dann eine "Sicherheitskopie" der Speicherseite, ändert die Seitenzugriffsrechte und läßt den Prozeß dann weiterlaufen.
      Dabei stellt sich natürlich die Frage: wie kommt VMMap an diese schöne Memory-Page-Auflistung? Muß ich dafür irgendwelche undokumentierten (bzw. nur fürs DDK dokumentierten) Kernel-APIs benutzen?
    • Dann von allen laufenden Threads den Thread-Kontext sichern.
    • Schließlich die relevanten Speicherverwaltungsfunktionen (VirtualAlloc und wahrscheinlich ein paar andere) "umbiegen" (-> Detours), so daß ich die Freigabe bestehender Pages verhindern, die Allokation neuer Pages protokollieren und somit das gesamte Speicherlayout in den alten Stand zurückversetzen kann.

    Wenn mich nicht alles täuscht, sollte das im Prinzip so funktionieren. Hat jemand dazu hilfreiche Tipps und Ratschläge oder weiterführende Informationen? Habe ich etwas Wichtiges übersehen? Und wie komme ich denn an eine Liste der Speicherseiten des Prozesses?

    Sollte es einen guten Grund geben, warum dieses Unterfangen vollkommen aussichtslos ist, so wüßte ich ihn natürlich auch gern 😉



  • audacia schrieb:

    Dabei stellt sich natürlich die Frage: wie kommt VMMap an diese schöne Memory-Page-Auflistung? Muß ich dafür irgendwelche undokumentierten (bzw. nur fürs DDK dokumentierten) Kernel-APIs benutzen?

    Das habe ich mittlerweile herausgefunden: VMMap ruft einfach VirtualQuery() auf und übergibt sukzessive alle infrage kommenden Blockadressen, angefangen bei der 0 und mit Inkrement MEMORY_BASIC_INFORMATION::RegionSize.


  • Mod

    Das wird für einen ganzen Prozess nicht funktionieren, weil Du auch die enzelnen Zustände der Systemhandles archivieren müsstest. Dito: Was ist mit Zuständen Deiener COM-Objekte...
    An manche Daten kommst Du gar nicht ran (Fenster-Handle etc.). Wie willst Du deren Zustand archivieren und wieder herstellen?

    Auf Klassenbasis ist so etwas nicht so schwer...

    Ansonsten: Wenn es genügt zu debuggen, dann ist ein Minidump alles was Du brauchst um einen Snapshot eines Prozesses herzustellen.



  • Martin Richter schrieb:

    Das wird für einen ganzen Prozess nicht funktionieren, weil Du auch die enzelnen Zustände der Systemhandles archivieren müsstest. Dito: Was ist mit Zuständen Deiener COM-Objekte...
    An manche Daten kommst Du gar nicht ran (Fenster-Handle etc.). Wie willst Du deren Zustand archivieren und wieder herstellen?

    Man könnte es doch auf Kernelebene machen.



  • Martin Richter schrieb:

    Das wird für einen ganzen Prozess nicht funktionieren, weil Du auch die enzelnen Zustände der Systemhandles archivieren müsstest.

    Das würde wieder auf die Ressourcenfrage hinauslaufen.

    Alle vom Prozeß beanspruchte Handles kann ich doch im Process Explorer einsehen, richtig? Wenn das so ist, dann dürfte das unproblematisch sein. Die einzigen Handles darunter, die der Prozeß selbst verwaltet, werden Datei-Handles sein, und den Dateisystemzugriff werde ich ohnehin virtualisieren.

    Martin Richter schrieb:

    Dito: Was ist mit Zuständen Deiener COM-Objekte...

    Es gibt keine. Der Prozeß ruft, glaube ich, nicht einmal CoInitialize() auf.

    Martin Richter schrieb:

    An manche Daten kommst Du gar nicht ran (Fenster-Handle etc.). Wie willst Du deren Zustand archivieren und wieder herstellen?

    Fensterhandles gibt es auch keine. Bis jetzt sind mir tatsächlich nur Datei-Handles aufgefallen.

    Martin Richter schrieb:

    Wenn es genügt zu debuggen

    Nein, der Prozeß soll nach dem Zurücksetzen schon noch einen Zweck erfüllen 😉


  • Mod

    Also das wird nicht gelingen...
    Wie willst Du mit Threads verfahren?
    Mit Critical Sections, die einem Thread in einem bestimmten Moment gehören etc.?
    Wie willst Du einen Zustand so einfrieren, dass Du genau weißt wem welche Semaphoren gehören?
    Selbst wenn Du Datenbank I/O virtualisierst. Du müsstest den Zustand des I/Os komplett in Deinem Snapshot einfrieren.
    Handles gibt es viele: z.B. Events etc...
    Wie willst Du den Zustand einer CRT funktionierend einfrieren wenn Du nicht mal Ihre komlette Funktionsweise mit Sicherheit kennst?
    Wer entlädt DLLs die in der zwwischenzeit geladen wurden und ein eigenes Leben im Speicher entwickleln?

    Ich bleibe dabei: Bezogen auf einzelne Klassen lässt sich so ein Snapshot sicher realisieren. Bezogen auf einen Prozess mit Sicherheit nicht.



  • Martin Richter schrieb:

    Wie willst Du mit Threads verfahren?

    Guter Punkt. -> Annahme: es gibt nur einen. Alles ist singlethreaded.

    Martin Richter schrieb:

    Mit Critical Sections, die einem Thread in einem bestimmten Moment gehören etc.?
    Wie willst Du einen Zustand so einfrieren, dass Du genau weißt wem welche Semaphoren gehören?

    Erledigt sich mit dem Verzicht auf das Unterstützen mehrerer Threads.

    Martin Richter schrieb:

    Selbst wenn Du Datenbank I/O virtualisierst.

    Datenbankzugriff wäre Zugriff auf eine externe Ressource, das habe ich per Voraussetzung ausgeschlossen.

    Martin Richter schrieb:

    Wie willst Du den Zustand einer CRT funktionierend einfrieren

    Indem ich den Inhalt aller Speicherseiten sowie alle Thread-Kontexte (bzw. nur den einen des Primärthreads, da es ja keine anderen gibt) sichere und später rekonstruiere.

    Martin Richter schrieb:

    wenn Du nicht mal Ihre komlette Funktionsweise mit Sicherheit kennst?

    Die kenne ich; ich habe ja den Quelltext. Das ist aber eigentlich nicht wichtig, oder?

    Martin Richter schrieb:

    Wer entlädt DLLs die in der zwwischenzeit geladen wurden

    Es werden keine DLLs geladen.

    Wie bereits oft gesagt: nimm an, daß ich volle Kontrolle über den Austausch des Prozesses mit der Außenwelt habe. Auch darüber, welche DLLs er lädt, welche Dateien er öffnet, ob er Threads erstellt, welche Prozesse er startet etc.

    Martin Richter schrieb:

    Bezogen auf einen Prozess mit Sicherheit nicht.

    Auch dann nicht, wenn du alle oben erwähnten Annahmen machst?


Log in to reply