2014-08-27 4 views
4

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

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()); 
    } 

ответ

3

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

В 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. Если это удается, оно возвращает значение, отличное от NULL, и это означает, что выведенная DLL DllMain DLL вызывается из удаленного процесса. Если это так, адрес 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.

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

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

5

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

Смежные вопросы