70

I've been searching for a way to get all the strings that map to function names in a dll.

I mean by this all the strings for which you can call GetProcAddress. If you do a hex dump of a dll the symbols (strings) are there but I figure there must me a system call to acquire those names.

minty
  • 22,235
  • 40
  • 89
  • 106
  • 1
    just a nitpick, but I think you meant > but I figure there must be a system call – Ryan Guill Jan 13 '09 at 20:19
  • If you are looking for a way to do it programmaticly, see my answer further down. – Aaron Jan 16 '09 at 04:32
  • 1
    Also keep in mind that DLLs can export functions that don't have string names, and must be accessed via their ordinal. – josh poley Oct 02 '13 at 17:33
  • 1
    Data can also be exported by ordinal. In both cases, though, it is still possible to use `GetProcAddress (...)` using a name. You just have to use the pseudo-name that `MAKEINTRESOURCEA ()` gives you; you are never going to find that name by walking the export table of the executable image, but `GetProcAddress` knows full well what to do with it ;) – Andon M. Coleman Dec 03 '16 at 04:43

13 Answers13

80

If you have MS Visual Studio, there is a command line tool called DUMPBIN.

dumpbin /exports <nameofdll>
Ates Goral
  • 137,716
  • 26
  • 137
  • 190
Die in Sente
  • 9,546
  • 3
  • 35
  • 41
36

There are three distinct types of DLLs under Windows:

  1. Classic DLLs that expose every available function in the exports table of the DLL. You can use dumpbin.exe or depends.exe from Visual Studio, or the free dependency walker to examine these types. Matt Pietrek wrote many articles and utilities for digging into Win32 PE files. Have a look at his classic MSDN Magazine articles. C++ DLLs that contain exported classes will export every method in the class. Unfortunately it exports the mangled names, so the output of dumpbin is virtually unreadable. You will need to use a program like vc++_filt.exe to demangle the output.

  2. COM DLLs that expose COM objects. These DLLs expose a handful of regular exported functions (DllRegisterServer etc) that enable the COM system to instantiate objects. There are many utilities that can look at these DLLs, but unless they have embedded type libraries they can be quite difficult to examine. 4Developers have a number of good COM/ActiveX tools

  3. .NET DLLs that contain .NET assemblies. Typiically you would use a tool like .NET Reflector to dig into these.

Edit: 4Developers link is not working.

Amogh
  • 4,453
  • 11
  • 45
  • 106
Mike Thompson
  • 6,708
  • 3
  • 32
  • 39
26

Also there is the DEPENDs program at http://www.dependencywalker.com/

Die in Sente
  • 9,546
  • 3
  • 35
  • 41
  • Alternativly, Depends is also available in the platform sdk installation. – Greg Domjan Jan 13 '09 at 01:53
  • @Greg The version in the SDK is a few versions older than what's on the website. Probably fine with it, but might as well recomend the source.. – Aaron Jan 14 '09 at 16:32
17

Try this (Linux) C code:

#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

unsigned int vpe2offset(void * base, unsigned int vpe) {
    unsigned int * ptr = base;
    unsigned int pe_offset;
    unsigned short num_sections;

    pe_offset = ptr[0x3c/4];                             //PE header offset
    ptr = base + pe_offset;                              //PE header address
    num_sections = ((unsigned short*)ptr)[6/2];          //Section count
    ptr = ((void*)base) + 0x18 + 0x60 + 16*8 + pe_offset;//Address of first section

    while (num_sections--) {
        if (vpe >= ptr[0x0c/4] && vpe < ptr[0x0c/4] + ptr[0x10/4]) {
            return vpe - ptr[0x0c/4] + ptr[0x14/4];
        }
        ptr += 0x28/4;
    }

    return 0;
}

void iterate_exports(void * base, int(*iterator)(char*)) {
    unsigned int * ptr = base;
    unsigned int pe_offset,
                 exports_offset,
                 number_of_names,
                 address_of_names;

    pe_offset = ptr[0x3c/4];
    ptr = base + pe_offset;
    exports_offset = ptr[0x78/4];
    ptr = base + vpe2offset(base, exports_offset);
    number_of_names = ptr[0x18/4];
    address_of_names = ptr[0x20/4];
    ptr = base + vpe2offset(base, address_of_names);
    while (number_of_names-- && iterator((char*)(base + vpe2offset(base, ptr++[0])))) {
        /* Do nothing */
    }
}

