проблемы с грубым инжектированием кода в чужой процесс

Тема в разделе "WASM.WIN32", создана пользователем Arisu, 19 авг 2007.

  1. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    Вобщем осваиваю сейчас это полезное дело. Пока что всё дубово, но и оно не работает почему-то.

    Проблема в том, что после вызова CreateRemoteThread целевое приложение выполняет недопустимую операцию и доблесно самоуничтожается. В чём проблема??? я не могу разобратся. Подскажите хотябы в каком направлении смотреть.

    Вот код:
    Код (Text):
    1. /*----------------------------------------------------------------------*/
    2. /*---- RAM Section -----------------------------------------------------*/
    3. /*----------------------------------------------------------------------*/
    4. DWORD (WINAPI *InjectedCodePtr)(LPVOID);
    5. /*----------------------------------------------------------------------*/
    6.  
    7. /*----------------------------------------------------------------------*/
    8. /*---- Functions -------------------------------------------------------*/
    9. /*----------------------------------------------------------------------*/
    10.  
    11. /*------------------------------------------------------------------*/
    12.     BYTE *PreyMem;
    13.    
    14.     DWORD BytesWritten;
    15.     DWORD InjectedThrID;
    16.     DWORD PreyProcID;
    17.    
    18.     HANDLE Prey;
    19.     HANDLE InjectedThr;
    20.    
    21.         PreyProcID = GetProcessID( "him.exe" );
    22.    
    23.         Prey = OpenProcess( PROCESS_ALL_ACCESS, 0, PreyProcID );
    24.         if ( Prey == INVALID_HANDLE_VALUE ) {
    25.             MessageBox( NULL, "invalid prey handle", "", MB_OK );
    26.             return 0;
    27.         }
    28.        
    29.         PreyMem = VirtualAllocEx( Prey, NULL, 128,
    30.                               MEM_COMMIT | MEM_RESERVE,
    31.                               PAGE_EXECUTE_READWRITE );
    32.         if ( PreyMem == NULL ) {
    33.             MessageBox( NULL, "invalid prey mem pointer", "", MB_OK );
    34.             return 0;
    35.         }
    36.        
    37.         InjectedCodePtr = &InjectedCode;
    38.        
    39.         if ( 0 == WriteProcessMemory( Prey, PreyMem, InjectedCodePtr,
    40.                                       64, &BytesWritten ) ) {
    41.             MessageBox( NULL, "write proc mem fail", "", MB_OK );
    42.             return 0;
    43.         }
    44.        
    45.         InjectedThr = CreateRemoteThread( Prey, NULL, 0, (DWORD (__stdcall *)(VOID *))PreyMem,
    46.                                       NULL, 0, &InjectedThrID );
    47.         if ( InjectedThr == INVALID_HANDLE_VALUE ) {
    48.             MessageBox( NULL, "create rem thr fail", "", MB_OK );
    49.             return 0;
    50.         }
    51.        
    52.         return 0; //bye bye
    53. } /*----------------------------------------------------------------*/
    54.  
    55. /*------------------------------------------------------------------*/
    56. DWORD WINAPI InjectedCode( VOID *Param )
    57. {
    58.         MessageBox( NULL, "Hello", "", MB_OK );
    59.         ExitThread( 0 );
    60.        
    61.         return 0;
    62. } /*----------------------------------------------------------------*/
     
  2. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Текстовые строки, вроде "Hello", тоже нужно инжектировать. Ведь адрес "Hello" в целевом процессе не будет указывать в адресное пространство исходного. Такие вещи вообще удобно разбирать под отладчиком.
     
  3. Cr4sh

    Cr4sh New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2006
    Сообщения:
    668
    ужс... читай доки по структуре исполняемого файла, в твоём случае нужно инжектить весь образ полностью, т.к. текстовая строка находится в секции инициализированых данных
     
  4. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    а.. начинаю понимать.
     
  5. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    ладно. я попробовал передать нужные мне параметры с помощью изменения контекста потока. Но это всё равно приводит к ошибке! хотя адрес функции messagebox в целевом процессе должен быть тотже.

    вот код

    Код (Text):
    1. //предыдуший код выше с той разницей лишь, что поток создаётся в подвешенном состоянии
    2.  
    3. Context.ContextFlags = CONTEXT_FULL;
    4.         if ( 0 == GetThreadContext( InjectedThr, &Context ) ) {
    5.             MessageBox( NULL, "get thr context fail", "", MB_OK );
    6.             return 0;
    7.         }
    8.        
    9.         Context.Eax = 0;
    10.         Context.Ebx = 0;
    11.         Context.Ecx = 0;
    12.         Context.Edx = MB_OK;
    13.         Context.Esi = (DWORD)MessageBoxPtr; //указатель на функцию.
    14.        
    15.         if ( 0 == SetThreadContext( InjectedThr, &Context ) ) {
    16.             MessageBox( NULL, "set thr context fail", "", MB_OK );
    17.             return 0;
    18.         }
    19.  
    20. //запускаю поток тут. и получаю ошибку
    21.  
    22. /*------------------------------------------------------------------*/
    23. DWORD WINAPI InjectedCode( VOID *Param )
    24. {
    25.         __asm {
    26.             push eax // handle
    27.             push ebx // text
    28.             push edx // captino
    29.             push ecx // mb_ok
    30.             call esi // messagebox
    31.         }
    32.        
    33.         return 0;
    34. } /*----------------------------------------------------------------*/
    но всё равно недопустимая операция.
     
  6. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Какой?
     
  7. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    инструкция по адресу 0х0 обратилась к памяти по адресу 0х0 . память не может быть read

    ошибка вылезает от имени целевого приложения, после чего оно скоропостижно умерает.

    PS
    странно однако. сейчас получилось инжектироватся в Сапёра ))). он конечно не пережил этого, но моё окно показал. Но почему же тогда не получается инжектироватся в мою прогу для тестов?? =\
     
  8. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    конфликт адресов?
     
  9. dead_body

    dead_body wasm.ru

    Публикаций:
    0
    Регистрация:
    3 сен 2004
    Сообщения:
    603
    Адрес:
    Украина;г.Харьков;г.Н.Каховка
    Arisu
    адреса функций могут оличаться. сталкивался с такой проблемой.
    Почему так и не нашел. База загрузки - одинаковая - адреса разные. Хотя в теории так не должно быть. Перепиши взятие адресов.

    и у меня были клюки с установкой еах,адх,есх.
    На моем компе в удаленном потоке, они категорически не хотели ставиться.
    Попробуй заменить на еди,еси.

    в асм вставке влепи инт3 и глянь, что к чему. ;)
     
  10. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    RTL передача параметров. ибо stdcall. запуш в другой последовательности.

    [эдитЪ]
    да вообще
    пишем так, а пушим ecx... повнимательнее.
     
  11. int2eh

    int2eh Alexander Leevy

    Публикаций:
    0
    Регистрация:
    19 авг 2007
    Сообщения:
    106
    Адрес:
    Москва
    Arisu
    Лучше так (без пролога и эпилога InjectedCode)
    Код (Text):
    1. __declspec (naked) InjectedCode()
    2. {
    3.     __asm{
    4.         mov esi, [esp+4] //pParam
    5.  
    6.         push 0
    7.         lea esi, Msg
    8.         push esi
    9.         push esi
    10.         push 0
    11.         lea esi, MsgBox
    12.         call [esi] //вызываю MessageBox
    13.  
    14.         retn 4
    15. Msg:
    16.         _emit 'O'
    17.         _emit 'k'
    18.         _emit 0x00
    19. MsgBox:
    20.         _emit 0xF2
    21.         _emit 0x04
    22.         _emit 0xD7
    23.         _emit 0x77
    24.     }
    25. }
    И ошибка была по-моему в этом - неправильные смещения были у переменных и адреса ф-ции.
     
  12. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    хм. спасибо )) да моя невнемательность меня погубит.

    int2eh а так не выйдет. яж хотел в 16 байт уложится.
     
  13. int2eh

    int2eh Alexander Leevy

    Публикаций:
    0
    Регистрация:
    19 авг 2007
    Сообщения:
    106
    Адрес:
    Москва
    Это хорошо. Но дело в том, что когда пишешь вызов функции (на С++), то тогда компилятор вставляет примерно такой код:

    Код (Text):
    1. push ля-ля
    2. push жу-жу
    3. call [__imp_Proc] //т.е. адрес ф-ции берет из секции импорта
    но ведь ты же этот код внедряешь в другой процесс и поэтому адрес переменной __imp_Proc там может быть (даже должен быть!) другой и вот - эксцептион, - ERROR!!!

    Когда создаешь ремоте поток лучше в ThreadProc передавать адрес GetProcAddress(), затем ты сможешь вычислить HMODULE kernel32.dll

    Код (Text):
    1. HMODULE WINAPI GetDllBase(ULONG AnyProcFromThisDll)
    2. {
    3.     HMODULE hDll = (HMODULE)AnyProcFromThisDll;
    4.     hDll = HMODULE((ULONG)hDll & 0xFFFF0000);
    5.    
    6.     while(*(WORD*)hDll != 0x5A4D)//ищу сигнатуру "MZ"
    7.         hDll -= 0x10000;   
    8.  
    9.     return hDll;
    10. }
    11.  
    12. HMODULE hKernel32Dll = GetDllBase(GetProcAddress)
    И вот теперь можешь узнать адрес LoadLibrary, = GetProcAddress(hKernel32Dll, "LoadLibraryA")
    Всё! Теперь у тебя есть LoadLibrary и GetProcAddress - можно делать что хочешь.
     
  14. wertyman

    wertyman Member

    Публикаций:
    0
    Регистрация:
    13 дек 2006
    Сообщения:
    74
    Извените, что вклиниваюсь.
    Я не очень понимаю принцип работы с изменением контекста потока, потому вопрос. Возможно ли через изменение контекста потока вызвать только функцию загрузки длл ? Ничего лишнего не писать, а лишь в выделеную память в удаленом процессе записать путь к длл, и вызвать функцию LoadLibrary с этим параметром ? Наверное это будет невозможно...
    Код (Text):
    1.     HANDLE z = CreateRemoteThread(hProcess, NULL, 0, (unsigned long (__stdcall *)(void *))GetProcAddress( hKernel, "LoadLibraryA"), (VOID*)p_code, 0, &id);
     
  15. int2eh

    int2eh Alexander Leevy

    Публикаций:
    0
    Регистрация:
    19 авг 2007
    Сообщения:
    106
    Адрес:
    Москва
    Конечно, можно. Дядька Рихтер такое делать предлагал в своей книжке.
    Смотрите аттач
     
  16. wertyman

    wertyman Member

    Публикаций:
    0
    Регистрация:
    13 дек 2006
    Сообщения:
    74
    Спасибо. Я не правильно сказал..
    Я как раз таки сейчас делаю именно так. А мне нужно через изменение контекста потока, подобным же образом.. Чтобы не писать кучу кода в процесс, записать только путь к длл и вызвать LoadLibrary.
     
  17. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    контекст позволяет менять только регистры потока по моему и иногда ещё какие-то переменные (в зависимости от системы). так что врятли

    можешь сделать как у меня - в своём процессе записать в геристры параметры для функции
    а в запущенном потоке положить их в стек и вызвать функцию
     
  18. int2eh

    int2eh Alexander Leevy

    Публикаций:
    0
    Регистрация:
    19 авг 2007
    Сообщения:
    106
    Адрес:
    Москва
    wertyman
    http://www.wasm.ru/article.php?article=apihook_2

    там в конце статьи
     
  19. tylerdurden

    tylerdurden New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2004
    Сообщения:
    322
    Код (Text):
    1. PVOID WriteRemoteMemory(HANDLE hProcess,PVOID pvMemory,SIZE_T stSize)
    2. {
    3.     PVOID pvRemoteMemory=0;
    4.  
    5.     pvRemoteMemory=VirtualAllocEx(hProcess,0,stSize,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE);
    6.     if(pvRemoteMemory==0)
    7.     {
    8.         return 0;
    9.     }
    10.     if(!WriteProcessMemory(hProcess,pvRemoteMemory,pvMemory,stSize,0))
    11.     {
    12.         return 0;
    13.     }
    14.     return pvRemoteMemory;
    15. }
    16.  
    17. DWORD ThreadRoutine(THREADPARAM *tpParam)
    18. {
    19.     HANDLE hDll;
    20.  
    21.     tpParam->pLdrLoadDll(0,0,&tpParam->usDllName,&hDll);
    22.     tpParam->pNtTerminateThread((HANDLE)-2,0);
    23.     return 0;
    24. }
    25.  
    26. VOID ThreadDummy()
    27. {
    28.     return;
    29. }
    30.  
    31. HANDLE InjectThread(HANDLE hProcess,LPTHREAD_START_ROUTINE pvAddress,PVOID pvParam)
    32. {
    33.     HANDLE hRemoteThread=0;
    34.     CLIENT_ID cidClient;
    35.  
    36.     RtlCreateUserThread(hProcess,0,FALSE,0,0,0,pvAddress,pvParam,&hRemoteThread,&cidClient);   
    37.     return hRemoteThread;
    38. }
    39.  
    40. BOOL InjectDll(HANDLE hProcess, LPCSTR szDllName)
    41. {
    42.     LPVOID pvDllName;
    43.     LPVOID pvThreadParam;
    44.     LPVOID pvThreadRoutine;
    45.     HANDLE hRemoteThread;
    46.     THREADPARAM tpParam;
    47.     WCHAR wcDllName[MAX_PATH];
    48.     USHORT dwSize;
    49.  
    50.     dwSize=MultiByteToWideChar(CP_ACP,0,szDllName,-1,wcDllName,sizeof(wcDllName));
    51.     if(dwSize==0)
    52.     {
    53.         return FALSE;
    54.     }
    55.     pvDllName=WriteRemoteMemory(hProcess,(PVOID)wcDllName,dwSize*sizeof(WCHAR));
    56.     if(pvDllName==0)
    57.     {
    58.         return FALSE;
    59.     }
    60.     tpParam.usDllName.Buffer=(PWSTR)pvDllName;
    61.     tpParam.usDllName.Length=dwSize*sizeof(WCHAR);
    62.     tpParam.usDllName.MaximumLength=(dwSize+1)*sizeof(WCHAR);
    63.     tpParam.pLdrLoadDll=(PLDRLOADDLL)LdrLoadDll;
    64.     tpParam.pNtTerminateThread=(PNTTERMINATETHREAD)NtTerminateThread;
    65.     pvThreadParam=WriteRemoteMemory(hProcess,(PVOID)&tpParam,sizeof(tpParam));
    66.     if(pvThreadParam==0)
    67.     {
    68.         return FALSE;
    69.     }
    70.     pvThreadRoutine=WriteRemoteMemory(hProcess,(PVOID)ThreadRoutine,(DWORD_PTR)ThreadDummy-(DWORD_PTR)ThreadRoutine);
    71.     if(pvThreadRoutine==0)
    72.     {
    73.         return FALSE;
    74.     }
    75.     hRemoteThread=InjectThread(hProcess,(LPTHREAD_START_ROUTINE)pvThreadRoutine,pvThreadParam);
    76.     if(hRemoteThread==0)
    77.     {
    78.         return FALSE;
    79.     }
    80.     WaitForSingleObject(hRemoteThread,INFINITE);
    81.     CloseHandle(hRemoteThread);
    82.     VirtualFreeEx(hProcess,pvDllName,0,MEM_DECOMMIT|MEM_RELEASE);
    83.     VirtualFreeEx(hProcess,pvThreadParam,0,MEM_DECOMMIT|MEM_RELEASE);
    84.     VirtualFreeEx(hProcess,pvThreadRoutine,0,MEM_DECOMMIT|MEM_RELEASE);
    85.     return TRUE;
    86. }
     
  20. wertyman

    wertyman Member

    Публикаций:
    0
    Регистрация:
    13 дек 2006
    Сообщения:
    74
    Интересный способ, нигде не видел :) Привел в рабочий вид, и работает еще на удивление... Только вот на совместимость с фаерами как он ?