Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a function in an injected DLL?

Using C++, I have an application which creates a remote process and injects a DLL into it. Is there a way to get the remote application to execute a function exported from the DLL, from the application which created it? And is it possible to send parameters to that function? Please note that I am trying to stay away from doing anything within DllMain.

like image 985
RectangleEquals Avatar asked Nov 17 '12 08:11

RectangleEquals


People also ask

What can you do with a DLL injector?

In computer programming, DLL injection is a technique used for running code within the address space of another process by forcing it to load a dynamic-link library. DLL injection is often used by external programs to influence the behavior of another program in a way its authors did not anticipate or intend.

How do DLL injection work?

Other sub-techniques of Process Injection (12) DLL injection is a method of executing arbitrary code in the address space of a separate live process. DLL injection is commonly performed by writing the path to a DLL in the virtual address space of the target process before loading the DLL by invoking a new thread.

Is DLL injection detectable?

There are many methods to detect injected DLLs and even more to avoid getting detected. In the simple case you can iterate over all the modules in the process and look for anything that shouldn't be there. Sometimes you might want to hook LoadLibrary in case the injected DLL removes itself from the module list.


1 Answers

Note:
For a much better answer, please see my update posted below!


Okay so here's how I was able to accomplish this:

BOOL RemoteLibraryFunction( HANDLE hProcess, LPCSTR lpModuleName, LPCSTR lpProcName, LPVOID lpParameters, SIZE_T dwParamSize, PVOID *ppReturn )
{
    LPVOID lpRemoteParams = NULL;

    LPVOID lpFunctionAddress = GetProcAddress(GetModuleHandleA(lpModuleName), lpProcName);
    if( !lpFunctionAddress ) lpFunctionAddress = GetProcAddress(LoadLibraryA(lpModuleName), lpProcName);
    if( !lpFunctionAddress ) goto ErrorHandler;

    if( lpParameters )
    {
        lpRemoteParams = VirtualAllocEx( hProcess, NULL, dwParamSize, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
        if( !lpRemoteParams ) goto ErrorHandler;

        SIZE_T dwBytesWritten = 0;
        BOOL result = WriteProcessMemory( hProcess, lpRemoteParams, lpParameters, dwParamSize, &dwBytesWritten);
        if( !result || dwBytesWritten < 1 ) goto ErrorHandler;
    }

    HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpFunctionAddress, lpRemoteParams, NULL, NULL );
    if( !hThread ) goto ErrorHandler;

    DWORD dwOut = 0;
    while(GetExitCodeThread(hThread, &dwOut)) {
        if(dwOut != STILL_ACTIVE) {
            *ppReturn = (PVOID)dwOut;
            break;
        }
    }

    return TRUE;

ErrorHandler:
    if( lpRemoteParams ) VirtualFreeEx( hProcess, lpRemoteParams, dwParamSize, MEM_RELEASE );
    return FALSE;
}

//...
CStringA targetDll = "injected.dll"

    // Inject the target library into the remote process
PVOID lpReturn = NULL;
RemoteLibraryFunction( hProcess, "kernel32.dll", "LoadLibraryA", targetDll.GetBuffer(MAX_PATH), targetDll.GetLength(), &lpReturn );
HMODULE hInjected = reinterpret_cast<HMODULE>( lpReturn );

    // Call our exported function
lpReturn = NULL;
RemoteLibraryFunction( hProcess, targetDll, "Initialize", NULL, 0, &lpReturn );
BOOL RemoteInitialize = reinterpret_cast<BOOL>( lpReturn );


This can also be used to send parameters to a remote function via a pointer to a struct or union, and gets around having to write anything in DllMain.

like image 145
RectangleEquals Avatar answered Sep 30 '22 03:09

RectangleEquals