![]() |
Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
Hallo,
viele APIs basieren darauf, dass man der aufgerufenen DLL Funktion einen Pointer (PChar) und eine Länge übergibt. Die Funktion schreibt dann direkt auf die Adresse der Variablen im .DATA Segment. Ein Beispiel hierfür ist z.B. GetWindowsDirectoryA(lpBuffer: PChar; uSize: UINT): UINT in der kernel32.dll Etwas ähnliches versuche ich auch, ich habe hier versucht, genau diese Funktion nachzubauen, um mein Problem zu verdeutlichen. Mein Problem ist: Die Adresse, die ich übergeben bekomme weicht aus irgendeinem Grund immer um einige Byte von der tatsächlichen ab ?!? Ich werde noch bald wahnsinnig und hoffe, hier kann mir geholfen werden:roll: Ich habe versucht, das Ganze mit etwas Code zu verdeutlichen, da es nicht ganz nicht einfach zu erklären ist: (Das ist mein erster Beitrag, bitte steinigt mich nicht, falls ich im falschen Channel bin oder etwas nicht perfekt formatiert ist :oops:) Der Code des "Callers":
Delphi-Quellcode:
und die DLL:
function DynamicDllCallName(Dll: String; const Name: String; HasResult: Boolean; var Returned: Cardinal; const Parameters: array of Pointer): Boolean;
var prc: Pointer; x, n: Integer; p: Pointer; dllh: THandle; begin dllh := GetModuleHandle(PChar(Dll)); if dllh = 0 then dllh := LoadLibrary(PChar(Dll)); if dllh <> 0 then begin prc := GetProcAddress(dllh, PChar(Name)); if Assigned(prc) then begin n := High(Parameters); if n > -1 then begin x := n; repeat p := Parameters[x]; asm PUSH p //Parameterpointer auf den Stack //bei stdcall, räumt die aufgerufene Funkion den Stack auf (POP nicht notwendig) end; Dec(x); until x = -1; end; asm CALL prc //Funktionsaufruf end; if HasResult then begin asm MOV p, EAX //Ergebnispointer aus EAX Register end; Returned := Cardinal(p); end else begin Returned := 0; end; end else begin Returned := 0; end; Result := Assigned(prc); end else begin Result := false; end; end; procedure TForm1.Button1Click(Sender: TObject); Var lpBuffer : PChar; parameters: array of Pointer; returned: Cardinal; begin GetMem(lpBuffer, 255); Label1.Caption := Format ('@lpBuffer:%p', [@lpBuffer]); //Ergibt bei mir: 0012F610 SetLength(parameters, 2); parameters[0] := Pointer(lpBuffer); parameters[1] := Pointer(255); //function GetWindowsDirectory(lpBuffer: PChar; uSize: UINT): UINT; stdcall; // DynamicDllCallName('C:\windows\system32\kernel32.dll', 'GetWindowsDirectoryA', true, returned, parameters); DynamicDllCallName('C:\DLL_Dynamisch_PChar\project1.dll', 'GetWindowsDirectoryA', true, returned, parameters); Label2.Caption := lpBuffer; Freemem(lpBuffer); end;
Delphi-Quellcode:
Die Zeile im Caller mit dem Aufruf der original kernel32.dll Funktion ist auskommentiert, mit diesem funktioniert es aber.
library Project1;
uses SysUtils, Windows; {$R *.res} function GetWindowsDirectoryA(lpBuffer : PChar; uSize : UINT) : UINT; stdcall; Begin OutputDebugString(PChar(Format('Project1.dll->GetWindowsDirectoryA(%p,%d)',[@lpBuffer, uSize]))); //@lpBuffer ist 0012F5AC, laut Project1.exe ist es aber 0012F610 lpBuffer := 'test'; Result := 0; End; Exports GetWindowsDirectoryA; begin end. Im unteren Codeschnipsel steht mein Kommentar, wo das Problem liegt: //@lpBuffer ist 0012F5AC, laut Project1.exe ist es aber 0012F610 Die Variable uSize wird z.B. korrekt übergeben. 0012F610 ist die korrekte Adresse, wenn ich die Variable nicht mit FreeMem freigebe und als global deklariere, kann ich den Bereich mit OllyDbg erfolgreich ansehen & ändern, um ihn z.B. per Button wieder aufs Label zu geben. Bin für jede Hilfe dankbar ! |
AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
Warum schiebst du alles von Hand auf den Stack? Hat das einen Grund? Ansonsten geht es so:
![]() |
AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
Ja, das hat einen Grund: Ich will die DLL Funktion tatsächlich dynamisch aurufen, in diesem Beispiel, gebe ich Dir Recht, würde es auch so gehen, wie in Deinem Beispiel. Das komplette Programm ist aber wesentlich komplexer und soll beliebige DLL Funktionen aufrufen können, deren Struktur zur Designzeit noch nicht feststeht.
Durch die Staplerei ("Stack-Schieben") habe ich den Vorteil, das ich mir quasi eine Skriptsprache bauen kann, bei der der User eigene DLLs einbinden kann und dafür eine beliebige Struktur verwenden kann, es ist also egal, ob er Function bla(a: DWord; b: Pchar; c: Byte) : Boolean; oder Function blubb(a: Integer) : Integer; .... benutzt. Ich muss die Struktur nicht kennen und so keinen Type ("Header") anlegen. |
AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
Zitat:
Es hat schon seine Gründe, warum dynamische Sprachen sich einen eigenen Stack basteln, bspw. Lua. Wenn ich deinem Programm mal ganz dynamisch sage, daß eine Funktion fünf Parameter hat, und keinen übergebe, kann ich es zu einem dynamischen Absturz bringen - wahrscheinlich sind aber auch allerlei dynamische Sicherheitslücken. Voll dynamisch eben ... Fazit: laß es. Der Laufzeitvorteil (Geschwindigkeit) wird minimal sein, selbst bei häufigem Aufruf. Nachteile überwiegen. |
AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
Erstmal danke für die Antworten:) Leider hilft mir das bei dem Grundproblem nicht viel weiter :(
Auch wenn ich es *sicher* mache, habe ich eine Verschiebung von 48Byte zwischen der Addr des PChar, die mir die .exe anzeigt und der, die mir die DLL angibt:
Delphi-Quellcode:
Woher kommt diese beknackte Verschiebung ?
type TGetWindowsDirectoryA = function(lpBuffer : PChar; uSize : UINT): UINT; stdcall;
procedure TForm1.Button3Click(Sender: TObject); var hLib: cardinal; MyGetWindowsDirectoryA: TGetWindowsDirectoryA; lpBuffer : PChar; begin hLib := LoadLibrary('C:\DLL_Dynamisch_PChar\project1.dll'); // hLib := LoadLibrary('C:\windows\system32\kernel32.dll'); if hLib <> 0 then begin @MyGetWindowsDirectoryA := GetProcAddress(hLib, 'GetWindowsDirectoryA'); if not Assigned(MyGetWindowsDirectoryA) then begin RaiseLastOSError; exit; end; end else begin RaiseLastOSError; exit; end; GetMem(lpBuffer, 255); Label1.Caption := Format ('@lpBuffer:%p', [@lpBuffer]); //Ergibt bei mir: 0012F614; DLL:0012F5E4 MyGetWindowsDirectoryA(lpBuffer, 255); Label2.Caption := lpBuffer; Freemem(lpBuffer); end; Muss jetzt ins Bett, vielleicht träum ich ja von der Lösung, ansonsten (androh:evil:) bin ich morgen früh wieder da... |
AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
Zitat:
Gut, man müßte es sich mal in einem Disassembler anschauen, aber dann solltest du mal die .exe rüberwachsen lassen ;) |
AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
Wäre es nicht sinnvoll das dann komplett in ASM zu schreiben?
|
AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
Zitat:
|
AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
Er will ja hoffentlich kein Atomkraftwerk damit steuern. ;)
|
AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
Delphi-Quellcode:
gibt die Adresse de Variable zurück und sagt nichts über den Inhalt der Variablen aus ... so müssen diese Werte also unterschiedlich sein.
@lpBuffer
PS: sicher daß dein ASM-Code den darumliegenden Pascallcode nicht negativ beeinflußt? Immerhin veränderst du den Stackpointer und verschiebst somit ganze Struckturen, welche am Stackpointer ausgerichtet sind. (darum auch Luckies vorschlag dieses als "zusammenhängenden" ADM-Code zu lösen, ohne dazwischenliegenden Pascalcode) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:48 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz