Connaissant l'Adresse d'une Fonction dans une DLL, comment récupérer son nom (ou son ordinal) et le nom de la DLL à laquelle elle appartient?
Connaissant l'Adresse d'une Fonction dans une DLL, comment récupérer son nom (ou son ordinal) et le nom de la DLL à laquelle elle appartient?
Bonjour,
On peut trouver les ordinaux et noms des fonctions dans la table d'export de la dll (voir ici). Dans la table d'import du programme (voir même lien), on a les noms des dll et adresses des fonctions.
Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
. Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !
sans doute la solution ici : https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx
Merci pour vos réponses.
Pourrais-je avoir un exemple (j’utilise Delphi7) de l’utilisation de la fonction SymFromAddr dans Dbghelp.dll.
J'ai toujours une erreur :ERROR_ACCESS_DENIED.
Bonjour,
As-tu encadré ton appel à SymFromAddr par un SymInitialize et un SymCleanup ?
Si l'erreur persiste malgré l'initialisation, c'est pê un problème de droits, à explorer.
Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
. Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !
Bonjour,
Je n'avais pas encadré avec un SymInitialize et un SymCleanup.
Maintenant ça marche un peu mieux.
Mais SymFromAddr me renvoie l'erreur 126:ERROR_MOD_NOT_FOUND
Dans SymInitialize que je mette le chemin de l'application ou de la DLL ou rien c'est pareil.
Pourtant la dll est bien là, et la fonction existe , j' extrait son adresse avec GetProcAdress.
J'ai encore du oublié quelque chose...
moi aussi ! avec le code suivant, j'obtiens une erreur 87 : paramètre incorrect...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 const DbgHelpDll = 'C:\windows\system32\dbghelp.dll'; SYMFLAG_FUNCTION = $00000800; // 2048 type TSYMBOL_INFO = packed record SizeOfStruct: DWORD; // 10 DWORD 5 uint64 256 AnsiChar => 336 TypeIndex: DWORD; Reserved_1, Reserved_2: uint64; Index: DWORD; Size: DWORD; ModBase: uint64; Flags: DWORD; // SYMFLAG_FUNCTION Value: uint64; Address: uint64; Registre: DWORD; Scope: DWORD; Tag: DWORD; NameLen: DWORD; MaxNameLen: DWORD; // 256 Name: array[0..255] of AnsiChar; end; function SymInitialize(aHandle: HMODULE; aUserSearchPath: PAnsiChar; aInvadeProcess: Boolean): Boolean; stdcall; external DbgHelpDll; function SymFromAddr(aHandle: HMODULE; aAdress: uint64; var aDisplacement: uint64; var aSymbolInfo: TSYMBOL_INFO): Boolean; stdcall; external DbgHelpDll; function SymCleanup(aHandle: HMODULE): Boolean; stdcall; external DbgHelpDll; procedure TForm1.Button1Click(Sender: TObject); var Hmod: HMODULE; P: Pointer; i, Deplacement: uint64; SymbolInfo: TSYMBOL_INFO; Result: AnsiString; begin Hmod:=LoadLibrary(DbgHelpDll); if Hmod=0 then begin ShowMessage('librairie pas chargée'); FreeLibrary(Hmod); Exit; end; P:=nil; P:=GetProcAddress(Hmod, 'SymFromName'); // pour charger la 1ère fonction if not Assigned(P) then begin ShowMessage('fonction pas chargée'); FreeLibrary(Hmod); Exit; end; if not SymInitialize(Hmod, nil, False) then begin ShowMessage('symboles pas initialisés'); FreeLibrary(Hmod); Exit; end; i:=SizeOf(TSymbol_Info); FillChar(SymbolInfo, i, 0); SymbolInfo.SizeOfStruct:=i; // 336 si packed SymbolInfo.MaxNameLen:=256; Deplacement:=0; if SymFromAddr(Hmod, UInt64(P), Deplacement, SymbolInfo) then begin if SymbolInfo.Flags and SYMFLAG_FUNCTION <> SYMFLAG_FUNCTION then begin ShowMessage('le symbole retourné n''est pas une fonction'); FreeLibrary(Hmod); Exit; end; SetLength(Result, SymbolInfo.NameLen); for i:=1 to SymbolInfo.NameLen do Result[i]:=SymbolInfo.Name[i]; ShowMessage(Result); end else begin i:=GetLastError; ShowMessage('infos pas retournées ; erreur '+IntToStr(i)); end; if not SymCleanup(Hmod) then ShowMessage('symboles pas nettoyés'); FreeLibrary(Hmod); end;
Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
. Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !
Comme ceci ça marche
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 const DbgHelpDll = 'C:\windows\system32\dbghelp.dll'; SYMFLAG_FUNCTION = $00000800 or $200; // fonction ou export table type TSYMBOL_INFO = record SizeOfStruct: DWORD; // 10 DWORD 5 uint64 256 AnsiChar => 336 TypeIndex: DWORD; Reserved_1, Reserved_2: uint64; Index: DWORD; Size: DWORD; ModBase: int64; Flags: DWORD; // SYMFLAG_FUNCTION Value: Int64; Address: int64; Registre: DWORD; Scope: DWORD; Tag: DWORD; NameLen: DWORD; MaxNameLen: DWORD; //256 Name: array[0..255] of AnsiChar; end; function SymInitialize(aHandle: HMODULE; aUserSearchPath: PAnsiChar; aInvadeProcess: Boolean): Boolean; stdcall; external DbgHelpDll; function SymFromAddr(aHandle: HMODULE; aAdress:int64; aDisplacement:DWORD; aSymbolInfo: pointer): Boolean; stdcall; external DbgHelpDll; function SymCleanup(aHandle: HMODULE): Boolean; stdcall; external DbgHelpDll; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var Hmod,Hprocessus: HMODULE; P: Pointer; i:cardinal; Deplacement:dword; SymbolInfo: TSYMBOL_INFO; Result: string; begin Hprocessus:=getcurrentprocess; Hmod:=LoadLibrary('kernel32.dll'); //une dll quelconque if Hmod=0 then begin ShowMessage('librairie pas chargée'); FreeLibrary(Hmod); Exit; end; P:=nil; P:=GetProcAddress(Hmod, 'AddAtomA');//une fonction quelconque,l'adresse peut être supérieur jusqu'à la prochaine fonction if not Assigned(P) then begin ShowMessage('fonction pas chargée'); FreeLibrary(Hmod); Exit; end; if not SymInitialize(Hprocessus, nil, true) then begin ShowMessage('symboles pas initialisés'); FreeLibrary(Hmod); Exit; end; i:=SizeOf(TSymbol_Info); zeromemory(@SymbolInfo,i); SymbolInfo.SizeOfStruct:=i; // 336 si packed SymbolInfo.MaxNameLen:=255; Deplacement:=0; if SymFromAddr(Hprocessus, int64(p), Deplacement, @SymbolInfo) then // mettre le handle du processus begin if (SymbolInfo.Flags and SYMFLAG_FUNCTION) = 0 then begin ShowMessage('le symbole retourné n''est pas une fonction'); FreeLibrary(Hmod); Exit; end; SetLength(Result, SymbolInfo.NameLen); for i:=0 to SymbolInfo.NameLen do Result:=SymbolInfo.Name; ShowMessage(Result); end else begin i:=GetLastError; ShowMessage('infos pas retournées ; erreur '+IntToStr(i)); end; if not SymCleanup(Hprocessus) then ShowMessage('symboles pas nettoyés'); FreeLibrary(Hmod); end;
Mince ! Je pensais qu'en passant le paramètre record en var on passait son adresse, soit l'équivalent d'un pointeur en C... Mauvaise traduction...
Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
. Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !
c'est surtout que tu ne prenez pas le bon handle de process aussi
tu passe le handle du loadlibrary alors qu'il faut le handle du processus courant (application)
Blaise PascalNous souhaitons la vérité et nous trouvons qu'incertitude. [...]
Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
PS : n'oubliez pas le tag
Ce serait bien d'ajouter le résultat final à FAQ.
Sergio ? ton avis ?
Bonjour,
comme le code m’intéresse aussi, je l'ai testé (le dernier posté par "angel_f") et j'ai toujours "infos pas retournées ; erreur 87" !!!
une idée du problème ?
testé sous D2009 & Win7
Cordialement,
@+
là, j'ai pas trop le temps mais je ferai un essai ce soir
Déjà, si le code a été testé correct sous Delphi 7, vu que tu utilises Delphi 2009 unicode, il y a peut-être à voir de ce côté là.
j'y ai pensé à l'UNICODE mais ça ne change rien
déjà de base les fonctions appelées sont en Ansi et le record aussi donc ça devrait passer mais non
j'ai changé pour appeler les fonctions UNICODE "W" et modifié le record en conséquence ... toujours erreur 87
du coup j'ai testé le code original tel quel avec D7 et j'ai le même problème ... erreur 87
j'ai également testé en mode Administrateur au cas ou ... idem
du coup je ne pense pas que ce soit lié à la version de Delphi (UNICODE ou non)
Mais il y a peut être un truc qui m'échappe
Cordialement,
@+
Erreur localisée :
Dans mon projet j’utilise la version 5.1 de dbghelp.dll.
Sous win 7 c’est la version 6.1 qui entraîne une erreur.
2 solutions :
- Mettre la version 5.1 dans le projet, marche sous win7
- Trouver la différence entre 5.1 et 6.1 que je ne connais pas
Problème résolu :
Pour Dbghelp.dll version 6.1
Dans SYMBOL_INFO. SizeOfStruct mettre la valeur $58 ne pas tenir compte de la longueur du nom.
Effectivement ça fonctionne parfaitement
Merci.
Fixer ainsi arbitrairement la taille du record ne me plait pas trop.
Pour donner une certaine cohérence au code (quand on essaye le lire) je propose de l'écrire comme ceci:ce qui me semble plus claire et surtout explique la taille de 88 ($58)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 SymbolInfo.MaxNameLen := 256; SymbolInfo.SizeOfStruct := I - SymbolInfo.MaxNameLen; // 88
EDIT:
Après avoir testé la version UNICODE et
dans un souci de compatibilité entre les deux je propose une dernière modification du code comme ceci:
Il fonctionne aussi bien sous D7(ansi) que sous D2009 (UNICODE) sans changer une virgule
je pense que cette fois c'est la dernière
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128 unit Unit5; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm5 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Déclarations privées } public { Déclarations publiques } end; const DbgHelpDll = 'C:\windows\system32\dbghelp.dll'; SYMFLAG_FUNCTION = $00000800 or $200; // fonction ou export table type TSYMBOL_INFO = record SizeOfStruct: DWORD; // 10 DWORD 5 uint64 256 AnsiChar => 336 TypeIndex: DWORD; Reserved_1, Reserved_2: uint64; Index: DWORD; Size: DWORD; ModBase: int64; Flags: DWORD; // SYMFLAG_FUNCTION Value: Int64; Address: int64; Registre: DWORD; Scope: DWORD; Tag: DWORD; NameLen: DWORD; MaxNameLen: DWORD; //256 Name: array[0..255] of Char; // AnsiChar end; function SymInitialize(aHandle: HMODULE; aUserSearchPath: PChar; aInvadeProcess: Boolean): Boolean; stdcall; external DbgHelpDll {$IFDEF UNICODE} name 'SymInitializeW' {$ELSE} name 'SymInitialize' {$ENDIF}; function SymFromAddr(aHandle: HMODULE; aAdress: int64; aDisplacement: DWORD; aSymbolInfo: Pointer): Boolean; stdcall; external DbgHelpDll {$IFDEF UNICODE} name 'SymFromAddrW' {$ELSE} name 'SymFromAddr' {$ENDIF}; function SymCleanup(aHandle: HMODULE): Boolean; stdcall; external DbgHelpDll; var Form5 : TForm5; implementation {$R *.dfm} procedure TForm5.Button1Click(Sender: TObject); var Hmod, Hprocessus: HMODULE; P : Pointer; i : cardinal; Deplacement : dword; SymbolInfo : TSYMBOL_INFO; Result : string; begin Hprocessus := getcurrentprocess; Hmod := LoadLibrary('kernel32.dll'); //une dll quelconque if Hmod = 0 then begin ShowMessage('librairie pas chargée'); FreeLibrary(Hmod); Exit; end; //P := nil; P := GetProcAddress(Hmod, 'AddAtomA'); //une fonction quelconque,l'adresse peut être supérieur jusqu'à la prochaine fonction if not Assigned(P) then begin ShowMessage('fonction pas chargée'); FreeLibrary(Hmod); Exit; end; if not SymInitialize(Hprocessus, nil, true) then begin ShowMessage('symboles pas initialisés'); FreeLibrary(Hmod); Exit; end; i := SizeOf(TSymbol_Info); zeromemory(@SymbolInfo, i); SymbolInfo.MaxNameLen := 256; SymbolInfo.SizeOfStruct := I - Length(SymbolInfo.Name) * SizeOf(SymbolInfo.Name[0]); // 88 Deplacement := 0; if SymFromAddr(Hprocessus, int64(p), Deplacement, @SymbolInfo) then // mettre le handle du processus begin if (SymbolInfo.Flags and SYMFLAG_FUNCTION) = 0 then begin ShowMessage('le symbole retourné n''est pas une fonction'); FreeLibrary(Hmod); Exit; end; {SetLength(Result, SymbolInfo.NameLen); for i := 0 to SymbolInfo.NameLen do} Result := SymbolInfo.Name; ShowMessage(Result); end else begin i := GetLastError; ShowMessage('infos pas retournées ; erreur ' + IntToStr(i)); end; if not SymCleanup(Hprocessus) then ShowMessage('symboles pas nettoyés'); FreeLibrary(Hmod); end; end.
qu'en pensez-vous ?
Cordialement,
@+
Je testerai ce w-e, pas le temps aujourd'hui.qu'en pensez-vous ?
Mais j'en pense qu'il faudrait juste extraire ça dans une unité séparée réutilisable et l'ajouter (je me répète, désolé) à la FAQ
Bonjour,
Je voulais revisiter le code de Cirec sous forme d'une fonction autonome, mais je ne parviens pas à inclure les déclarations de fonctions externes dedans : le compilateur n'y reconnaît pas la directive external.
Du coup, je propose ceci, qui n'est pas self-contained, que je n'ai testé qu'avec Berlin 10.1 sous Win7, et dans lequel j'ai ôté tout le code de gestion d'erreurs, surtout utile lors du débogage :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 const DbgHelpDll = 'C:\windows\system32\dbghelp.dll'; function SymInitialize(aHandle: HMODULE; aUserSearchPath: PChar; aInvadeProcess: Boolean): Boolean; stdcall; external DbgHelpDll {$IFDEF UNICODE} name 'SymInitializeW' {$ELSE} name 'SymInitialize' {$ENDIF}; function SymFromAddr(aHandle: HMODULE; aAdress: uint64; var aDisplacement: Cardinal; aSymbolInfo: Pointer): Boolean; stdcall; external DbgHelpDll {$IFDEF UNICODE} name 'SymFromAddrW' {$ELSE} name 'SymFromAddr' {$ENDIF}; function SymCleanup(aHandle: HMODULE): Boolean; stdcall; external DbgHelpDll; // retourne le nom d'une fonction d'une bibliothèque à partir de son adresse. function GetDllFunctionNameFromAddress(aAddress: Pointer): String; const SYMFLAG_FUNCTION = $00000800 or $00000200; // fonction ou export table MaxSymbolNameLen = 256; type TSYMBOL_INFO = record SizeOfStruct: Cardinal; TypeIndex: Cardinal; Reserved_1, Reserved_2: uint64; Index: Cardinal; Size: Cardinal; ModBase: uint64; Flags: Cardinal; // SYMFLAG_FUNCTION Value: uint64; Address: uint64; Registre: Cardinal; Scope: Cardinal; Tag: Cardinal; NameLen: Cardinal; MaxNameLen: Cardinal; // MaxSymbolNameLen (modifiable) Name: array[0..MaxSymbolNameLen-1] of Char; // pas à inclure dans TSYMBOL_INFO.SizeOfStruct end; var ProcessHandle: HMODULE; i, Deplacement: Cardinal; SymbolInfo: TSYMBOL_INFO; begin Result := EmptyStr; ProcessHandle := GetCurrentProcess; // initialisation de la table des symboles if not SymInitialize(ProcessHandle, nil, True) then Exit; // initialisation de la structure pour le retour des infos i := SizeOf(TSymbol_Info); ZeroMemory(@SymbolInfo, i); SymbolInfo.MaxNameLen := MaxSymbolNameLen; SymbolInfo.SizeOfStruct := i - Length(SymbolInfo.Name) * SizeOf(SymbolInfo.Name[0]); Deplacement := 0; // informations sur l'adresse demandée if SymFromAddr(ProcessHandle, int64(aAddress), Deplacement, @SymbolInfo) then begin if (SymbolInfo.Flags or SYMFLAG_FUNCTION) = SYMFLAG_FUNCTION // filtre les fonctions then Result := SymbolInfo.Name; end; // libération de la table des symboles SymCleanup(ProcessHandle); end;
Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
. Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !
je ne comprends pas bien où se situe ton problème ?
j'ai repris ton code tel quel et je l'ai mis dans une unité et voilà:et ça fonctionne
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 unit UGetProcName; interface function GetDllFunctionNameFromAddress(aAddress: Pointer): String; implementation uses Windows, SysUtils; const DbgHelpDll = 'dbghelp.dll'; function SymInitialize(aHandle: HMODULE; aUserSearchPath: PChar; aInvadeProcess: Boolean): Boolean; stdcall; external DbgHelpDll {$IFDEF UNICODE} name 'SymInitializeW' {$ELSE} name 'SymInitialize' {$ENDIF}; function SymFromAddr(aHandle: HMODULE; aAdress: uint64; var aDisplacement: Cardinal; aSymbolInfo: Pointer): Boolean; stdcall; external DbgHelpDll {$IFDEF UNICODE} name 'SymFromAddrW' {$ELSE} name 'SymFromAddr' {$ENDIF}; function SymCleanup(aHandle: HMODULE): Boolean; stdcall; external DbgHelpDll; // retourne le nom d'une fonction d'une bibliothèque à partir de son adresse. function GetDllFunctionNameFromAddress(aAddress: Pointer): String; const SYMFLAG_FUNCTION = $00000800 or $00000200; // fonction ou export table MaxSymbolNameLen = 256; type TSYMBOL_INFO = record SizeOfStruct: Cardinal; TypeIndex: Cardinal; Reserved_1, Reserved_2: uint64; Index: Cardinal; Size: Cardinal; ModBase: uint64; Flags: Cardinal; // SYMFLAG_FUNCTION Value: uint64; Address: uint64; Registre: Cardinal; Scope: Cardinal; Tag: Cardinal; NameLen: Cardinal; MaxNameLen: Cardinal; // MaxSymbolNameLen (modifiable) Name: array[0..MaxSymbolNameLen-1] of Char; // pas à inclure dans TSYMBOL_INFO.SizeOfStruct end; var ProcessHandle: HMODULE; i, Deplacement: Cardinal; SymbolInfo: TSYMBOL_INFO; begin Result := EmptyStr; ProcessHandle := GetCurrentProcess; // initialisation de la table des symboles if not SymInitialize(ProcessHandle, nil, True) then Exit; // initialisation de la structure pour le retour des infos i := SizeOf(TSymbol_Info); ZeroMemory(@SymbolInfo, i); SymbolInfo.MaxNameLen := MaxSymbolNameLen; SymbolInfo.SizeOfStruct := i - Length(SymbolInfo.Name) * SizeOf(SymbolInfo.Name[0]); Deplacement := 0; // informations sur l'adresse demandée if SymFromAddr(ProcessHandle, int64(aAddress), Deplacement, @SymbolInfo) then begin if (SymbolInfo.Flags or SYMFLAG_FUNCTION) = SYMFLAG_FUNCTION // filtre les fonctions then Result := SymbolInfo.Name; end; // libération de la table des symboles SymCleanup(ProcessHandle); end; end.
Cordialement,
@+
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager