DLL Export Viewer

Post your working scripts, libraries and tools
User avatar
Drugwash
Posts: 745
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania

Re: DLL Export Viewer

03 Aug 2017, 05:00

Yep, looks good. If you could squeeze in the module count (maybe in the header, in left hand list?) it would be perfect. :)
I've deleted my CloudMe account because of GDPR - the now legal base for privacy invasion and data theft.
User avatar
jNizM
Posts: 2583
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: DLL Export Viewer

03 Aug 2017, 05:13

If I would minify the GetDllExports function to return the number of functions in a module it would looks like this. And every dll needs a call to this function for the listview.

Code: Select all

MsgBox % GetNumberOfFunctions("gdi32.dll")    ; -> 923 on Win10

GetNumberOfFunctions(DllFile)
{
    VarSetCapacity(LOADED_IMAGE, 88, 0)
    if (DllCall("imagehlp\MapAndLoad", "astr", DllFile, "ptr", 0, "ptr", &LOADED_IMAGE, "int", 1, "int", 1)) {
        Machine := NumGet(NumGet(LOADED_IMAGE, A_PtrSize * 3, "uptr") + 4, "ushort")
        if (Machine = 0x014c) || (Machine = 0x8664)
            if (IMAGE_EXPORT_DIRECTORY := DllCall("imagehlp\ImageDirectoryEntryToData", "ptr", NumGet(LOADED_IMAGE, A_PtrSize * 2, "uptr"), "int", 0, "ushort", 0, "uint*", size, "uptr"))
                NumberOfNames := NumGet(IMAGE_EXPORT_DIRECTORY + 0x18, "uint")
        DllCall("imagehlp\UnMapAndLoad", "ptr", &LOADED_IMAGE)
    }
    return NumberOfNames
}
If you find something else on your search engine here let me now =)

or do you mean the count of moduls in this listview?
[AHK] 1.1.30.03 x64 Unicode | [WIN] 10 Pro (Version 1909) x64 | [GitHub] Profile
Donations are appreciated if I could help you
User avatar
Drugwash
Posts: 745
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania

Re: DLL Export Viewer

03 Aug 2017, 05:34

I meant the count of libraries/files (modules as you call them) in the selected directory.
I.e. user selects C:\Windows\System32 and the left-hand list displays XXXX Modules (or libraries or whatever) in its header. :)
May not be that important to most people but some control freaks (like me :D ) might get tipped off it the current count doesn't match the previous one.

I'll have to look again in my Pale Moon profile or just run it (ugh, the bloat I created there!) and then fire up all search engines, one at a time, and look at the queries. Tedious job, I tell you that. ;)
I've deleted my CloudMe account because of GDPR - the now legal base for privacy invasion and data theft.
User avatar
jNizM
Posts: 2583
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: DLL Export Viewer

03 Aug 2017, 05:41

Like this:
Image
[AHK] 1.1.30.03 x64 Unicode | [WIN] 10 Pro (Version 1909) x64 | [GitHub] Profile
Donations are appreciated if I could help you
User avatar
Drugwash
Posts: 745
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania

Re: DLL Export Viewer

03 Aug 2017, 05:51

Yes, that's the idea. :thumbup:
Yikes, over 3000 libraries?! Gosh… :)
I've deleted my CloudMe account because of GDPR - the now legal base for privacy invasion and data theft.
Helgef
Posts: 4182
Joined: 17 Jul 2016, 01:02
Contact:

Re: DLL Export Viewer

03 Aug 2017, 05:54

:shock: Looks great!
Most wanted :D
  • Bookmark dll
  • Put GetProcAddress code to clipboard. Eg, clipboard = DllCall("Kernel32.dll\GetProcAddress", "Ptr", DllCall("Kernel32.dll\LoadLibrary", "Str", ModuleName, "Ptr"), "AStr", Function Name, "Ptr")
If it is not of general interest, I might dig in and make it myself :wave:

Cheers.
User avatar
Drugwash
Posts: 745
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania

Re: DLL Export Viewer

03 Aug 2017, 06:24

Getting procedure address for named functions may be of use sometimes, probably mostly when trying to improve script speed, but more useful would be for ordinals, where there's no function name to call directly.
Unfortunately I haven't seen any ordinals with this script… yet. ;)
I've deleted my CloudMe account because of GDPR - the now legal base for privacy invasion and data theft.
User avatar
jNizM
Posts: 2583
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: DLL Export Viewer

03 Aug 2017, 07:42

Where DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", ModuleName, "Ptr"), "AStr", FunctionName, "Ptr") is for already loaded library's like kernel32 / user32 / gdi32 /...
You should use LoadLibrary in place of GetModuleHandle if the dll is not already loaded.

