CreateRemoteThread, LoadLibrary и PostThreadMessage. Какой правильный метод IPC? - PullRequest
1 голос
/ 22 июля 2009

Хорошо, я внедряю некоторый код в другой процесс, используя CreateRemoteThread / LoadLibrary"трюк".

Я получаю идентификатор потока и процесс с DLL на мой выбор. По крайней мере, теоретически, DLL ничего не делает в данный момент, поэтому проверить это немного сложно. Пока я готов принять это только на веру. Кроме того, на этот вопрос нужно ответить, прежде чем я настойчиво буду двигаться в этом направлении.

По сути, вы не можете заблокировать в DllMain. Однако все, что мне нужно для связи с удаленным потоком, это его идентификатор. Это практически напрашивается на PostThreadMessage / GetMessage shenanigans, которые блокируют. Я мог бы раскрутить другой поток в DllMain, но у меня нет способа передать его идентификатор обратно в поток создания и нет способа передать идентификатор другого потока в удаленный.

В двух словах, если я создаю удаленный поток в процессе, как я должен общаться с исходным процессом?

Ответы [ 2 ]

6 голосов
/ 22 июля 2009

Шаг ноль; внедренная DLL должна иметь точку входа, давайте назовем ее Init(), которая принимает LPCWSTR в качестве единственного параметра и возвращает int; то есть такая же подпись, как у LoadLibrary() и, следовательно, одинаково действительна как адрес функции запуска потока ...

Шаг первый; внедрить, используя библиотеку загрузки и удаленный поток. Не делайте ничего умного во введенных DLL DLLMain(). Сохраните HMODULE, который возвращается как код завершения потока ввода, это HMODULE введенной DLL и возвращаемое значение LoadLibrary().

Обратите внимание , что это более не надежный подход на x64, если /DYNAMICBASE и ASLR (рандомизация размещения адресного пространства) включены, так как HMODULE на x64 больше, чем DWORD значение, возвращаемое из GetThreadExitCode(), и изменение адресного пространства означают, что более не вероятно, что значение HMODULE будет достаточно маленьким, чтобы поместиться в DWORD. См. Комментарии ниже и связанный вопрос (здесь), чтобы обойти использование общей памяти для передачи HMODULE

Шаг второй; загрузить внедренную DLL с помощью LoadLibrary в процесс, который выполняет внедрение. Затем найдите смещение вашей Init() точки входа в вашем адресном пространстве и вычтите из нее HMODULE вашей внедренной DLL в вашем адресном пространстве. Теперь у вас есть относительное смещение функции Init(). Возьмите HMODULE внедренной DLL в целевом процессе (то есть значение, которое вы сохранили на первом этапе) и добавьте к нему относительный адрес Init(). Теперь у вас есть адрес Init() в целевом процессе.

Шаг третий; вызовите Init() в целевом процессе, используя тот же подход «удаленного потока», который вы использовали для вызова LoadLibrary(). Вы можете передать строку в вызов Init (), это может быть что угодно.

Я обычно передаю уникальный строковый ключ, который я использую как часть имени именованного канала. Теперь Injected DLL и процесс внедрения знают имя именованного канала, и вы можете общаться между ними. Функция Init() не является DLLMain() и не страдает от ограничений, влияющих на DLLMain() (так как она не вызывается из LoadLibrary и т. Д.), И поэтому вы можете делать в ней обычные вещи. Как только внедренная DLL и процесс внедрения соединены через именованный канал, вы можете передавать команды и результаты данных туда и обратно, как вам нравится. Поскольку вы передаете функции Init() строку, вы можете убедиться, что именованный канал уникален для данного конкретного экземпляра вашего процесса инъекции и этой конкретной внедренной DLL, что означает, что вы можете запускать несколько экземпляров процесса инъекции одновременно и каждый Процесс может внедряться в несколько целевых процессов, и все эти каналы связи являются уникальными и управляемыми.

1 голос
/ 22 июля 2009

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

Вы можете легко использовать обычные методы межпроцессного взаимодействия, такие как именованные секции / pipe / создание именованного окна / etc. общаться с вашим «инъекционным» процессом.

...