Всем привет. В общем сразу скажу гуглил-шмуглил, ничего не нагуглил. Есть ф-ия, которая должна загружать dll в адресное пространство другого процесса. Код (Text): BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile) { BOOL fOk = FALSE; HANDLE hProcess = NULL, hThread = NULL; PWSTR pszLibFileRemote = NULL; try { hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, false, dwProcessId); if (hProcess == NULL) throw false; int cb = (1 + lstrlenW(pszLibFile)) * sizeof(WCHAR); pszLibFileRemote = (PWSTR)VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE); if (pszLibFileRemote == NULL) throw false; if ( !WriteProcessMemory(hProcess, pszLibFileRemote, pszLibFile, cb, NULL) ) throw false; LPTHREAD_START_ROUTINE pfnThreadRtn = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW"); if (pfnThreadRtn == NULL) throw false; hThread = CreateRemoteThread(hProcess, NULL, NULL, pfnThreadRtn, pszLibFileRemote, 0, NULL); printf("Error = %i\n", GetLastError()); if (hThread == NULL) throw false; WaitForSingleObject(hThread, INFINITE); fOk = TRUE; } catch( bool ) { if (pszLibFileRemote != NULL) VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE); if (hThread != NULL) CloseHandle(hThread); if (hProcess != NULL) CloseHandle(hProcess); } return(fOk); } Она работает на ХР 32, но отказывается на 7 х64. Проблема в CreateRemoteThread, ошибка ERROR_ACCESS_DENIED, пробовал с PROCESS_ALL_ACCESS - тоже самое, пробовал DEP отрубать - ничего не изменилось... в общем я склоняюсь к тому, что какая-то служба мешает... или какая-то фишка... помогите плз ) OS: Win 7 6.1.7600
для начала ответьте на вопросы: из какого процесса в какой? из x86 в x64 или из x64 в х64? не имеют ли процессы разный integrity level? установлены ли на машине какие-нить средства безопасности?
Стоит КИС 2010, отрубал, так же. У блокнота и инжектора "Обязательная метка\Высокий обязательный уровень" выставлен в integrity. x86 -> x64 (если блокнот x64), да и из х86 -> х86 тоже не пашет ( Где-то на XX странице гугла прочитал, что адрес ф-ии в моём и чужом пространстве может отличатся (http://www.gamedev.net/community/forums/topic.asp?topic_id=432792&whichpage=1�) Код (Text): void InjectCode() { int (*load)(LPCWSTR lpLibFileName); (FARPROC&) load = GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW"); load(L"test_dll.dll"); return; } ... pszLibFileRemote = (LPTHREAD_START_ROUTINE)VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_EXECUTE_READWRITE); ... if ( !WriteProcessMemory(hProcess, pszLibFileRemote, InjectCode, 0x20, NULL) ) throw false; 0х20 - под отладкой посмотрел, в любом случае код должен выполнятся и заканчиватся ошибкой в случае обрезки ф-ии. Но этого непроисходит - все та же ошибка ERROR_ACCESS_DENIED.
Позволю себе процитировать (http://lhc645.wordpress.com/) "Краткая справка. Механизм ASLR – Address Space Layout Randomization (случайное расположение в адресном пространстве) появился впервые в XP и затрагивал PEB и TEB only. Начиная с Vista сабж уже стал применяться к базам загрузки исполняемых файлов и длл (в частности системных ntdll, kernel32 etc), а также к стеку и куче." Вам надо определить расположение (базовый адрес загрузки) Kernel32 в целевом процессе, используя связку Module32First - Module32Next.
можно ещё найти через PEB базовый адрес kernel32 и прибавить смещение функции от базового адреса (смещение найти в своем процессе)...
Про ALSR слышал, посмотрите код, что выше, он должен ведь выполнятся в целевом процессе, вызывается GetProcAddress(), а потом LoadLibrary(), только стринги надо еще копировать ), а так код должен работать поидее, и не надо высчитывать разные смещения... или я что-то не так понял. Но проблема немного в другом, проблема в том что CreateRemoteThread возвращает ERROR_ACCESS_DENIED, а CreateRemoteThreadEx которая появилась в 7-ке использовать не охото..
Применяться-то он стал, но только именно к (первой) загрузке dll в память, а не к маппингу уже загруженных dll в разные процессы по разным адресам (см.Inside... Руссиновича. Соотв-но базовые адреса сис. dll м.б. различны в разных сессиях, но в пределах одной сессии для всех процессов они по прежнему одинаковы (иначе бы это был пипец производительности из-за постоянных релоков). Поэтому нельзя жестко прошивать адреса ф-й в проге, а определять их в своем процессе и юзать в другом - можно, пока... PS: Да и потом, стоит ли "растекаться мыслью по древу", если в данном случае CreateRemoteThread валится с конкретной ошибкой ACCESS_DENIED, что недвысмысленно указывает на недостаток прав\привелегий. Может для начала все необходимые права задать в OpenProcess, перечисленные в msdn для CreateRemoteThread ?
Вот рабочий код: Код (Text): #define _WIN32_WINNT 0x500 #include <windows.h> #include <tlhelp32.h> #include <tchar.h> BOOL AdjustDebugPrivilege(void) { HANDLE hToken; BOOL bRet = FALSE; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) { LUID luid; if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { TOKEN_PRIVILEGES tp; tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; tp.Privileges[0].Luid = luid; if (AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL) && GetLastError() != ERROR_NOT_ALL_ASSIGNED) { bRet = TRUE; } } CloseHandle(hToken); } return bRet; } DWORD GetProcessIdByName(LPCTSTR lpszProcessName) { HANDLE hSnapshot; DWORD dwProcessId = 0; hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot) { PROCESSENTRY32 pe = {sizeof(PROCESSENTRY32)}; if (Process32First(hSnapshot, &pe)) { do { if (_tcscmp(pe.szExeFile, lpszProcessName) == 0) { dwProcessId = pe.th32ProcessID; break; } } while (Process32Next(hSnapshot, &pe)); } CloseHandle(hSnapshot); } return dwProcessId; } HMODULE RemoteLoadLibrary(DWORD dwProcessId, LPCTSTR lpszLibName) { HANDLE hProcess; HMODULE hLib = NULL; hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, dwProcessId); if (hProcess) { HANDLE hThread; SIZE_T dwBytesToWrite; SIZE_T dwBytesWritten; LPVOID lpszRemoteLibName; dwBytesToWrite = (_tcslen(lpszLibName)+1)*sizeof(TCHAR); lpszRemoteLibName = VirtualAllocEx(hProcess, NULL, dwBytesToWrite, MEM_COMMIT, PAGE_READWRITE); if (lpszRemoteLibName) { if (WriteProcessMemory(hProcess, lpszRemoteLibName, lpszLibName, dwBytesToWrite, &dwBytesWritten) && dwBytesWritten == dwBytesToWrite) { hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, lpszRemoteLibName, 0, NULL); if (hThread) { if (WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0) { GetExitCodeThread(hThread, (LPDWORD)&hLib); } CloseHandle(hThread); } } VirtualFreeEx(hProcess, lpszRemoteLibName, 0, MEM_RELEASE); } CloseHandle(hProcess); } return hLib; } BOOL RemoteFreeLibrary(DWORD dwProcessId, HMODULE hLib) { HANDLE hProcess; BOOL bRet = FALSE; hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, dwProcessId); if (hProcess) { HANDLE hThread; hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, hLib, 0, NULL); if (hThread) { if (WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0) { GetExitCodeThread(hThread, (LPDWORD)&bRet); } CloseHandle(hThread); } CloseHandle(hProcess); } return bRet; } int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpszCmdLine, int nCmdShow) { TCHAR szLibName[MAX_PATH]; DWORD dwProcessId; HMODULE hLib; AdjustDebugPrivilege(); dwProcessId = GetProcessIdByName(TEXT("explorer.exe")); GetModuleFileName(NULL, szLibName, MAX_PATH); *_tcsrchr(szLibName, '\\') = '\0'; _tcscat_s(szLibName, MAX_PATH, __T("\\Hook.dll")); hLib = RemoteLoadLibrary(dwProcessId, szLibName); if (hLib) { MessageBox(0, 0, 0, 0); RemoteFreeLibrary(dwProcessId, hLib); } return 0; }
lobzik На семерке не пробовал, на висте x64 работало, сейчас не могу проверить, т.к. вернул 32хбитную.
Все права и привилегии есть. Ну не может же быть такого, что бы в 7ке CreateRemouteThread не работал совсем, как же тогда совместимость (которую я тоже кстати тыкал, эффекта не дало).
lobzik Ваша функа это не чёрный ящик. Что в ней возвращает ошибку ? Сервис какой и какой статус ? Уже стопяцот раз говорил за неделю чтобы не юзали винапишные коды ошибок. Если у вас стек не выравнен, то я уж и не знаю тогда что сказать..
Clerk Да вроде на С человек пишет, вряд ли. ЗЫ Почему бы не собрать статьи в пачку и не выложить на wasm.ru? Сложно искать их по всему форуму, indy-vx.narod.ru как там и написано, лог, а не сайт.
а вы уверены что процесс в который вы делайте инжект запущен в той же сессии что и вы? нужно сравнивать еще и sessionid процесса со своим если юзайте такой инжект.
Это очень вряд ли, как сказал Билли, обратная совместимость превыше всего. Косяки в моем коде могуть быть с GetExitCodeThread который возвращает DWORD, а на x64 HMODULE - 64битная величина(?), но до этого момента всё вроде должно быть нормально...