改變程序流程通常就是改變線程EIP、創建新線程或者修改目標進程的代碼使其執行LoadLibrary來加載目標DLL。
CreateRemoteThread法:就是目標進程中申請一塊內存儲存目標DLL路徑,然後調用CreateRemoteThread創建一個線程函數是LoadLibrary,參數是存放目標DLL路徑的內存指針。
代碼如下:
void InjectDLL::InjectDLLToProcessMethodOne(wchar_t* targetProcName, char* dllPath)
{
DWORD targetPid = GetProcessPid(targetProcName);
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPid);
if (hProc == NULL)
{
cout << "進程加載錯誤!" << endl;
return;
}
LPTSTR AllocatedMem = (LPTSTR)VirtualAllocEx(hProc, NULL, strlen(dllPath)+1, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (AllocatedMem == NULL)
{
cout << "內存分配失敗!" << endl;
return;
}
if (WriteProcessMemory(hProc, AllocatedMem, dllPath, strlen(dllPath), NULL) == 0)
{
cout << "dll路徑寫入失敗!" << endl;
return;
}
//LoadLibraryA函數位於kernel32.dll中,GetModuleHandle函數只能獲取已經映射到當前進程的模塊
HMODULE mKernel = GetModuleHandleA("kernel32");
if (mKernel == NULL)
{
cout << "kernel32句柄獲取失敗!" << endl;
return;
}
LPTHREAD_START_ROUTINE lpStartAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(mKernel, "LoadLibraryA");
if (lpStartAddress == NULL)
{
cout << "獲取LoadLibraryA失敗" << endl;
return;
}
HANDLE mHandle = CreateRemoteThread(hProc, NULL, 0, lpStartAddress, AllocatedMem, 0, NULL);
if (mHandle == NULL)
{
cout << "創建線程失敗!" << endl;
return;
}
}
DWORD InjectDLL::GetProcessPid(wchar_t* processName)
{
HANDLE lpSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == lpSnapshot)
{
cout << "進程快照獲取失敗!" << endl;
return 0;
}
PROCESSENTRY32 pe32 = { 0 };
pe32.dwSize = sizeof(pe32);
Process32First(lpSnapshot, &pe32);
do
{
if (_wcsicmp(processName, pe32.szExeFile) == 0)
return pe32.th32ProcessID;
} while (Process32Next(lpSnapshot, &pe32));
return 0;
}