Seite 1 von 1

Funktionen weiterleiten ohne die Parameter zu kennenn

Verfasst: 18.02.2014, 16:24
von Helmut
Hallo!
Ich habe ein kleines Problem. Und zwar möchte ich aus verschiedenen Gründen eine DLL erstellen, die eine andere imitiert, also die gleichen Funktionen exportiert und die Aufrufe einfach nur weiterleitet. Das funktioniert soweit auch ganz gut und sieht etwa so aus:

Code: Alles auswählen

HMODULE hReal = 0;

void* LoadProc(const char* Function)
{
	DWORD E = GetLastError();
	if(!hReal)
	{
		wchar Buffer[1024];
		SHGetSpecialFolderPath(0, Buffer, CSIDL_SYSTEM, false);
		wcscat_s(Buffer, 1024, L"\\real_dll.dll");
		hReal = LoadLibrary(Buffer);
	}
	void* r = GetProcAddress(hReal, Function);
	SetLastError(E);
	return r;
}


EXTERN_C HRESULT STDAPICALLTYPE 
ExportedFunction(
    UINT Param
    )
{
	typedef HRESULT (STDAPICALLTYPE* P)(
	    UINT Param
		);
	return P(LoadProc("ExportedFunction"))(Param);
}
Das Problem ist nun, dass diese DLL leider einige Funktionen exportiert, deren Funktionskopf ich nicht kenne. Und da das ziemlich viele sind habe ich auch nicht sonderlich Lust jede Funktion per Hand zu dissamblieren. Und eigentlich sollte diese Information ja auch nicht nötig sein. Es muss ja möglich sein den Stack in den Zustand vor dem Aufruf der eigenen Funktion zu bringen und dann eine bestimmte Adresse anzuspringen. Die Frage ist nur wie? (mit VS)

Helmut

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Verfasst: 18.02.2014, 16:38
von Krishty
Mit welcher Aufrufart werden die Funktionen denn gerufen?

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Verfasst: 18.02.2014, 16:56
von Helmut
__stdcall.

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Verfasst: 18.02.2014, 17:37
von Krishty
Hm. Würde der Stapel vom Aufrufer aufgeräumt werden, übergäbe der dir die Basisadresse der Parameter, und du könntest durch die Adressen deiner lokalen Variablen darauf schließen, wie groß der Parameterblock ist. Den würdest du kopieren und an die Zielfunktion weiterleiten.

Bei __stdcall räumt aber der Aufgerufene auf; da fällt mir nicht wirklich ein, wie man das machen könnte :(

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Verfasst: 18.02.2014, 17:55
von Helmut
Ich habe gerade festgestellt, dass VS im Releasemodus mit leichten Änderungen genau das macht, was ich wollte:

Code: Alles auswählen

EXTERN_C HRESULT STDAPICALLTYPE
Bla(
    DWORD_PTR Param
    )
{
	typedef HRESULT (STDAPICALLTYPE* P)(
	    DWORD_PTR Param
		);
	static P p = (P)LoadProc("Bla");
	return p(Param);
}
Er überschreibt keine Parameter und macht am Ende einfach ein Jump (kein Call) in die Funktion. Manchmal läuft's einfacher als gedacht!
Ist natürlich nicht so schön, dass man sich auf eine Optimierung verlässt und im 64-Bit Modus wird vielleicht doch der ein oder andere Parameter überschrieben, aber man kann halt nicht alles haben :). Außerdem ist wegen dem static ne kleine Racecondition drin, aber naja... Falls sich die User über völlig seltsame Bugs beschweren weiß ich wo ich gucken muss :)

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Verfasst: 18.02.2014, 18:23
von Krishty
Tatsächlich; schöne Lösung durch Tail Call Optimization :-) Du kannst deinem Projekt eine entsprechend geschriebene Assembler-Datei hinzufügen, damit es auf allen Architekturen mit allen Konfigurationen klappt.

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Verfasst: 18.02.2014, 18:58
von Helmut
Hm, ja, wenn ich nur Assembler könnte. :) Und das müsste man dann ja auch pro Architektur machen oder?

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Verfasst: 18.02.2014, 20:00
von Spiele Programmierer
Ja, im Prinzip schon.
Ich vermute aber mal, dass du nur den x64/x64 nutzt, wenn es um VisualStudio geht. Dann kommst du mit 1er Variante aus.
Der Vorteil dabei ist halt, das es für die Architektur wirklich sicher ist.
Deine Lösungen finde ich extrem hässlich: Nach einem Compilerupdate oder bloß einer anderen Compilereinstellungen kann mal einfach gar nichts mehr gehen.

Und in Assembler eine Funktion mit einer einzelnen Sprunganweisung zu schreiben, dass solltest du schon hinbekommen.
Da braucht man doch dann keine erweiterten Asm-Kenntnisse.

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Verfasst: 18.02.2014, 20:26
von Helmut
Es ist nicht nur eine Sprunganweisung. Die Funktion muss erst die Funktion aus der richtigen DLL laden, falls das nicht schon geschehen ist. Außerdem hab ich keine Ahnung, wie man Assemblercode einbindet, aufruft, wie das in Kombination mit Makros funktioniert und wie man da globale Variablen anlegt. Ein paar Stunden würde ich schon brauchen. Ich brauche sowohl x86 als auch x64.

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Verfasst: 18.02.2014, 20:40
von Spiele Programmierer
Die Funktion muss erst die Funktion aus der richtigen DLL laden
Das würde ich in C(++) machen.
Außerdem hab ich keine Ahnung, wie man Assemblercode einbindet, aufruft
Du definierst in der Assemblerdatei ein exportiertes Label, auf das du in C zugreifen kannst.
In C(++) definierst du die Funktion dann einfach als "extern "c"" damit damit der Symbolname in der Objektdatei noch übereinstimmt. (Name mangling von C++ umgehen)
Bei NASM in Kombination mit C(++) zb. so: (Von MASM habe ich keine Ahnung)

Code: Alles auswählen

global  _SomeFunction ;Symbol exportieren, um von außerhalb darauf zugreifen zu können....
_SomeFunction:
        jmp 0x12345678
In C(++) dann...

Code: Alles auswählen

extern "C" /*Irgend ein Rückgabetyp*/ SomeFunction(/*Irgendwelche Parameter*/);
Ich brauche sowohl x86 als auch x64.
Es kann die Assemblerdatei wahrscheinlich auch so ziemlich gleich aussehen, weil x86 ja (weitgehend) eine Untermenge von x64 ist.
An der Stelle, wo es einen Unterschied macht, kann man mit Makros ersetzen.