But:
lexikos wrote:It's also completely ineffective to do the GetProcAddress "optimization" for functions in DLLs which AutoHotkey imports (i.e. because they are always resolved at startup). At minimum, that includes User32.dll, Kernel32.dll, ComCtl32.dll, and Gdi32.dll. That is, unless the function name is an expression/variable.
We got this already discussed in an old thread of mine (https://autohotkey.com/boards/viewtopic ... 461#p46461)

@lexikos
Correct me if I missed something
[AHK] 1.1.30.03 x64 Unicode | [WIN] 10 Pro (Version 1909) x64 | [GitHub] Profile
Donations are appreciated if I could help you
Helgef
Posts: 4182
Joined: 17 Jul 2016, 01:02
Contact:

Re: DLL Export Viewer

03 Aug 2017, 07:53

It is not for explicit dllcalls, it is for passing fnptrs to compiled code.

Edit: I guess there isn't a general interest :D
User avatar
jNizM
Posts: 2583
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: DLL Export Viewer

03 Aug 2017, 07:59

So you want on the rightlick menu (or gui menu) a copy address of an exported function?
How should I name this? Copy ProcAddress or Copy FuncAddress or something else?

btw. can someone check the whole english part of the gui? it's not my main language :D
[AHK] 1.1.30.03 x64 Unicode | [WIN] 10 Pro (Version 1909) x64 | [GitHub] Profile
Donations are appreciated if I could help you
Helgef
Posts: 4182
Joined: 17 Jul 2016, 01:02
Contact:

Re: DLL Export Viewer

03 Aug 2017, 08:04

Where it is matters less, what I need in the clipboard is the explicit text,

Code: Select all

DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", ModuleName, "Ptr"), "AStr", FunctionName, "Ptr") 
where ModuleName and FunctionName matches whatever is selected. :)
Helgef
Posts: 4182
Joined: 17 Jul 2016, 01:02
Contact:

Re: DLL Export Viewer

03 Aug 2017, 08:10

btw. can someone check the whole english part of the gui? it's not my main language
File -> Load Common Dll's change to -> File -> Load common Dlls. ' is for possessive, not plural.

I see nothing else.

Edit: ModuleName -> Module Name in the right ListView.
User avatar
jNizM
Posts: 2583
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: DLL Export Viewer

03 Aug 2017, 08:17

Changed =)
What do you mean with Bookmark?
Most used modules? If yes, that's why I added common dll's in menu.

If I move Module Name (List) to right the Expand Listview menu will be removed (no need any more)
[AHK] 1.1.30.03 x64 Unicode | [WIN] 10 Pro (Version 1909) x64 | [GitHub] Profile
Donations are appreciated if I could help you
Helgef
Posts: 4182
Joined: 17 Jul 2016, 01:02
Contact:

Re: DLL Export Viewer

03 Aug 2017, 08:52

With Bookmark, I mean something like save to ini file, so next time I load the app, I can select my favourite* modules from some list or something. Some dll names are hard for me to remember :facepalm: :oops:
*Yes, I have favourite modules :ugeek:
Edit
this one will be bigger and bigger
:dance:
Last edited by Helgef on 03 Aug 2017, 09:20, edited 1 time in total.
User avatar
jNizM
Posts: 2583
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: DLL Export Viewer

03 Aug 2017, 09:09

I love one-file-ahk-projects.. but since this one will be bigger and bigger, I will move to includes now :? and will the first time (for me) add releases (x86.exe - x64.exe - ahk.zip)
[AHK] 1.1.30.03 x64 Unicode | [WIN] 10 Pro (Version 1909) x64 | [GitHub] Profile
Donations are appreciated if I could help you
just me
Posts: 6804
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: DLL Export Viewer

09 Aug 2017, 09:04

This is rather a proof of concept than an improvement. I was wondering whether all needed information could be retrieved directly from the DLL file without calling external functions. Apparently ist's possible. The only required step seems to be to 'load' the section data contained in the file to their (relative) virtual addresses as defined in the section headers. After this the RVAs defined in the optional header data directory entry and the export directory table are matching the corresponding data.

It also demonstrates the power of AHK's File Object.

Code: Select all

#NoEnv
SetBatchLines, -1
DllFile := A_WinDir . "\System32\Ntdll.dll"
S := A_TickCount
Exports := DllExports(DllFile)
T := A_TickCount - S
Module  := Exports.Module
Named   := Exports.Named
Bitness := Exports.Bitness
OrdBase := Exports.OrdBase
Gui, Add, ListView, xm ym w800 h450 Count%Named% vMyLV1 hWndhMyLV1 +LV0x14000, Ordinal|Function Name|Entry Point (RVA)
For Index, Function In Exports.Functions
   LV_Add("", Function.Ordinal, Function.Name, Function.EntryPoint)
