AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Problem bei dynamischem Aufruf einer DLL mit Übergabe von Pointern ala Win32API

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

Ein Thema von eric_draven · begonnen am 14. Mär 2011 · letzter Beitrag vom 15. Mär 2011
Antwort Antwort
Seite 1 von 2  1 2   
eric_draven

Registriert seit: 26. Jul 2007
15 Beiträge
 
#1

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

  Alt 14. Mär 2011, 17:14
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
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 )

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 !

Geändert von eric_draven (14. Mär 2011 um 18:37 Uhr) Grund: Zeile hinzugefügt
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#2

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

  Alt 14. Mär 2011, 21:26
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
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
eric_draven

Registriert seit: 26. Jul 2007
15 Beiträge
 
#3

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

  Alt 14. Mär 2011, 22:13
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.

Geändert von eric_draven (14. Mär 2011 um 22:19 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Assarbad
Assarbad

Registriert seit: 8. Okt 2010
Ort: Frankfurt am Main
1.234 Beiträge
 
#4

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

  Alt 14. Mär 2011, 22:36
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.
Oliver
"... aber vertrauen Sie uns, die Physik stimmt." (Prof. Harald Lesch)
  Mit Zitat antworten Zitat
eric_draven

Registriert seit: 26. Jul 2007
15 Beiträge
 
#5

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

  Alt 14. Mär 2011, 23:08
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) bin ich morgen früh wieder da...
  Mit Zitat antworten Zitat
Benutzerbild von Assarbad
Assarbad

Registriert seit: 8. Okt 2010
Ort: Frankfurt am Main
1.234 Beiträge
 
#6

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

  Alt 15. Mär 2011, 01:11
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
Oliver
"... aber vertrauen Sie uns, die Physik stimmt." (Prof. Harald Lesch)
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#7

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

  Alt 15. Mär 2011, 01:14
Wäre es nicht sinnvoll das dann komplett in ASM zu schreiben?
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Assarbad
Assarbad

Registriert seit: 8. Okt 2010
Ort: Frankfurt am Main
1.234 Beiträge
 
#8

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

  Alt 15. Mär 2011, 01:22
Wäre es nicht sinnvoll das dann komplett in ASM zu schreiben?
Wenn man auf x64 pfeift und Sicherheitslücken beseitewischt. Jupp.
Oliver
"... aber vertrauen Sie uns, die Physik stimmt." (Prof. Harald Lesch)
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#9

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

  Alt 15. Mär 2011, 01:28
Er will ja hoffentlich kein Atomkraftwerk damit steuern.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.097 Beiträge
 
Delphi 12 Athens
 
#10

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

  Alt 15. Mär 2011, 06:58
@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)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (15. Mär 2011 um 07:10 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:07 Uhr.
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