2009-06-25 13 views
2

Ich entwickle eine Bibliothek, die eine oder mehrere ausführbare Hilfsprogramme im Verlauf der Geschäftstätigkeit verwendet. Meine aktuelle Implementierung erfordert, dass der Benutzer das ausführbare Hilfsprogramm auf dem System an einem bekannten Speicherort installiert hat. Damit die Bibliothek ordnungsgemäß funktioniert, muss sich die Hilfsanwendung an der richtigen Position befinden und die richtige Version sein.Entpacken einer ausführbaren Datei aus einer Bibliothek in C/C++

Ich möchte die Anforderung, dass das System in der oben beschriebenen Weise konfiguriert werden.

Gibt es eine Möglichkeit, die ausführbare Hilfsdatei in der Bibliothek so zu bündeln, dass sie zur Laufzeit entpackt, in einem temporären Verzeichnis installiert und für die Dauer eines Laufs verwendet werden kann? Am Ende des Laufs konnte die temporäre ausführbare Datei entfernt werden.

Ich habe überlegt, automatisch eine Datei zu generieren, die ein Zeichenfeld ohne Vorzeichen enthält, das den Text der ausführbaren Datei enthält. Dies würde zur Kompilierzeit als Teil des Build-Prozesses erfolgen. Zur Laufzeit wird diese Zeichenfolge in eine Datei geschrieben, wodurch die ausführbare Datei erstellt wird.

Wäre es möglich, eine solche Aufgabe auszuführen, ohne die ausführbare Datei auf eine Diskette zu schreiben (vielleicht eine Art RAM-Diskette)? Ich könnte mir vorstellen, dass bestimmte Virenscanner und andere Sicherheitssoftware gegen eine solche Operation protestieren. Gibt es andere Sorgen, um die ich mir Sorgen machen sollte?

Die Bibliothek wird in C/C++ für den plattformübergreifenden Einsatz unter Windows und Linux entwickelt.

+1

Fügen Sie die Hilfefunktionalität in lib und fork(), aber nicht exec() ein. Nicht sicher über Windows obwohl – sigjuice

Antwort

2

Sie können xxd verwenden, um eine Binärdatei in eine C-Headerdatei zu konvertieren.

$ echo -en "\001\002\005" > x.binary 

$ xxd -i x.binary 
unsigned char x_binary[] = { 
    0x01, 0x02, 0x05 
}; 
unsigned int x_binary_len = 3; 

xxd ist ziemlich Standard auf * nix-Systemen, und es ist verfügbar unter Windows mit Cygwin oder MinGW oder Vim enthält es im Standard-Installationsprogramm auch. Dies ist eine extrem plattformübergreifende Möglichkeit, binäre Daten in kompilierten Code einzubinden.

Ein weiterer Ansatz ist objcopy zu verwenden, um Daten anzuhängen, auf das Ende einer ausführbaren - IIRC Sie könnenobjcopy erhalten und es für PEs auf Windows zu verwenden.

Ein Ansatz, den ich ein wenig besser als das ist, ist, nur Rohdaten direkt an das Ende Ihrer ausführbaren Datei anhängen. In der ausführbaren Datei suchen Sie bis zum Ende der Datei und lesen eine Zahl ein, die die Größe der angehängten Binärdaten angibt. Dann suchen Sie rückwärts so viele Bytes und fread diese Daten und kopieren Sie es in das Dateisystem, wo Sie es als ausführbare Datei behandeln könnten. Dies ist übrigens the way that many, if not all, self-extracting executables are created.

Wenn Sie die Binärdaten anhängen, funktioniert es sowohl mit Windows PE-Dateien als auch mit * nix ELF-Dateien - keiner von beiden liest das "Limit" der ausführbaren Datei.

Natürlich, wenn Sie mehrere Dateien anhängen müssen, können Sie entweder eine tar/zip-Datei an Ihre exe anhängen, oder Sie benötigen eine etwas weitergehende Datenstruktur, um zu lesen, was angehängt wurde.