int print_symbol_name(char * name) {
    printf("%s\n", name);
    return 1;
}

int main(int argc, char const *argv[]) {
    int fd;
    struct stat st;
    void * base;

    if (argc == 1) {
        printf("Usage: %s <dll>\n", argv[0]);
    } else if (stat(argv[1], &st) == 0 && (fd = open(argv[1], O_RDONLY)) >= 0) {
        base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
        if (base != MAP_FAILED) {
            iterate_exports(base, print_symbol_name);
            munmap(base, st.st_size);
        } else {
            fprintf(stderr, "Could not map \"%s\".\n", argv[1]);
        }
        close(fd);
    } else {
        fprintf(stderr, "Could not open \"%s\" for reading.\n", argv[1]);
    }
    return 0;
}

It follows references inside the PE file and finally calls a callback function for each exported symbol. For an overview of the PE file format see this: http://www.openrce.org/reference_library/files/reference/PE%20Format.pdf

Robert Larsen
  • 1,018
  • 2
  • 11
  • 18
10

I don't know of a WIn32 API to do it: instead, you (or one of the tools mentioned in other posts) do it by knowing the binary format of a PE file, and reading the file: see http://msdn.microsoft.com/en-us/magazine/cc301808.aspx (and that article mentioned a "PEDUMP" utility).

ChrisW
  • 54,973
  • 13
  • 116
  • 224
  • An excellent answer, which I'm voting up, but I'll add the link to the definitive reference document on the PE file format: http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx – Die in Sente Jan 12 '09 at 23:38
7

It takes a bit of work, but you can do this programmaticly using the DbgHelp library from Microsoft.

Debugging Applications for Microsoft .Net and Microsoft Windows, by John Robbins is an excellent (if a little older) book which contains use details and full source. And, you can pick it up on Amazon for the cheap!

Aaron
  • 3,726
  • 2
  • 26
  • 23
6

I use dumpbinGUI, which gives you the list of exports (and a lot more) from a right click in Windows Explorer. dumpbin and depends will both give you the lists as well.

RealSollyM
  • 1,530
  • 1
  • 22
  • 35
ctacke
  • 66,480
  • 18
  • 94
  • 155
5

You need to inspect the PE header of the .dll, since that's ultimately what Windows does anyways.

Assuming you have a pointer to the .dll's IMAGE_OPTIONAL_HEADER (you can either use dbghelp's ImageNtHeader function with a handle to a .dll loaded via LoadLibrary or attempt to find it yourself if you know the layout of the .dll yourself), you'll want to look at optional_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT], find the export table relative to the optional header with the offset in there, then walk the export table (it's a IMAGE_EXPORT_DIRECTORY).

For funsies, a backwards compatible PE image starts out with a IMAGE_DOS_HEADER; the offset to the IMAGE_NT_HEADER is IMAGE_DOS_HEADER::e_lfanew, and the IMAGE_OPTIONAL_HEADER is embedded in the NT header.

MSN
  • 53,214
  • 7
  • 75
  • 105
4

there is a program called dll export viewer you can use: http://www.nirsoft.net/utils/dll_export_viewer.html

2

I always have to do this. I just go to one of these sites. They host the information we usually need.

Windows 7 DLL File Information

Windows XP DLL File Information

claws
  • 52,236
  • 58
  • 146
  • 195
2

You can also use the "objdump" linux tool under windows, but you may have to install cygwin first.

I use the following commands:

# feed the output to less
objdump -x nameOfThe.Dll| less
# or use egrep to filter
objdump -x /cygdrive/c/Windows/system32/user32.dll | \ 
    egrep "^\s*\[[ [:digit:]]{4}\] \w{1,}" | less
minus one
  • 642
  • 1
  • 7
  • 28
0

I guess you will end up parsing PE file and do demangling yourself if you want to find the function names of an unknown dll in the runtime or extremely useless system("dumpbin"); magic.

You should be more clear about what you want.

BFD library does what you want (and the kitchen sink) which is the main component of several GNU binutils tools. I can't be sure if it will fit your problem.

artificialidiot
  • 5,309
  • 29
  • 27
0

You don't need any tool and you don't need to parse PE. Just use standard Win32 api (D)

The code (in C) has been published many times on Adv.Win32 api ng ( news://comp.os.ms-windows.programmer.win32) (since 1992...)