LV_ModifyCol(1, "Integer 50")
LV_ModifyCol(2, "AutoHdr")
LV_ModifyCol(3, "AutoHdr")
Gui, Add, StatusBar
SB_SetText("   Module: " . Module . " - " . Bitness . "-bit - " . Named . " named functions - ordinal base: " . OrdBase)
Gui, Show, , %DllFile% (%T% ms)
Return
; --------------------------------------------------------------------------------------------------------------------------------
GuiClose:
ExitApp
; ================================================================================================================================
DllExports(DllPath) {
   Static LocSignatureOff  := 0x3C ; location of the file offset to the PE signature
   Static SizeOfSignature  := 4    ; size of the PE signature
   Static SizeOfCoffHdr    := 20   ; size of the COFF header
   Static SizeOfSectionHdr := 40   ; size of a section header
   ; Check the file path ---------------------------------------------------------------------------------------------------------
   SplitPath, DllPath, , , FileExt
   If (FileExt <> "dll")
      Return !(ErrorLevel := 1) ; invalid file extension
   ; Open the file ---------------------------------------------------------------------------------------------------------------
   If !(DllFile := FileOpen(DllPath, "r"))
      Return !(ErrorLevel := 2) ; could not open the file for reading
   If (DllFile.Pos <> 0)                     
      Return !(ErrorLevel := 3) ; AHK found a BOM, it isn't a DLL
   ; MS-DOS header----------------------------------------------------------------------------------------------------------------
   DllFile.RawRead(RawBytes, 2)
   If !(StrGet(&RawBytes, 2, "CP0") == "MZ") 
      Return !(ErrorLevel := 4) ; no MS-DOS stub
   ; PE Signature ----------------------------------------------------------------------------------------------------------------
   DllFile.Pos := LocSignatureOff
   DllFile.Pos := DllFile.ReadUInt() ; offset to the PE signature
   ; Read the signature and advance the file pointer to the begin of the COFF header.
   DllFile.RawRead(RawBytes, SizeOfSignature)
   If !(StrGet(&RawBytes, SizeOfSignature, "CP0") == "PE")
      Return !(ErrorLevel := 5) ; no PE file
   ; COFF header -----------------------------------------------------------------------------------------------------------------
   ; Machine types: IMAGE_FILE_MACHINE_I386 (x86) = 0x014C, IMAGE_FILE_MACHINE_AMD64 (x64) = 0x8664
   ; Characteristics: IMAGE_FILE_DLL = 0x2000
   ; Read the COFF file header and advance the file pointer to the begin of the optional header.
   DllFile.RawRead(RawBytes, SizeOfCoffHdr)
   Machine := NumGet(RawBytes, 0, "UShort") ; the type of the target machine
   If (Machine <> 0x014C) && (Machine <> 0x8664)
      Return !(ErrorLevel := 6) ; wrong CPU type
   NumberOfSections := NumGet(RawBytes, 2, "UShort") ; the number of section headers
   SizeOfOptionalHeader := NumGet(RawBytes, 16, "UShort") ; the size of the optional header (required for DLL files)
   Characteristics := NumGet(RawBytes, 18, "UShort") ; the attributes of the file
   If !(Characteristics & 0x2000) ; IMAGE_FILE_DLL
      Return !(ErrorLevel := 7) ; not a valid DLL file
   ; Optional header -------------------------------------------------------------------------------------------------------------
   ; PE format (magic number): PE32 (32-bit) = 0x010B, PE32+ (64-bit) = 0x020B
   ; Read the optional header and advance the file pointer to the begin of the section headers.
   DllFile.RawRead(RawBytes, SizeOfOptionalHeader)
   Magic := NumGet(RawBytes, 0, "UShort") ; the state of the image file
   Off_64 := (Magic = 0x020B) ? 16 : 0 ; additional offset for 64-bit, zero for 32-bit
   SizeOfImage := NumGet(RawBytes, 56, "UInt") ; the size of the image as loaded into memory
   OffSet := 92 + Off_64
   If ((NumberOfRvaAndSizes := NumGet(RawBytes, Offset + 0, "UInt")) < 1) ; the number of data directory entries
   || ((ExportAddr          := NumGet(RawBytes, Offset + 4, "UInt")) < 1) ; the address of the export table (RVA)
   || ((ExportSize          := NumGet(RawBytes, Offset + 8, "UInt")) < 1) ; the size of the export table
      Return !(ErrorLevel := 8) ; couldn't find an export table
   ; Section headers -------------------------------------------------------------------------------------------------------------
   ; The section data have to be 'loaded' to the relative virtual addresses defined in the section headers.
   ; Otherwise, the RVAs defined in the export table don't match the corresponding data.
   ; Read the section headers
   SectionsLength := SizeOfSectionHdr * NumberOfSections
   DllFile.RawRead(RawBytes, SectionsLength)
   ; 'Load' the sections.
   VarSetCapacity(ImageData, SizeOfImage, 0) ; create a variable capable to store the sections data
   Offset := 0
   Loop, %NumberOfSections%
   {
      VirtualAddress   := NumGet(RawBytes, Offset + 12, "UInt")
      SizeOfRawData    := NumGet(RawBytes, Offset + 16, "UInt")
      PointerToRawData := NumGet(RawBytes, Offset + 20, "UInt")
      DllFile.Pos := PointerToRawData
      DllFile.RawRead(&ImageData + VirtualAddress, SizeOfRawData)
      Offset += SizeOfSectionHdr
   }
   ; Export table ----------------------------------------------------------------------------------------------------------------
   ImageBase    := &ImageData ; the address of the string buffer of ImageData is used as image base address.
   EndOfSection := ExportAddr + ExportSize
   ModNamePtr   := NumGet(ImageBase + ExportAddr + 0x0C, "UInt") ; pointer to an ASCII string that contains the name of the DLL
   OrdinalBase  := NumGet(ImageBase + ExportAddr + 0x10, "UInt") ; starting ordinal number for exports in this image
   FuncCount    := NumGet(ImageBase + ExportAddr + 0x14, "UInt") ; number of entries in the export address table
   NameCount    := NumGet(ImageBase + ExportAddr + 0x18, "UInt") ; number of entries in the name pointer table
   FuncTblPtr   := NumGet(ImageBase + ExportAddr + 0x1C, "uint") ; pointer to the export address table
   NameTblPtr   := NumGet(ImageBase + ExportAddr + 0x20, "UInt") ; pointer to the export name pointer table
   OrdTblPtr    := NumGet(ImageBase + ExportAddr + 0x24, "UInt") ; pointer to the ordinal table
   Exports      := {Module: StrGet(ImageBase + ModNamePtr, "CP0")
                  , Total: FuncCount
                  , Named: NameCount
                  , OrdBase: OrdinalBase
                  , Bitness: (Magic = 0x020B) ? 64 : 32
                  , Functions: []}
   Loop %NameCount%
   {
      NamePtr := NumGet(ImageBase + NameTblPtr, "UInt")
      Ordinal := NumGet(ImageBase + OrdTblPtr, "UShort")
      FnAddr  := NumGet(ImageBase + FuncTblPtr + (Ordinal * 4), "UInt")
      EntryPt := (FnAddr > ExportAddr) && (FnAddr < EndOfSection) ? StrGet(ImageBase + FnAddr, "CP0")
                                                                  : Format("0x{:08X}", FnAddr)
      Exports.Functions.Push({Name: StrGet(ImageBase + NamePtr, "CP0"), EntryPoint: EntryPt, Ordinal: Ordinal + OrdinalBase})
      NameTblPtr += 4, OrdTblPtr += 2
   }
   VarSetCapacity(ImageData, 0) ; free the memory used to store the image data
   Return Exports
}
User avatar
Delta Pythagorean
Posts: 514
Joined: 13 Feb 2017, 13:44
GitHub: DelPyth
Location: Somewhere in the US

