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