Вызов функций в DLL, загруженной другим процессом

У меня есть DLL, которую я вставляю в другой процесс, но я хочу иметь возможность вызывать экспорт этой DLL из своего приложения. Я где-то читал, что у вас есть API SendMessage, но я понятия не имею, что делать. Есть ли пример кода, как это делается?


person 123    schedule 08.07.2011    source источник
comment
Вы можете использовать экспорт непосредственно из своего приложения, ничего не нужно, кроме ссылки или загрузки этой DLL. Вот как работают библиотеки DLL. У него может быть другой адрес в адресном пространстве вашего процесса, но это будут точно такие же страницы. По этой причине DLL также имеет свою собственную кучу (вместо того, чтобы просто использовать кучу приложения).   -  person Damon    schedule 09.07.2011


Ответы (3)


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

Во-первых, если вы знаете адрес экспорта (что не всегда так), а вызываемая вами функция использует соглашение о вызовах __stdcall, принимает в качестве аргумента целое число размером с указатель и возвращает DWORD, вы можете использовать CreateRemoteThread для его выполнения в потоке удаленного процесса. Это часто используется для запуска LoadLibrary для внедрения DLL в целевой процесс, поскольку LoadLibrary загружается по одному и тому же адресу во всех процессах на данном компьютере.

В противном случае внедренная вами DLL должна будет выполнить своего рода RPC с процессом, который ее вызвал. Например, ваша внедренная DLL может порождать поток в своем обработчике DLL_PROCESS_ATTACH, который, в свою очередь, подключается к именованному каналу или подключается через COM или что-то еще к главному процессу.

person bdonlan    schedule 08.07.2011
comment
Я только что взглянул на именованные каналы, и это сделает то, что я ищу. Спасибо! - person 123; 09.07.2011

Хотя невозможно напрямую вызвать функцию в другом процессе, вы можете сделать это косвенно довольно легко, выполнив несколько шагов и используя Windows API.

  1. Получите адреса LoadLibrary и GetProcAddress из собственного процесса. kernel32.dll должны быть загружены по одному и тому же адресу в каждом процессе, поэтому вы можете быть уверены, что они присутствуют в процессе, в который вы внедряете
  2. Создайте struct, который будет содержать все аргументы, которые вы хотите передать своей функции, которая будет вызывать функции в другом процессе (поскольку CreateRemoteThread может передать только один аргумент в функцию, поэтому мы будем использовать его для передачи указателя на структуру ), который по крайней мере содержит указатели функций-членов для хранения адресов LoadLibrary и GetProcAddress
  3. Выделите достаточно памяти для структуры в удаленном процессе с помощью VirtualAllocEx, затем заполните ее правильной информацией с помощью WriteProcessMemory
  4. Напишите функцию, взяв указатель на написанное вами struct, которая использует LoadLibrary/GetProcAddress для вызова нужной функции. Не забудьте использовать указатели на те функции в структуре, которую вы передаете функции, а не имена.
  5. Выделите достаточно памяти в удаленном процессе для хранения функции с VirtualAllocEx, обязательно передайте VAX флаг PAGE_EXECUTE_READWRITE, чтобы он мог содержать исполняемый код
  6. Прочитайте и запишите код функции из вашего процесса в другой процесс через Read/WriteProcessMemory
  7. Вызовите функцию в удаленном процессе (который находится по адресу, возвращаемому VirtualAllocEx), используя CreateRemoteThread.

Убедитесь, что все данные, которые вы передаете функции, либо хранятся внутри структуры, либо находятся в адресном пространстве удаленного процесса (получите их туда с помощью VirtualAllocEx/WriteProcessMemory.

Это может показаться немного запутанным, но на самом деле это не так сложно. Если вам нужна помощь с этим, не стесняйтесь спрашивать в комментарии.

person Seth Carnegie    schedule 08.07.2011
comment
Как насчет случая, когда этот процесс и другой имеют разную разрядность (32/64 бита)? Есть ли способ выяснить из возвращаемого значения GetProcAddress() в этом процессе, каким оно будет в другом процессе с другой разрядностью? - person tml; 26.04.2018

SendMessage потребуется дескриптор окна (скрытый или видимый) и связанный с ним насос сообщений, который может обрабатывать настраиваемое сообщение. Как и в случае с UAC/Windows-7, уровни целостности приложений могут препятствовать другим приложениям отправлять/отправлять сообщения из других процессов с низкой целостностью.

Лучше иметь другой поток, который ждет этих пользовательских сообщений. Для этого вы можете использовать каналы (именованные или неименованные), сокеты, почтовые слоты, разделяемую память (вместе с мьютексом/событием для запуска). Другие процессы отправят сообщение, используя тот же протокол.

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

person Ajay    schedule 09.07.2011