Инъекция Qt dll в процесс
Задача вставить dll, которая содержит QtApp в сторонний процесс.
Есть метод который делает инжект dll в процесс, метод работает без ошибок, все функции отрабатывают корректно, и сам метод завершается true. Однако после вставки от самой dll нет никаких признаков и сигналов (хотя должно показаться окно).
Вот метод, который делает инъекцию:
bool WINAPI InjectDll(__in LPCWSTR lpcwszDll, __in LPCWSTR targetPath) {
SIZE_T nLength;
LPTHREAD_START_ROUTINE lpLoadLibraryA = NULL;
LPVOID lpRemoteString;
PROCESS_INFORMATION processInformation;
DWORD pid = (DWORD)_wtoi(lpcwszDll);
processInformation.hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!processInformation.hProcess)
{
PrintError(LPTSTR("OpenedProcess"));
return FALSE;
}
lpLoadLibraryA = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"KERNEL32.DLL"), "LoadLibraryA");
if (!lpLoadLibraryA)
{
PrintError(LPTSTR("GetProcAddress"));
CloseHandle(processInformation.hProcess);
return FALSE;
}
nLength = wcslen(targetPath) * sizeof(WCHAR);
lpRemoteString = (LPVOID)VirtualAllocEx(processInformation.hProcess, NULL, nLength + 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!lpRemoteString)
{
PrintError(LPTSTR("VirtualAllocEx"));
CloseHandle(processInformation.hProcess);
return FALSE;
}
if (!WriteProcessMemory(processInformation.hProcess, lpRemoteString, (LPVOID)targetPath, nLength + 1, NULL)) {
PrintError(LPTSTR("WriteProcessMemory"));
VirtualFreeEx(processInformation.hProcess, lpRemoteString, 0, MEM_RELEASE);
CloseHandle(processInformation.hProcess);
return FALSE;
}
HANDLE hThread = CreateRemoteThread(processInformation.hProcess, NULL, 0, lpLoadLibraryA, lpRemoteString, NULL, NULL);
if (!hThread)
{
PrintError(LPTSTR("CreateRemoteThread"));
VirtualFreeEx(processInformation.hProcess, lpRemoteString, 0, MEM_RELEASE);
CloseHandle(processInformation.hProcess);
return FALSE;
}
WaitForSingleObject(hThread, INFINITE);
CloseHandle(processInformation.hProcess);
return TRUE;
}
А вот собственно DllMain (смысл в том, чтобы создать поток, а внутри потока создается QtApp и выполняется какой то рабочий код, для теста сейчас просто показывается окно):
class Worker : public QObject
{
Q_INVOKABLE void CreateInjectedApp()
{
MessageBox(NULL, (LPCWSTR)L"Hello, I'm Worker.", (LPCWSTR)L"Worker launched", MB_OK);
}
private:
void Connect()
{
QMetaObject::invokeMethod(this, "CreateInjectedApp", Qt::QueuedConnection);
}
public:
Worker()
{
Connect();
}
};
class AppThread : public QThread
{
QPointer<QCoreApplication> m_app;
void run() override
{
int argc;
char* argv;
QCoreApplication app(argc, &argv);
m_app = &app;
Worker worker;
app.exec();
}
public:
AppThread() {}
~AppThread()
{
m_app->quit();
wait();
}
};
extern "C"
{
_declspec(dllexport) BOOL __stdcall DllMain(HINSTANCE hDllHandle, DWORD reason, LPVOID)
{
static AppThread* thread;
switch (reason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hDllHandle);
thread = new AppThread;
thread->start();
break;
case DLL_PROCESS_DETACH:
delete thread;
break;
default:
break;
}
return TRUE;
}
}
Dll и код, который делает инжект, зависят от процесса, в который встраивается библиотека. Сама dll скомпилирована и на x86 и на x64. Ось, в которой пытаюсь запустить WINDOWS 10. Версия Qt: Qt 5.12.9
UPD
Попробовал еще плюс 3 разных способа (к тому, что уже описал выше) по созданию QApp в DllMain
Способ 1:
static int argc = 1;
static char arg0[] = "";
static char * argv[] = { arg0, nullptr };
Q_GLOBAL_STATIC_WITH_ARGS(QCoreApplication, app, (argc, argv))
extern "C" __declspec(dllexport) void initialize() {
app->processEvents(); // prime the application instance
}
extern "C"
{
_declspec(dllexport) BOOL __stdcall DllMain(HINSTANCE hDllHandle, DWORD reason, LPVOID)
{
switch (reason) {
case DLL_PROCESS_ATTACH:
initialize();
break;
case DLL_PROCESS_DETACH:
if (QCoreApplication::instance()) QCoreApplication::instance()->quit();
break;
default:
break;
}
return TRUE;
}
}
Способ 2:
void guiWorker()
{
int argc = 1;
const char dummy[] = "";
char * argv[] = { const_cast<char*>(dummy), 0 };
QCoreApplication app(argc, argv);
app.exec();
}
VOID CALLBACK Start(_In_ ULONG_PTR) {
std::thread thread { guiWorker };
thread.detach();
}
extern "C"
{
_declspec(dllexport) BOOL __stdcall DllMain(HINSTANCE hDllHandle, DWORD reason, LPVOID)
{
switch (reason) {
case DLL_PROCESS_ATTACH:
QueueUserAPC(Start, GetCurrentThread(), NULL);
break;
case DLL_PROCESS_DETACH:
if (QCoreApplication::instance()) QCoreApplication::instance()->quit();
break;
default:
break;
}
return TRUE;
}
}
Способ 3:
DWORD WINAPI MainLoop(LPVOID) {
int argc = 0;
char** argv = nullptr;
QCoreApplication loop(argc, argv);
return loop.exec();
}
extern "C"
{
__declspec (dllexport) BOOL __stdcall DllMain(HMODULE, DWORD ul_reason_for_call, LPVOID)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: {
DWORD thrID;
CreateThread(0, 0, MainLoop, 0, 0, &thrID);
} break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
}
Ни один из способов не работает
Есть подозрение, что не работает именно код инжекта, а не dll. Хотя он отрабатывает без ошибок.