Совместное использование памяти между двумя процессами (C, Windows) - PullRequest
28 голосов
/ 29 июля 2009

Поскольку я не нашел ответа на вопрос, заданный ранее здесь Я пытаюсь использовать другой подход.

Есть ли способ разделить память между двумя процессами?

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

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

Возможно ли это? Как?

Код приветствуется.

EDIT:

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

Ответы [ 7 ]

25 голосов
/ 29 июля 2009

Несмотря на то, что Windows поддерживает совместно используемую память через API-интерфейс для сопоставления файлов *1002*, вы не можете легко внедрить сопоставление совместно используемой памяти непосредственно в другой процесс, поскольку MapViewOfFileEx не принимает аргумент процесса.

Однако вы можете внедрить некоторые данные, выделив память в другом процессе, используя VirtualAllocEx и WriteProcessMemory . Если бы вы скопировали в дескриптор, используя DuplicateHandle , а затем внедрили заглушку, которая вызывает MapViewOfFileEx , вы могли бы установить отображение общей памяти в другом процессе. Поскольку, похоже, вы все равно будете вводить код, это должно сработать для вас.

Подводя итог, вам нужно:

  • Создание анонимного дескриптора сегмента совместно используемой памяти путем вызова CreateFileMapping с INVALID_HANDLE_VALUE для hFile и NULL для lpName.
  • Скопируйте этот дескриптор в целевой процесс с помощью DuplicateHandle
  • Выделите немного памяти для кода, используя VirtualAllocEx , с flAllocationType = MEM_COMMIT | MEM_RESERVE и flProtect = PAGE_EXECUTE_READWRITE
  • Запишите свой код заглушки в эту память, используя WriteProcessMemory . Эта заглушка, вероятно, должна быть написана на ассемблере. Передайте РУЧКУ от DuplicateHandle, написав ее где-то здесь.
  • Выполните свою заглушку, используя CreateRemoteThread . Затем заглушка должна использовать полученную РУЧКУ для вызова MapViewOfFileEx . Затем процессы будут иметь общий сегмент общей памяти.

Вам может быть немного легче, если ваша заглушка загружает внешнюю библиотеку - то есть просто вызовите LoadLibrary (поиск адреса LoadLibrary оставлен для чтения читателю) и выполните свою работу из записи библиотеки dllmain. точка. В этом случае использование именованной совместно используемой памяти, вероятно, будет проще, чем работа с DuplicateHandle. См. Статью MSDN по CreateFileMapping для получения более подробной информации, но, по сути, передайте INVALID_HANDLE_VALUE для hFile и имя для lpName.

Редактировать : Поскольку ваша проблема заключается в передаче данных, а не в ввод кода, вот несколько вариантов.

  1. Использовать разделяемую память переменного размера. Ваша заглушка получает размер и либо имя, либо дескриптор общей памяти. Это уместно, если вам нужно обмениваться данными только один раз. Обратите внимание, что размер сегмента общей памяти не может быть легко изменен после создания.
  2. Использовать именованный канал . Ваша заглушка получает имя или ручку к трубе. Затем вы можете использовать соответствующий протокол для обмена блоками переменного размера - например, напишите size_t для длины, за которой следует фактическое сообщение. Или используйте PIPE_TYPE_MESSAGE и PIPE_READMODE_MESSAGE и следите за ERROR_MORE_DATA, чтобы определить, где заканчиваются сообщения. Это подходит, если вам нужно обмениваться данными несколько раз.

Редактировать 2 : Вот эскиз того, как вы можете реализовать ручку или хранение указателя для вашей заглушки:

.db B8            ;; mov eax, imm32
.dl handle_value  ;; fill this in (located at the start of the image + one byte)
;; handle value is now in eax, do with it as you will
;; more code follows...

Вы также можете просто использовать фиксированное имя, которое, вероятно, проще.

10 голосов
/ 29 июля 2009

Вы можете попробовать файл с отображением в памяти .

Это дает немного больше пошаговых деталей.

3 голосов
/ 29 июля 2009

Вы можете использовать общую память

1 голос
/ 12 сентября 2011

Отображение памяти - путь, вам даже не нужно создавать постоянное пространство памяти, сектор памяти выходит из области видимости, когда все процессы, разделяющие его, выключаются. Есть и другие способы. Быстрый и грязный способ передачи данных из одного приложения C в другое - просто использовать ОС. В командной строке введите app1 | app2. Это приводит к тому, что app2 становится адресатом вывода app1 или iow команда printf из app1 отправляет его в app2 (это называется конвейером).

1 голос
/ 01 сентября 2010

Вы пытались использовать каналы (для памяти) или даже сериализацию (для своих объектов)? Вы можете использовать файлы для управления памятью между процессами. Сокеты также хороши для установления связи между процессами.

0 голосов
/ 29 июля 2009

Вы можете попробовать использовать Boost.Interprocess для связи между двумя процессами. Но чтобы внедрить код в ранее существующее, не поддерживаемое программное обеспечение, вам, вероятно, придется использовать способ @ bdonlan, используя WriteProcessMemory .

0 голосов
/ 29 июля 2009

Если вы говорите о Windows, основным препятствием является то, что каждый из них обрабатывается в своем собственном виртуальном адресном пространстве. К сожалению, вы не можете передавать нормальные адреса памяти от процесса к процессу и получать ожидаемые результаты. (С другой стороны, все потоки живут в одном и том же адресном пространстве, поэтому потоки могут видеть память одинаково.)

Windows, однако, имеет общее пространство памяти, с которым вам нужно быть очень осторожным, чтобы правильно управлять. Любой процесс, который выделяет пространство в общей памяти, отвечает за освобождение этой памяти явно. Это в отличие от локальной памяти, которая более или менее исчезает, когда процесс умирает.

См. этот пример статьи MSDN , где приведены некоторые идеи о том, как вы можете использовать пространство совместно используемой памяти для захвата мира. Э-э, интерфейс с устаревшим программным обеспечением. Или что угодно :) Удачи, что бы ты ни делал!

...