Sie möchten wahrscheinlich auch Ihre ausführbaren Dateien UPX, bevor Sie sie anhängen.

Sie könnten auch interessiert sein an der LZO library, die eine der am schnellsten dekomprimierenden Komprimierungsbibliotheken ist. Sie haben eine MiniLZO-Bibliothek, die Sie für einen sehr leichten Dekompressor verwenden können. Die LZO-Bibliotheken sind jedoch GPL-lizenziert, sodass möglicherweise bedeutet, dass Sie es nicht in Ihren Quellcode aufnehmen können, es sei denn, Ihr Code ist ebenfalls GPL. Auf der anderen Seite sind kommerzielle Lizenzen verfügbar.

1

Ein etwas anderer Ansatz als die Verwendung eines vorzeichenlosen char * -Arrays besteht darin, die gesamte ausführbare Binärdatei als Ressource der DLL zu verwenden. Zur Laufzeit können Sie die Binärdaten als lokale temporäre Datei speichern und die App ausführen. Ich bin mir nicht sicher, ob es eine Möglichkeit gibt, eine ausführbare Datei im Speicher auszuführen.

6

"Eine kluge Person löst ein Problem. Eine weise Person vermeidet es." - Albert Einstein

Im Geiste dieses Zitats empfehle ich, dass Sie einfach diese ausführbare Datei zusammen mit der Endanwendung bündeln.

Nur meine 2 Cent.

+0

Ich mag das Zitat :) +1 –

+0

Mein Ziel ist es zu vermeiden, die Entwickler der Endanwendung (sei es meine Organisation oder eine dritte Partei) von der Verwaltung der Hilfsanwendungen zu zwingen. – Marc

+1

@Marc, ich verstehe, und ich schätze Ihren Ehrgeiz. Versuche es. Schreibe die Datei im RAM aus und starte sie von dort. Ich weiß nicht, wie das geht, bitte posten Sie Ihre Lösung, wenn Sie sie finden. Ich habe dieses kleine Hilfsprogramm gefunden, vielleicht wird es helfen: http://deadnode.org/sw/bin2h/ – StackedCrooked

0

Es gibt eine Möglichkeit in Windows, eine ausführbare Datei aus dem Speicher auszuführen, ohne sie auf die Festplatte zu schreiben. Das Problem ist, dass dies aufgrund moderner Sicherheitssysteme (DEP) wahrscheinlich nicht auf allen Systemen funktioniert und fast jeder Anti-Malware-Scanner wird es erkennen und den Benutzer warnen.

Mein Rat ist einfach die ausführbare Datei in Ihre Distribution zu packen, es ist sicherlich der zuverlässigste Weg, dies zu erreichen.

+0

DEP ist überhaupt kein Problem. Sie müssen Windows lediglich mitteilen, dass es einen Speicherblock jetzt als Code und nicht mehr als Daten behandeln soll. Und dieser Funktionsaufruf muss offensichtlich aus dem vorhandenen Code stammen. Selbst Programme, die dumm genug sind, um gets() aufzurufen, werden diesen Puffer später nicht als ausführbar markieren. – MSalters

1

Für die Bibliothek richtig der Helfer funktionieren App in der richtigen Lage sein muss

Unter Windows würde, dass das Programmverzeichnis oder System32-Verzeichnis sein?

Dies könnte ein Problem sein. Wenn eine Anwendung installiert wird, insbesondere in einer Unternehmensumgebung, geschieht dies normalerweise in einem Kontext mit Administratorrechten. Unter Vista und später mit aktiviertem UAC (Standardeinstellung) ist dies erforderlich, um in bestimmte Verzeichnisse zu schreiben. Und die meisten Unix-Varianten haben so lange vernünftige Einschränkungen, wie sich jeder erinnern kann.

Wenn Sie es also zu dem Zeitpunkt versuchen, an dem die Host-Anwendung in Ihre Bibliothek aufruft, befinden sich diese möglicherweise nicht in einem Kontext mit ausreichenden Rechten zum Installieren der Dateien, sodass Ihre Bibliothek die Hostanwendung einschränkt.

