Как вызвать конкретную функцию в dll-инъекции?

Следующий код внедрит dll и будет вызван DllMain. Как я вызываю конкретную функцию из DLL, а не только DllMain?

    DWORD pid;
    HANDLE hd;
    LPVOID gp, rs, proc;

    gp = (LPVOID)GetProcAddress(GetModuleHandle(L"Kernel32.dll"), "LoadLibraryA");
    pid = 6096;

    hd = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);    


    rs = (LPVOID)VirtualAllocEx(hd, 0, sizeof(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

    if (!WriteProcessMemory(hd, (LPVOID)rs, DLL_NAME, strlen(DLL_NAME), 0))
    {
        printf("WriteProcessMemory %d", GetLastError());
    }

    if (!CreateRemoteThread(hd, 0, 0, (LPTHREAD_START_ROUTINE)gp, rs, 0, 0))
    {
        printf("CreateRemoteThread %d", GetLastError());
    }

2 ответа

Когда ваши введенные DLL DllMain запускается впервые, звоните CreateThread создать новую тему, которая может делать все что угодно. Обратите внимание, что вы не можете вызвать произвольный код из DllMain как описано в документации. Отсюда и призыв к CreateThread от DllMain,

Ну, я использую следующий подход.

В DLL, которая вводится, я создаю общий раздел, например так:

#pragma data_seg(".MyShared")

LPTHREAD_START_ROUTINE g_lpMyFunc = NULL;

#pragma data_seg()
#pragma section(".MyShared", read, write, shared)

Переменная общего раздела g_lpMyFunc затем инициализируется внутри DllMain как это:

BOOL APIENTRY DllMain(HMODULE, DWORD dwReasonForCall, LPVOID)
{
    if (NULL != GetModuleHandle(_T("MyApp.exe")))
    {
        if (DLL_PROCESS_ATTACH == dwReasonForCall)
        {
            g_lpMyFunc = (LPTHREAD_START_ROUTINE)&MyFunc;
        }
        else if (DLL_PROCESS_DETACH == dwReasonForCall)
        {
            g_lpMyFunc = NULL;
        }
    }
    return TRUE;
}

Этот код делает следующее. Вызов функции GetModuleHandle пытается получить дескриптор исполняемого модуля MyApp. Если это успешно, это возвращает ненулевое значение, и это означает, что введенные DLL DllMain вызывается из удаленного процесса. Если это так, адрес MyFunc сохраняется в g_lpMyFunc общая переменная. И если DLL отсоединяется от процесса (например, когда он выходит), я устанавливаю g_lpMyFunc в NULL, чтобы не иметь возможности вызывать функцию по удаленному адресу, которого там нет.

Затем я создаю внешнюю функцию MyFuncExtern что вызывает MyFunc в удаленном процессе, как это:

extern "C" __declspec(dllexport) bool __cdecl MyFuncExtern(HANDLE hProcess)
{
    if (NULL == g_lpMyFunc)
    {
        return false;
    }

    return NULL != CreateRemoteThread(hProcess, NULL, 0, g_lpMyFunc, NULL, 0, NULL);
}

Это очень упрощенная версия, но она показывает основную концепцию: если g_lpMyFunc не NULL, он создает удаленный поток в hProcess (так же, как в вашем коде), который вызывает функцию по адресу, указанному g_lpMyFunc,

Есть некоторые ограничения на эту функцию, хотя с CreateRemoteThread принимает только один аргумент для удаленной функции (вы можете передать больше, однако для этого потребуется значительно более сложный подход), и если вам нужно возвращаемое значение, вам придется подождать, пока удаленный поток завершит выполнение и получить код выхода, что это DWORD,

Этот подход хорош при написании функций Initialize / Uninitialize и, кроме того, он отлично работает для управляемых DLL C++/CLI.

И, конечно, вы можете использовать любое другое межпроцессное хранилище данных для сохранения указателя (ей) функции. Файлы, отображенные в память, являются хорошим примером.

Другие вопросы по тегам