Tuesday, 4 April 2017

Using DUMPBIN.exe to replicate functionality of Dependency Walker (Depends.exe)

So Depends.exe is a nice program that can interrogate an executable and determine its dependencies as its name suggests but it is packed with tons of extra features as well. One such feature is the ability to see the entry points into a Dll.

Here is a screenshot showing Excel.exe and its dependent Dlls, one of which OLE32.DLL is selected. On the right hand side one can see the entry points of OLE32.DLL. In other words this shows you all the functions you can call into. OLE32.DLL is a COM runtime and it comes as no surprise that it implements the most famous COM functions such CoCreateInstance.

Although Depends.exe has a clipboard feature that allows copying and pasting of fragments of this list it would be nicer to get a list of these functions programatically. Listing a DLL's exported functions is what the command line program DUMPBIN.exe can do. It will be installed as part of Microsoft Visual Studio if you selected C++ as an option (DUMPBIN.exe is a program familiar to C++ programmers).

In the example below I have shortened the path to a temporary environment variable so its fits on one blog page and does not spill over. You may ignore such typesetting cosmetics.


C:\set dumpbinpath="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\
                   VC\Tools\MSVC\14.10.25017\bin\HostX86\x86"

C:\%dumpbinpath%\dumpbin /EXPORTS c:\windows\system32\oleaut32.dll > n:\dump.txt

C:\n:\dump.txt

The final line should launch notepad or whatever text editor you have assigned to launch for .txt files. Inside the files you should see contents such as this extract

        866   1A 000B0C20 CoCheckElevationEnabled
        867   1B          CoCopyProxy (forwarded to ...
        868   1C          CoCreateFreeThreadedMarshaler (forwarded to ...
        869   1D          CoCreateGuid (forwarded to ...
        870   1E          CoCreateInstance (forwarded to ...
        871   1F          CoCreateInstanceEx (forwarded to ...
        872   20          CoCreateInstanceFromApp (forwarded to ...
        873   21          CoCreateObjectInContext (forwarded to ...
        874   22          CoDeactivateObject (forwarded to ...


It can be seen that the function name always begins at column 27 and is terminated either by end of line or by a space. So we can write some code for this.

Option Explicit

Sub Test()
    Dim vOle32Exports As Variant, plCount As Long
    vOle32Exports = GetExports("n:\dumpbin_ol32_dll_exports.txt", plCount)
    
    shDllExports.Cells(1, 1) = "ole32.dll"
    shDllExports.Cells(2, 1).Resize(plCount).Value = Application.Transpose(vOle32Exports)
    
    
    Dim vOleAut32Exports As Variant
    vOleAut32Exports = GetExports("n:\dumpbin_oleaut32_dll_exports.txt", plCount)
    
    shDllExports.Cells(1, 2) = "oleaut32.dll"
    shDllExports.Cells(2, 2).Resize(plCount).Value = Application.Transpose(vOleAut32Exports)
    
End Sub

Function GetExports(ByVal sFileName As String, ByRef plCount As Long) As Variant
    Dim fso As Scripting.FileSystemObject
    Set fso = New Scripting.FileSystemObject
    
    Dim dicLines As Scripting.Dictionary
    Set dicLines = New Scripting.Dictionary
    
    Dim txt As Scripting.TextStream
    Set txt = fso.OpenTextFile(sFileName)
    
    Dim bExportsSection As Boolean
    bExportsSection = False
    While Not txt.AtEndOfStream
        Dim sLine As String
        sLine = txt.ReadLine
        If Not bExportsSection Then
            If Trim(sLine) = "ordinal hint RVA      name" Then
            
                bExportsSection = True
                sLine = txt.ReadLine
            End If
        Else
            If Trim(sLine) = "" Then
                bExportsSection = False
            Else
                Dim sExport As String
                sExport = Mid(sLine, 27)
                sExport = Split(sExport)(0)
                
                dicLines.Add dicLines.Count, sExport
            End If
        End If
        
    Wend
    txt.Close
    Set txt = Nothing
    
    Set fso = Nothing
    plCount = dicLines.Count
    
    GetExports = dicLines.Items
    
    Set dicLines = Nothing

End Function


No comments:

Post a Comment