Взаимодействие между процессами

Дата публикации 27 июн 2002

Взаимодействие между процессами — Архив WASM.RU

Взаимодействие между процессами (IPC) - это путь, с помощью которого процессы могут взаимодействовать между собой. У каждого процесса есть свое собственное отдельное адресное пространство, поэтому процессы не могут напрямую видеть память других процессов. Win32 API предоставляет несколько разновидностей IPC. IPC может быть очень полезно для вирусов, поэтому я объясню несколько путей, хотя я не уверен, что в вирусах применимы все из этих путей.

В этой статье объясняются следующие виды IPC:

  • атомы
  • мэппинг файлов
  • анонимные пайпы
  • мейлслоты

Атомы

Атомы - это очень простой и доступный путь IPC. Идея состоит в том, что процесс может поместить строку в таблицу атомов и эта строка будет видна другим процессам. Когда процесс помещает строку в таблицу атомов, он получает 32-х битное значение (атом), и это значение используется для доступа к строке. Система не различает регистр строки.

Есть два типа таблиц атомов - глобальная (GAT) и локальная (LAT).

Код (Text):
  1.  
  2.   Добавление строки в GAT
  3.  
  4.     push _address_of_string - строка, заканчивающаяся NULL, максимальный
  5.                               размер равен 255 байтам
  6.     call GlobalAddAtom(A/W)
  7.  
  8.     Возвращает в eax атом
  9.  
  10.   Удаление атома из GAT
  11.  
  12.     push _atom
  13.     call GlobalDeleteAtom(A/W)
  14.  
  15.     Возвращает 0 в eax, если вызов функции прошел успешно
  16.  
  17.   Поиск атома
  18.  
  19.     push _адрес_строки - заканчивающаяся NULL'ом строка, максимальный размер
  20.                          которой равен 256 байтам
  21.     call GlobalFindAtom(A/W)
  22.  
  23.     Возвращает 0 в eax, если вызов функции неудался, либо атом, если вызов
  24.     прошел успешно
  25.  
  26.   Получить строку атома, имея атом
  27.  
  28.     push _size_of_buffer      - длина буфера
  29.     push _address_of_buffer   - буфер
  30.     push _atom                - атом <img src="styles/smiles_s/smile3.gif" class="mceSmilie" alt=":smile3:" title="Smile3    :smile3:">
  31.     call GlobalGetAtomName(A/W)
  32.                                                                           |
  33.     Если вызов прошел успешно, буфер будет заполнен строкой атома

| LAT использует те же функции для работы с атомами, только без приставки 'Global'. Как бы то ни было, LAT виден тольк для текущего процесса, но не для других. Количество элементов по умолчанию равно 37, но его можно изменить с помощью функции InitAtomTable. Максимальное количество, которое можно установить, равно 3FFF. Хм, это число указано в MSDN, но я пытался получить сообщение об ошибке, вызывая эту функцию с более высоким значением, и у меня ничего не вышло. Похоже, что функция работает с любым количеством элементов.

Код (Text):
  1.  
  2.  Инициализация LAT
  3.  
  4.    push _размер_LAT
  5.    call InitAtomTable
  6.  
  7.    Возвращает ...

Вот и все об атомах...

Мэппинг файлов

Я думаю, что мэппинг файлов - это хорошо известный путь для доступа к файлам. Он объяснен во многих статьях, поэтому я не буду тратить время на подробности. Идея в том, что мы можем промэппировать файл в память. Тогда с каждым изменением в памяти, будет меняться и файл. Применительно к IPC мы можем промэппировать файл в нескольких процессах и взаимодействовать через него.

