List all exported functions in a dll or exe

Share your advanced PureBasic knowledge/code with the community.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

REMOVED (talking *ollox again!)
Last edited by srod on Mon Mar 05, 2007 1:00 am, edited 1 time in total.
I may look like a mule, but I'm not a complete ass.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Strange, netmaestro's code works fine for me with all .dll's so far including dwmapi.dll
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

I'm running it on xp and it looks like dwmapi.dll requires an updated version of user32.dll.
I may look like a mule, but I'm not a complete ass.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Okay, this one works on xp:

Code: Select all

;'DllFunctionDump'. 
;----------------- 
;   Stephen Rodriguez. 
;   Created with Purebasic 4.02 for Windows. 
; 
;   Based on some code by Torsten Rienow;  http://www.powerbasic.com/support/forums/Forum7/HTML/001216.html 

;   Date:  March 2007. 
; 
;   Platforms:  Windows only.  Tested on XP professional SP2. 
; 
;Licence. 
;------- 
;   You are not allowed to use this code or any derivative for any hacking (api hijacking) 
;   tools. 
; 
;   No warranties... etc. 
;****************************************************************************************** 
; 
;The function GetDllFunctions() will retrieve all exported function names residing within 
;the specified dll/exe file.  The names are placed within a string array passed as a parameter 
;to the Procedure. 
;The function returns a count of the number of functions retrieved. 
;It will also return zero in the case of an error. 
; 
;The array will be redimensioned as appropriate, 
;****************************************************************************************** 


#IMAGE_DOS_SIGNATURE = $5A4D 
#IMAGE_NT_SIGNATURE = $4550 

;The following structure is not already defined by PB, 
Structure _IMAGE_SECTION_HEADER 
  Name.b[8]    ;8 bytes for a null-padded section name. UTF 8 format. 
  VirtualSize.l ;= 0 
  VirtualAddress.l ; = 0 
  SizeOfRawData.l 
  PointerToRawData.l 
  PointerToRelocations.l 
  PointerToLineNumbers.l ; = 0 
  NumberOfRelocations.w 
  NumberOfLineNumbers.w ; = 0 
  Characteristics.l 
EndStructure 



