원격 스레드 CreateRemoteThread 메서드를 사용하여 다른 프로세스에 주입하려는 DLL을 주입하므로 이 메서드를 사용하여 손상을 일으키지 마십시오.
LOAD DLL만큼 프로세스가 팝업되도록 창을 띄울 수 있는 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에 주입된 프로세스 코드는 프로그램이 항상 실행될 수 있는 한 자유롭게 작성할 수 있습니다. :
#include<windows.h>
#include<iostream>
int main()
{
while (1)
{
Sleep(1000 * 2);
std::cout << "***\n" << std::endl;
}
}
다음 단계는 주입된 코드를 실행하는 것입니다.
조금 복잡한 주입 단계에 대해 먼저 이야기하겠습니다.
1. 주입할 프로세스의 프로세스 ID를 구합니다. 프로세스 이름을 사용하여 얻을 수 있습니다.
2. VirtualAllocEx API를 사용하여 프로세스에서 메모리 조각을 엽니다. 크기는 정확히 DLL 경로입니다.
3. WriteProcessMemory를 통해 DLL 경로 정보를 프로세스 공간에 씁니다.
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는 원래 다른 프로세스를 디버깅하기 위해 Microsoft에서 만들었으며 다른 동기를 가진 사람들도 사용했다고 들었습니다.