Код (Text):
  1.  
  2.      функции
  3.  
  4.     push шаблонный хэндл файла           ; по умолчанию - 0
  5.     push флаги и аттрибуты               ; по умолчанию - 0
  6.     push флаги открытия и создания
  7.     push аттрибуты безопасности          ; по умолчанию - 0
  8.     push флаги разделяемого доступа      ; по умолчанию - 1
  9.     push доступ к файлу
  10.     push имя файла
  11.  
  12.     call CreateFile(A/W)
  13.  
  14.  
  15.     Возвращает хэндл файла
  16.  
  17.     флаги создания и открытия
  18.           CREATE_NEW          equ 1
  19.           CREATE_ALWAYS       equ 2
  20.           OPEN_EXISTING       equ 3
  21.           OPEN_ALWAYS         equ 4
  22.           TRUNCATE_EXISTING   equ 5
  23.  
  24.     доступ к объекту
  25.           GENERIC_READ        equ 080000000h
  26.           GENERIC_WRITE       equ 040000000h
  27.           GENERIC_EXECUTE     equ 020000000h
  28.           GENERIC_ALL         equ 010000000h
  29.  
  30.     Правильный мэппинг файла начинается здесь, ...объект, который должен быть
  31.     промэппирован, не нужно открывать CreateFile(A/W). Если мы используем
  32.     значение (-1) в аргументе хэндла файла, мы промэппируем часть разделяемой
  33.     пммяти без связывания с файлом, ...идеально для IPC.
  34.  
  35.     push имя промэппированного объекта     ; по умолчанию - 0
  36.     push нижние 32 бита размера объекта    ; по умолчанию - размер
  37.     push верхние 32 32 bits of object size ; по умолчанию - 0
  38.     push защита                            ; по умолчанию - 4
  39.     push аттрибуты безопасности            ; по умолчанию - 0
  40.     push хэндл файла                       ; по умолчанию - HNDL от CreateFile
  41.  
  42.     call CreateFileMapping(A/W)
  43.  
  44.     Возвращает хэндл объекта
  45.  
  46.     Эта функция создает объект мэппинга и возвращает хэндл его защиты
  47.                  PAGE_READONLY             equ 2
  48.                  PAGE_READWRITE            equ 4
  49.                  PAGE_WRITECOPY            equ 8
  50.  
  51.     Аттрибуты безопасности - указатель может быть установлен в NULL, как бы
  52.     то ни было, вот структура:
  53.                  SECURITY_ATTRIBUTES struc
  54.                    _saSize               dd ? ; размер структуры
  55.                    _lpSecurityDescriptor dd ? ; указатель на дескриптор
  56.                                               ; безопасности
  57.                    _bInheritHandle       dd ? ; булевое значение, истинно для
  58.                                               ; наследования
  59.                  SECURITY_ATTRIBUTES ends
  60.  
  61.     push имя мэппирующегося объекта
  62.     push флаг наследования
  63.     push реим доступа
  64.  
  65.     call OpenFileMapping(A/W)
  66.  
  67.     Возвращает хэндл объекта
  68.  
  69.     Режим доступа
  70.                 FILE_MAP_WRITE   equ 2       ;R/W access
  71.                 FILE_MAP_READ    equ 4       ;R access
  72.  
  73.          теперь у нас есть map-объект
  74.  
  75.     push сколько байтов мэппировать ; по умолчанию - размер
  76.     push нижняя часть смещения      ; по умолчанию - 0
  77.     push верхняя часть смещения     ; по умолчанию - 0
  78.     push access mode      ;----------------------------------
  79.     push object handle    ; по умолчанию - HNDL from Create(Open)FileMapping
  80.  
  81.     call MapViewOfFile
  82.  
  83.     Возвращает адрес в памяти
  84.  
  85.            теперь у нас есть промэппированный в память файл
  86.            мы можем записать часть промэппированного файла на диск, используя:
  87.  
  88.              push количество байтов, которое нужно записать
  89.              push начальный адрес
  90.  
  91.              call FlushViewOfFile
  92.  
  93.  
  94.     push адрес в памяти
  95.     call UnmapViewOfFile   ; демэппирует файл
  96.  
  97.  
  98.     push хэндл объекта     ; закрывает объект мэппинга
  99.     call CloseHandle
  100.  
  101.  
  102.     push хэндл файла       ; закрывает хэндл файла
  103.     call CloseHandle

Вот и все о мэппинге файлов.

Анонимные пайпы

Есть два типа пайпов: анонимные и именованные. Именованные пайпы 'немного' труднее использовать, чем анонимные, поэтому я расскажу о них в другой статье.

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

Код (Text):
  1.  
  2.     создание анонимного (безымянного) пайпа
  3.  
  4.     push размер пайпа
  5.     push защита
  6.     push указатель на хэндл записи в пайп
  7.     push указатель на хэндл чтения из пайпа
  8.  
  9.     call CreatePipe
  10.  
  11.  
  12.     pipe size  - size of pipe buffer
  13.                  if it's NULL system uses default size
  14.     protection - pointer to SECURITY_ATTRIBUTES
  15.                  if it's NULL pipe cant be inherited
  16.  
  17.     размер пайпа - размер его буфера
  18.     защита       - указатель на SECURITY_ATTRIBUTES, если NULL - пайп нельзя
  19.                    унаследовать
  20.  
  21.     Когда пайп создается, мы имеем доступ к обоим концам. После создания
  22.     пайпа, сервер должен отослать один хэндл клиентскому процессу.
  23.  
  24.     чтение из пайпа синхронно - это означает, что функция не возвратится, пока
  25.     чтение не будет закончено
  26.  
  27.     push указатель на структуру данных
  28.     push указатель на количество прочтенных байтов
  29.     push количество байтов, которое нужно считать
  30.     push указатель на буфер, куда будет производиться чтение
  31.     push хэндл чтения из пайпа
  32.  
  33.     call ReadFile
  34.  
  35.  
  36.     указатель на структуру данных - эта структура используется для
  37.                                     асинхронного ввода и вывода; поэтому
  38.                                     напишем NULL
  39.     указатель на количество считанных байтов - указатель на dword, который
  40.                                                будет содержать количество
  41.                                                считанных байтов
  42.  
  43.     запись в пайп синхронна - это означает, что функция не возвратится, пока
  44.     запись не будет выполнена
  45.  
  46.     push указатель на структуру данных
  47.     push указатель на количество записанных байтов
  48.     push количество байтов, которое нужно записать
  49.     push указатель на буфер, содержащий записываемые данные
  50.     push хэндл записи в пайп
  51.  
  52.     call WriteFile
  53.  
  54.     Анонимные пайпы живут, пока открыты хэндлы чтения и записи. Мы можем
  55.     закрыть их с помощью функции CloseHandle.

