使用远程线程CreateRemoteThread的方法可以在其他进程中注入自己想注入的DLL,千万不要用这个方法搞破坏哦。
我们搞一个可以弹窗的DLL代码,让进程只要LOAD DLL就会弹窗。
DLL代码:
#include <windows.h>
// DLL入口点函数
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
// 弹窗代码
MessageBox(NULL, L"Hello from YourDLL!", L"DLL Injection", MB_OK | MB_ICONINFORMATION);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
被注入DLL的进程代码,这个可以随意写,只要程序能一直run就可以。:
#include<windows.h>
#include<iostream>
int main()
{
while (1)
{
Sleep(1000 * 2);
std::cout << "***\n" << std::endl;
}
}
接下来就是执行注入的代码:
先说注入的步骤,这个有点复杂。
1. 获得要注入进程的进程ID,可以使用进程名获得。
2. 使用VirtualAllocEx api来在该进程内开辟一块内存,大小正好是DLL路径。
3. 将DLL路径信息通过WriteProcessMemory 写入该进程空间。
4. 获得kernal32在本进程的地址。因为同平台下所有exe都在同一位置加载kernal32。
5. 在kernal32中获得LoadLibraryW的地址,此地址也是被注入进程的LoadLibraryW地址。
6. 创建远程线程执行这个LoadLibraryW操作,参数就是要传入的DLL路径。
代码示例:
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <stdio.h>
// 获取目标进程ID
DWORD GetTargetProcessID(const TCHAR* targetProcessName)
{
DWORD processID = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 processEntry;
processEntry.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hSnapshot, &processEntry))
{
do
{
if (_tcsicmp(processEntry.szExeFile, targetProcessName) == 0)
{
processID = processEntry.th32ProcessID;
break;
}
} while (Process32Next(hSnapshot, &processEntry));
}
CloseHandle(hSnapshot);
}
return processID;
}
// 远程线程注入DLL
BOOL InjectDll(DWORD processID, const TCHAR* dllPath)
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
if (hProcess == NULL)
{
return FALSE;
}
LPVOID dllPathAddress = VirtualAllocEx(hProcess, NULL, _tcslen(dllPath) * sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE);
if (dllPathAddress == NULL)
{
CloseHandle(hProcess);
return FALSE;
}
SIZE_T bytesWritten;
if (!WriteProcessMemory(hProcess, dllPathAddress, dllPath, _tcslen(dllPath) * sizeof(TCHAR), &bytesWritten))
{
VirtualFreeEx(hProcess, dllPathAddress, 0, MEM_RELEASE);
CloseHandle(hProcess);
return FALSE;
}
HMODULE kernel32Module = GetModuleHandle(_T("kernel32.dll"));
LPTHREAD_START_ROUTINE loadLibraryFunction = (LPTHREAD_START_ROUTINE)GetProcAddress(kernel32Module, "LoadLibraryW");
HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, loadLibraryFunction, dllPathAddress, 0, NULL);
if (hRemoteThread == NULL)
{
VirtualFreeEx(hProcess, dllPathAddress, 0, MEM_RELEASE);
CloseHandle(hProcess);
return FALSE;
}
WaitForSingleObject(hRemoteThread, INFINITE);
VirtualFreeEx(hProcess, dllPathAddress, 0, MEM_RELEASE);
CloseHandle(hRemoteThread);
CloseHandle(hProcess);
return TRUE;
}
int main()
{
const TCHAR* targetProcessName = _T("runTest.exe"); // 目标进程的名称
const TCHAR* dllPath = _T("C:\\Users\\admin\\source\\repos\\DLLinject\\x64\\Debug\\DLLinject.dll"); // 自定义DLL的路径
DWORD targetProcessID = GetTargetProcessID(targetProcessName);
if (targetProcessID != 0)
{
if (InjectDll(targetProcessID, dllPath))
{
printf("DLL injected successfully.\n");
}
else
{
printf("Failed to inject DLL.\n");
}
}
else
{
printf("Target process not found.\n");
}
return 0;
}
执行结果:
procxp查看dll已经在被注入的进程中了。
还是那句话,不能用来搞破坏哦。这是盗版软件或者游戏外挂什么的经常使用的方式,在其他进程里搞一些自己的东西。听说原本CreateRemoteThread是微软为调试其他进程而创建的,同样的被别有用心的人给利用了。