5

Here's my DLL code:

#include <Windows.h>
#include <iostream>

int sysLol(char *arg);

int sysLol(char *arg)
{
   std::cout<<arg<<"\n";
   return 1;
}

And here's my application code:

#include <Windows.h>
#include <iostream>
#include <TlHelp32.h>
#include <stdlib.h>

typedef int (WINAPI* Lol)(char* argv);
struct PARAMETERS
{
    DWORD Lol;
};

int main()
{
    PARAMETERS testData;
    HMODULE e = LoadLibrary(L"LIB.dll"); //This executes without problem
    if (!e) std::cout<<"LOADLIBRARY: "<<GetLastError()<<"\n";
    else std::cout<<"LOADLIBRARY: "<<e<<"\n";
    testData.Lol = (DWORD)GetProcAddress(e,"sysLol"); //Error 127?
    if (!testData.Lol) std::cout<<testData.Lol<<" "<<GetLastError()<<"\n";
    else std::cout<<"MESSAGEBOX: "<<testData.Lol<<"\n";
    std::cin.ignore();
    return 1;
}

So, my LIB.dll is successfully loaded using LoadLibrary(), yet GetProcAddress() fails with 127. This seems to be because it's not finding my function name, but I don't see why that would fail.

Assistance is greatly appreciated! :) ~P

Moon
  • 329
  • 2
  • 3
  • 20

5 Answers5

5

Since that tag is C++, you'll need to declare a C name for the function:

extern "C" int sysLol(char *arg);

You can see the actual name the compiler gave your C++ function with Dependency Walker.

When successful, cast the function to pointer returned by GetProcAddress to the actual function type:

typedef int (*sysLol_t)(char *arg);
sysLol_t pFunc = GetProcAddress(e,"sysLol");
egur
  • 7,830
  • 2
  • 27
  • 47
2

That is ERROR_PROC_NOT_FOUND which means that there is no exported function with that name.

There's not much more to say. Perhaps you've got the name wrong. It could be a simple mismatch of letter case. Perhaps the DLL has been built incorrectly and is not exporting the function. Perhaps the DLL is decorating or mangling the names. Certainly from the code in the question, there's no evidence that you attempted to export the function, or indeed suppress decoration/mangling.

Use a tool like dumpbin or Dependency Walker to inspect the names of the functions that are exported. That may shed some light on the problem.

Rather than linking at runtime with LoadLibrary and GetProcAddress, it is much more convenient to link at load time. Use the .lib import library generated when you build the DLL to do that.

It's also worth pointing out that the calling conventions don't match. You have cdecl on the DLL side, and stdcall on the executable side. And don't cast pointers to DWORD. That ends badly when you compile for 64 bit.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Well, this is intended to be used with process injection, so load-time linking isn't an option for me. The calling conventions don't match because the actual sources are much more complex than the ones I posted, so I had to go through and quickly compress the code into what you see above. It's likely I made a quick typing error. As far as casting to DWORD, right now my process injection is pointed at 32-bit processes, and is being compiled as a 32-bit executable, but I do plan to expand it to 64-bit eventually, so thanks for the tip. :) – Moon Sep 16 '14 at 21:26
  • That's fine. I answered from what I could see. I still think I answered your question. – David Heffernan Sep 16 '14 at 21:44
  • Put your function in an extern "C" block. Use __declspec(dllexport) and cdecl to have no mangling. If you need different calling convention use a def file to export. – David Heffernan Sep 16 '14 at 22:45
  • @TamásSzelei No. That results in `ERROR_MOD_NOT_FOUND`. – David Heffernan Aug 11 '20 at 17:00
  • @tamás perhaps we can tidy up these comments – David Heffernan Aug 11 '20 at 18:11
1

Symbols must be explicitly exported from Windows DLLs. Either declare your function as __declspec(dllexport) or pass a DEF file to the linker to instruct it to export your function. See this description of dllexport.

Khouri Giordano
  • 1,426
  • 15
  • 17
  • It seems to be a start, but apparently my function name is decorated. I'm googling now, but while I'm here, do you know of any way to solve this in a Visual Studio 2012 environment? – Moon Sep 16 '14 at 21:31
1

Please use Dependancy Walker and it will give hint about the method name which is registered inside dll.

http://www.dependencywalker.com/

If method name is - getNumber Dependency Walker will show the actual method name as- _Z9GetNumberd

Ex -

lpGetNumber = (LPGETNUMBER)GetProcAddress(hDLL, "_Z9GetNumberd");

Now LoadLibrary and GetProcAddress() both will work.

CAPSLOCK
  • 6,243
  • 3
  • 33
  • 56
  • 2
    Please [edit] your answer to improve the formatting and remove all the caps. – Baum mit Augen Apr 05 '19 at 13:06
  • Augen , please clarify why this answer is not useful and why you downvoted me ? – Bhushan Mahajan May 04 '19 at 14:25
  • I had downvoted this because the poor formatting made it very hard to read, and thus close to useless. I see it is fixed now. Though the actual usefulness is still debatable, as the answer is pretty much the same as the accepted one, sans the `extern "C"` alternative. Anyway, downvote removed for now. – Baum mit Augen May 04 '19 at 15:15
0

Using DependencyWalker you can view function decorated/undecorated (View->Undecorate C++ functions)

Try to call GetProcAddress with decorated function name form.

Leon .Leon
  • 11
  • 3