Pfad umbiegen



  • Hallo zusammen,

    ich hoffe ich bin hier im richtigen Unterforum gelandet.

    Wir haben ein Problem. Seit Jahren haben wir eine Oracle Forms Anwendung bei uns im Einsatz, welche nicht so ganz rund läuft. Ich kann von Anfang an sagen, dass wir keinen Code haben, da das Ding, welches die Probleme erzeugt, von Oracle kommt und weder weiterentwickelt noch supportet wird. Nun zum Problem: Diese Anwendung schaut bei jedem Start in den Windows Fonts Ordner und verarbeitet alle Schriftarten. Jetzt kam mir die Idee, sämtliche Fonts via RAM Disk in den schnellen Arbeitsspeicher zu verschieben. Ich habe keine Lust mit IDA Pro oder so das Programm auseinander zu nehmen und zu modifizieren. Viel mehr dachte ich daran, dem Programm vorzugauckeln, dass der Fonts Ordner nicht auf der Platte liegt sondern im RAM. Also wäre doch an der Stelle ein Dateisystem Treiber das richtige oder? Hat jemand mit sowas Erfahrung? Dann würden nämlich noch einige Fragen folgen;-)



  • Als erstes: Bist du sicher dass die HDD der Flaschenhals ist und nicht z.B. die CPU?

    Ansonsten: Treiber würde ich nicht empfehlen. Würde zwar gehen, aber totaler Overkill. Dann schon einen Userlandhook. Hab ich auch schon öfter gemacht, ist aber doch eine eher hässliche Lösung.

    Machbar ist so einiges, nur die Frage ist ob es sich wirklich lohnt. 😉
    Mir fällt da halt auch keine schöne Lösung ein wie man das gut umsetzen könnte, ist halt doch eher eine ungewöhnliche Problemstellung.


  • Mod

    Ich würde es einfach mal mit einem Hardlink, oder einer Junction probieren.
    Ich denke für den Font Ordner geht das.

    Ich bezweifle aber auch schwer, dass hier der I/O das Problem ist.

    Last die Anwendung doch mal auf einem Rechner mit SSD laufen und schaut was passiert. An so etwas merkt man schnell ohne großes Profiling ob die Platte der Flaschenhals ist.



  • Hallo zusammen,

    @DarkShadow44: Ich glaube das hat irgendetwas mit dem Auslesen von Berechtigungen oder so zu tun. So ganz genau bin ich noch nicht dahinter gestiegen, da ein Haufen DLL's an der Anwendung klebt:-( Allerdings können wir die HDD als Flaschenhals ausfindig machen UND die CPU da kein Multithreading. Habe mich jetzt auch für einen Usermode Hook entschieden. Beschreibung weiter unten. Zum Thema Overkill. Es ist jetzt schon absehbar, dass die Anwendung noch 3 Jahre laufen soll bis die Ablöse kommt. Lieber einmal den Scheiß zusammen bauen als über 3 Jahre Hunderte von Benutzer ständig warten zu lassen;-)

    @Martin Richter: Hardlinks funktionieren meines Wissens nach nur dann, wenn sie auf der selben Partition liegen. Zumal ich auch ganz gerne wüsste wie genau du das meinst. Ich kann ja nicht einfach den Order doppelt unter C:\Windows haben. Ansich muss ich ja nur der Anwendung sagen wo sie hingucken soll. Und das sollen eben nicht mehr in den C:\Windows\Font sein sondern in den bspw. D:\Font\

    Habe nun folgendes gemacht: Habe mir eine DLL geschrieben und diese mit einem Tool in die Importtabelle der exe gehangen. Jedes mal wenn also die exe aufgerufen wird, wird auch meine DLL geladen. Und zwar noch bevor die exe überhaupt irgendetwas machen kann und ohne dass ich mich im Hook drum kümmern muss, welche Applikation nun die Datei anfordert. Soweit so gut. Meine umgebogene CreateFile wird auch aufgerufen nur leider kommt es dann irgendwo zu einem Fehler im Stack. Jedoch nicht in meiner Funktion sondern, wie ich in der Aufrufliste sehen kann, in der Funktion die meine umgebogene CreateFile aufruft. Scheinbar wird vor dem ret in der Aufruferfunktion irgendwas aus dem Stack geholt, womit er dann bei 0x00000003 landet. Wenn ich die Original CreateFile drin lasse, dann läuft es problemlos. System ist Winwows 10 x64 aber eine 32Bit Anwendung. Hier mal mein Code. Vielleicht fällt euch ja noch etwas auf:

    #pragma region Includes
    #include <Windows.h>
    #include <string>
    using namespace std;
    #pragma endregion 
    
    #pragma region typedef 
    typedef HANDLE (WINAPI *__CreateFileA)(LPCSTR  lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
    __CreateFileA _CreateFileA;
    
    typedef HANDLE (WINAPI *__CreateFileW)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
    __CreateFileW _CreateFileW;
    #pragma endregion
    
    #pragma region Dummy Export
    extern "C" __declspec(dllexport) bool TestFunc(char* test)
    {
    	UNREFERENCED_PARAMETER(test);
    	return true;
    }
    #pragma endregion
    
    #pragma region DetourFunc 
    void *DetourFunc(BYTE *src, const BYTE *dst, const int len)
    {
    	DWORD dwback;
    	VirtualProtect(src, len, PAGE_READWRITE, &dwback);
    
    	BYTE *jmp = static_cast<BYTE*>(malloc(5 + len));
    	memcpy(jmp, src, len);
    
    	jmp += len;
    	jmp[0] = 0xE9;
    	*reinterpret_cast<DWORD*>(jmp + 1) = static_cast<DWORD>(src + len - jmp) - 5;
    
    	src[0] = 0xE9;
    	src[5] = 0xCC;
    	*reinterpret_cast<DWORD*>(src + 1) = static_cast<DWORD>(dst - src) - 5;
    
    	VirtualProtect(src, len, dwback, &dwback);
    
    	return (jmp - len);
    }
    #pragma endregion
    
    #pragma region Hook Functions
    HANDLE cCreateFileA(LPCSTR  lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
    {
    	//string message; 
    	//       message.append("Folgender CreateFileA Aufruf wurde umgeleitet: ").append(lpFileName);
    	//OutputDebugStringA(reinterpret_cast<LPCSTR>(message.c_str()));
    
    	return _CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    } 
    
    HANDLE cCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
    {
    	//wstring message; 
    	//        message.append(L"Folgender CreateFileW Aufruf wurde umgeleitet: ").append(lpFileName);
    	//OutputDebugStringW(reinterpret_cast<LPCWSTR>(message.c_str()));
    
    	return _CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    }
    #pragma endregion 
    
    BOOL ProcessAttach(HMODULE hModule)
    {
    	UNREFERENCED_PARAMETER(hModule);
    	Sleep(20000);
    
    	HMODULE kernel_modul = LoadLibraryA("kernel32");
    	if(kernel_modul)
    	{
    		FARPROC cfa_proc = GetProcAddress(kernel_modul, "CreateFileA");
    		FARPROC cfw_proc = GetProcAddress(kernel_modul, "CreateFileW");
    
    		if(cfa_proc && cfw_proc)
    		{
    			_CreateFileA = static_cast<__CreateFileA>(DetourFunc(reinterpret_cast<BYTE*>(cfa_proc), reinterpret_cast<BYTE*>(cCreateFileA), 6));
    			OutputDebugStringA("CreateFileA modified!");
    
    			_CreateFileW = static_cast<__CreateFileW>(DetourFunc(reinterpret_cast<BYTE*>(cfw_proc), reinterpret_cast<BYTE*>(cCreateFileW), 6));
    			OutputDebugStringA("CreateFileW modified!");
    
    			return TRUE;
    		}
    		else
    		{
    			return FALSE;
    		}
    	}
    	else
    	{
    		return FALSE;
    	}
    }
    
    BOOL ProcessDetach(HMODULE hModule)
    {
    	UNREFERENCED_PARAMETER(hModule);
    	return TRUE;
    }
    
    BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
    {
    	UNREFERENCED_PARAMETER(lpReserved);
    
    	switch(ul_reason_for_call)
    	{
    		case DLL_PROCESS_ATTACH:
    			/*return*/ ProcessAttach(hModule);
    			break;
    		case DLL_THREAD_ATTACH:
    			break;
    		case DLL_THREAD_DETACH:
    			break;
    		case DLL_PROCESS_DETACH:
    			/*return*/ ProcessDetach(hModule);
    			break;
    	}
    	return TRUE;
    }
    


  • Vielleicht falsche Aufrufkonvention? Soweit ich weiß wird in der winapi stdcall verwendet, und wenn sich die aufgerufene funktion darum kümmern soll die Parameter vom stack zu schubsen, sie es aber nicht macht weil sie erwartet, dass das jemand anders macht, gibts natürlich Probleme.
    Dein malloc sieht btw recht einsam aus 😉



  • Hey man, du bist mein Star für heute!!! Das war das Problem. Ich wäre da wohl im Leben nicht drauf gekommen.

    Was gefällt dir am malloc nicht? Ich muss sagen, dass ich die Funktion nur kopiert und ganz leicht modifiziert habe. Verbesserungsvorschlag?



  • troubleshooter schrieb:

    Verbesserungsvorschlag?

    free ()


  • Mod

    OK. Hardlink geht nicht, aber eine Junction.

    Also den ganzen Ordner C:\Windows\Fonts als Junction auf D:\Fonts legen.
    Sollte keine Problem sein.

    Evtl. eine Sache des abgesicherten Modus oder indem man es über die Wartungs Console macht.

    NOCHMAL: Ich bezweifle dass dies irgendwas bringt. Hast Du es mal mit einer SSD getestet? Oder mit einem komplett gecachtem Virtuellen Umfeld?



  • Guten Morgen,

    @Fake oder Echt: Ok, kein malloc ohne free. Bin ich bei dir;-) Werde mir das genauer ansehen und ggf umsetzen.

    @Martin Richter: Nein das konnten wir leider noch nicht testen. Selbst wenn es so sein sollte, dann wäre es noch eine Mordsarbeit 20 Citrix Server komplett umzustellen. Früher noder später wird die Aufgabe noch anstehen aber sollte das wirklich so funktionieren wie ich mir das vorgestellt habe, dann bin ich mit der super schmutzigen Lösung erstmal zufrieden. Ganz allgemein kann ich dir aber zustimmen. In den nächsten Tagen wird sich herausstellen, ob das so klappt oder nicht. Ich werde ich an der Stelle auf dem Laufenden halte;-) Leider finde ich vor Freitag jedoch keine Zeit für das Thema:-(


Log in to reply