CreateRemoteThread

Тема в разделе "WASM.WIN32", создана пользователем lobzik, 20 май 2010.

  1. lobzik

    lobzik New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2009
    Сообщения:
    34
    Всем привет.

    В общем сразу скажу гуглил-шмуглил, ничего не нагуглил.
    Есть ф-ия, которая должна загружать dll в адресное пространство другого процесса.

    Код (Text):
    1. BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile) {
    2.  
    3.    BOOL fOk = FALSE;
    4.    HANDLE hProcess = NULL, hThread = NULL;
    5.    PWSTR pszLibFileRemote = NULL;
    6.  
    7.    try {
    8.  
    9.        hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, false, dwProcessId);
    10.       if (hProcess == NULL)
    11.           throw false;
    12.  
    13.       int cb = (1 + lstrlenW(pszLibFile)) * sizeof(WCHAR);
    14.  
    15.       pszLibFileRemote = (PWSTR)VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
    16.       if (pszLibFileRemote == NULL)
    17.           throw false;
    18.  
    19.       if ( !WriteProcessMemory(hProcess, pszLibFileRemote, pszLibFile, cb, NULL) )
    20.           throw false;
    21.  
    22.       LPTHREAD_START_ROUTINE pfnThreadRtn = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
    23.       if (pfnThreadRtn == NULL)
    24.           throw false;
    25.  
    26.       hThread = CreateRemoteThread(hProcess, NULL, NULL, pfnThreadRtn, pszLibFileRemote, 0, NULL);
    27.       printf("Error = %i\n", GetLastError());
    28.       if (hThread == NULL)
    29.           throw false;
    30.  
    31.       WaitForSingleObject(hThread, INFINITE);
    32.  
    33.       fOk = TRUE;
    34.    }
    35.    catch( bool ) {
    36.  
    37.       if (pszLibFileRemote != NULL)
    38.          VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);
    39.  
    40.       if (hThread  != NULL)
    41.          CloseHandle(hThread);
    42.  
    43.       if (hProcess != NULL)
    44.          CloseHandle(hProcess);
    45.    }
    46.  
    47.    return(fOk);
    48. }
    Она работает на ХР 32, но отказывается на 7 х64. Проблема в CreateRemoteThread, ошибка ERROR_ACCESS_DENIED, пробовал с PROCESS_ALL_ACCESS - тоже самое, пробовал DEP отрубать - ничего не изменилось... в общем я склоняюсь к тому, что какая-то служба мешает... или какая-то фишка... помогите плз )

    OS: Win 7 6.1.7600
     
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    для начала ответьте на вопросы: из какого процесса в какой? из x86 в x64 или из x64 в х64? не имеют ли процессы разный integrity level? установлены ли на машине какие-нить средства безопасности?
     
  3. lobzik

    lobzik New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2009
    Сообщения:
    34
    Стоит КИС 2010, отрубал, так же.
    У блокнота и инжектора "Обязательная метка\Высокий обязательный уровень" выставлен в integrity.
    x86 -> x64 (если блокнот x64), да и из х86 -> х86 тоже не пашет (

    Где-то на XX странице гугла прочитал, что адрес ф-ии в моём и чужом пространстве может отличатся (http://www.gamedev.net/community/forums/topic.asp?topic_id=432792&whichpage=1&#2878776)

    Код (Text):
    1. void InjectCode()
    2. {
    3.     int (*load)(LPCWSTR lpLibFileName);
    4.  
    5.     (FARPROC&) load = GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
    6.     load(L"test_dll.dll");
    7.  
    8.     return;
    9. }
    10. ...
    11.       pszLibFileRemote = (LPTHREAD_START_ROUTINE)VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    12. ...
    13.       if ( !WriteProcessMemory(hProcess, pszLibFileRemote, InjectCode, 0x20, NULL) )
    14.           throw false;
    0х20 - под отладкой посмотрел, в любом случае код должен выполнятся и заканчиватся ошибкой в случае обрезки ф-ии. Но этого непроисходит - все та же ошибка ERROR_ACCESS_DENIED.
     
  4. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    Позволю себе процитировать (http://lhc645.wordpress.com/)
    "Краткая справка. Механизм ASLR – Address Space Layout Randomization (случайное расположение в адресном пространстве) появился впервые в XP и затрагивал PEB и TEB only. Начиная с Vista сабж уже стал применяться к базам загрузки исполняемых файлов и длл (в частности системных ntdll, kernel32 etc), а также к стеку и куче."
    Вам надо определить расположение (базовый адрес загрузки) Kernel32 в целевом процессе, используя связку Module32First - Module32Next.
     
  5. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    можно ещё найти через PEB базовый адрес kernel32 и прибавить смещение функции от базового адреса (смещение найти в своем процессе)...
     
  6. lhc645

    lhc645 New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2009
    Сообщения:
    106
    Ага, учитывая, что в 32-битном процессе одна kernel32.dll (wow), а в 64-битном другая.
     
  7. lobzik

    lobzik New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2009
    Сообщения:
    34
    Про ALSR слышал, посмотрите код, что выше, он должен ведь выполнятся в целевом процессе, вызывается GetProcAddress(), а потом LoadLibrary(), только стринги надо еще копировать ), а так код должен работать поидее, и не надо высчитывать разные смещения... или я что-то не так понял.

    Но проблема немного в другом, проблема в том что CreateRemoteThread возвращает ERROR_ACCESS_DENIED, а CreateRemoteThreadEx которая появилась в 7-ке использовать не охото..
     
  8. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Применяться-то он стал, но только именно к (первой) загрузке dll в память, а не к маппингу уже загруженных dll в разные процессы по разным адресам (см.Inside... Руссиновича. Соотв-но базовые адреса сис. dll м.б. различны в разных сессиях, но в пределах одной сессии для всех процессов они по прежнему одинаковы (иначе бы это был пипец производительности из-за постоянных релоков).
    Поэтому нельзя жестко прошивать адреса ф-й в проге, а определять их в своем процессе и юзать в другом - можно, пока... :)
    PS:

    Да и потом, стоит ли "растекаться мыслью по древу", если в данном случае CreateRemoteThread валится с конкретной ошибкой ACCESS_DENIED, что недвысмысленно указывает на недостаток прав\привелегий. Может для начала все необходимые права задать в OpenProcess, перечисленные в msdn для CreateRemoteThread ?
     
  9. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    +Установка привилегии SeDebugPrivilege
     
  10. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Вот рабочий код:
    Код (Text):
    1. #define _WIN32_WINNT 0x500
    2. #include <windows.h>
    3. #include <tlhelp32.h>
    4. #include <tchar.h>
    5.  
    6. BOOL AdjustDebugPrivilege(void)
    7. {
    8.     HANDLE  hToken;
    9.     BOOL    bRet = FALSE;
    10.     if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
    11.     {
    12.         LUID    luid;
    13.         if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
    14.         {
    15.             TOKEN_PRIVILEGES    tp;
    16.             tp.PrivilegeCount = 1;
    17.             tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    18.             tp.Privileges[0].Luid = luid;
    19.             if (AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL)
    20.                 && GetLastError() != ERROR_NOT_ALL_ASSIGNED)
    21.             {
    22.                 bRet = TRUE;
    23.             }
    24.         }
    25.         CloseHandle(hToken);
    26.     }
    27.     return bRet;
    28. }
    29.  
    30. DWORD GetProcessIdByName(LPCTSTR lpszProcessName)
    31. {
    32.     HANDLE hSnapshot;
    33.     DWORD dwProcessId = 0;
    34.  
    35.     hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    36.     if (hSnapshot)
    37.     {
    38.         PROCESSENTRY32 pe = {sizeof(PROCESSENTRY32)};
    39.         if (Process32First(hSnapshot, &pe))
    40.         {
    41.             do {
    42.                 if (_tcscmp(pe.szExeFile, lpszProcessName) == 0)
    43.                 {
    44.                     dwProcessId = pe.th32ProcessID;
    45.                     break;
    46.                 }
    47.             } while (Process32Next(hSnapshot, &pe));
    48.         }
    49.         CloseHandle(hSnapshot);
    50.     }
    51.     return dwProcessId;
    52. }
    53.  
    54. HMODULE RemoteLoadLibrary(DWORD dwProcessId, LPCTSTR lpszLibName)
    55. {
    56.     HANDLE  hProcess;
    57.     HMODULE hLib = NULL;
    58.  
    59.     hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
    60.         FALSE, dwProcessId);
    61.     if (hProcess)
    62.     {
    63.         HANDLE  hThread;
    64.         SIZE_T  dwBytesToWrite;
    65.         SIZE_T  dwBytesWritten;
    66.         LPVOID  lpszRemoteLibName;
    67.  
    68.         dwBytesToWrite = (_tcslen(lpszLibName)+1)*sizeof(TCHAR);
    69.  
    70.         lpszRemoteLibName = VirtualAllocEx(hProcess, NULL, dwBytesToWrite, MEM_COMMIT, PAGE_READWRITE);
    71.         if (lpszRemoteLibName)
    72.         {
    73.             if (WriteProcessMemory(hProcess, lpszRemoteLibName, lpszLibName, dwBytesToWrite, &dwBytesWritten)
    74.                 && dwBytesWritten == dwBytesToWrite)
    75.             {
    76.                 hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, lpszRemoteLibName, 0, NULL);
    77.                 if (hThread)
    78.                 {
    79.                     if (WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0)
    80.                     {
    81.                         GetExitCodeThread(hThread, (LPDWORD)&hLib);
    82.                     }
    83.                     CloseHandle(hThread);
    84.                 }
    85.             }
    86.             VirtualFreeEx(hProcess, lpszRemoteLibName, 0, MEM_RELEASE);
    87.         }
    88.         CloseHandle(hProcess);
    89.     }
    90.     return hLib;
    91. }
    92.  
    93. BOOL RemoteFreeLibrary(DWORD dwProcessId, HMODULE hLib)
    94. {
    95.     HANDLE  hProcess;
    96.     BOOL    bRet = FALSE;
    97.  
    98.     hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
    99.         FALSE, dwProcessId);
    100.     if (hProcess)
    101.     {
    102.         HANDLE  hThread;
    103.  
    104.         hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, hLib, 0, NULL);
    105.         if (hThread)
    106.         {
    107.             if (WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0)
    108.             {
    109.                 GetExitCodeThread(hThread, (LPDWORD)&bRet);
    110.             }
    111.             CloseHandle(hThread);
    112.         }
    113.         CloseHandle(hProcess);
    114.     }
    115.     return bRet;
    116. }
    117.  
    118.  
    119. int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpszCmdLine, int nCmdShow)
    120. {
    121.     TCHAR szLibName[MAX_PATH];
    122.     DWORD   dwProcessId;
    123.     HMODULE hLib;
    124.  
    125.     AdjustDebugPrivilege();
    126.     dwProcessId = GetProcessIdByName(TEXT("explorer.exe"));
    127.  
    128.     GetModuleFileName(NULL, szLibName, MAX_PATH);
    129.     *_tcsrchr(szLibName, '\\') = '\0';
    130.     _tcscat_s(szLibName, MAX_PATH, __T("\\Hook.dll"));
    131.  
    132.     hLib = RemoteLoadLibrary(dwProcessId, szLibName);
    133.     if (hLib)
    134.     {
    135.         MessageBox(0, 0, 0, 0);
    136.         RemoteFreeLibrary(dwProcessId, hLib);
    137.     }
    138.  
    139.     return 0;
    140. }
     
  11. lobzik

    lobzik New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2009
    Сообщения:
    34
    KeSqueer, спасибо за код, но ошибка осталась(, у Вас на 7ке х64 работает ? какая сборка ?
     
  12. lobzik

    lobzik New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2009
    Сообщения:
    34
    Запускаю от Админа само собой.
     
  13. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    lobzik
    На семерке не пробовал, на висте x64 работало, сейчас не могу проверить, т.к. вернул 32хбитную.
     
  14. lobzik

    lobzik New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2009
    Сообщения:
    34
    Все права и привилегии есть.

    Ну не может же быть такого, что бы в 7ке CreateRemouteThread не работал совсем, как же тогда совместимость (которую я тоже кстати тыкал, эффекта не дало).
     
  15. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    lobzik
    Ваша функа это не чёрный ящик. Что в ней возвращает ошибку ?
    Сервис какой и какой статус ?
    Уже стопяцот раз говорил за неделю чтобы не юзали винапишные коды ошибок. Если у вас стек не выравнен, то я уж и не знаю тогда что сказать..
     
  16. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Clerk
    Да вроде на С человек пишет, вряд ли.
    ЗЫ
    Почему бы не собрать статьи в пачку и не выложить на wasm.ru? Сложно искать их по всему форуму, indy-vx.narod.ru как там и написано, лог, а не сайт.
     
  17. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    KeSqueer
    Так мб в 7'ке ссылка на TID не опциональный параметр.
     
  18. freeq

    freeq New Member

    Публикаций:
    0
    Регистрация:
    2 дек 2008
    Сообщения:
    47
    а вы уверены что процесс в который вы делайте инжект запущен в той же сессии что и вы?
    нужно сравнивать еще и sessionid процесса со своим если юзайте такой инжект.
     
  19. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Это очень вряд ли, как сказал Билли, обратная совместимость превыше всего.
    Косяки в моем коде могуть быть с GetExitCodeThread который возвращает DWORD, а на x64 HMODULE - 64битная величина(?), но до этого момента всё вроде должно быть нормально...
     
  20. lobzik

    lobzik New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2009
    Сообщения:
    34
    freeq
    А как её узнать?