[gelöst] Problem mit Proxy-DLL
-
Hi,
ich bin noch sehr neu in der Windows-C(++) Welt, habe früher hauptsächlich unter Linux programmiert und deshalb noch ein wenig unerfahren, ich hoffe das meine Frage nicht allzu dumm ist

Ich soll eine DLL schreiben, die bestimmte Funktionen einer anderen DLL überwacht und entsprechend das Aufrufen der originalen Funktion blockt oder irgendwie filtert.
Ich schreibe also eine Proxy-DLL, die alle Funktionen der originalen DLL exportiert und die Funktionen, die beobachtet werden sollen, entsprechend neu implementiert.
Im Moment macht die Proxy-DLL gar nichts, außer alle Aufrufe an die originale DLL zu leiten, also quasi eine transparente Proxy-DLL.
Ich bin nach folgendem Artikel vorgegangen und habe ein Python-Skript geschrieben, das die dort beschriebene Technik umsetzt (jedoch leicht modifiziert):
http://www.codeproject.com/KB/DLL/CreateYourProxyDLLs.aspxDiese Proxy-DLL soll nun in zwei verschiedenen Programmen genutzt werden, in SQLPlus und TOAD. Beide Programme nutzen eine DLL oci.dll, die mit einem Oracle-Server kommuniziert.
Ich habe also die originale oci.dll in ooci.dll umbenannt und unsere oci.dll in das entsprechende Verzeichnis kopiert.
Ich habe ein paar MessageBox Aufrufe in unsere DLL eingebaut, um zu sehen, ob wir aufgerufen werden.
TOAD lädt unsere DLL und führt auch Abfragen an den Oracle-Server durch, SQLPlus jedoch verweigert jegliche Arbeit, und liefert immer "Error 998 (ACCESS_VIOLATION)" in der LoadLibrary Funktion.Schaue ich mir nun beide EXE Dateien im Dependency Walker an, bekomme ich folgende Ergebnisse:
http://img532.imageshack.us/img532/1191/toad.png
http://img689.imageshack.us/img689/9191/sqlplus.pngNun ist meine Vermutung, das die MSVCR90.dll in OCI.dll (unsere Proxy-DLL) das Problem ist.
Wie man sieht, linkt TOAD weder gegen MSVCR*.dll, noch gegen OCI.dll. Meine Vermutung ist nun, das TOAD auch LoadLibrary() nutzt, um die oci.dll zu laden.
SQLPlus scheint jedoch gegen die oci.dll und MSVCR71.dll zu linken. Dummerweise macht das unsere Proxy-DLL auch, allerdings gegen eine neuere MSVCR90.dll.Kann das der Konflikt sein?
Falls ja, wie kann ich Visual Studio 2008 Express (daheim, auf der Arbeit hätte ich VSC++ 2005) beibringen, nicht gegen diese DLL zu linken?Kann es eventuell auch was ganz anderes sein?
Hier wäre mal ein Codebeispiel meiner Proxy-DLL:
http://www.pastebin.ca/1838934Ich habe ein globales Objekt angelegt, welches die originale DLL lädt, da SQLPlus unsere DllMain() nie aufruft und ich somit eine andere Lösung finden musste, als in
http://www.codeproject.com/KB/DLL/CreateYourProxyDLLs.aspx
beschrieben.Jemand eine Idee, was ich tun könnte? Oder besteht eventuell sogar keine Möglichkeit, die Proxy-DLL mit SQLPlus zum Laufen zu bringen?
-
Du solltest auch nicht gegen die DLL-Version der CRT linken...
=> Statisch linken:
http://blog.kalmbach-software.de/de/2008/03/05/wie-man-statisch-gegen-die-c-runtime-crt-linkt/
-
Hallo Jochen,
danke für deine Antwort. Ich habe nun gegen die Runtime statisch gelinkt, aber leider funktioniert es immer noch nicht, TOAD läuft, SQLPlus liefert 998 bei LoadLibrary().
Ich habe mit depends.exe nachgeschaut, ob die Runtime auch wirklich nicht mehr dynamisch hinzugelinkt wird, und das ist auch der Fall.Hmm sonst noch irgendwelche Ideen?
998 heißt ja auch, das nicht alle Ressourcen, die die DLL benötigt, geladen werden konnten. Aber warum geht es dann in einer Applikation, aber nicht in der anderen?
Außerdem laufen ja beide Programme, wenn ich unsere oci.dll wieder herausschmeiße (beide Programme greifen auf die selbe Oracle-Runtime / Umgebung zu).
-
Ich habe nochmal einen Screenshot von depends.exe gemacht, einmal SQLPlus mit originaler oci.dll, und einmal mit unserer Proxy-DLL.
original: http://img59.imageshack.us/img59/7200/sqlplusoriginal.png
proxy: http://img704.imageshack.us/img704/1065/sqlplusproxy.pngKann es eventuell sein, das ich gegen alle Libs, so wie sie in der originalen DLL zu sehen sind, auch linken muss?
Kann SQLPlus irgendwie "merken", das wir nicht die echte DLL sind?
-
Wer liefert den Fehlercode? Du in Deinem Programm, wenn Du die "ooci.dll" laden willst?
-
Ja... ich generiere die Fehlermeldung...
Wenn SQLPlus meine DLL lädt, sehe ich noch die erste MessageBox (Startup), und danach die zweite MessageBox mit dem Errorcode.
Danach fliegt SQLPlus auf die Nase, weil es wohl einen Nullpointer anspricht (klar, LoadLibrary schlug fehl und somit sind die ganzen Funktionspointer nicht gesetzt) und das war es dann. Die letzte MessageBox (Shutdown) sehe ich nicht mehr, da vorher aus dem Programmcode gesprungen wird.
-
Also hat die Fehlermeldung doch gar nichts mit Deiner DLL zu tun, sondern Du kannst die umbenannte DLL nicht laden, oder?
-
Ja, aber ich würde sie ja gerne laden. Und wenn ich meine DLL in TOAD verwende, geht es ja auch (oder in einer Testapplikation).
Nur wenn ich meine Proxy-DLL mit SQLPlus nutze, kann die umbenannte DLL auf einmal nicht mehr geladen werden.
-
Sieht aber so aus als würde die eine Anwednung die DLL finden und die andere eben nicht. Kannst ja mal testweise einen absoluten Pfad zum Laden der ooci.dll angeben. Wenn das funktioniert ist die "Dateisuche" tatsächlich das Problem.
-
Ich gebe doch einen absoluten Pfad an, siehe
http://www.pastebin.ca/1838934Oder meintest du rein zufällig "relativer Pfad"?

