#include <Windows.h> #include <iostream> int wmain(int argc, wchar_t * argv[]) { std::cout << "Target running!" << std::endl; std::cout << "Press any key to exit!" << std::endl; std::getchar(); return 0; }
Per quanto riguarda la DLL, il codice è altrettanto banale
#include <Windows.h> BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved ) { switch (dwReason) { case DLL_PROCESS_ATTACH: { MessageBox(NULL, L"MyDLL.dll Loaded!", L"MyDLL", MB_OK | MB_ICONWARNING); break; } case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
Non resta che il codice dell'iniettore in cui la funzione GetProcessIdByProcessName usa l'API esposta in TlHelp32.h per calcolare l'ID del processo target partendo dal suo nome (si veda [2] per maggiori info). La funzione CreateRemoteThreadInjectDll, invece, usa l'API di Windows (si veda [1] o la documentazione online di Microsoft) per ottenere l'HANDLE del processo target, allocare spazio sufficiente a contenere il percorso assoluto della DLL, scrivere tale percorso nello spazio appena allocato, ottenere un puntatore a LoadLibraryW definita in kernel32.dll ed infine chiamare CreateRemoteThread che avvierà un thread nel processo target con il compito di chiamare LoadLibraryW per caricare la DLL. Da notare che poiché la chiamata a LoadLibraryW viene eseguita nel processo target la stringa che contiene il percorso assoluto della DLL deve trovarsi nello spazio degli indirizzi di quest'ultimo. Ecco perché si alloca lo spazio nel processo target e ci si scrive dentro tale percorso.
#include <Windows.h> #include <iostream> #include "InjectDll.h" // sopprime warning di sicurezza per alcune funzioni deprecate tipo wcscat #pragma warning(disable : 4996) void GetAppPath(wchar_t *szCurFile) { GetModuleFileName(0, szCurFile, MAX_PATH); for (SIZE_T i = wcslen(szCurFile) - 1; i >= 0; i--) { if (szCurFile[i] == '\\') { szCurFile[i + 1] = '\0'; break; } } } int wmain(int argc, wchar_t * argv[]) { wchar_t szDllFile[MAX_PATH] = { 0 }; GetAppPath(szDllFile); std::wcscat(szDllFile, L"MyDLL.dll"); BOOL bRet = CreateRemoteThreadInjectDll(L"MyTarget.exe", szDllFile); if (bRet == FALSE) std::cout << "Dll Injection Error." << std::endl; else std::cout << "Dll Injection OK!" << std::endl; std::cout << "Press any key to Exit!" << std::endl; std::getchar(); return 0; }
#include "InjectDll.h" void ShowError(const wchar_t *pszText) { wchar_t szErr[MAX_PATH] = { 0 }; wsprintf(szErr, L"%s Error[%d]\n", pszText, GetLastError()); MessageBox(NULL, szErr, L"ERROR", MB_OK); } DWORD GetProcessIdByProcessName(const wchar_t *pszProcessName) { DWORD dwProcessId = 0; PROCESSENTRY32 pe32 = { 0 }; HANDLE hSnapshot = NULL; BOOL bRet = FALSE; RtlZeroMemory(&pe32, sizeof(pe32)); pe32.dwSize = sizeof(pe32); hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (NULL == hSnapshot) { ShowError(L"CreateToolhelp32Snapshot"); return dwProcessId; } bRet = Process32First(hSnapshot, &pe32); while (bRet) { if (0 == lstrcmpi(pe32.szExeFile, pszProcessName)) { dwProcessId = pe32.th32ProcessID; break; } bRet = Process32Next(hSnapshot, &pe32); } return dwProcessId; } BOOL CreateRemoteThreadInjectDll(const wchar_t *pszProcessName, wchar_t *pszDllFileName) { HANDLE hProcess = NULL; DWORD dwProcessId = 0; SIZE_T dwSize = 0; LPVOID pDllAddr = NULL; FARPROC pFuncProcAddr = NULL; dwProcessId = GetProcessIdByProcessName(pszProcessName); if (dwProcessId <= 0) { return FALSE; } hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if (hProcess == NULL) { ShowError(L"OpenProcess"); return FALSE; } // lstrlen restituisce il numero di caratteri (meno quello nullo finale) // ma a noi interessa il numero di byte da allocare // ricordando che ogni wchar_t è 2 byte dwSize = 1 + lstrlen(pszDllFileName) * 2; pDllAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); if (pDllAddr == NULL) { ShowError(L"VirtualAllocEx"); return FALSE; } if (WriteProcessMemory(hProcess, pDllAddr, pszDllFileName, dwSize, NULL) == FALSE) { ShowError(L"WriteProcessMemory"); return FALSE; } pFuncProcAddr = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW"); if (pFuncProcAddr == NULL) { ShowError(L"GetProcAddress_LoadLibraryW"); return FALSE; } HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0, NULL); if (hRemoteThread == NULL) { ShowError(L"CreateRemoteThread"); return FALSE; } CloseHandle(hProcess); return TRUE; }
Codice Sorgente:
RemoteThread_Injection
Riferimenti:
[1] Windows Via C/C++ - Richter, Nasarre
[2] Taking a Snapshot and Viewing Processes
[3] https://github.com/DemonGan/Windows-Hack-Programming
Nessun commento:
Posta un commento