只能显示DLL可导出函数<br><br>uses DLLTools; <br><br>function TForm1.ListExport( const name: String; ordinal: Integer; addressointer ): Boolean; <br>var <br>listentry: TLIstItem; <br>begin <br>Result := true; <br>listentry:= listview.Items.Add; <br>listentry.Caption := Format('%p',[address] ); <br>listentry.Subitems.Add( format('%d',[ordinal] )); <br>listentry.Subitems.Add( name ); <br>end; <br><br>procedure TForm1.Button1Click(Sender: TObject); <br>begin <br>if opendialog.execute then <br>begin <br>listview.items.clear; <br>ListDLLExports( opendialog.filename, listexport ); <br>end; <br>end; <br><br><br>***** <br>DLLTOOLS 单元 <br>***** <br><br><br>unit dlltools; <br><br>interface <br><br>Uses Windows, Classes, Sysutils, imagehlp ; <br><br>type <br>TDLLExportCallback = function (const name: String; ordinal: Integer; <br>address: Pointer): Boolean of Object; <br>{ Note: address is a RVA here, not a usable virtual address! } <br>DLLToolsError = Class( Exception ); <br><br>Procedure ListDLLExports( const filename: String; callback: <br>TDLLExportCallback ); <br>Procedure DumpExportDirectory( Const ExportDirectory: TImageExportDirectory; <br>lines: TStrings; const Image: LoadedImage ); <br>Function RVAToPchar( rva: DWORD; const Image: LoadedImage ): PChar; <br>Function RVAToPointer( rva: DWORD; const Image: LoadedImage ): Pointer; <br><br>implementation <br><br>resourcestring <br>eDLLNotFound = <br>'ListDLLExports: DLL %s does not exist!'; <br><br>{+---------------------------------------------------------------------- <br>Procedure EnumExports <br><br>Parameters : <br>ExportDirectory: IMAGE_EXPORT_DIRECTORY record to enumerate <br>image : LOADED_IMAGE record for the DLL the export directory belongs <br>to. <br>callback : callback function to hand the found exports to, must not be <br>Nil <br>Description: <br>The export directory of a PE image contains three RVAs that point at <br>tables <br>which describe the exported functions. The first is an array of RVAs <br>that <br>refer to the exported function names, these we translate to PChars to <br>get the exported name. The second array is an array of Word that <br>contains <br>the export ordinal for the matching entry in the names array. The <br>ordinal <br>is biased, that is we have to add the ExportDirectory.Base value to it <br>to <br>get the actual export ordinal. The biased ordinal serves as index for <br>the <br>third array, which is an array of RVAs that give the position of the <br>function code in the image. We don't translate these RVAs since the DLL <br>is not relocated since we load it via MapAndLoad. The function array is <br>usually much larger than the names array, since the ordinals for the <br>exported functions do not have to be in sequence, there can be (and <br>frequently are) gaps in the sequence, for which the matching entries in <br>the <br>function RVA array are garbage. <br>Error Conditions: none <br>Created: 9.1.2000 by P. Below <br>+----------------------------------------------------------------------} <br>Procedure EnumExports( const ExportDirectory : TImageExportDirectory ; <br>const image : LoadedImage ; <br>callback : TDLLExportCallback ) ; <br>Type <br>TDWordArray = Array [0..$FFFFF] of DWORD; <br>Var <br>i: Cardinal; <br>pNameRVAs, pFunctionRVas: ^TDWordArray; <br>pOrdinals: ^TWordArray; <br>name: String; <br>address: Pointer; <br>ordinal: Word; <br>Begin { EnumExports } <br>pNameRVAs := <br>RVAToPointer( DWORD(ExportDirectory.AddressOfNames), image ); <br>pFunctionRVAs := <br>RVAToPointer( DWORD(ExportDirectory.AddressOfFunctions), image ); <br>pOrdinals := <br>RVAToPointer( DWORD(ExportDirectory.AddressOfNameOrdinals), image ); <br>For i:= 0 to Pred( ExportDirectory.NumberOfNames ) Do Begin <br>name := RVAToPChar( pNameRVAs^, image ); <br>ordinal := pOrdinals^; <br>address := Pointer( pFunctionRVAs^[ ordinal ] ); <br>If not callback( name, ordinal+ExportDirectory.Base, address ) Then <br>Exit; <br>End; { For } <br>End; { EnumExports } <br><br>{+---------------------------------------------------------------------- <br>Procedure ListDLLExports <br><br>Parameters : <br>filename : full pathname of DLL to examine <br>callback : callback to hand the found exports to, must not be Nil <br>Description: <br>Loads the passed DLL using the LoadImage function, finds the exported <br>names table and reads it. Each found entry is handed to the callback <br>for further processing, until no more entries remain or the callback <br>returns false. Note that the address passed to the callback for a <br>exported <br>function is an RVA, so not identical to the address the function would <br>have in a properly loaded and relocated DLL! <br>Error Conditions: <br>Exceptions are raised if <br>- the passed DLL does not exist or could not be loaded <br>- no callback was passed (only if assertions are on) <br>- an API function failed <br>Created: 9.1.2000 by P. Below <br>+----------------------------------------------------------------------} <br>Procedure ListDLLExports( const filename : String ; callback : <br>TDLLExportCallback ) ; <br>Var <br>imageinfo: LoadedImage; <br>pExportDirectory: PImageExportDirectory; <br>dirsize: Cardinal; <br>Begin { ListDLLExports } <br>Assert( Assigned( callback )); <br>If not FileExists( filename ) Then <br>raise DLLToolsError.CreateFmt( eDLLnotFound, [filename] ); <br><br>If MapAndLoad( PChar( filename ), nil, @imageinfo, true, true ) Then <br>try <br>pExportDirectory := <br>ImageDirectoryEntryToData( <br>imageinfo.MappedAddress, false, <br>IMAGE_DIRECTORY_ENTRY_EXPORT, dirsize ); <br><br>If pExportDirectory = Nil Then <br>RaiseLastWin32Error <br>Else <br>EnumExports( pExportDirectory^, imageinfo, callback ); <br>finally <br>UnMapAndLoad( @imageinfo ); <br>end <br>Else <br>RaiseLastWin32Error; <br>End; { ListDLLExports } <br><br>{+---------------------------------------------------------------------- <br>Procedure DumpExportDirectory <br><br>Parameters : <br>ExportDirectory: a IMAGE_EXPORT_DIRECTORY record <br>lines : a TStrings descendend to put the info into, must not be Nil <br>Description: <br>Dumps the fields of the passed structure to the passed strings <br>descendent <br>as strings. <br>Error Conditions: <br>will raise an exception if lines is Nil and assertions are enabled. <br>Created: 9.1.2000 by P. Below <br>+----------------------------------------------------------------------} <br>Procedure DumpExportDirectory( Const ExportDirectory : TImageExportDirectory; <br>lines : TStrings; const Image: LoadedImage ) ; <br>Begin { DumpExportDirectory } <br>Assert( Assigned( lines )); <br><br>lines.add( 'Dump of IMAGE_EXPORT_DIRECTORY' ); <br>lines.add( format('Characteristics: %d', <br>[ExportDirectory.Characteristics])); <br>lines.add( format('TimeDateStamp: %d', <br>[ExportDirectory.TimeDateStamp])); <br>lines.add( format('Version: %d.%d', <br>[ExportDirectory.MajorVersion, <br>ExportDirectory.MinorVersion])); <br>lines.add( format('Name (RVA): %x', <br>[ExportDirectory.Name])); <br>lines.add( format('Name (translated): %s', <br>[RVAToPchar( ExportDirectory.name, Image )])); <br>lines.add( format('Base: %d', <br>[ExportDirectory.Base])); <br>lines.add( format('NumberOfFunctions: %d', <br>[ExportDirectory.NumberOfFunctions])); <br>lines.add( format('NumberOfNames: %d', <br>[ExportDirectory.NumberOfNames])); <br>lines.add( format('AddressOfFunctions (RVA): %p', <br>[Pointer(ExportDirectory.AddressOfFunctions)])); <br>lines.add( format('AddressOfNames (RVA): %p', <br>[Pointer(ExportDirectory.AddressOfNames)])); <br>lines.add( format('AddressOfNameOrdinals (RVA): %p', <br>[Pointer(ExportDirectory.AddressOfNameOrdinals)])); <br>End; { DumpExportDirectory } <br><br>{+---------------------------------------------------------------------- <br>Function RVAToPointer <br><br>Parameters : <br>rva : a relative virtual address to translate <br>Image : LOADED_IMAGE structure for the image the RVA relates to <br>Returns : translated address <br>Description: <br>Uses the ImageRVAToVA function to translate the RVA to a virtual <br>address. <br>Error Conditions: <br>Will raise an exception if the translation failed <br>Created: 9.1.2000 by P. Below <br>+----------------------------------------------------------------------} <br>Function RVAToPointer( rva : DWORD ; const Image : LoadedImage ) : Pointer; <br>var <br>pDummy: PImageSectionHeader; <br>Begin { RVAToPchar } <br>pDummy := nil; <br>Result := <br>ImageRvaToVa( Image.FileHeader, Image.MappedAddress, rva, <br>pDummy ); <br>If Result = Nil Then <br>RaiseLastWin32Error; <br>End; { RVAToPointer } <br><br>{+---------------------------------------------------------------------- <br>Function RVAToPchar <br><br>Parameters : <br>rva : a relative virtual address to translate <br>Image : LOADED_IMAGE structure for the image the RVA relates to <br>Returns : translated address <br>Description: <br>Uses the RVAToPointer function to translate the RVA to a virtual <br>address. Note that we do not check that the address does indeed point <br>to a zero-terminated string! <br>Error Conditions: <br>Will raise an exception if the translation failed <br>Created: 9.1.2000 by P. Below <br>+----------------------------------------------------------------------} <br>Function RVAToPchar( rva : DWORD ; const Image : LoadedImage ) : PChar ; <br>Begin { RVAToPchar } <br>Result := RVAToPointer( rva, image ); <br>End; { RVAToPchar } <br><br>end. <br> <br>
//显示DLL可导出函数<br> // 为了测试,你需要在Form上放置一个TButton、TOpenDialog和TListView构件<br><br><br> // 完整的DLLTools单元的代码在示例代码之后<br><br><br> uses DLLTools; <br><br><br> function TForm1.ListExport( const name: String; ordinal: Integer; addressointer ): Boolean; <br><br> var <br><br> listentry: TLIstItem; <br><br> begin <br><br> Result := true; <br><br> listentry:= listview.Items.Add; <br><br> listentry.Caption := Format('%p',[address] ); <br><br> listentry.Subitems.Add( format('%d',[ordinal] )); <br><br> listentry.Subitems.Add( name ); <br><br> end; <br><br><br> procedure TForm1.Button1Click(Sender: TObject); <br><br> begin <br><br> if opendialog.execute then <br><br> begin <br><br> listview.items.clear; <br><br> ListDLLExports( opendialog.filename, listexport ); <br><br> end; <br><br> end; <br><br><br><br> ***** <br><br> DLLTOOLS 单元<br><br> ***** <br><br><br><br> unit dlltools; <br><br><br> interface <br><br><br> Uses Windows, Classes, Sysutils, imagehlp ; <br><br><br> type <br><br> TDLLExportCallback = function (const name: String; ordinal: Integer; <br><br> address: Pointer): Boolean of Object; <br><br> { Note: address is a RVA here, not a usable virtual address! } <br><br> DLLToolsError = Class( Exception ); <br><br><br> Procedure ListDLLExports( const filename: String; callback: <br><br> TDLLExportCallback ); <br><br> Procedure DumpExportDirectory( Const ExportDirectory: TImageExportDirectory; <br><br> lines: TStrings; const Image: LoadedImage ); <br><br> Function RVAToPchar( rva: DWORD; const Image: LoadedImage ): PChar; <br><br> Function RVAToPointer( rva: DWORD; const Image: LoadedImage ): Pointer; <br><br><br> implementation <br><br><br> resourcestring <br><br> eDLLNotFound = <br><br> 'ListDLLExports: DLL %s does not exist!'; <br><br><br> {+---------------------------------------------------------------------- <br><br> | Procedure EnumExports <br><br> | <br><br> | Parameters : <br><br> | ExportDirectory: IMAGE_EXPORT_DIRECTORY record to enumerate <br><br> | image : LOADED_IMAGE record for the DLL the export directory belongs <br><br> | to. <br><br> | callback : callback function to hand the found exports to, must not be <br><br> Nil <br><br> | Description: <br><br> | The export directory of a PE image contains three RVAs that point at <br><br> tables <br><br> | which describe the exported functions. The first is an array of RVAs <br><br> that <br><br> | refer to the exported function names, these we translate to PChars to <br><br> | get the exported name. The second array is an array of Word that <br><br> contains <br><br> | the export ordinal for the matching entry in the names array. The <br><br> ordinal <br><br> | is biased, that is we have to add the ExportDirectory.Base value to it <br><br> to <br><br> | get the actual export ordinal. The biased ordinal serves as index for <br><br> the <br><br> | third array, which is an array of RVAs that give the position of the <br><br> | function code in the image. We don't translate these RVAs since the DLL <br><br> | is not relocated since we load it via MapAndLoad. The function array is <br><br> | usually much larger than the names array, since the ordinals for the <br><br> | exported functions do not have to be in sequence, there can be (and <br><br> | frequently are) gaps in the sequence, for which the matching entries in <br><br> the <br><br> | function RVA array are garbage. <br><br> | Error Conditions: none <br><br> | Created: 9.1.2000 by P. Below <br><br> +----------------------------------------------------------------------} <br><br> Procedure EnumExports( const ExportDirectory : TImageExportDirectory ; <br><br> const image : LoadedImage ; <br><br> callback : TDLLExportCallback ) ; <br><br> Type <br><br> TDWordArray = Array [0..$FFFFF] of DWORD; <br><br> Var <br><br> i: Cardinal; <br><br> pNameRVAs, pFunctionRVas: ^TDWordArray; <br><br> pOrdinals: ^TWordArray; <br><br> name: String; <br><br> address: Pointer; <br><br> ordinal: Word; <br><br> Begin { EnumExports } <br><br> pNameRVAs := <br><br> RVAToPointer( DWORD(ExportDirectory.AddressOfNames), image ); <br><br> pFunctionRVAs := <br><br> RVAToPointer( DWORD(ExportDirectory.AddressOfFunctions), image ); <br><br> pOrdinals := <br><br> RVAToPointer( DWORD(ExportDirectory.AddressOfNameOrdinals), image ); <br><br> For i:= 0 to Pred( ExportDirectory.NumberOfNames ) Do Begin <br><br> name := RVAToPChar( pNameRVAs^, image ); <br><br> ordinal := pOrdinals^; <br><br> address := Pointer( pFunctionRVAs^[ ordinal ] ); <br><br> If not callback( name, ordinal+ExportDirectory.Base, address ) Then <br><br> Exit; <br><br> End; { For } <br><br> End; { EnumExports } <br><br><br> {+---------------------------------------------------------------------- <br><br> | Procedure ListDLLExports <br><br> | <br><br> | Parameters : <br><br> | filename : full pathname of DLL to examine <br><br> | callback : callback to hand the found exports to, must not be Nil <br><br> | Description: <br><br> | Loads the passed DLL using the LoadImage function, finds the exported <br><br> | names table and reads it. Each found entry is handed to the callback <br><br> | for further processing, until no more entries remain or the callback <br><br> | returns false. Note that the address passed to the callback for a <br><br> exported <br><br> | function is an RVA, so not identical to the address the function would <br><br> | have in a properly loaded and relocated DLL! <br><br> | Error Conditions: <br><br> | Exceptions are raised if <br><br> | - the passed DLL does not exist or could not be loaded <br><br> | - no callback was passed (only if assertions are on) <br><br> | - an API function failed <br><br> | Created: 9.1.2000 by P. Below <br><br> +----------------------------------------------------------------------} <br><br> Procedure ListDLLExports( const filename : String ; callback : <br><br> TDLLExportCallback ) ; <br><br> Var <br><br> imageinfo: LoadedImage; <br><br> pExportDirectory: PImageExportDirectory; <br><br> dirsize: Cardinal; <br><br> Begin { ListDLLExports } <br><br> Assert( Assigned( callback )); <br><br> If not FileExists( filename ) Then <br><br> raise DLLToolsError.CreateFmt( eDLLnotFound, [filename] ); <br><br><br> If MapAndLoad( PChar( filename ), nil, @imageinfo, true, true ) Then <br><br> try <br><br> pExportDirectory := <br><br> ImageDirectoryEntryToData( <br><br> imageinfo.MappedAddress, false, <br><br> IMAGE_DIRECTORY_ENTRY_EXPORT, dirsize ); <br><br><br> If pExportDirectory = Nil Then <br><br> RaiseLastWin32Error <br><br> Else <br><br> EnumExports( pExportDirectory^, imageinfo, callback ); <br><br> finally <br><br> UnMapAndLoad( @imageinfo ); <br><br> end <br><br> Else <br><br> RaiseLastWin32Error; <br><br> End; { ListDLLExports } <br><br><br> {+---------------------------------------------------------------------- <br><br> | Procedure DumpExportDirectory <br><br> | <br><br> | Parameters : <br><br> | ExportDirectory: a IMAGE_EXPORT_DIRECTORY record <br><br> | lines : a TStrings descendend to put the info into, must not be Nil <br><br> | Description: <br><br> | Dumps the fields of the passed structure to the passed strings <br><br> descendent <br><br> | as strings. <br><br> | Error Conditions: <br><br> | will raise an exception if lines is Nil and assertions are enabled. <br><br> | Created: 9.1.2000 by P. Below <br><br> +----------------------------------------------------------------------} <br><br> Procedure DumpExportDirectory( Const ExportDirectory : TImageExportDirectory; <br><br> lines : TStrings; const Image: LoadedImage ) ; <br><br> Begin { DumpExportDirectory } <br><br> Assert( Assigned( lines )); <br><br><br> lines.add( 'Dump of IMAGE_EXPORT_DIRECTORY' ); <br><br> lines.add( format('Characteristics: %d', <br><br> [ExportDirectory.Characteristics])); <br><br> lines.add( format('TimeDateStamp: %d', <br><br> [ExportDirectory.TimeDateStamp])); <br><br> lines.add( format('Version: %d.%d', <br><br> [ExportDirectory.MajorVersion, <br><br> ExportDirectory.MinorVersion])); <br><br> lines.add( format('Name (RVA): %x', <br><br> [ExportDirectory.Name])); <br><br> lines.add( format('Name (translated): %s', <br><br> [RVAToPchar( ExportDirectory.name, Image )])); <br><br> lines.add( format('Base: %d', <br><br> [ExportDirectory.Base])); <br><br> lines.add( format('NumberOfFunctions: %d', <br><br> [ExportDirectory.NumberOfFunctions])); <br><br> lines.add( format('NumberOfNames: %d', <br><br> [ExportDirectory.NumberOfNames])); <br><br> lines.add( format('AddressOfFunctions (RVA): %p', <br><br> [Pointer(ExportDirectory.AddressOfFunctions)])); <br><br> lines.add( format('AddressOfNames (RVA): %p', <br><br> [Pointer(ExportDirectory.AddressOfNames)])); <br><br> lines.add( format('AddressOfNameOrdinals (RVA): %p', <br><br> [Pointer(ExportDirectory.AddressOfNameOrdinals)])); <br><br> End; { DumpExportDirectory } <br><br><br> {+---------------------------------------------------------------------- <br><br> | Function RVAToPointer <br><br> | <br><br> | Parameters : <br><br> | rva : a relative virtual address to translate <br><br> | Image : LOADED_IMAGE structure for the image the RVA relates to <br><br> | Returns : translated address <br><br> | Description: <br><br> | Uses the ImageRVAToVA function to translate the RVA to a virtual <br><br> | address. <br><br> | Error Conditions: <br><br> | Will raise an exception if the translation failed <br><br> | Created: 9.1.2000 by P. Below <br><br> +----------------------------------------------------------------------} <br><br> Function RVAToPointer( rva : DWORD ; const Image : LoadedImage ) : Pointer; <br><br> var <br><br> pDummy: PImageSectionHeader; <br><br> Begin { RVAToPchar } <br><br> pDummy := nil; <br><br> Result := <br><br> ImageRvaToVa( Image.FileHeader, Image.MappedAddress, rva, <br><br> pDummy ); <br><br> If Result = Nil Then <br><br> RaiseLastWin32Error; <br><br> End; { RVAToPointer } <br><br><br> {+---------------------------------------------------------------------- <br><br> | Function RVAToPchar <br><br> | <br><br> | Parameters : <br><br> | rva : a relative virtual address to translate <br><br> | Image : LOADED_IMAGE structure for the image the RVA relates to <br><br> | Returns : translated address <br><br> | Description: <br><br> | Uses the RVAToPointer function to translate the RVA to a virtual <br><br> | address. Note that we do not check that the address does indeed point <br><br> | to a zero-terminated string! <br><br> | Error Conditions: <br><br> | Will raise an exception if the translation failed <br><br> | Created: 9.1.2000 by P. Below <br><br> +----------------------------------------------------------------------} <br><br> Function RVAToPchar( rva : DWORD ; const Image : LoadedImage ) : PChar ; <br><br> Begin { RVAToPchar } <br><br> Result := RVAToPointer( rva, image ); <br><br> End; { RVAToPchar } <br><br><br> end. <br><br> ----------------------------------------- <br><br>取得某一dll所有输出函数名 <br><br>取得某一dll所有输出函数名<br>在uses里加上ImageHlp<br><br>procedure ListDLLFunctions(DLLName: String; List: TStrings);<br>type<br> chararr = array [0..$FFFFFF] of Char;<br> var<br> H: THandle;<br> I,<br> fc: integer;<br> st: string;<br> arr: Pointer;<br> ImageDebugInformation: PImageDebugInformation;<br>begin<br> List.Clear;<br> DLLName := ExpandFileName(DLLName);<br> if FileExists(DLLName) then<br> begin<br> H := CreateFile(PChar(DLLName), GENERIC_READ, FILE_SHARE_READ or<br> FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);<br> if H<>INVALID_HANDLE_VALUE then<br> try<br> ImageDebugInformation := MapDebugInformation(H, PChar(DLLName), nil, 0);<br> if ImageDebugInformation<>nil then<br> try<br> arr := ImageDebugInformation^.ExportedNames;<br> fc := 0;<br> for I := 0 to ImageDebugInformation^.ExportedNamesSize - 1 do<br> if chararr(arr^)=#0 then<br> begin<br> st := PChar(@chararr(arr^)[fc]);<br> if Length(st)>0 then<br> List.Add(st);<br> if (I>0) and (chararr(arr^)[I-1]=#0) then<br> Break;<br> fc := I + 1<br> end<br> finally<br> UnmapDebugInformation(ImageDebugInformation)<br> end<br> finally<br> CloseHandle(H)<br> end<br> end<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br> List: TStrings;<br> I: integer;<br> S: String;<br><br>begin<br> List := TStringList.Create;<br><br> ListDLLFunctions('c:/windows/system/Abcsda.dll', List);<br> showmessage(inttostr(list.count));<br> S := 'List of functions';<br> for I := 0 to List.Count - 1 do<br> S := S + #13#10 + List;<br> ShowMessage(S);<br><br> List.Free<br>end;<br><br><br> <br>