Re: DLL Export Viewer

09 Aug 2017, 09:27

@just me
That's quite an interesting take on this project. I'll say I now know how to return errorlevel with a number instead of just returning a normal number.

- [AHK].......: 1.1.32.00 Unicode 64-bit
- [OS].........: Windows 10.0.18362
- [GITHUB]...: github.com/DeltaPyth
- [PAYPAL]....: paypal.me/DelPyth
- [DISCORD]..: Delta#3324

Remember to use [code]CODE[/code] for your multi-line scripts.
Stay safe, stay inside, and remember to wash your hands for 20 seconds!
User avatar
jNizM
Posts: 2583
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: DLL Export Viewer

07 Feb 2020, 09:21

Edit
- rewritten
[AHK] 1.1.30.03 x64 Unicode | [WIN] 10 Pro (Version 1909) x64 | [GitHub] Profile
Donations are appreciated if I could help you
User avatar
TLM
Posts: 1580
Joined: 01 Oct 2013, 07:52
GitHub: TLMcode
Contact:

Re: DLL Export Viewer

07 Feb 2020, 16:13

Thanks @jNizM
Wish i'd seen this before trying to do it myself :headwall:

Return to “Scripts and Functions”

Who is online

Users browsing this forum: JBensimon, JoeWinograd, MSN [Bot] and 62 guests