Внедрение DLL ( странности )

Тема в разделе "WASM.WIN32", создана пользователем psu, 8 июн 2007.

  1. psu

    psu New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    198
    Пишу GUI прогу-оболочку, которая запускает процес-жертву, внедряет в него длл, перехватывает нужные функции, общается с родительским процесом. В общем тулза для исследования алгоритма работы неизвестных прог.
    Все достаточно банально:
    - запуск жертвы через CreateProcess( .. CREATE_SUSPENDED .. )
    - внедрение длл через CreateRemoteThread
    - ResumeThread

    Столкнулся в с проблемой. Некоректное внедрение в некоторые процесы. Например, калькулятор не отображается, а просто висит в памяти ( длл загружается, удаленный поток завершается нормально, ResumeThread - ok ), в notepad длл даже не загружается. В то же время консольные приложения нормально отрабатывают ( хотя GUI, созданное визардом VC, тоже работает ).
    З.Ы. поиск уже перерыл..
     
  2. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    поподробнее кодес даваЙ )
     
  3. psu

    psu New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    198
    запуск
    Код (Text):
    1. char drv[ MAX_PATH ];
    2. char dir[ MAX_PATH ];
    3. _splitpath( AppPath, drv, dir, 0, 0 );
    4. lstrcat( drv, dir );
    5.  
    6. CreateProcess( 0, AppPath, 0, 0, 0, CREATE_SUSPENDED, 0, drv, &si, &pi );
    7. InjectDll( pi.dwProcessId );
    8. ResumeThread( pi.hThread );
    внедрение
    Код (Text):
    1. BOOL InjectDll( DWORD pid, char*ModulePath )
    2. {
    3.     BYTE* Memory;
    4.     DWORD ThreadId;
    5.     HANDLE hThread;
    6.     HANDLE hProcess;
    7.    
    8.     hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid );
    9.    
    10.     DWORD Written;
    11.     Memory = ( BYTE* )VirtualAllocEx( hProcess, 0, sizeof( Inject ), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );
    12.     if( !Memory )
    13.     {
    14.         return( 0 );
    15.     }
    16.  
    17.     //инициализация внедряемого кода:
    18.     Inject inject( Memory, ModulePath );
    19.  
    20.     //записать машинный код по зарезервированному адресу
    21.     WriteProcessMemory( hProcess, Memory, &inject, sizeof( Inject ), &Written );
    22.    
    23.     //выполнить машинный код
    24.     hThread = CreateRemoteThread( hProcess, 0, 0, ( LPTHREAD_START_ROUTINE )Memory, 0, 0, &ThreadId );
    25.     if( !hThread )
    26.     {
    27.         return( 0 );
    28.     }
    29.     WaitForSingleObject( hThread, INFINITE );
    30.     return( 1 );
    31. }
     
  4. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    psu
    Навскидку: ты копируешь указатель на ModulePath в процесс, а не саму строку. Если только Inject - не хитрый класс, перегружающий operator& :)
     
  5. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    IceStudent
    может конструктор как раз и копирует строку.
     
  6. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Было бы неплохо увидеть описание этого класса ))
     
  7. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    n0name
    Да, может, если в Inject статический массив.

    А вот перегрузка оператора не поможет, т.к. размер задаётся через sizeof.
     
  8. psu

    psu New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    198
    Код (Text):
    1. struct Inject
    2. {
    3.     BYTE        PushCommand;                //push
    4.     BYTE*       PushArgument;               //LibraryName
    5.     WORD        CallCommand;                //call
    6.     BYTE*       LoadLibraryCallAddr;        //loadlibrary
    7.    
    8.     BYTE        PushExitThread;             //push
    9.     BYTE*       ExitThreadArg;              //0
    10.     WORD        CallExitThread;             //call
    11.     BYTE*       ExitThreadAddr;             //exitthread
    12.    
    13.     FARPROC     AddrLoadLibrary ;           //kernel32.LoadLibraryA
    14.     FARPROC     AddrExitThread;         //kernel32.ExitThread
    15.        
    16.     char        LibraryName[MAX_PATH];
    17.  
    18.     //-----------------------------------------------------------------
    19.     Inject( BYTE* Memory, char* ModulePath )
    20.     {
    21.         HMODULE hKernel32 = GetModuleHandle( "kernel32.dll" );
    22.  
    23.         PushCommand         = 0x68;
    24.         PushArgument        = Memory + 30;
    25.         CallCommand         = 0x15FF;
    26.         LoadLibraryCallAddr = Memory + 22;
    27.        
    28.         PushExitThread      = 0x68;
    29.         ExitThreadArg       = 0;
    30.         CallExitThread      = 0x15FF;
    31.         ExitThreadAddr      = Memory + 26;
    32.        
    33.         AddrLoadLibrary     = GetProcAddress( hKernel32, "LoadLibraryA" );
    34.         AddrExitThread      = GetProcAddress( hKernel32, "ExitThread" );
    35.  
    36.         lstrcpy( LibraryName, ModulePath );
    37.     }
    38.     //-----------------------------------------------------------------
    39. };
    Выравнивание побайтовое
     
  9. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    гыгы, я жу говорил ;)
     
  10. psu

    psu New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    198
    Да, да, угадал, маладэц! :)
    Други, может все-таки кто-нибуть подскажет куда смотреть? Поделюсь исходниками, если надо
     
  11. z0mailbox

    z0mailbox z0

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    635
    Адрес:
    Russia СПБ
    подскажу

    такой код невалиден:
    CreateProcess( ... CREATE_SUSPENDED ... )
    VirtualAllocEx()
    WriteProcessMemory()
    CreateRemoteThread( обычно на LoadLibraryA )
    WaitForSingleObject()
    ResumeThread( ProcInfo.hProcess )

    иногда (зависит от набора ДЛЛ) при этом ломается список модулей процесса
    глюки самые невероятные
    см:
    http://forum.sources.ru/index.php?showtopic=177691&view=showall
    http://wasm.ru/forum/viewtopic.php?pid=168358
    https://www.rootkit.com/newsread.php?newsid=715

    правильно имеено так как на рутките, вместо CreateRemoteThread -> QueueUserAPC

    меньше рихтеру доверяйте!
     
  12. tylerdurden

    tylerdurden New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2004
    Сообщения:
    322
    Инжекть APC а не Thread, наблюдаются глюки со многими прогами (к примеру Total Commander)... Я скоро планирую написать небольшую статейку, а то инжект от ms-rem'а (вроде как его) немного... гм... страннен... и не полный, в любом случае
     
  13. tinok

    tinok New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2007
    Сообщения:
    26
    psu
    Попробуй ключ в реестре: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\APPINIT_DLLS. Он содержит имена библиотек подгружаемых ко всем новым процессам (если у тебя ключа нет - создай).
     
  14. Mental_Mirror

    Mental_Mirror New Member

    Публикаций:
    0
    Регистрация:
    7 май 2007
    Сообщения:
    431
    tinok
    Вообще это всем известный способ, поэтому и жутко палевный.
     
  15. leniviy

    leniviy New Member

    Публикаций:
    0
    Регистрация:
    1 апр 2009
    Сообщения:
    11
    Спасибо, очень помогли!

    upd: Под XP работает. Под win98 QueueUserAPC() возвращает "успех" , но внедрённый код почему-то не запускается. Сразу запускается threadproc. Это происходит даже если пытаешься внедрить в свой собственный процесс. Но зато под win98 я не заметил проблем с запуском гуишных программ через _CreateRemoteThread() из RemoteLib.
     
  16. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    Здо́рово.. Сейчас сам с этим столкнулся. Тотал после CreateRemoteThread такое мочит.. )
     
  17. leniviy

    leniviy New Member

    Публикаций:
    0
    Регистрация:
    1 апр 2009
    Сообщения:
    11
    Натолкнулся на очередной глюк.

    процесс А:
    - запуск жертвы через CreateProcess( .. CREATE_SUSPENDED .. )
    - внедрение куска кода через QueueUserAPC()
    - ResumeThread

    - Жду, пока тред сам себя остановит

    процесс Б:
    в этом куске запускается и сохр. результат LoadLibraryW, потом GetLastError,
    потом подмена retAddr и jmp в SuspendThread

    процесс А:
    ReadProcessMemory
    VirtualFreeEx
    ResumeThread

    Глюк вот в чем:
    Запускаю проги типа calc, notepad из Total Commander. Если найти соотв. exe файл и запустить его кликом, то внедрение проходит успешно.
    Если ввести путь к exe в командной строке Total Commander, то LoadLibraryW() возвращает NULL , а GetLastError() ERROR_NOACCESS

    Оказалось, что где-то в внутри ntdll:LdrLoadDll() происходит нарушение доступа, причём даже LoadLibrary("kernel32.dll") возвращает эту ошибку.

    Не знаю, совпадение или нет, но есть ещё глюк с буфером обмена, который проявляется всесте с ошибкой LoadLibrary().

    Если запустить Total Commander под дебагом, но без перехватов API,
    поставить точку останова на CreateProcessW,
    запустить что угодно из командной строки Total Commander,
    и в любой другой программе попытаться скопировать текст в буфер, та программа подвисает на несколько секунд.

    Всё это под WinXP sp3
     
  18. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Не юзать гуан.
    > Суспендим все потоки.
    > Создаём стек для каждого потока.
    > Сохраняем контекст всех потоков.
    > Загружаем в контекст всех потоков Esp и Ss на новый стек.
    > Выводим потоки из спящего состояния.
    > Управление получает наш код.
    > Восстанавливаем сохранённый контекст потоков.
     
  19. leniviy

    leniviy New Member

    Публикаций:
    0
    Регистрация:
    1 апр 2009
    Сообщения:
    11
    похоже на внедрение в уже работающий процесс. Мне же надо, загрузить длл в новый процесс до его инициализации. Похоже, что придётся использовать DetourCreateProcessWithDll() , хотя я и не хотел, потому что она меняет таблицу импортов, и такая длл становится невыгружаемой.

    Хотя можно применить последнее средство - найти и поменять в новом процессе точку входа. Тогда наш код вызовется уже после всей инициализации, и работать это будет даже под "девятками".
     
  20. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Тоесть тебе нужно подгрузить модуль пока загрузчик не инициализирован ?
    Или до нотификации модулей ?
    Или пока поток не начал исполнять главную точку входа модуля ?