Arbeitsverzeichnis von fremder Anwendung verändern



  • Wir haben folgendes Problem:

    Auf einer CD befindet sich eine verschlüsselte Exe Datei. Die wird dann von einem Programm entschlüsselt und in ausführbarer Form auf die Festplatte kopiert.

    Dannach wird sie gestartet. Das Problem ist jetzt, dass sie ja jetzt nicht mehr in ihrem Verzeichnis auf der CD ist, wo es noch andere Dateien wie zB dlls gibt, auf die sie zugreift.
    Die Frage ist jetzt, wie ich die Exe auf der HD starten kann und ihr dann sofort den Pfad auf der CD mitteilen kann, den sie (bzw. Windows) dann auch als Standardpfad benutzen soll.

    Geht das überhaupt? Und wenn ja, wie 😕



  • Vielleicht klappt es, wenn du bei CreateProcess (oder wie startest du die Anwendung) ind lpCurrentDirectory das gewünschte Laufwerk und Verzeichnis angibst 🙄



  • Bah bin ich doof! So einfach kann es sein, wenn man sich mal die Doku richtig anschaut. *schäm*

    Danke.

    Wenn das dann doch nicht klappt, meld ich mich wieder 🙄



  • Wie auch nicht anderst zu erwarten war melde ich mich jetzt wieder 😉

    Die Sache mit CreateProcess und dem übergebenen Arbeitsverzeichnis funktioniert grundsätzlich sehr gut.
    Das Problem ist nur, dass manche Anwendungen anscheinend nicht den Pfad benutzen wollen, den man ihnen übergibt.
    (Als Arbeitspfad übergeb ich ihnen immer den Ort, wo sie sich selbst drin befinden d.h. ihre verschlüsselte Version. Die exe, die letztendlich augeführt wird, befindet sich direkt auf c: Aber das ist eigentlich nicht sonderlich von Interesse.)

    Die Frage ist jetzt, wie ich dem Programmen 'befehlen' kann, meinen Pfad zu benutzen. Wenn es zB sowas wie SetModuleFilename( hProcess, strPfad ) gäbe, könnte man dem Programm was vorgaukeln. Sowas gibts aber leider nicht.

    Weiß jemand einen Rat 😕



  • Hi!

    So wie ich es verstanden habe, stammt das verschlüsselte Programm nicht von euch. Nur der Ver-/Entschlüsseler kann geändert werden, richtig?

    Wenn ja, dann:
    In den meisten Fällen sollte es ja schon genügen, den CurrentPath entsprechend zu setzen, denn LoadLibrary o.ä. suchen ja zuerst im aktuellen Pfad und danach erst im Pfad der Anwendung-Exe. Problematisch wirds nur dann, wenn die Anwendung zuerst über GetModuleFilename den Pfad der exe ermittelt und dann in diesem Pfad etwas sucht. Das Ziel wäre also, das Ergebnis der Funktion GetModuleFilename zu beeinflussen.

    Ein möglicher Weg wäre (keine Garantie, dass ich nichts übersehen habe):
    1. Ihr schreibt eine kleine DLL, die eine Funktion exportiert, die den Pfad zur Exe auf der CD zurückliefert.
    2. Ihr startet die Anwendung über CreateProcess mit dem Flag CREATE_SUSPENDED, damit die Anwendung nicht sofort los rennt.
    3. Ihr ermittelt über den EXE-Header die Startadresse des Codes in dieser Anwendung.
    4. Ihr merkt euch die ersten Paar Bytes an dieser Adresse und schreibt mit WriteProcessMemory an diese Startadresse den ASM-Befehl zum Aufruf von LoadLibrary, der dann eure eigene kleine DLL in den Adressraum der fremdem Anwendung lädt. Kopiert nur so viele Bytes wie auch der Maschinenbefehl für den LoadLibrary-Call belegt. Vorher müsst ihr noch den String "kernel32.dll" in den fremden Adressraum bekommen. Dazu könnt ihr VirtualAllocEx verwenden und dann wieder mit WriteProcessMemory den String rüberkopieren. Unter W98 ist das nicht nötig, da der Speicher oberhalb von 2GB von allen Prozessen gemeinsam genutzt wird.
    5. Jetzt kannst du mit ResumeThread die Anwendung laufen lassen.
    6. In der DLL (DllMain()), die ja jetzt sofort aufgerufen wird, kannst du dann mit LoadLibrary und GetProcAddress die Adresse der Funktion GetModuleFilename ermitteln. Nun überschreibst du in gleicher Weise wie oben die ersten Bytes der Funktion GetModuleFilename mit einem Sprung an die Adresse an der deine eigene GetModuleFilename aus (1) liegt.
    7. Jetzt führst du noch den gesicherten Code aus (4) aus und schreibst ihn sicherheitshalber zurück an seine Originalposition. LoadLibrary kehrt dann zurück an den Anfang des Originalprogramms (wo ja mittlerweile nicht mehr der Aufruf von LoadLibrary steht. Dann ist hier alles wieder so, wie es mal war. Das was überschrieben war, hast du ja eben gerade ausgeführt und die Ausführung geht dann mit der ersten Anweisung weiter, die bisher unberührt geblieben ist.

    Das Originalprogramm läuft los und immer wenn es seinen eigenen Exe-Pfad rausbekommen will, liefert deine eigene GetModuleFilename-Funktion den Pfad der Exe auf CD zurück.

    Alternativ zu 6 könnte man auch den Importabschnitt der Exe abändern(ImageDirectoryEntryToData).

    Sollten dir noch andere API-Funktionen einfallen, die den Exe-Pfad zurückliefern, musst du natürlich vorsichtshalber auch diese durch eigene ersetzen.

    Diese Herangehensweise ist zwar ziemlich heavy, aber eine andere Lösung fällt mir nicht ein. Wahrscheinlich sind hier noch viele kleine Hürden drin versteckt, an die ich gerade nicht denke (Sorgen macht mir noch Punkt 6 wegen JMP vs. CALL. Hier müsstest du aufpassen, damit der Stack beim Rücksprung nicht durcheinander gerät), aber es sollte zumindest mal eine Idee für euch sein.

    mfg
    Klaus



  • Danke Klaus, für Deine mächtige Antwort 😉

    Also 'heavy' ist dafür gar kein Ausdruck! Aber das ganze hört sich sehr spannend an und ich glaube, wenn ich das hinbekommen würde, wäre ich so stolz wie seit meinem ersten Basic-Programm nicht mehr 😃

    Einige Sachen hab ich beim 3. mal Durchlesen noch nicht geblickt, aber ich werd das ganze morgen (bzw in den nächsten Tagen) mal angehen.

    Ich werd dann versuchen, mehr Google.de anstatt dem Forum hier zu belästigen. Aber ich fürchte, es wird sich nicht vermeiden lassen 😉



  • Also vertreiben wollte ich dich damit nicht....

    Mir ist noch etwas eingefallen:
    Unter W9x ist die kernel32.dll geschützt, so dass du deren Speicher nicht überschreiben kannst. Um es trotzdem zu können, müsstest du einen virtual device driver (vxd) machen 😉



  • warp schrieb:

    Unter W9x ist die kernel32.dll geschützt, so dass du deren Speicher nicht überschreiben kannst. Um es trotzdem zu können, müsstest du einen virtual device driver (vxd) machen 😉

    Also ne, jetzt wirds mir zu bunt 😉

    Mein Praktukum endet hier in 2 Wochen, bis dahin wäre ich damit bei weitem überfordert.

    Ich werd mich mit der ganzen Sache (exe manipulieren usw.) aber privat weiterbeschäftigen, das reizt mich doch schon ziemlich....

    P.S: Zu meinem ursprünglichen Problem: Ich habe jetzt eine ziemlich unschöne, aber dafür funktionierende Variante realisiert:
    Das ganze Programm, das installiert werden soll, wird jetzt einfach mit allem drum und dran auf die HD kopiert, dort wird die exe entschlüsselt und gestartet.



  • warp schrieb:

    P.S: Zu meinem ursprünglichen Problem: Ich habe jetzt eine ziemlich unschöne, aber dafür funktionierende Variante realisiert:
    Das ganze Programm, das installiert werden soll, wird jetzt einfach mit allem drum und dran auf die HD kopiert, dort wird die exe entschlüsselt und gestartet.

    Das machen sogar viele Installer so. Entpacken das eigentliche Installationsprogramm in ein Temp Verzeichnis auf der Festplatte und starten das dann dort. (-> Installation wird vorbereitet)



  • So, da bin ich schon wieder.
    Ich habe es jetzt gemacht wie Klaus es im Prinzip gesagt hat (etwas einfacher, wie ich finde)

    1.) Mit CreateProcess die Exe, die allein auf der Festplatte ist starten (CREATE_SUSPENDED)

    2.) Mit CreateRemoteThread wird in den fremden Prozess meine Dll geladen, die da dann folgendes tut:

    2a.) Den ganzen Speicher der Anwendung nach der Adresse von 'GetModuleFileNameA/W' scannen, und diese dann mit der Adresse meiner eigenen Funktion ersetzen (die sich auch in der Dll befindet)

    3.) Exe laufen lassen, mit ResumeThread()

    Das ist das Prinzip, und es klappt eigentlich auch. Er findet immer einen Aufruf der Funktion und ersetz ihn.
    Das Problem ist jetzt aber, dass es erstens nach wie vor nicht funktioniert (Setup.exe meckert, dass ihm dateien fehlen) und außerdem wird MyGetModuleFileName() nie aufgerufen. Ich habe zum Test eine MessageBox reingemacht.

    Meine Vermutung ist jetzt, dass sich diese Setup.exe noch ein paar dll Dateien lädt (die tatsächlich dabei sind) und erst in diesen wird dann der Pfad irgendwie ermittelt. Das ganze passiert aber erst nachdem ich den Speicher gescannt habe, es werden also nicht alle 'GetModuleFileName()'s ersetzt.

    So, ich hoffe dass das jetzt irgendjemand blickt 🙄
    Ist meine Überlegung überhaupt richtig? Und was kann man tun?

    P.S: Ich sehe grade, dass mein Testprogramm garkeine Dll's benutzt. Einfacher macht es das nicht, aber vielleicht hat jemand von Euch ja ne Idee 😕


Anmelden zum Antworten