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...

List all exported functions in a dll or exe

Post by srod »

Hi,

similar to my coff dump utility posted earlier, the following procedure will fill a string array with the names of all the functions exported from a dll or indeed an exe.

Unlike my previous post, however, this is not my original work! :cry:

Instead I have converted some Powerbasic code: http://www.powerbasic.com/support/forum ... 01216.html

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, 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\NumberOfFunctions - 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.
                  currentsymname$=PeekS(PeekL(pNames+i*4)- delta + *idh,-1, #PB_Ascii)
                  ReDim strTable.s(count)
                  strTable(count)=currentsymname$
                  count+1
              EndIf
          Next
        EndIf        
      EndIf
    EndIf
    UnmapViewOfFile_(FileBase)
    CloseHandle_(hFileMapping)
    CloseFile(fileid)
  ProcedureReturn count
EndProcedure


;Test.
Dim names.s(0)
num=GetDllFunctions("c:\windows\System32\kernel32.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.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Uh, teach? One question, why not:

Code: Select all

OpenLibrary(0, "kernel32.dll")
ExamineLibraryFunctions(0)
While NextLibraryFunction()
  cc+1
  Debug LibraryFunctionName()
Wend
Debug cc
Seems to produce identical output. I'm probably just missing something important.
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

If that weren't so funny, I'd strangle myself! :oops:

What an arse head! I've spent several hours on this and didn't even think of looking at the PB library commands!

Doh!

Oh well, at least I learnt a lot about PE file structures along the way. That at least makes me feel a little better!

hehe. That's gotta be the dopiest thing ever!
Last edited by srod on Sun Mar 04, 2007 3:56 am, edited 1 time in total.
I may look like a mule, but I'm not a complete ass.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

:lol: :lol: :lol:

Not to worry, I've still got the boobyprize for my frigging timepicker.
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

netmaestro wrote::lol: :lol: :lol:

Not to worry, I've still got the boobyprize for my frigging timepicker.
What happened with the timepicker?
I may look like a mule, but I'm not a complete ass.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

I spent an entire day writing a heavily subclassed set of stringgadgets in a container that functioned as an updown-controlled timepicker gadget. A few days later I found the same thing could be done with:

Code: Select all

CreateWindowEx_(0,"SysDateTimePick32","",#WS_CHILD|#WS_VISIBLE|#DTS_TIMEFORMAT... etc.
That was a bummer.
BERESHEIT
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Anyways, that's what you get for looking on the PowerBasic forum. You should have just known PureBasic does everything better!
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

netmaestro wrote:You should have just known PureBasic does everything better!
As much as I want that statement to be true, alas I'd have to say that there are some things which are easier in Powerbasic than Purebasic. gui stuff is far easier in Purebasic, but Powerbasic does offer a greater range of datatypes which are actually more flexible when you get down to some serious api work.

Must admit that I do like Powerbasic and there are some great tips to be found in their forums.
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 »

netmaestro and srod, your the experts.

As long as were dealing with

List all exported functions in a dll or exe

Try this code and tear it apart if you like, or give me some suggestions.
I've been kind of busy lately and haven't had time to work on it lately.
Also my newby understanding about what's found at the address, well
maybe you can enlighten me more on how to use it? I'm really new at
some of this stuff. What I was really trying to do was to list the function
along with how many and what variables etc are used with each function.
It's easy to get the function name. But how to use it? I don't know?

This program also list some file info including http and ftp addresses
if found. Try it on some microsoft dll's.
'microsoft hidden phone home etc'
Actually that is how I have found and eliminated some spy ware in the
past by changing the internal address so it can't call home.

It opens up the results in notepad, so make sure your path to notepad
in this code is right.
I also added dashed lines to kind of align the data as different fonts
would cause it to be wavy.

-----watch out for line wrap----------
(also, I only have enable debugger checked in compiler options)

Code: Select all

;NOTE: CHANGE DRIVE AND PROGRAM LOCATIONS
;ACCORDING TO WHERE THEY ARE AT ON YOUR SYSTEM.

#SILENT_YNBOX = $C4   ;this gives you the silent yes no box

;Libfile.s ="c:\purebasic4_0\work\dlls\rmchart.dll"

agn:
   Libfile.s = OpenFileRequester ( "Select DLL file", "", "DLL (*.dll)|*.dll", 0 )
   
   If Trim(Libfile)=""
      End
   EndIf
   
   ;seperate path and file, and create info file with same name_info.txt
   
   ;GetFilePart retrieves the file part of full path. Eg: if full path is "C:\PureBasic\PB.exe", result will be "PB.exe"
   ;FileName$ = GetFilePart(FullPathName$)
   f$=GetFilePart(Libfile)
   
   ;GetPathPart retrieves path part of full path. Eg: if full path is "C:\PureBasic\PB.exe", result will be "C:\PureBasic\".
   ;Path$ = GetPathPart(FullPathName$)
   pth$ = GetPathPart(Libfile)
   
   f$=Left(f$,Len(f$)-4)+"_info.txt"
   
   File$=pth$+f$
   
   CreateFile(1,File$)
   WriteStringN(1,Libfile)
   WriteStringN(1,Space(15)+"(best viewed with  Font:Fixedsys or Courier  Style:Regular  Size:12)")
   WriteStringN(1,"  ")
   
   adrs=0
   dat$=""
   www_info$=""
   at_end=0
   If ReadFile(0,Libfile)
      Repeat
         adrs+1
         If at_end=0                ;Use to speed up file search until "VERSION_INFO" is found.
            car=ReadCharacter(0)    ;This method is needed to remove the nulls between characters.
            If car>31
               dat$=dat$+Chr(car)
               If Len(dat$)>100
                  dat$=Mid(dat$,70,999)
               EndIf
               
            EndIf
         Else
            car=ReadCharacter(0)
            If car>31 And car<127
               dat$=dat$+Chr(car)
               If Len(dat$)>100
                  dat$=Mid(dat$,60,999)
               EndIf
               
            EndIf
         EndIf
         
         If FindString(LCase(dat$),"http://",1)>0
            p=FindString(LCase(dat$),"http://",1)
            dat$=Mid(dat$,p,999)
            dat2$=""
            
            Repeat
               adrs+1
               car=ReadCharacter(0)
            Until car<>0
            
            If car>31 And car<127
               dat$=dat$+Chr(car)
            EndIf
            
            Repeat
               adrs+1
               car=ReadCharacter(0)
               dat2$=dat2$+" "+Str(car)
               If car>31 And car<127
                  dat$=dat$+Chr(car)
                  l=Len(dat$)
                  
               EndIf
               If Right(dat2$,5)="0 0 0"
                  car=1
               EndIf
               If Right(dat2$,5)="13 10"
                  car=1
               EndIf
            Until car=1
            la$=Hex(adrs-7)+"     "
            www_info$=www_info$+la$+dat$+"\"
            dat$=""
         EndIf
         
         If FindString(LCase(dat$),"www.",1)>0
            p=FindString(LCase(dat$),"www.",1)
            dat$=Mid(dat$,p,999)
            dat2$=""
            
            Repeat
               adrs+1
               car=ReadCharacter(0)
            Until car<>0
            
            If car>31 And car<127
               dat$=dat$+Chr(car)
            EndIf
            
            Repeat
               adrs+1
               car=ReadCharacter(0)
               dat2$=dat2$+" "+Str(car)
               If car>31 And car<127
                  dat$=dat$+Chr(car)
                  l=Len(dat$)
                  
               EndIf
               If Right(dat2$,5)="0 0 0"
                  car=1
               EndIf
               If Right(dat2$,5)="13 10"
                  car=1
               EndIf
            Until car=1
            
            If Len(dat$)>10
               la$=Hex(adrs-4)+"     "
               www_info$=www_info$+la$+dat$+"\"
            EndIf
            dat$=""
         EndIf
         
         If FindString(LCase(dat$),"ftp://",1)>0
            p=FindString(LCase(dat$),"ftp://",1)
            dat$=Mid(dat$,p,999)
            dat2$=""
            
            Repeat
               adrs+1
               car=ReadCharacter(0)
            Until car<>0
            
            If car>31 And car<127
               dat$=dat$+Chr(car)
            EndIf
            
            Repeat
               adrs+1
               car=ReadCharacter(0)
               dat2$=dat2$+" "+Str(car)
               If car>31 And car<127
                  dat$=dat$+Chr(car)
                  l=Len(dat$)
                  
               EndIf
               If Right(dat2$,5)="0 0 0"
                  car=1
               EndIf
               If Right(dat2$,5)="13 10"
                  car=1
               EndIf
            Until car=1
            la$=Hex(adrs-6)+"     "
            ftp_info$=ftp_info$+la$+dat$+"\"
            dat$=""
         EndIf
         
         If FindString(UCase(dat$), "VS_VERSION_INFO",1)>0
            p=FindString(UCase(dat$), "VS_VERSION_INFO",1)
            dat$=Mid(dat$,p,999)
            
            Repeat
               adrs+1
               car=ReadCharacter(0)
            Until car<>0
            
            If car>31 And car<127
               dat$=dat$+Chr(car)
            EndIf
            
            Repeat
               adrs+1
               car=ReadCharacter(0)
               dat2$=dat2$+" "+Str(car)
               If car>31 And car<127
                  dat$=dat$+Chr(car)
                  l=Len(dat$)
                  
               EndIf
               If Right(dat2$,5)="0 0 0"
                  car=1
               EndIf
            Until car=1
            info$="VERSION_INFO  "+Mid(dat$,16,999)
            WriteStringN(1,"File location address: "+Hex(adrs-15))
            WriteStringN(1,info$)
            dat$=""
            dat2$=""
            at_end=1
         EndIf
         
         If at_end=1
            If FindString(LCase(dat$),"stringfileinfo",1)>0
               p=FindString(LCase(dat$),"stringfileinfo",1)
               dat$=Mid(dat$,p,999)
               dat2$=""
               got=0
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
               Until car<>0
               
               If car>31 And car<127
                  dat$=dat$+Chr(car)
               EndIf
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
                  dat2$=dat2$+" "+Str(car)
                  If car>31 And car<127
                     dat$=dat$+Chr(car)
                     l=Len(dat$)
                     
                  EndIf
                  If Right(dat2$,5)="0 0 0"
                     got=1
                  EndIf
               Until got=1;car>0 And car<32
               
               info$="StringFileInfo  "+Mid(dat$,15,999)
               WriteStringN(1, info$)
               dat$=""
            EndIf
            
            If FindString(LCase(dat$),"companyname",1)>0
               p=FindString(LCase(dat$),"companyname",1)
               dat$=Mid(dat$,p,999)
               dat2$=""
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
               Until car<>0
               
               If car>31 And car<127
                  dat$=dat$+Chr(car)
               EndIf
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
                  dat2$=dat2$+" "+Str(car)
                  If car>31 And car<127
                     dat$=dat$+Chr(car)
                     l=Len(dat$)
                     
                  EndIf
                  If Right(dat2$,5)="0 0 0"
                     car=1
                  EndIf
               Until car=1
               
               info$="CompanyName  "+Mid(dat$,12,999)
               WriteStringN(1, info$)
               dat$=""
            EndIf
            
            If FindString(LCase(dat$),"filedescription",1)>0
               p=FindString(LCase(dat$),"filedescription",1)
               dat$=Mid(dat$,p,999)
               dat2$=""
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
               Until car<>0
               
               If car>31 And car<127
                  dat$=dat$+Chr(car)
               EndIf
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
                  dat2$=dat2$+" "+Str(car)
                  If car>31 And car<127
                     dat$=dat$+Chr(car)
                     l=Len(dat$)
                     
                  EndIf
                  If Right(dat2$,5)="0 0 0"
                     car=1
                  EndIf
               Until car=1
               info$="FileDescription  "+Mid(dat$,16,999)
               WriteStringN(1, info$)
               dat$=""
            EndIf
            
            If FindString(LCase(dat$),"fileversion",1)>0
               p=FindString(LCase(dat$),"fileversion",1)
               dat$=Mid(dat$,p,999)
               dat2$=""
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
               Until car<>0
               
               If car>31 And car<127
                  dat$=dat$+Chr(car)
               EndIf
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
                  dat2$=dat2$+" "+Str(car)
                  If car>31 And car<127
                     dat$=dat$+Chr(car)
                     l=Len(dat$)
                     
                  EndIf
                  If Right(dat2$,5)="0 0 0"
                     car=1
                  EndIf
               Until car=1
               info$="FileVersion  "+Mid(dat$,12,999)
               WriteStringN(1, info$)
               dat$=""
            EndIf
            
            If FindString(LCase(dat$),"internalname",1)>0
               p=FindString(LCase(dat$),"internalname",1)
               dat$=Mid(dat$,p,999)
               dat2$=""
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
               Until car<>0
               
               If car>31 And car<127
                  dat$=dat$+Chr(car)
               EndIf
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
                  dat2$=dat2$+" "+Str(car)
                  If car>31 And car<127
                     dat$=dat$+Chr(car)
                     l=Len(dat$)
                     
                  EndIf
                  If Right(dat2$,5)="0 0 0"
                     car=1
                  EndIf
               Until car=1
               info$="InternalName  "+Mid(dat$,13,999)
               WriteStringN(1, info$)
               dat$=""
            EndIf
            
            If FindString(LCase(dat$),"legalcopyright",1)>0
               p=FindString(LCase(dat$),"legalcopyright",1)
               dat$=Mid(dat$,p,999)
               dat2$=""
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
               Until car<>0
               
               If car>31 And car<127
                  dat$=dat$+Chr(car)
               EndIf
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
                  dat2$=dat2$+" "+Str(car)
                  If car>31 And car<127
                     dat$=dat$+Chr(car)
                     l=Len(dat$)
                     
                  EndIf
                  If Right(dat2$,5)="0 0 0"
                     car=1
                  EndIf
               Until car=1
               info$="LegalCopyright  "+Mid(dat$,15,999)
               WriteStringN(1, info$)
               dat$=""
            EndIf
            
            If FindString(LCase(dat$),"originalfilename",1)>0
               p=FindString(LCase(dat$),"originalfilename",1)
               dat$=Mid(dat$,p,999)
               dat2$=""
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
               Until car<>0
               
               If car>31 And car<127
                  dat$=dat$+Chr(car)
               EndIf
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
                  dat2$=dat2$+" "+Str(car)
                  If car>31 And car<127
                     dat$=dat$+Chr(car)
                     l=Len(dat$)
                     
                  EndIf
                  If Right(dat2$,5)="0 0 0"
                     car=1
                  EndIf
               Until car=1
               info$="OriginalFilename  "+Mid(dat$,17,999)
               WriteStringN(1, info$)
               dat$=""
            EndIf
            
            If FindString(LCase(dat$),"productname",1)>0
               p=FindString(LCase(dat$),"productname",1)
               dat$=Mid(dat$,p,999)
               dat2$=""
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
               Until car<>0
               
               If car>31 And car<127
                  dat$=dat$+Chr(car)
               EndIf
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
                  dat2$=dat2$+" "+Str(car)
                  If car>31 And car<127
                     dat$=dat$+Chr(car)
                     l=Len(dat$)
                     
                  EndIf
                  If Right(dat2$,5)="0 0 0"
                     car=1
                  EndIf
               Until car=1
               info$="ProductName  "+Mid(dat$,12,999)
               WriteStringN(1, info$)
               dat$=""
            EndIf
            
            If FindString(LCase(dat$),"productversion",1)>0
               p=FindString(LCase(dat$),"productversion",1)
               dat$=Mid(dat$,p,999)
               dat2$=""
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
               Until car<>0
               
               If car>31 And car<127
                  dat$=dat$+Chr(car)
               EndIf
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
                  dat2$=dat2$+" "+Str(car)
                  If car>31 And car<127
                     dat$=dat$+Chr(car)
                     l=Len(dat$)
                     
                  EndIf
                  If Right(dat2$,5)="0 0 0"
                     car=1
                  EndIf
               Until car=1
               info$="ProductVersion  "+Mid(dat$,15,999)
               WriteStringN(1, info$)
               dat$=""
            EndIf
            
            If FindString(LCase(dat$),"varfileinfo",1)>0
               p=FindString(LCase(dat$),"varfileinfo",1)
               dat$=Mid(dat$,p,999)
               dat2$=""
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
               Until car<>0
               
               If car>31 And car<127
                  dat$=dat$+Chr(car)
               EndIf
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
                  dat2$=dat2$+" "+Str(car)
                  If car>31 And car<127
                     dat$=dat$+Chr(car)
                     l=Len(dat$)
                     
                  EndIf
                  If Right(dat2$,5)="0 0 0"
                     car=1
                  EndIf
               Until car=1
               info$="VarFileInfo  "+Mid(dat$,15,999)
               WriteStringN(1, info$)
               dat$=""
            EndIf
            
            If FindString(LCase(dat$),"translation",1)>0
               p=FindString(LCase(dat$),"translation",1)
               dat$=Mid(dat$,p,999)
               dat2$=""
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
               Until car<>0
               
               If car>31 And car<127
                  dat$=dat$+Chr(car)
               EndIf
               
               Repeat
                  adrs+1
                  car=ReadCharacter(0)
                  dat2$=dat2$+" "+Str(car)
                  If car>31 And car<127
                     dat$=dat$+Chr(car)
                     l=Len(dat$)
                     
                  EndIf
                  If Right(dat2$,5)="0 0 0"
                     car=1
                  EndIf
                  If Right(dat2$,5)="4 4 0"
                     car=1
                  EndIf
               Until car=1
               info$="Translation  "+Mid(dat$,15,999)
               WriteStringN(1, info$)
               dat$=""
               at_end=0
            EndIf
            
         EndIf
         
      Until Eof(0)<>0
      
      CloseFile(0)
      Delay(1000)
      
   EndIf
   
   If Len(www_info$)>0
      WriteStringN(1, " ")
      WriteStringN(1, "Location address      File http info:")
      If FindString(www_info$,"\",1)>0
         While FindString(www_info$,"\",1)>0
            p=FindString(www_info$,"\",1)
            l$=Left(www_info$,p-1)
            WriteStringN(1, l$)
            www_info$=Mid(www_info$,p+1,999)
         Wend
         
      Else
         WriteStringN(1, www_info$)
      EndIf
   EndIf
   
   If Len(ftp_info$)>0
      WriteStringN(1, " ")
      WriteStringN(1, "Location address      File ftp info:")
      If FindString(ftp_info$,"\",1)>0
         While FindString(ftp_info$,"\",1)>0
            p=FindString(ftp_info$,"\",1)
            l$=Left(ftp_info$,p-1)
            WriteStringN(1, l$)
            ftp_info$=Mid(ftp_info$,p+1,999)
         Wend
         
      Else
         WriteStringN(1, ftp_info$)
      EndIf
   EndIf
   
   WriteStringN(1, "  ")
   WriteStringN(1, "  ")
   
   OpenLibrary(0,Libfile)
   Delay(1000)

   WriteStringN(1,"See what functions this version offers")
   WriteStringN(1," ")
   WriteStringN(1,"FN #"+Space(3)+"Function Address"+Space(2)+"Function Name"+Space(30)+"Hex Values Found at Address")
   
   n=1
      
   ;Result = ExamineLibraryFunctions(#Library)
   ;To examine the functions contained in a library.
   If ExamineLibraryFunctions(0)
      
      ;Result = NextLibraryFunction()
      ;Allows you to step through the functions in the library
      While NextLibraryFunction()
         
         ;Result$ = LSet(String$, Length [, Character$])  eg: , 40,"_") = 40 _ characters added.
         
         ;Result$ = LibraryFunctionName()
         ;Returns the name of the function in the library currently being examined
         lfn$ = LSet(LibraryFunctionName(), 40,"_")
         
         ;Result.l = LibraryFunctionAddress()
         ;Returns the address of the function in the library currently being examined.
         
         ;Text$ = PeekS(*MemoryBuffer [, Length [, Flags]])
         ;Very useful to read a string at the specified memory address.
         ;The string should be ended by a '0' character, else it will
         ;read the memory until a '0' character is encounter.
         
         ;Text$ = PeekS(LibraryFunctionAddress())
         ;Text$ = PeekS(LibraryFunctionAddress(),-1,#PB_UTF8)
         ;Text$ = PeekS(LibraryFunctionAddress(),-1,#PB_Unicode)
         Text$ = PeekS(LibraryFunctionAddress(),-1,#PB_Ascii)
         
         n$ = LSet(Str(n), 10,"_")
                  
         ;hex #
         ;lfa$ = Str(LibraryFunctionAddress())
         lfa = LibraryFunctionAddress()
         lfa$=Hex(lfa)
         lfa$ = LSet(lfa$, 15,"_")
         
         lfnd$=LSet(n$+lfa$+lfn$,63,"_")
         
         ;CallDebugger
         ;convert text to hex values
         text3$=""
         For a =1 To Len(text$)
            a$=Mid(text$,a,1)
            ha=Asc(a$)
            ha$=Hex(ha)
            If Len(ha$)<2
               ha$="0"+ha$
            EndIf
            text3$=text3$+ha$+" "
         Next a
         text$=text3$
         
         If Len(Text$)>54
            fl=0
            While Len(Text$)>54
               LText$=Left(Text$,54)
               If fl=0
                  WriteStringN(1,lfnd$+LText$)
                  fl=1
               EndIf
               Text$=Mid(Text$,55,99999)
               
               Text2$ = LSet("  ", 28,"_")+" continued"+LSet(" ", 25,"_")+Left(Text$,54)
               WriteStringN(1,Text2$)
               Text$=Mid(Text$,55,99999)
            Wend
            If Trim(text$)<>""
               Text2$ = LSet("  ", 28,"_")+" continued"+LSet(" ", 25,"_")+Text$
               WriteStringN(1,Text2$)
            EndIf
            WriteStringN(1," ")  ;add divider space
            
         Else
            WriteStringN(1,lfnd$+Text$)
         EndIf
         
         n+1
         Delay(10)
      Wend
      
      CloseFile(1)
      
   EndIf
   
   ;CloseLibrary(0)
   Delay(10)
   
   RunProgram("c:\windows\notepad.exe" , f$, pth$, #PB_Program_Wait)
   
   result=MessageRequester(" ","Examine another DLL file ? ",#PB_MessageRequester_YesNo);#SILENT_YNBOX)
   If result<>7
      ;CloseLibrary(0)
      Goto agn
   EndIf
   End
   
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Hi,

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! :)
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:

Gives me an Invalid memory error with this line:

Code: Select all

currentsymname$=PeekS(PeekL(pNames+i*4)- delta + *idh,-1, #PB_Ascii) 
If I try to do any .dll except for kernel32.dll
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Works okay here on sqlite3.dll, every windows dll I try, some dll's created with PB!

Try:

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\NumberOfFunctions - 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("user32.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 »

second example, had to put in the complete path to the user32.dll. Seems to work with the standard system .dll's like user32.dll and kernel32.dll but when you start to do something like dwmapi.dll it crashes. So...i'm using Vista, maybe that has something to do with it. back to the dll2PB importer. Nice code though. Thank You :)
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Ah, but this is the dopiest code I've ever put together! Try netmaestro's code above which uses the PB library commands, see if that crashes on the particular dll you mentioned?
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 »

The method posted by nemaestro above which uses the purebasic library commands also crashes with dwmapi.dll.
I may look like a mule, but I'm not a complete ass.
Post Reply