У меня есть DLL, которую я вставляю в другой процесс, но я хочу иметь возможность вызывать экспорт этой DLL из своего приложения. Я где-то читал, что у вас есть API SendMessage, но я понятия не имею, что делать. Есть ли пример кода, как это делается?
Вызов функций в DLL, загруженной другим процессом
Ответы (3)
В общем случае вы не можете напрямую вызывать функции в другом процессе. Однако есть некоторые обходные пути, которые вы можете использовать.
Во-первых, если вы знаете адрес экспорта (что не всегда так), а вызываемая вами функция использует соглашение о вызовах __stdcall
, принимает в качестве аргумента целое число размером с указатель и возвращает DWORD, вы можете использовать CreateRemoteThread
для его выполнения в потоке удаленного процесса. Это часто используется для запуска LoadLibrary
для внедрения DLL в целевой процесс, поскольку LoadLibrary
загружается по одному и тому же адресу во всех процессах на данном компьютере.
В противном случае внедренная вами DLL должна будет выполнить своего рода RPC с процессом, который ее вызвал. Например, ваша внедренная DLL может порождать поток в своем обработчике DLL_PROCESS_ATTACH, который, в свою очередь, подключается к именованному каналу или подключается через COM или что-то еще к главному процессу.
Хотя невозможно напрямую вызвать функцию в другом процессе, вы можете сделать это косвенно довольно легко, выполнив несколько шагов и используя Windows API.
- Получите адреса
LoadLibrary
иGetProcAddress
из собственного процесса.kernel32.dll
должны быть загружены по одному и тому же адресу в каждом процессе, поэтому вы можете быть уверены, что они присутствуют в процессе, в который вы внедряете - Создайте
struct
, который будет содержать все аргументы, которые вы хотите передать своей функции, которая будет вызывать функции в другом процессе (посколькуCreateRemoteThread
может передать только один аргумент в функцию, поэтому мы будем использовать его для передачи указателя на структуру ), который по крайней мере содержит указатели функций-членов для хранения адресовLoadLibrary
иGetProcAddress
- Выделите достаточно памяти для структуры в удаленном процессе с помощью
VirtualAllocEx
, затем заполните ее правильной информацией с помощьюWriteProcessMemory
- Напишите функцию, взяв указатель на написанное вами
struct
, которая используетLoadLibrary
/GetProcAddress
для вызова нужной функции. Не забудьте использовать указатели на те функции в структуре, которую вы передаете функции, а не имена. - Выделите достаточно памяти в удаленном процессе для хранения функции с
VirtualAllocEx
, обязательно передайтеVAX
флагPAGE_EXECUTE_READWRITE
, чтобы он мог содержать исполняемый код - Прочитайте и запишите код функции из вашего процесса в другой процесс через
Read/WriteProcessMemory
- Вызовите функцию в удаленном процессе (который находится по адресу, возвращаемому
VirtualAllocEx
), используяCreateRemoteThread
.
Убедитесь, что все данные, которые вы передаете функции, либо хранятся внутри структуры, либо находятся в адресном пространстве удаленного процесса (получите их туда с помощью VirtualAllocEx
/WriteProcessMemory
.
Это может показаться немного запутанным, но на самом деле это не так сложно. Если вам нужна помощь с этим, не стесняйтесь спрашивать в комментарии.
SendMessage
потребуется дескриптор окна (скрытый или видимый) и связанный с ним насос сообщений, который может обрабатывать настраиваемое сообщение. Как и в случае с UAC/Windows-7, уровни целостности приложений могут препятствовать другим приложениям отправлять/отправлять сообщения из других процессов с низкой целостностью.
Лучше иметь другой поток, который ждет этих пользовательских сообщений. Для этого вы можете использовать каналы (именованные или неименованные), сокеты, почтовые слоты, разделяемую память (вместе с мьютексом/событием для запуска). Другие процессы отправят сообщение, используя тот же протокол.
Но прежде чем внедрять этот настраиваемый механизм обмена сообщениями/протокола/IPC, я предлагаю вам сначала определить точную потребность.