Funktionen weiterleiten ohne die Parameter zu kennenn

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Funktionen weiterleiten ohne die Parameter zu kennenn

Beitrag 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
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Beitrag von Krishty »

Mit welcher Aufrufart werden die Funktionen denn gerufen?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Beitrag von Helmut »

__stdcall.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Beitrag 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 :(
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Beitrag 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 :)
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Beitrag 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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Beitrag von Helmut »

Hm, ja, wenn ich nur Assembler könnte. :) Und das müsste man dann ja auch pro Architektur machen oder?
Spiele Programmierer
Establishment
Beiträge: 426
Registriert: 23.01.2013, 15:55

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Beitrag 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.
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Beitrag 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.
Spiele Programmierer
Establishment
Beiträge: 426
Registriert: 23.01.2013, 15:55

Re: Funktionen weiterleiten ohne die Parameter zu kennenn

Beitrag 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.
Antworten