Page 1 of 1

How to enumerate DLL exported functions using API

Posted: Sat Feb 21, 2015 10:46 pm
by luis
Asked by nco2k here -> http://www.purebasic.fr/english/viewtop ... =5&t=61702

Code: Select all

; Here it is how to enumerate the exported functions from a DLL using API and some pointer arithmetic instead of PB commands.
; Should work for Ascii/Unicode/x86/x64

; Why use this ? I don't know. 
; Maybe the ImageDirectoryEntryToData() usage example can be useful as a starting point for someone wanting to explore the PE file format.

EnableExplicit

#PBCODE = 1

#DLLNAME$ = "OPENGL32.DLL" ; also try "USER32.DLL"

CompilerIf #PBCODE = 1

Define hDLL

Debug "USING PB COMMANDS"

hDLL = OpenLibrary(#PB_Any, #DLLNAME$)

If hDLL
    Debug CountLibraryFunctions(hDLL)
    
    If ExamineLibraryFunctions(hDLL)
        While NextLibraryFunction()
            Debug LibraryFunctionName() + " = $" + Hex(LibraryFunctionAddress())
        Wend
    EndIf
    CloseLibrary(hDLL)
EndIf

CompilerElse

Define hDLL

Define *ied.IMAGE_EXPORT_DIRECTORY
Define NumberOfNames, size, i, ord
Define *AddressOfFunctions, *AddressOfNames, *AddressOfNameOrdinals
Define FunctionName$, *FunctionAddress 

Debug "USING API AND IMAGE_EXPORT_DIRECTORY STRUCTURE"

hDLL = LoadLibrary_(#DLLNAME$)

If hDLL
    *ied = ImageDirectoryEntryToData_(hDLL, 1, #IMAGE_DIRECTORY_ENTRY_EXPORT, @size)
    
    If *ied 
        NumberOfNames = *ied\NumberOfNames        
        
        Debug NumberOfNames
        
        *AddressOfFunctions = hDLL + *ied\AddressOfFunctions
        *AddressOfNames = hDLL + *ied\AddressOfNames
        *AddressOfNameOrdinals = hDLL + *ied\AddressOfNameOrdinals
        
        For i = 0 To NumberOfNames - 1            
            FunctionName$ = PeekS(hDLL + PeekL(*AddressOfNames + (i * SizeOf(Long))), -1, #PB_Ascii)
            ord = PeekU(*AddressOfNameOrdinals + (i * SizeOf(Word)))           
            *FunctionAddress = hDLL + PeekL(*AddressOfFunctions + (ord * SizeOf(Long)))
            Debug FunctionName$ + " = $" + Hex(*FunctionAddress)
        Next    
    EndIf
    FreeLibrary_(hDLL)
EndIf

CompilerEndIf


BTW: Processing USER32.DLL with the PB code branch I get strange results, while I seem to get nice ones with my code.

Did I found a bug while doing this ?

Re: How to enumerate DLL exported functions using API

Posted: Sun Feb 22, 2015 3:18 am
by Teddy Rogers
luis wrote:Did I found a bug while doing this ?
No. PureBasic is querying functions in ordinal list and is displaying unnamed functions in the library (these could have been reserved for future use). You can filter out these results if you wish which, is essentially what the API version has done...

Ted.

Re: How to enumerate DLL exported functions using API

Posted: Sun Feb 22, 2015 12:31 pm
by luis
@Ted
Yes, that's correct I'm sorry, there is no bug.

Actually I was not referring to the exported functions without a name, I really saw some weird (like as in garbage) short strings in the first results, not empty strings, and I don't see them anymore. :shock:
Maybe I did something wrong, then I've modified the code and forgot to try again the PB part. Don't know, they are not there anymore so... ok.

I wonder anyway why by using ImageDirectoryEntryToData_() it doesn't list the unnamed functions ... I think it should just navigating the image of the module in memory and returning the base address of the appropriate section, like working on the file.

I also tried to use
hDLL = LoadLibraryEx_(#DLLNAME$, 0, #LOAD_LIBRARY_AS_DATAFILE)
just to be sure.

Re: How to enumerate DLL exported functions using API

Posted: Sun Feb 22, 2015 6:17 pm
by nco2k
> I wonder anyway why by using ImageDirectoryEntryToData_() it doesn't list the unnamed functions
actually you should be able to list them aswell. thats what IMAGE_EXPORT_DIRECTORY\NumberOfFunctions is for. the msdn link you provided, does use it at some point. but im still trying to decypher the whole thing.

c ya,
nco2k

Re: How to enumerate DLL exported functions using API

Posted: Sun Feb 22, 2015 6:29 pm
by luis
I've completely overlooked that, in fact the number returned by that is the total number of the functions exported, not only the named ones.
Thanks, I'll look into it later unless you beat me to it :wink:

Re: How to enumerate DLL exported functions using API

Posted: Sun Feb 22, 2015 7:26 pm
by Zebuddi123

Re: How to enumerate DLL exported functions using API

Posted: Sun Feb 22, 2015 9:35 pm
by luis
@Zebuddi
Thanks, the first link explains it very well ! I'm really happy you posted it.

I've fixed the code to enumerate the exported functions for both named and unnamed.

The problem was as nco2k pointed out, I missed completely the presence of the relevant field in the structure.
That's what happen when you try to finish something before going to bed and you can see only what you think is useful instead of taking a step back and look at it without fixed ideas in the head.

I mean, the name of the field was pretty self explanatory, and yet I didn't see it. :shock:

OK, back to business, armed with the link provided by Zebuddi and the dinner to sustain me I think I've managed to make it work.

I leave the original post untouched so the example to get just the named functions (a little simpler and most of the times is just what you need) is not lost.

Code: Select all

Define hDLL
Define *ied.IMAGE_EXPORT_DIRECTORY
Define NumberOfNames, NumberOfFunctions, size, i, idx, OrdinalBase
Define *AddressOfFunctions, *AddressOfNames, *AddressOfNameOrdinals
Define FunctionName$, *FunctionAddress
Dim NamedExportIDX(0)

#DLLNAME$ = "user32.dll" 

hDLL = LoadLibrary_(#DLLNAME$)

If hDLL
    *ied = ImageDirectoryEntryToData_(hDLL, 1, #IMAGE_DIRECTORY_ENTRY_EXPORT, @size)
   
    If *ied       
        NumberOfNames = *ied\NumberOfNames       
        NumberOfFunctions = *ied\NumberOfFunctions         
        OrdinalBase = *ied\Base               

        Debug "NumberOfFunctions = " + NumberOfFunctions
        Debug "NumberOfNames = " + NumberOfNames
   
        ReDim NamedExportIDX(NumberOfFunctions - 1)
       
        *AddressOfFunctions = hDLL + *ied\AddressOfFunctions
        *AddressOfNames = hDLL + *ied\AddressOfNames
        *AddressOfNameOrdinals = hDLL + *ied\AddressOfNameOrdinals
        
        For i = 0 To NumberOfNames - 1 ; first pass to map the index for only the functions with a name            
            NamedExportIDX(PeekU(*AddressOfNameOrdinals + (i * SizeOf(Word)))) = i + 1
        Next   
        
        For i = 0 To NumberOfFunctions - 1
            FunctionName$ = "?" ; default unnamed
            If NamedExportIDX(i) ; if we saved the index for this entry, we know this has a name
                FunctionName$ = PeekS(hDLL + PeekL(*AddressOfNames + ((NamedExportIDX(i) - 1) * SizeOf(Long))), -1, #PB_Ascii)
            EndIf
            *FunctionAddress = hDLL + PeekL(*AddressOfFunctions + (i * SizeOf(Long)))
            Debug "["+ Str(OrdinalBase + i) + "] " + FunctionName$ + " = $" + Hex(*FunctionAddress)
        Next   
    EndIf
    FreeLibrary_(hDLL)
EndIf

Re: How to enumerate DLL exported functions using API

Posted: Mon Feb 23, 2015 2:43 am
by Teddy Rogers
There is a section on my website dedicated to the PE format that has a lot of papers and documentation. For those interested you can find it here...

https://tuts4you.com/download.php?list.30

NirSoft have a nice freeware tool called DLL Export Viewer that people interested in this topic may find useful...

http://nirsoft.net/programmer_tools.html

Ted.

Re: How to enumerate DLL exported functions using API

Posted: Mon Feb 23, 2015 11:48 am
by luis
Interesting, thanks.

Yep, nirsoft makes a lot of nice little utils.

Re: How to enumerate DLL exported functions using API

Posted: Fri Feb 27, 2015 4:33 pm
by nco2k
thanks luis for the update and thanks Teddy Rogers for the insane collection :shock:

c ya,
nco2k