-
Er findet vermutlich die mscvr71.dll nicht... leg die mal in das gleiche Verzeichnis wie die DLL.
-
Die liegt in demselben Verzeichnis:
http://img687.imageshack.us/img687/9781/foldert.pngDie war schon bei der SQLPlus Installation dabei.
-
Und wieso lädst Du es dann mit einem absoluten Pfad, wenn eh beide DLLs im gleichen Verzeichnis liegen???
-
Ich hatte vorher einen relativen Pfad, das ging nicht. Also habe ich es danach mit einem absoluten Pfad versucht, was auch nicht ging

Ich habe eben noch einmal mit relativem Pfad probiert, aber es funktioniert leider nicht.
-
Ich habe eben erst gemerkt, das Dependency Walker wohl auch zum Debuggen genutzt werden kann

Jedenfalls habe ich mal einen Trace laufen lassen und folgendes bekommen:
http://img12.imageshack.us/img12/9808/dependserror.pngKann jemand mit den Fehlern was anfangen?
Ich werde das Log auch nochmal posten...
-
Dependency Walker Tracelog:
http://pastebin.ca/1841150
-
Das Problem wird vermutlich sein, dass Du in DllMain, die LoadLibrary Funktion aufrufst!
Das sollte man tunlichst vermeiden! (ist auch irgendwo so dokumentiert).Rufe die "Init" Funktion einfach mal in jeder Funktion auf, dann sollte es gehen...
Oder Du linkst doch gegen all die DLLs, welche die original-DLL auch verwendet!
-
Also ich habe ein globales Objekt, in dem die Funktionspointer geladen werden:
http://www.pastebin.ca/1838934Aber ich habe vorhin noch einen Artikel gefunden, wo stand, das wohl dieses globale Objekt irgendwie auch durch die DllMain()-Methode der Laufzeitbibliothek erstellt... oder so ähnlich, das war ein sehr technischer Artikel

Ok ich werde mal versuchen, in jede der 4000 Methoden folgendes einzubauen:
if (dllObject.hL == NULL) dllObject.hL = LoadLibrary(L"ooci.dll"); if (dllObject.p[xxx] == NULL) dllObject.p[xxx] = GetProcAddress(hL,"funcxxx"); __asm jmp dllObject.p[xxx*4];
-
TheGrudge schrieb:
if (dllObject.hL == NULL) dllObject.hL = LoadLibrary(L"ooci.dll"); if (dllObject.p[xxx] == NULL) dllObject.p[xxx] = GetProcAddress(hL,"funcxxx"); __asm jmp dllObject.p[xxx*4];Ja ich weiß, Schreibfehler
War ja nur ein Beispiel.
Aber leider funktioniert das auch nicht, ich bekomme wieder eine Access Violation, und selbst TOAD, was immer lief, will nun nicht mehr.
-
Hmm es scheint nun zu funktionieren, jedoch sehr instabil. Logging in eine Datei führt schnell zum Absturz (fprintf). Aber immerhin, SQLPlus startet endlich einmal.
-
Warum deklarierst Du die Funktionen nicht ganz normal und rufst diese dann ohne Assembler auf?????