Gaslight Deceive Subvert
Gaslight Deceive Subvert

Reputation: 20438

Using GetProcAddress when the name might be decorated

What is the correct way to use GetProcAddress() on a 32 bit DLL? On win32, there are three calling conventions, cdecl, stdcall and fastcall. If the function in the DLL is foo they will decorate the name in the following ways _foo, _foo@N and @foo@N.

But if the author of the dll has used a .def file, then the exported name will be changed to just "foo" without any decoration.

This spells trouble for me because if I want to load foo from a dll that is using stdcall, should I use the decorated name:

void *h = LoadLibraryEx(L"foo.dll", NULL, 0);
GetProcAddres((HMODULE)h, L"_foo@16");

Or the undecorated one:

void *h = LoadLibraryEx(L"foo.dll", NULL, 0);
GetProcAddres((HMODULE)h, L"foo");

? Should I guess? I've looked at lots of 32 bit DLL files (stdcall and cdecl) and they all seem to export the undecorated name. But can you assume that is always the case?

Upvotes: 1

Views: 1996

Answers (2)

Abraham Le
Abraham Le

Reputation: 134

If __declspec(dllexport) is used during compilation and __declspec(dllimport) in header file, as well as extern "c", then you do not need to decorate those functions. The __declspec helps in using the undecorated names, but function overloads, namespaces, and classes still require same way to distinguish them.

Usually, object oriented functions are exported using function ordinals instead of their decorated names. Cast the ordinal as (char*)(unsigned short)ordinal, thus, GetProcAddress(module, (char*)(unsigned short)ordinal);

Edit: while most of Windows use UTF-16, GetProcAddress uses UTF-8, so it cannot use a wide character string.

GetProcAddress(module, L"foo") is identical to GetProcAddress(module, "f");

Upvotes: 0

David Heffernan
David Heffernan

Reputation: 613481

There's really no shortcut or definitive rule here. You have to know the name of the function. The normal scenario is that you know at compile time the name of the function. In which case it does not matter whether the exported name is mangled, decorated, or indeed completely unrelated to the semantic name. Functions can be exported without names, by ordinal. Again, you need to know how the function was exported.

If you are presented with a header file for a library, and want to link to it with explicit linking (LoadLibrary/GetProcAddress) then you will need to find out the names of the function. Use a tool like dumpbin or Dependency Walker to do that.

Now, the other scenario which might lead to you asking the question is that you don't know the name at compile time. For instance, the name is provided by the user of your program in one way or another. Again, it is quite reasonable to require the user to know the exported name of the function.

Finally, you can parse the PE meta data for the executable file to enumerate its exported function. This will give you a list of exported function names, and exported function ordinals. This is what tools like dumpbin and Dependency Walker do.

Upvotes: 5

Related Questions