C++Dll注入——Hello world Dll只有在注入到注入它的相同.exe中时才能工作

C++ Dll injection -- Hello world dll only works when injected into the same .exe that injects it

本文关键字:注入 exe 工作 Dll world Hello C++Dll      更新时间:2023-10-16

在过去的一周里,我一直在努力让我的简单注入应用程序成功地将dll注入到其他进程中。然而,到目前为止,只有当我将dll注入注入器本身时,它才起作用。当我尝试注入不同的应用程序时,我的函数会报告成功(线程已成功创建,内存已分配并写入目标),但我的dllMain似乎没有被调用。此外,错误代码0(error_SUCCESS)由GetLastError()指定。

targetProcessId指定为GetCurrentProcess()时,会显示对话框,并且RemoteThread会成功执行。

但是,当我尝试将targetProcessId设置为calc.exe的运行实例时,什么也没发生。我在其他地方读到,从DllMain调用MessageBox是个坏主意,因为它的模块可能还没有加载,所以我还尝试在DllMain中创建一个无限循环,并检查calc.exe中的线程数是否增加了1。它保持不变。

这是我在StackOverflow上的第一个问题,在发布之前,我试图尽可能多地研究这个话题,但几个小时后我就没有运气了。我显然是dll注入的新手(我最近读完了里彻的书,Windows通过C/C++)。非常感谢您的帮助。

我的所有代码都是从Visual Studio 2010为x64平台编译的。

以下是我的Injector应用程序的相关代码:

BOOL WINAPI Inject(DWORD processID, PCWSTR sourceDLL)
{
BOOL success = false;
HANDLE targetProcess = NULL, createdThread = NULL;
PWSTR pszLibFileRemote = NULL;
__try
{
std::cout << "Process ID: "<< processID << std::endl;
targetProcess = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION  | PROCESS_VM_WRITE,
FALSE, processID);
if (targetProcess == NULL)
{
std::cout << "ERROR: " << GetLastError();
MessageBox(NULL, L"Unable to open process.", L"Error", MB_OK);
__leave;
}
int cch = 1 + lstrlenW(sourceDLL); //Calculate the number of bytes required for the DLL's path
int cb = cch * sizeof(wchar_t);
pszLibFileRemote = (PWSTR)VirtualAllocEx(targetProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
if (pszLibFileRemote == NULL)
{
MessageBox(NULL, L"Could not allocate dll pathname in target process.", L"Error", MB_OK);
__leave;
}
if (!WriteProcessMemory(targetProcess, pszLibFileRemote, (PVOID) sourceDLL, cb, NULL))
{
MessageBox(NULL, L"Could not write dll pathname in target process.", L"Error", MB_OK);
__leave;
}
PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryW");
if (pfnThreadRtn == NULL)
{
MessageBox(NULL, L"Error finding LoadLibraryW address.", L"Error", MB_OK);
__leave;
}
createdThread = CreateRemoteThread(targetProcess, NULL, 0, pfnThreadRtn, pszLibFileRemote, 0, NULL);
if (createdThread == NULL)
{
__leave;
}
WaitForSingleObject(createdThread, INFINITE);
success = true;
}
__finally { // Now, we can clean everything up
// Free the remote memory that contained the DLL's pathname
if (pszLibFileRemote != NULL)
VirtualFreeEx(targetProcess, pszLibFileRemote, 0, MEM_RELEASE);
if (createdThread != NULL)
CloseHandle(createdThread);
if (targetProcess != NULL)
CloseHandle(targetProcess);
}
return success;
}
int _tmain(int argc, _TCHAR* argv[])
{
PCWSTR srcDll = L"test.dll"; //dll in the same directory as the injector.exe, its code is specified below.
DWORD processID = "768"; //Hard coded process ID of a running calc.exe. When I change this line to GetCurrentProcessId() the messagebox from my dll shows.      
if (Inject(processID, srcDll))
{
std::cout << "Injection successful" << std::endl;
Eject(processID, srcDll); //This detaches the dll by calling freelibrary from a remote thread. This function was omitted from this response to keep things relavent.
}
system("PAUSE");
return 0;
}

下面是我的简单helloworld test.dll的代码:

#include "stdafx.h"
#include <Windows.h>
#include <tchar.h>
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD  ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBox(NULL, L"HULLO.", L"DLL", MB_OK);
break;
case DLL_THREAD_ATTACH:
MessageBox(NULL, L"HULLO.", L"DLL", MB_OK);
break;
case DLL_THREAD_DETACH:
MessageBox(NULL, L"HULLO.", L"DLL", MB_OK);
break;
case DLL_PROCESS_DETACH:
MessageBox(NULL, L"HULLO.", L"DLL", MB_OK);
break;
}
return TRUE;
}

已解决:注入的dll的目录必须相对于目标进程指定,或者指定为完整路径,这样目标进程才能找到它。(我把它放在Injector的目录中,这导致了加载问题——calc不知道它在哪里。)

PCWSTR srcDll = L"test.dll"; //dll in the same directory as the injector.exe

由于您在目标程序中执行LoadLibraryW(),而不是注入器,所以它不知道"与注入器相同的目录"是什么——它只是在MSDN上记录的标准目录中搜索它。

您需要通过完整路径,而不是相对路径。