Вот и все об анонимных пайпах.

Мейлслоты

Мейлслоты - это еще один простой способ взаимодействия между процессами. Его суть заключается в том, что один процесс (сервер) может коннектиться к мейлслоту и посылать эти сообщения. Мейлслоты используют датаграмы для коммуникации, а именованные слоты - нет (для удаленного взаимодействия). Уффф...

Код (Text):
  1.  
  2.   push защита
  3.   push время(ms) ожидания
  4.   push максимальный размер сообщения
  5.   push имя мейлслота
  6.  
  7.   call CreateMailslot(A/W)
  8.  
  9.   Возвращает имя мейлслота
  10.  
  11.   имя мейлслота - имя, которое имеет следующую форму:
  12.                   db "\\.\mailslot\[path]name", 0
  13.                 - имя должно быть уникальным, и в нем могут быть
  14.                   псевдодиректории ([path]), и (как обычно) оно не
  15.                   чувствительно к регистру
  16.  
  17.   максимальный размер сообщения - мы можем указать максимальную длину
  18.                                   записанного сообщения в мейлслот, как бы то
  19.                                   ни было, если это поле равно NULL, сообщение
  20.                                   может быть любого размера
  21.  
  22.   время ожидания - это время, которое ReadFile будет ждать, если сообщение
  23.                    еще не находится в мейлслоте. Есть несколько специальных
  24.                    значений:
  25.  
  26.                   0  - если нет сообщения в мейлслоте, функция не будет
  27.                        работать <img src="styles/smiles_s/smile3.gif" class="mceSmilie" alt=":smile3:" title="Smile3    :smile3:">
  28.                   -1 - функция будет ждать, пока в мейлслоте не появится
  29.                        сообщение - (MAILSLOT_WAIT_FOREVER)

Ладно, мы создаем мейлслот и у нас есть его хэндл. Мы можем закрыть его с помощью CloseHandle...

Теперь мейлслот создан и к нему можено получить доступ по имени. Клиенты могут подсоединяться с помощью функции CreateFile(A/W), используя имя мейлслота в качестве имени файла. После подсоединения клиент получает хэндл мейлслота и может записывать сообщения в него. Это делается с помощью функции WriteFile. Сервер считывает сообщения с помощью ReadFile. Как CreateFile, и ReadFile уже затрагивались в этом тексте, поэтому я не буду тратить время на повторное объяснения. как бы то ни было, есть еще несколько функций для работы с мейлслотами.

Код (Text):
  1.  
  2.   функции сервера мейлслота:
  3.  
  4.   push указатель на время ожидания чтения
  5.   push указатель на количество соощений
  6.   push указатель на размер следующего сообщения
  7.   push указатель на максимальный размер сообщения
  8.   push хэндл мейлслота        ; возвращается функцией CreateMailslot(A/W)
  9.  
  10.   call GetMailslotInfo
  11.  
  12.   Возвращает TRUE(1), если вызов прошел успешно
  13.  
  14.   указатель на размер следующего сообщения - этот параметр может быть равен
  15.             NULL, как бы то ни было, мы получим размер следующего сообщения в
  16.             мейлслоте. Мы можем получить MAILSLOT_NO_MESSAGE(-1) - это значит,
  17.             что в мейлслоте больше нет сообщений.
  18.  
  19.   указатель на количество сообщений - этот параметр может быть равен NULL,
  20.             если нет, то мы получим общее количество сообщений, которое нужно
  21.             прочитать.
  22.  
  23.   Чтобы установить время ожидания для операции чтения из мейлслота, мы можем
  24.   использовать:
  25.  
  26.   push время ожидания для операции чтения
  27.   push хэндл мейлслота
  28.  
  29.   call SetMailslotInfo
  30.  
  31.   Когда у нас есть хэндл мейлслота, мы можем использовать стандартные функции,
  32.   чтобы получить информацию о нем. Мы можем использовать:
  33.  
  34.      DuplicateHandle
  35.      GetFileTime
  36.      SetFileTime
  37.      GetHandleInformation
  38.      SetHandleInformation

Вот и все. © mort[MATRiX], пер. Aquila


0 1.240
archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532