![]() |
GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Hi zusammen,
ich komme nicht mehr weiter und brauche mal Tipps von euch. Direkt vorweg: "ja, du musst ja auch die 64-Bit-DLL nehmen, wenn du für 64-Bit kompilierst!" werden vielleicht einige direkt zurecht antworten wollen. Ja, habe ich. Ganz so einfach ist es leider nicht. Geht noch nicht mal um meinen eigenen Code, sondern um eine Bibliothek, die ich nutzen möchte. Aber der Reihe nach: Wenn man sich mit "modernen" Anmeldeverfahren im Netz rumschlägt, dann stolpert man irgendwann über OAuth2 und die "Access Token" und "Identity Token", die man da so bekommt. Meistens liegen diese Token in Form eines "JSON Web Tokens" vor, welche diverse Informationen über die Anmeldung enthalten und schließlich auch mit einem Zertifikat signiert sind, mit dem man die Echtheit prüfen kann und soll. Damit man nicht bei Null anfangen muss, wenn man so ein Token auswerten und prüfen will, haben andere zum Glück schon vorgearbeitet, in dem Fall gibt es u.a. die ![]() Und hier kommt es nun zu meinem Problem. Folgender Code aus der Unit JOSE.Signing.RSA von Paolo:
Delphi-Quellcode:
Hier soll also
unit JOSE.Signing.RSA;
interface uses [...]IdSSLOpenSSLHeaders, [...] class procedure TRSA.LoadOpenSSL; begin if not IdSSLOpenSSLHeaders.Load then raise Exception.Create('[RSA] Unable to load OpenSSL libraries'); if @EVP_DigestVerifyInit = nil then raise Exception.Create('[RSA] Please, use OpenSSL 1.0.0. or newer!'); if GetCryptLibHandle <> 0 then begin // *** Die folgende Zeile macht nicht, was sie soll! *** _PEM_read_bio_RSA_PUBKEY := GetProcAddress(GetCryptLibHandle, 'PEM_read_bio_RSA_PUBKEY'); if @_PEM_read_bio_RSA_PUBKEY = nil then raise Exception.Create('[RSA] Unable to get proc address for "PEM_read_bio_RSA_PUBKEY"'); [...] end; end;
Delphi-Quellcode:
in der libeay32.dll die Funktion PEM_read_bio_RSA_PUBKEY finden. Die Funktion
GetProcAddress(GetCryptLibHandle, 'PEM_read_bio_RSA_PUBKEY')
Delphi-Quellcode:
kommt aus der Indy-Unit IdSSLOpenSSLHeaders und liefert das Handle auf die libeay32.dll. Unter Win32 funktioniert das auch alles ganz wunderbar. Unter Win64 bekomme ich immer ein NIL von der Funktion.
GetCryptoLibHandle
Mit einem "DLL Export Viewer" habe ich gesehen, dass die gesuchte Funktion in der DLL auch tatsächlich existiert. Mit dem ProcessMonitor habe ich geprüft, dass auch tatsächlich die richtige, 64 bittige Version von libeay32.dll geladen wird. Wird sie ohnehin schon vorher, weil das ganze in einer Web Broker-Anwendung läuft, die auch auf OpenSSL zugreift. Da kann man beim Debuggen dann auch sehen, dass die ganzen Funktionen auch unter Win64 in der dll problemlos gefunden werden, wenn man sich die Funktion "Load" in der IdSSLOpenSSLHeaders anguckt und da einen Breakpoint setzt. Nur oben klappt es nicht. Ich hab auch schon mal
Delphi-Quellcode:
@_PEM_read_bio_RSA_PUBKEY := GetProcAddress(GetCryptLibHandle, PChar('PEM_read_bio_RSA_PUBKEY'));
probiert, aber das brachte keinen Unterschied. Hat irgendwer irgendeine Idee? (Zur Info: hab das auch in einem ![]() |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Zitat:
Delphi-Quellcode:
Aber keine Ahnung ob dir das hilft.
function GetProcAddress(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; external kernel32 name 'GetProcAddress';
function GetProcAddress(hModule: HMODULE; lpProcName: LPCWSTR): FARPROC; begin if ULONG_PTR(lpProcName) shr 16 = 0 then // IS_INTRESOURCE Result := GetProcAddress(hModule, LPCSTR(lpProcName)) else Result := GetProcAddress(hModule, LPCSTR(TMarshal.AsAnsi(lpProcName))); end; Habe da einiges recherchiert. HModule <> THandle Int <> IntPtr wenn die DLL geladen wird. Viele haben damit ein Problem. ![]() |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Und natürlich kann man auch mal schauen, ob es auch einen Export mit diesem Namen in der 64-Bit-DLL gibt.
![]() |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Zitat:
Zitat:
Aber ich finde den Key definitiv nicht! Zumindest nicht in der DLL die ich auf dem System habe. |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Zitat:
Windows SDK:
Code:
Die Delphi RTL ebenso:
typedef PVOID HANDLE;
typedef HANDLE HINSTANCE; typedef HINSTANCE HMODULE;
Delphi-Quellcode:
THandle = NativeUInt;
HINST = THandle; { HINSTANCE from widnef.h } HMODULE = HINST; { from windef.h } |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Zitat:
Nein aber so wie ich gelesen (Recherchiert) habe ist Cardinal 64Bit und THandle 32 oder? ![]() |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Zitat:
|
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Zitat:
Keine Ahnung wie viele DLL's es davon gibt. |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Zitat:
![]() Zitat:
![]() Zitat:
Delphi-Quellcode:
, egal wieviel Bit.
HMODULE = HINST = THandle
|
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,
Danke für euer erstes Feedback. dass ich das schon geprüft habe, dass die Funktion auch wirklich vorhanden ist, hatte ich ja schon im Eingangspost geschrieben. Die Funktion ist in der DLL vorhanden (und auch in älteren Versionen der DLL). Also, wenn ich die OpenSSL-Doku richtig verstanden habe, müsste das zumindest in der Version 1.0.2 dabei sein. Auszug aus dem DLL Export Viewer als Bildchen im Anhang. Vielleicht gibt es ja tatsächlich irgendwelche Eigenarten bzgl. HModule <> THandle oder irgendwelcher anderer Typen bei der Funktion unter Win64. Ich versuche morgen mal mit frischem Kopf ein Demo-Projekt zu basteln. |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Zitat:
Ich arbeite unter 64Bit meistens mit LONG_PTR da bin ich auf der sicheren Seite. Am ende habe ich nur versucht zu ergründen woran das liegen könnte. |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Ersetze doch auch das
Delphi-Quellcode:
mal durch RaiseLastOSError(), dann können wir auch sehen was Windows selbst dazu sagt warum es nicht geht.
raise Exception.Create(..)
Auch: Wir sehen dass du dir eine DLL anschaust, was sie denn exportierst. Aber sind wir uns wirklich sicher dass er auch genau diese DLL einlädt? Ich weiß nicht ob das wasserdicht ist, aber im Zweifelsfall führe ich immer where.exe im .exe-Verzeichnis aus und lasse sie nach der DLL suchen. Ich meine der listet die gefundenen Treffer in der gleichen Reihenfolge auf wie LoadLibrary(..) suchen würde... |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
WHERE sollte nur den %PATH% zum Suchen nuzten, inkl. %PATHEXT%.
(WHERE /R sucht ähnlich wie FOR /R) LoadLibrary macht da bissl was Anderes. Aber Debugger, SysInternals oder GetModuleFileName (mit dem Handle der DLL) helfen. |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Zitat:
Zitat:
|
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
[OT]
Zitat:
Ich glaube dir :-D |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Liste der Anhänge anzeigen (Anzahl: 1)
Hab's gefunden. Danke euch für die Unterstützung. Letztlich liegt der Fehler bei Indy. Kann man das irgendwo melden, in der Hoffnung, dass das gefixt wird? Macht das bei QC Sinn, weil ja Teil von Delphi, oder kann man sowas auch direkt ans Indy-Team melden?
Folgendes Beispielprojekt (für Interessierte auch als Paket im Anhang):
Delphi-Quellcode:
unit main;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdSSLOpenSSLHeaders, Vcl.StdCtrls; type TForm2 = class(TForm) MemoStatus: TMemo; ButtonLoadLib: TButton; ButtonLoadLibOwn: TButton; procedure ButtonLoadLibClick(Sender: TObject); procedure ButtonLoadLibOwnClick(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } class var _PEM_read_bio_RSA_PUBKEY: function(bp: PBIO; x: PPRSA; cb: ppem_password_cb; u: Pointer): PRSA cdecl; end; var Form2: TForm2; implementation {$R *.dfm} procedure TForm2.ButtonLoadLibClick(Sender: TObject); begin MemoStatus.Clear; if IdSSLOpenSSLHeaders.Load then begin MemoStatus.Lines.Add('OpenSSL loaded'); MemoStatus.Lines.Add('Handle: '+GetCryptLibHandle.ToString); if GetCryptLibHandle <> 0 then begin _PEM_read_bio_RSA_PUBKEY := GetProcAddress(GetCryptLibHandle, 'PEM_read_bio_RSA_PUBKEY'); if @_PEM_read_bio_RSA_PUBKEY = nil then MemoStatus.Lines.Add('Function not found') else MemoStatus.Lines.Add('Success! Function found!'); end else MemoStatus.Lines.Add('Crypo handle invalid') end else MemoStatus.Lines.Add('Failed loading OpenSSL'); end; procedure TForm2.ButtonLoadLibOwnClick(Sender: TObject); var crypHandle: HMODULE; begin MemoStatus.Clear; crypHandle:=SafeLoadLibrary('libeay32.dll'); if crypHandle<>0 then begin MemoStatus.Lines.Add('OpenSSL loaded'); MemoStatus.Lines.Add('Handle: '+crypHandle.ToString); _PEM_read_bio_RSA_PUBKEY := GetProcAddress(crypHandle, 'PEM_read_bio_RSA_PUBKEY'); if @_PEM_read_bio_RSA_PUBKEY = nil then MemoStatus.Lines.Add('Function not found') else MemoStatus.Lines.Add('Success! Function found!'); end else MemoStatus.Lines.Add('Failed loading OpenSSL'); end; end. Der erste Aufruf,
Delphi-Quellcode:
ist angelehnt an das, wie es auch in der von mir genutzten Bibliotheke JOSE.Signing.RSA gemacht werden soll. Hier läuft es auch genauso: unter 32-Bit funktioniert es super, unter 64-Bit findet er die Funktion nicht.
ButtonLoadLibClick
Der zweite Button mit dem Aufruf
Delphi-Quellcode:
kümmert sich selbst nochmal um das Laden der Bibliothek. Das Suchen der gewünschten Funktion klappt dann problemlos sowohl unter Win32 und Win64.
ButtonLoadLibClick
Und warum behaupte ich nun, das Indy "schuld" ist? In der Unit IdSSLOpenSSLHeaders wird das Handle auf die libeay32.dll in der globalen Variable hIdCrypto gespeichert und diese ist auch vom Typ HModule. Unter Win32 wird HModule zu "Cardinal", unter Win64 aber zu UInt64. Die Variable ist aber nur im Implementation-Bereich definiert, also können wir nicht von außen auf sie zugreifen. Nach außen verfügbar macht die Unit diese Variable über die oben auch genutzte Funktion
Delphi-Quellcode:
. Diese Funktion liefert aber nicht HModule zurück, sondern ein Integer. Dadurch wird in der Rückgabe also das Handle zerschossen - sieht man ganz gut, wenn man mein Testprogramm ausführt und die beiden Handles vergleicht. Dass das nicht passt, ist offensichtlich, denke ich mal.
GetCryptLibHandle
Ich sag mal so: Aaaaaargh! :wall: ;-) Jemand eine Idee für einen Workaround, ohne dass ich die IdSSLOpenSSLHeaders patchen muss? |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
So wie ich das sehe lag es dann doch an den Datentypen.
So wie ich sagte. Zitat:
|
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Nachtrag: gerade mal nachgesehen: im Indy, das mit Delphi 10.4 mitgeliefert wird, ist das Problem gefixt. Insofern werde ich mir wohl - bis ich mal auf 10.4 aktualisiere - doch eine lokale Kopie von IdSSLOpenSSLHeaders ins Projekt holen und es dort korrigieren, falls keiner eine bessere Idee hat.
@venice2: Genau, warst da auf der richtigen Spur. |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Alternativ einfach die aktuellen Version der Indy-Komponenten nutzen - dort ist der Typ des Rückgabewertes definiert als "TIdLibHandle", der seinerseits ein Thandle" ist, was als "NativeUInt" wiederum prächtig unter Win64 funktioniert.
//Edit - da warst Du schneller. |
AW: GetProcAddress liefert kein Ergebnis unter Win64, unter Win32 schon
Zitat:
Funktioniert mit Indy unter 10.4 gerade getestet. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:54 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