Инжект PE образа в процесс

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

  1. seda

    seda New Member

    Публикаций:
    0
    Регистрация:
    11 апр 2010
    Сообщения:
    47
    Адрес:
    Россия
    Тема казалось бы освещена со всех сторон и ничего сложного в реализации быть не должно. Инжект длл образа в уже запущенные и запускаемые процессы описывался еще ms-rem в 2005. Однако у меня возникла проблема "глобализации" инжекта. Ринг 3. Огромное количество кода, попавшее ко мне в руки использует для глобализации перехват NtResumeThread->CreateRemoteThread. Однако способ этот хоть и работает - но работает нестабильно (в диспечере задач ,например, отключется прорисовка графиков производительности, перестает работать закладка сеть). И это понятно - в момент запуска "нашего" потока запускаемый процесс еще не инициализирован до конца...
    Наша цель - дождаться момента, когда загрузчик полностью инициализирует новый процесс и приступит к выполнению его основного кода. Вариантов опять же много. Я выбрал такой:
    1. Перехватываем запуск нового процсса по NtResumeThread
    2. Непосредственно перед NtResumeThread:
    - проецируем образ на адресное пространство целевого процесса
    - настраиваем релоки
    - ставим наш обработчик APC(используется всесто CreateRemoteThread). Он выполняет две основные задачи - устанавливает наш SEH и помечает EP целевого процесса как Page_GUARD
    3. Выполняем NtResumeThread. Срабатывает наш SEH, через который мы передаем управление на EP нашей DLL
    Все работает.

    Но тут я наткнулся на странный (и непонятный) для меня момент. У меня не получилось вызвать функции LdrLoadDll, LdrGetDllHandle, LdrGetProcedureAddress(многие другие функции из ntdll нормлаьно отрабатывают) из обработчика APC, не возникает никаких ошибок - приложение тихо закрывается и все. Проиcходит это только, если обработчик APC был поставлен из Explorer.exe или winlogon.exe. В стеке RtlFindActiovationContextSectionString - то есть проблема возникает где то внутри ее. Может быть кто то сталкивался с такой проблемой и сможет подтолкнуть меня в паравильном направлении?
     
  2. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Вроде я тут уже отвечал. В контексте регистр Eax содержит линк на стартуп рантайм http://indy-vx.narod.ru/Bin/Ij.zip
     
  3. seda

    seda New Member

    Публикаций:
    0
    Регистрация:
    11 апр 2010
    Сообщения:
    47
    Адрес:
    Россия
    Ага, спасибо.
    Что касается ошибки
    заменил QueueUserAPC на ZwQueueApcThread и все заработало.
    Тему можно закрыть.
     
  4. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Дело в том, что функция kernel32!QueueUserApc() добавляет в качестве APC дополнительную обёртку – kernel32!RtlDispatchAPC(), которая активирует переданный Активационный Контекст и уже после этого вызывает оригинальную APC-процедуру. (После вызова или в случае исключения в APC-процедуре Активационный Контекст обёрткой деактивируется). Фактически Активационный Контекст передаётся по указателю – в контексте других процессов использование этого указателя может привести к непредсказуемым последствиям. Хотя часто всё работает, поскольку в большинстве процессов какой-либо специальный Контекст не создаётся – в таких случаях RtlDispatchAPC() получает в качестве Контекста нуль.

    Кстати, в w7 существует ещё одна потенциальная проблема с межпроцессными APC – фактически вместо kernel32!QueueUserApc() выполняется kernelbase!QueueUserApc(), и вместо kernel32!RtlDispatchAPC() хардкодом добавляется kernelbase!RtlDispatchAPC(). Тогда как лоадер требует, чтобы kernel32 во всех процессах была отображена по одному и тому же адресу, для kernelbase таких требований не предъявляется. Конечно, маловероятно, чтобы эта dll загрузилась не по базе в результате неумышленного акта – всё-таки это одна из первых dll, появляющихся в процессе – однако такое возможно, поскольку её загрузка выполняется в юзермодном контексте после старта первичного потока (неявно; прямо загружаемая kernel32 импортирует из неё).

    Таким образом, процедура QueueUserApc() непригодна для межпроцессных APC, несмотря на имплицитное утверждение об обратном в MSDN. Использование NtQueueApcThread() в таких случаях будет предпочтительным.

    Здесь Clerk сообщил о Context.Eax – мы лишь дополним это данными применительно к x64: Context.Rcx.
     
  5. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв