So führen Sie nicht verwaltete ausführbare Dateien aus dem Speicher und nicht von der CD aus

8

Ich möchte ein Befehlszeilendienstprogramm in meine C # -Anwendung einbetten, so dass ich seine Bytes als Array abrufen und die ausführbare Datei ausführen kann, ohne sie als separate Datei auf der Festplatte zu speichern (vermeidet die Speicherung der ausführbaren Datei als separate Datei und vermeidet Fähigkeit, temporäre Dateien irgendwo zu schreiben).

Ich kann keine Methode finden, um eine ausführbare Datei nur aus ihrem Byte-Stream auszuführen. Benötigt Windows es auf einer Festplatte oder gibt es eine Möglichkeit, es aus dem Speicher auszuführen? Wenn es windows erfordert, dass es sich auf der Festplatte befindet, gibt es einen einfachen Weg im .NET-Framework, um ein virtuelles Laufwerk / eine Datei irgendeiner Art zu erstellen und die Datei dem Speicherstrom der ausführbaren Datei zuzuordnen?

    
Triynko 03.08.2009, 19:23
quelle

4 Antworten

11

Sie fordern eine plattformspezifische Funktion auf sehr niedriger Ebene, die in einer verwalteten Umgebung auf hoher Ebene implementiert werden soll. Alles ist möglich ... aber niemand hat gesagt, es wäre einfach ...

(Übrigens, ich weiß nicht, warum Sie denken, dass die Verwaltung von temporären Dateien beschwerlich ist. Die BCL erledigt das für Sie: Ссылка )

  1. Weisen Sie genügend Speicher zu, um die ausführbare Datei zu speichern. Es kann natürlich nicht auf dem verwalteten Heap gespeichert werden, so wie fast alles in dieser Übung müssen Sie PInvoke. (Ich empfehle C ++ / CLI, eigentlich, um sich nicht selbst zu verrückt zu machen). Achten Sie besonders auf die Attributbits, die Sie auf die zugewiesenen Speicherseiten anwenden: Wenn Sie sie falsch eingeben, öffnen Sie entweder ein Sicherheitslücken oder lassen Sie Ihren Prozess von DEP herunterfahren (d. H. Sie werden abstürzen). Siehe Ссылка

  2. Suchen Sie die ausführbare Datei in der Ressourcenbibliothek Ihrer Assembly, und Sie erhalten eine festgelegte Verknüpfung es.

  3. Memcpy () der Code aus der gepinnten Region des verwalteten Heapspeichers in den systemeigenen Block.

  4. Befreie die GCHandle.

  5. Rufen Sie VirtualProtect auf, um weitere Schreibvorgänge in der ausführbaren Datei zu verhindern Speicherblock.

  6. Berechnen Sie die Adresse der Hauptfunktion der ausführbaren Datei im virtuellen Adressraum des Prozesses, basierend auf dem von VirtualAlloc erhaltenen Handle und dem Offset innerhalb der Datei, wie von DUMPBIN oder ähnlichen Tools angezeigt.

  7. Platzieren Sie die gewünschten Befehlszeilenargumente auf dem Stapel. ( Windows Stdcall-Konvention ). Alle Zeiger müssen natürlich auf native oder gepinnte Bereiche zeigen.

  8. Springe zur berechneten Adresse. Am einfachsten zu verwenden _call (Inline-Assemblersprache).

  9. Bete zu Gott, dass das ausführbare Bild keine absoluten Sprünge enthält, die durch den normalen Aufruf von LoadLibrary behoben worden wären. (Es sei denn, Sie möchten die Gehirne von LoadLibrary während Schritt 3 neu implementieren).

  10. Ruft den Rückgabewert aus dem @ eax-Register ab.

  11. Rufen Sie VirtualFree an.

Die Schritte # 5 und # 11 sollten in einem finally-Block ausgeführt werden und / oder das IDisposable-Muster verwenden.

Die andere Hauptoption wäre, ein RAMdrive zu erstellen, die ausführbare Datei dort zu schreiben, sie auszuführen und zu bereinigen. Das ist vielleicht etwas sicherer, weil Sie nicht versuchen, selbst modifizierenden Code zu schreiben (was in jedem Fall schwierig ist, aber besonders, wenn der Code nicht einmal Ihr ist). Aber ich bin ziemlich sicher, dass es noch mehr Plattform-API-Aufrufe als die dynamische Code-Injection-Option erfordern wird - alle von ihnen natürlich C ++ oder PInvoke erfordern.

    
Richard Berg 15.11.2009 21:18
quelle
2

Sehen Sie sich den Abschnitt "Im Speicher" dieses Artikels an. Stellen Sie fest, dass es sich um eine Remote-DLL-Injektionsperspektive handelt, aber das Konzept sollte identisch sein.

Remote Library Injection

    
pcorey 03.08.2009 19:55
quelle
1

Es ist möglich, eine RAM-Disk zu erstellen oder den Code in den Speicher zu schreiben und dann auszuführen, aber extrem komplizierte Lösungen (möglicherweise mehr im verwalteten Code).

Muss es eine ausführbare Datei sein? Wenn Sie es als Assembly verpacken, können Sie Assembly.Load () aus einem Speicherstream verwenden - ein paar triviale Codezeilen.

Oder wenn es wirklich eine ausführbare Datei sein muss, was ist eigentlich falsch daran, eine temporäre Datei zu schreiben? Es dauert ein paar Zeilen Code, um es in eine temporäre Datei zu speichern, auszuführen, zu warten, bis es beendet wird, und dann die temporäre Datei zu löschen - es wird möglicherweise nicht einmal aus dem Platten-Cache gelöscht, bevor Sie es gelöscht haben! Manchmal ist die einfache, offensichtliche Lösung die beste Lösung.

    
Jason Williams 03.08.2009 19:45
quelle
-1

Dies ist in Vista + ausdrücklich nicht erlaubt. Sie können einige undokumentierte Win32-API-Aufrufe in XP verwenden, um dies zu tun, aber es war in Vista zerbrochen, weil es eine massive Sicherheitslücke war und die einzigen Leute, die es nutzten, waren Malware-Autoren.

    
Karl Strings 11.05.2010 17:51
quelle