(andere Sache, die ausgeschlossen wird, ist Registry Änderungen oder Konfigurationsdatei-Updates auf den verschiedenen Unix-Varianten, wenn die Host-Anwendung nicht die Fähigkeit hat, den Prozess zu administrativer Ebene zu heben.)

Having sagte alles, du sagst du denkst darüber nach, die Helfer in ein temporäres Verzeichnis auszupacken, also ist das vielleicht alles verwerflich.

0

Nun, mein erster Gedanke wäre: Was macht diese Hilfsdatei, die nicht innerhalb des Codes Ihrer Bibliothek selbst ausgeführt werden könnte, vielleicht mit einem sekundären Thread, wenn nötig. Dies könnte etwas zu berücksichtigen sein.

Aber wie für die eigentliche Frage ... Wenn Ihre "Bibliothek" tatsächlich als DLL (oder sogar eine EXE) gebündelt ist, dann hat zumindest Windows relativ einfache Unterstützung für das Einbetten von Dateien in Ihrer Bibliothek.

Der Ressourcenmechanismus, der ermöglicht, dass Versionsinformationen und Symbole in ausführbare Dateien eingebettet werden, kann auch beliebige Datenblöcke zulassen. Da ich nicht weiß, welche Entwicklungsumgebung Sie verwenden, kann ich nicht genau sagen, wie das geht. Aber grob gesagt, müssten Sie eine benutzerdefinierte Ressource mit einer Art von "FILE" oder etwas Sinnvollem erstellen und auf die Exe zeigen, die Sie einbetten möchten.

Dann, wenn Sie es extrahieren möchten, können Sie so etwas wie

HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(IDR_MY_EMBEDDED_FILE), "FILE"); 
HGLOBAL hResourceData = LoadResource(NULL, hResource); 
LPVOID pData = LockResource(hResourceData); 
HANDLE hFile = CreateFile("DestinationPath\\Helper.exe", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
DWORD dwBytesWritten = 0; 
WriteFile(hFile, pData, SizeofResource(NULL, hResource), &dwBytesWritten, NULL); 
CloseHandle(hFile); 

(Füllung in Ihrem eigenen gewünschten Pfad, Dateiname und jede geeignete Fehlerprüfung natürlich)

Danach schreiben würde, Die helper exe existiert als normale exe-Datei und kann somit wie gewohnt ausgeführt werden.

Um die Datei nach der Verwendung zu entfernen, sollten Sie die Flags für CreateFile, insbesondere FILE_FLAG_DELETE_ON_CLOSE untersuchen. Sie können auch mit MoveFileEx betrachten, wenn Sie das MOVEFILE_DELAY_UNTIL_REBOOT-Flag mit NULL kombinieren, das für den neuen Dateinamen übergeben wird. Und natürlich können Sie es jederzeit in Ihrem eigenen Code löschen, wenn Sie wissen, wann die ausführbare Datei beendet wurde.

Ich weiß nicht genug über ausführbare Linux-Dateien, daher weiß ich nicht, ob dort eine ähnliche Funktion verfügbar ist.

Wenn Linux keinen geeigneten Mechanismus bietet und/oder diese Idee nicht Ihren Anforderungen in Windows entspricht, dann nehme ich an, dass Ihre Idee, aus dem Inhalt der helper exe ein Zeichenfeld ohne Vorzeichen zu generieren, das nächste wäre beste Möglichkeit, die exe in Ihre Bibliothek einzubetten.

1

Qt hat eine ausgezeichnete Methode, dies zu erreichen „Das Qt Ressourcensystem eine Plattform-unabhängige Mechanismus zum Speichern von Binärdateien in der ausführbaren Datei der Anwendung ist“ QResource

Sie sagen nicht, wenn Sie derzeit Qt verwenden, aber Sie sagen "C++ für Cross-Plattform-Nutzung unter Windows und Linux", also wenn Sie es nicht verwenden möchten, sollten Sie vielleicht in Betracht ziehen.

Verwandte Themen