Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API (https://www.delphipraxis.net/159102-problem-bei-dynamischem-aufruf-einer-dll-mit-uebergabe-von-pointern-ala-win32api.html)

eric_draven 14. Mär 2011 17:14

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:
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;
und die DLL:
Delphi-Quellcode:
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.
Die Zeile im Caller mit dem Aufruf der original kernel32.dll Funktion ist auskommentiert, mit diesem funktioniert es aber.
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 !

Luckie 14. Mär 2011 21:26

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: http://www.michael-puff.de/Programmi...ch_laden.shtml

eric_draven 14. Mär 2011 22:13

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.

Assarbad 14. Mär 2011 22:36

AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
 
Zitat:

Zitat von eric_draven (Beitrag 1088499)
Ich muss die Struktur nicht kennen und so keinen Type ("Header") anlegen.

Sorry, aber das ist unsinnig und bestenfalls gefährlich.

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.

eric_draven 14. Mär 2011 23:08

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:
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;
Woher kommt diese beknackte Verschiebung ?
Muss jetzt ins Bett, vielleicht träum ich ja von der Lösung, ansonsten (androh:evil:) bin ich morgen früh wieder da...

Assarbad 15. Mär 2011 01:11

AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
 
Zitat:

Zitat von eric_draven (Beitrag 1088505)
Woher kommt diese beknackte Verschiebung ?

Ich nehme an von der gewagten Mischung aus Assembler und Delphi. Du machst Annahmen über den umliegenden Delphi-Code und sein Verhalten.

Gut, man müßte es sich mal in einem Disassembler anschauen, aber dann solltest du mal die .exe rüberwachsen lassen ;)

Luckie 15. Mär 2011 01:14

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?

Assarbad 15. Mär 2011 01:22

AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
 
Zitat:

Zitat von Luckie (Beitrag 1088521)
Wäre es nicht sinnvoll das dann komplett in ASM zu schreiben?

Wenn man auf x64 pfeift und Sicherheitslücken beseitewischt. Jupp. :stupid:

Luckie 15. Mär 2011 01:28

AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
 
Er will ja hoffentlich kein Atomkraftwerk damit steuern. ;)

himitsu 15. Mär 2011 06:58

AW: Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API
 
Delphi-Quellcode:
@lpBuffer
gibt die Adresse de Variable zurück und sagt nichts über den Inhalt der Variablen aus ... so müssen diese Werte also unterschiedlich sein.

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 19:27 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz