Вызов функции в другом процессе
Вызов функции в другом процессе
Сергей Холодилов
I just called to say I love you,
And I mean it from the bottom of my heart.
Stevie Wonder
Внедрению DLL так или иначе (обычно в связи с
перехватом API) посвящено достаточно большое количество статей. Но ни в одной
из тех, которые я читал, не говорится, как извне заставить эту DLL сделать
что-нибудь полезное. Обычно авторы ограничиваются перехватом необходимых
API-функций где-нибудь в DllMain и последующей реакцией на вызовы этих самых
функций. Между тем, взаимодействие с внедрённой DLL даёт возможность
корректировать и направлять её работу и, тем самым, позволяет добиваться
значительно большего эффекта.
Если внедрённая DLL создаёт свой поток, задача
взаимодействия легко решается, так как в этом случае можно использовать любые
методы IPC: сообщения, сокеты, именованные каналы, … , при желании можно даже
COM-сервер сделать :)
ПРЕДУПРЕЖДЕНИЕ
В описании DllMain сказано, что
некоторые функции, в том числе CreateThread, из неё вызывать нельзя.
Объяснение «почему они говорят, что нельзя» можно найти у Рихтера (в русском
четвёртом издании это глава «DLL: более сложные методы программирования»,
раздел «Как система упорядочивает вызовы DllMain»), у него же написано, что
на самом деле можно, если осторожно. :) Просто при создании потока надо не
забывать, что его выполнение начнётся не раньше, чем текущий поток покинет
DllMain.
|
Но это всё более-менее очевидные и не очень красивые
(на мой взгляд) способы. Мне кажется, я нашёл более интересный и элегантный
метод. Ему и посвящена эта статья.
Идея
Идея тривиальна. Алгоритм состоит всего из четырёх
шагов (плюс ещё один по желанию):
Так или иначе загрузить в адресное пространство
процесса-жертвы DLL, содержащую нужную функцию.
ПРИМЕЧАНИЕ
«Так или иначе» означает, что DLL может
быть загружена любым способом. Например, это может быть advapi32.DLL, которую
процесс-жертва грузит сам. Если вы хотите, чтобы исполнялся ваш код, скорее
всего, DLL придётся внедрять. Описание внедрения DLL смотрите в
дополнительных источниках в конце статьи.
|
Получить адрес загрузки DLL.
Получить адрес функции.
Вызвать функцию при помощи CreateRemoteThread.
(опционально) Дождаться завершения потока и получить
возвращаемое значение функции вызовом GetExitCodeThread.
А зачем нам DLL?
код будет расположен в случайном месте адресного
пространства, так как вам вряд ли удастся выделить память по тому же адресу;
DLL могут быть загружены по другим адресам,
«само собой» ничего не получится. Чтобы добиться
работоспособности кода, нужно модифицировать используемые вашим кодом адреса,
то есть, фактически, выполнить задачу загрузчика. А зачем выполнять её вручную,
если можно положиться на загрузчик :) ?
Ограничения
Использование CreateRemoteThread связано с очевидными
ограничениями:
Поддерживается только линейка Windows NT/2000/XP.
ПРИМЕЧАНИЕ
Существует платная реализация
CreateRemoteThread для Windows 9x, смотрите сайт #"#">http://www.rsdn.ru/
Похожие работы на - Вызов функции в другом процессе
|