Home > C/C++, Programming and Scripting, win32 > Calling an exported function from an injected DLL library

Calling an exported function from an injected DLL library

January 2nd, 2009

As I am interested in function hooking/detouring in win32 I have read alot of articles about injecting a library into a remote process. Although none of these guides cover how to remotely call an exported function from the injected DLL. Most injectable library’s just execute their code in the DLLMain entry function.

In the past I have written a DLL that acquired the mouse using DirectInput. The initialization code in the DLLMain entry function actually made the process lockup. Microsoft doesn’t guarantee the DLLMain code to be executed successfully. Microsoft does not recommend this approach. I find creating a thread also a nasty way to initialize your code, eventhough it decreases the chance of an execution failure, creating the thread itself can still fail in theory.

This guide describes how to call a function from the injected library after injecting it.

What do you need

  • Your DLL obviously should have been injected successfully.
  • An open handle (called hProcess) to the remote process with the permission to use CreateRemoteThread.
  • You have saved the remote DLL base address into a DWORD variable called dwBaseAddress. (Use GetExitCodeThread on the remote LoadLibrary thread to retrieve this address).
  • The remote function of the injected DLL should be exported.
  • The name of the export of the DLL function (entryPoint in this guide).
  • The path to the DLL (c:\lib.dll in this guide).

The steps required after injection

  1. Load the library into the local process (injector).
  2. Retrieve the absolute address of the DLL function in the injector.
  3. Calculate the relative address using the absolute address.
  4. Locally unload the library.
  5. Calculate the absolute address of the DLL function in the remote process using adding the relative function address to the DLL base address.
  6. Call the function using CreateRemoteThread.
  7. Retrieve the remote thread exit code to determine if the remote execution was successful.

Retrieving the relative function address

FARPROC getRelativeEntryAddress(LPWSTR pwszLibrary, char* szEntryFunction) {
	if (GetFileAttributesW(pwszLibrary) == INVALID_FILE_ATTRIBUTES) return NULL;
	HINSTANCE hLibrary = LoadLibraryW(pwszLibrary);
	if (!hLibrary) return NULL;
	FARPROC pFunction = GetProcAddress(hLibrary, szEntryFunction);
	if (!pFunction) return NULL;
	return (FARPROC)((DWORD)pFunction - (DWORD)hLibrary);

Retrieving the absolute address of the remote function

LPVOID getAbsoluteAddress(DWORD dwBaseAddress, LPVOID pFunction) {
	return (LPVOID)((DWORD)pFunction + dwBaseAddress);

Calling the remote function by it’s absolute address

bool callRemoteFunction(HANDLE hProcess, LPVOID pFunction) {
	DWORD dwExitCode;
	HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunction, NULL, 0, NULL);
	if (!hThread) return false;
	if (WaitForSingleObject(hThread, THREAD_WAIT) != WAIT_OBJECT_0) return false;
	if (!GetExitCodeThread(hThread, &dwExitCode)) return false;
	return (dwExitCode != 0);    // Assuming your function returns 0 if it does not succeed

Using the functions in your code

// You should have an open handle to the process, called hProcess
// You also should have the base address of the DLL, called dwBaseAddress
FARPROC pEntry = getRelativeEntryAddress(L"c:\\lib.dll", "entryPoint");
if (!pEntry) {
	// Failed to load the library into local process or retrieve the function address
LPVOID pFunction = getAbsoluteAddress(dwBaseAddress, pEntry);
if (!callRemoteFunction(hProcess, pFunction)) {
	// Failed to call the remote function

If you found this article useful please leave me a comment.

C/C++, Programming and Scripting, win32 , , , , , , , , , , , , ,

  1. AP.Codeguru
    January 31st, 2009 at 09:56 | #1

    Hello there!

    You cannot imagine how happy I was when I found your article! It works just fine in my case, but a there’s always a little ‘but’…

    Does it work only for functions which doesn’t have a return value? I mean, it works for my void-type functions, but not for those who return some kind of value.

    In my case, there’s a .dll to be injected in some process, hook it’s d3d9 functions and do some stuff inside. I have an exported function which returns IDirect3D9* value and it seems this technique won’t work for it. Or maybe I’m doing things not the right way?

    I inject a proxy D3D9 dll from here – http://www.mikoweb.eu/index.php?node=28

    Injection is made by RemoteDll – http://www.novell.com/coolsolutions/tools/17354.html

    I use MessageBox() to see if the exported ‘IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion)’ function is executed or not, and it is executed inside the process!

    But it doesn’t seem to return a pointer to IDirect3D9.

    Any ideas on how to achieve a this?

    Thanks in advance.

    Kindest Regards, AP.Codeguru.

  2. wanghongsheng
    July 7th, 2010 at 10:11 | #2

    Thanks! Great job!

    one comment on:
    “You have saved the remote DLL base address into a DWORD variable called dwBaseAddress. (Use GetExitCodeThread on the remote LoadLibrary thread to retrieve this address). ”

    when call function:
    BOOL GetExitCodeThread(
    HANDLE hThread,
    LPDWORD lpExitCode

    the “dwBaseAddress” is the value of “lpExitCode”.

  3. Focus-gfx
    October 18th, 2010 at 23:19 | #3

    would you please provide a working example dll ?

  1. June 2nd, 2012 at 17:51 | #1