Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ejecting after injecting DLL from running process

I wrote this function to inject DLL into running process:

DLL_Results CDLL_Loader::InjectDll()
{
    DWORD ThreadTeminationStatus;
    LPVOID VirtualMem;
    HANDLE hProcess, hRemoteThread;
    HMODULE hModule;

    if (!isInit())
        return NOT_INIT;

    if (isInjected())
        return DLL_ALREADY_HOOKED;

    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);
    if (hProcess == NULL)
        return PROCESS_ERROR_OPEN;

    VirtualMem = VirtualAllocEx (hProcess, NULL, strlen(DllFilePath), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (VirtualMem == NULL)
        return PROCESS_ERRORR_VALLOC;

    if (WriteProcessMemory(hProcess, (LPVOID)VirtualMem, DllFilePath, strlen(DllFilePath), NULL) == 0)
    {
        VirtualFreeEx(hProcess, NULL, (size_t)strlen(DllFilePath), MEM_RESERVE|MEM_COMMIT);
        CloseHandle(hProcess); 
        return PROCESS_ERROR_WRITE;
    }

    hModule = GetModuleHandle(L"kernel32.dll");
    hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, 
                        (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "LoadLibraryA"),
                          (LPVOID)VirtualMem, 0, NULL);

    if (hRemoteThread == NULL)
    {
        FreeLibrary(hModule);
        VirtualFreeEx(hProcess, NULL, (size_t)strlen(DllFilePath), MEM_RESERVE | MEM_COMMIT);
        CloseHandle(hProcess); 
        return PROCESS_ERROR_CREATE_RTHREAD;
    }

    WaitForSingleObject(hRemoteThread, INFINITE);
    GetExitCodeThread(hRemoteThread, &ThreadTeminationStatus);
    FreeLibrary(hModule);

    VirtualFreeEx(hProcess, NULL, (size_t)strlen(DllFilePath), MEM_RESERVE | MEM_COMMIT);
    CloseHandle(hRemoteThread);
    CloseHandle(hProcess); 
    injected = true;
    return DLLHOOK_OK;
}

And It works great, but when i was trying to eject the dll i was unable to find information about unhooking.. i was trying to build some function to do it and i think i'm close this is what i've got so far:

is that the right way? if so what parameter should i pass in createRemoteThread instade of VirtualMem (That was used in the injecting function)...

DLL_Results CDLL_Loader::EjectDll()
{
    DWORD ThreadTeminationStatus;
    HANDLE hProcess, hRemoteThread;
    HMODULE hModule;

    if (isInjected())
        return DLLEJECT_OK;

    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);
    if (hProcess == NULL)
        return PROCESS_ERROR_OPEN;

    hModule = GetModuleHandle(L"kernel32.dll");
    hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, 
                        (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary"),
                          /*(LPVOID)VirtualMem <- What do i need to send here?*/, 0, NULL);

    if (hRemoteThread != NULL)
    {
        WaitForSingleObject(hRemoteThread, INFINITE);
        GetExitCodeThread(hRemoteThread, &ThreadTeminationStatus);
    }

    CloseHandle(hRemoteThread);
    CloseHandle(hProcess); 
    injected = false;
    return DLLEJECT_OK;
}
like image 935
D_R Avatar asked Dec 04 '11 01:12

D_R


2 Answers

On 32-bit systems, the value of ThreadTeminationStatus after GetExitCodeThread contains the return value of LoadLibraryA in the remote process. This is the module handle of the newly loaded dll. You can use it as the parameter to FreeLibrary in the remote thread.

If you want to use the code on 64-bit Windows, the thread exit code is truncated to a 32-bit DWORD, so it's unusable. You have to create a callable routine in the remote process (as Necrolis suggested) or resort to finding the module base of the DLL via psapi or the Toolhelp API (CreateToolhelp32Snapshot, Module32First, Module32Next).

like image 145
pezcode Avatar answered Nov 10 '22 09:11

pezcode


You need to pass it the HANDLE of the dll you injected, else you can pass it VirtualMem but then your remote thread routine would need to be:

DWORD WINAPI UnloadDll(void* pMem)
{
    FreeLibrary(GetModuleHandleA((const char*)pMem));
    return 0;
}

However, generally the dll you inject should unload itself (see how DllMain works), either manually or automatically when the host is closed.

like image 21
Necrolis Avatar answered Nov 10 '22 10:11

Necrolis