Procedure.l GetDllFunctions(filename.s,  strTable.s(1)) 
  Protected filesize, fileid, hFileMapping, filebase 
  Protected *idh.IMAGE_DOS_HEADER, *inth.IMAGE_NT_HEADERS 
  Protected *ExpDir.IMAGE_EXPORT_DIRECTORY, *section._IMAGE_SECTION_HEADER, *exsection._IMAGE_SECTION_HEADER 
  Protected exportsStartRVA, exportsEndRVA, entryPointRVA 
  Protected delta, *pFunctions.LONG, *pNames.LONG, currentsymname$ 
  Protected flag, i, j, count, dirsize 
  ;First job, check the filename. 
    filesize = FileSize(filename) 
    If filesize <=0 : ProcedureReturn 0 : EndIf 
    fileid=ReadFile(#PB_Any, filename) 
    If fileid = 0 : ProcedureReturn 0 : EndIf 
  ;Create a file mapping object so that we can treat the dll as if it were in memory. 
    hFileMapping = CreateFileMapping_(FileID(fileid), 0, #PAGE_READONLY, 0, 0, 0) 
    If hFileMapping = 0 : CloseFile(fileid) : ProcedureReturn 0 : EndIf 
  ;Map the file. 
    FileBase = MapViewOfFile_(hFileMapping, #FILE_MAP_READ, 0, 0, 0) 
    If FileBase  = 0 
      CloseHandle_(hFileMapping) 
      CloseFile(fileid) 
      ProcedureReturn 0 
    EndIf 
    *idh=FileBase 
    If *idh\e_magic = #IMAGE_DOS_SIGNATURE 
      *inth=*idh + *idh\e_lfanew 
      ;Check that the current process has access to the memory and the image is a valid pe dll/exe.. 
      If IsBadReadPtr_(*inth, SizeOf(IMAGE_NT_HEADERS)) = 0  And*inth\Signature = #IMAGE_NT_SIGNATURE 
      ;Good to go! 
      ;Determine the RVA of the exports data directory. 
        exportsStartRVA = *inth\OptionalHeader\DataDirectory[#IMAGE_DIRECTORY_ENTRY_EXPORT]\VirtualAddress 
        exportsEndRVA = exportsStartRVA + *inth\OptionalHeader\DataDirectory[#IMAGE_DIRECTORY_ENTRY_EXPORT]\Size 
        ;Get the first section. 
          *section = *inth + SizeOf(IMAGE_FILE_HEADER)+4 + *inth\FileHeader\SizeOfOptionalHeader 
        ;Identify the section containing the exports.  It is not always .edata ! 
          For i=1 To *inth\FileHeader\NumberOfSections 
            If exportsStartRVA >= *section\VirtualAddress And exportsStartRVA < *section\VirtualAddress + *section\VirtualSize 
              *exsection = *section 
              Break        
            EndIf 
            *section +SizeOf(_IMAGE_SECTION_HEADER) 
          Next 
        If *exsection 
          ;Calculate the difference between the RVA's and the file offsets for the current section. 
            delta = *exsection\VirtualAddress - *exsection\PointerToRawData 
          ;Adjust the exportsStartRVa accordingly to give the file offset of the image export directory, 
          *ExpDir = *idh + exportsStartRVA - delta 
          *pFunctions  = *idh+ *ExpDir\AddressOfFunctions - delta 
          *pNames = *idh+ *ExpDir\AddressOfNames - delta 
          For i = 0 To *ExpDir\NumberOfNames - 1 
            ;Only add the function name if it actually points to some code! 
              entryPointRVA = *pFunctions\l : *pFunctions + SizeOf(LONG) 
              If entryPointRVA <> 0 
                ;Add the name to the strTable() array and increase the count. 
                  If *pNames\l
                    currentsymname$=PeekS(*pNames\l- delta + *idh,-1, #PB_Ascii) 
                    ReDim strTable.s(count) 
                    strTable(count)=currentsymname$ 
                    count+1 
                  EndIf
              EndIf 
            *pNames+SizeOf(LONG)
          Next 
        EndIf        
      EndIf 
    EndIf 
    UnmapViewOfFile_(FileBase) 
    CloseHandle_(hFileMapping) 
    CloseFile(fileid) 
  ProcedureReturn count 
EndProcedure 


;Test. 
Dim names.s(0) 
num=GetDllFunctions("dwmapi.dll", names()) 
For i = 0 To num-1 
  Debug names(i) 
Next 
I may look like a mule, but I'm not a complete ass.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

OK, now it works. have to put the full path to the .dll but it works now. Thank You :)

P.S. May want to look at your COFF code also that you posted earlier. It didn't work for Vista either.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Bloody Vista! :)

Actually, could you e-mail me an MSCOFF file built for Vista so that I can take a look.

Or is it that the MSCOFF symbol dump program simply doesn't run on Vista?
I may look like a mule, but I'm not a complete ass.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

srod wrote:Bloody Vista! :)

Actually, could you e-mail me an MSCOFF file built for Vista so that I can take a look.

Or is it that the MSCOFF symbol dump program simply doesn't run on Vista?
The COFF code compiles, runs, then terminates. Debug never comes up and shows anything. Sure, I can email a .obj file to you, PM me the email address.

EDIT: OK, made a mistake. The code for the COFF dumper works fine. I was using a .obj that didn't have any functions in it by mistake. Sorry for the confusion.
yrreti
Enthusiast
Enthusiast
Posts: 546
Joined: Tue Oct 31, 2006 4:34 am

Post by yrreti »

srod wrote:
just to say that dll's do not contain information on the parameters of the exported functions, so you'll search in vain for these!
Do you have any idea where one could get that information?
Obviously it's there somewhere in the code, because it responds to the parameters you call the function with,
and has to know what to do with them. I know that you can get the info from some dll creators like for instance
RMCHARTS, who generously lists them on his site. I know that you can get the info on microsofts dll's
using the win32api list. But as for ones you can't find, really what good is knowing the function names, or
even printing them out like the programs listed here do, if you don't know the parameters needed to use it.

I'm just curious and really appreciate your expertise and experience on this question.
Thank you much for any help or suggestions.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

There is nothing in a dll which will give you any information on the number and type of parameters used by any exported function. I say nothing, obviously you could disassemble the code, but determining parameter info this way would be a very imprecise science at best!

Obviously, as a creator of a dll you would publish information on the individual functions; info such as calling convention, number of parameters etc.

It is possible to gleam some information from a dll's import library (if you have access to one), but this depends upon the naming convention used for the exported functions. E.g. _MessageBoxA@16 tells us that there are 4 parameters (16 bytes) etc. But this name only appears in the import lib and not the Windows dll etc.
I may look like a mule, but I'm not a complete ass.
yrreti
Enthusiast
Enthusiast
Posts: 546
Joined: Tue Oct 31, 2006 4:34 am

Post by yrreti »

srod, thank you very much for your input and explanation on my question.
Post Reply