OLE, COM, COM+
Обратная разработка программного обеспечения — процедура получения информации об алгоритме. При этом получение этих данных напрямую зависит от того, насколько много есть информации о приложении в документации, и от того, какой использовался способ для создания файла. Всё еще больше усложняется, если алгоритм заимствует фрагменты из других приложений или операционной системы. Эта статья расскажет о механизмах, которые заложены в ОС Windows, благодаря которым процесс обратной разработки может стать весьма сложным процессом.
С чего всё началось
Появление парадигмы объектно-ориентированного программирования подарило программистам очень мощные инструменты для обработки информации. Начали появляться новые языки, которые использовались для разных спектров задач, программное обеспечение становилось модульным. Написание новой программы с функционалом, который использовал стандартные механизмы ввода/вывода стало тривиальной задачей. Нужно было только подключить нужную библиотеку, которая уже содержала все необходимые функции.
Результатом использования парадигмы объектно-ориентированного подхода стали методы логического разбиения приложений на отдельные фрагменты, при этом можно было создавать уже скомпилированные части кода, которые собирались в новые приложения. Модульность позволила задуматься о механизмах, которые могли бы позволить объединять код, фрагменты которого были бы написаны на разных языках программирования, в одну систему, которая решала бы отдельно взятую проблему или целый класс проблем.
В операционной системе Windows подход к созданию отдельных компонентов был реализован в предоставлении унифицированных интерфейсов, которыми приложения пользуются и по сей день. Эти интерфейсы называются WinAPI. Их исследование достаточно тривиально, большая часть интерфейсов задокументирована и поэтому их обратная разработка заключается в том, чтобы найти в документации название и прочитать данные о параметрах и возвращаемом значении.
Каждый WinAPI интерфейс позволяет сделать минимальное действие, которое может произвести ОС, то есть если программист решит написать приложение, то для его реализации придётся задействовать несколько сотен, а то и тысяч интерфейсов. Отдельно стоит упомянуть, что это далеко не единственный способ, который доступен в ОС для реализации алгоритмов. ОС Windows также предлагает компонентный подход для построения приложений. Это означает, что программист может объединять целые программы вместе, чтобы реализовать выполнение алгоритма. Возможно это за счет использования механизма Component Object Module.
Появление COM не случайно, реализация этого механизма — логичный этап развития. На схеме ниже можно увидеть ретроспективу создания механизмов в ОС Windows:

Картинка наглядно показывает, как связано появление того или иного механизма. Реализация каждого нового механизма это решение проблем, которые возникли при реализации предыдущего механизма. Картинка включает в себя такие механизмы как OLE, COM+, DCOM, которые тоже, надо сказать очень сложные с точки зрения реализации и изучения.
Некоторые полезные определения
Представленная выше картинка с годами внедрения механизмов в ОС дает наглядное представление, что механизмы, которые сегодня используются, были созданы почти 22 года назад. Создание актуальной документации для такого длительного периода времени весьма сложная задача и соответственно, когда встает вопрос об обратной разработке ПО, которое использует указанные выше механизмы, нужно точно знать, ЧТО делает каждый из них.
COM дает возможность переиспользовать куски приложения. Работает за счет того, что можно собрать исполняемый кусок кода и расположить его в реестре ОС. Кусок кода получит уникальный идентификатор и будет вызывать ОС каждый раз, как приложения будут запрашивать обработку данных по идентификатору. Для создания кода можно использовать любой компилируемый язык программирования.
OLE — механизм связывания и внедрения данных в различные приложения. Больше всего распространен в приложениях, которые используются для офисных задач. Открытие таблицы Excel в документе Word самый распространенный пример использования механизма.
DCOM — механизм, который предоставляет возможность работать с объектами COM в рамках локальной сети или Интернета.
COM+ — механизм, который может быть использован для создания распределенного на целые кластера программного обеспечения. Включается в себя COM, предоставляет для объектов механизмы, которые позволяют с ними общаться по сети. Предоставляет механизмы по синхронизации, отказоустойчивости и разграничению доступа.
Примеры и практика
Давайте попробуем посмотреть, как обозначенные выше механизмы выглядят в ПО при обратной разработке. Начнем с OLE. Как было сказано выше, этот механизм проще всего обнаружить в офисных документах. Попробуем найти такой документ.
Для исследования был выбран вот этот документ. Он представляет собой docx файл, по сути это архив, который содержит некоторое количество файлов с инструкциями, как его рендерить. Заглянем внутрь: в этом формате все данные, которые могут быть добавлены через OLE это файлы, которые расположены в директории «word/embeddings». Заголовок содержимого объекта можно видеть ниже:

Ничего особенно примечательного, такие объекты можно анализировать с использованием набор инструментов oletools.
OLE объект представляет собой файловую систему, в которую можно положить информацию необходимую для встраивания данных. Если воспользоваться инструментом oleobj, то можно увидеть, что внутри объекта находится txt файл. Кстати, это можно увидеть и из шестнадцатеричного редактора:

Объект COM — представление зависит от типа предоставляемого функционала, чаще всего в программном обеспечении используется в совокупности с WinAPI CoCreateInstance. Визуально исследовать объекты можно через относительно простой инструмент — COMView. Пример работы инструмента:

Почти все элементы пользовательского интерфейса, которыми мы пользуемся каждый день, это COM объекты.
Как найти объекты COM+? Если в COMView вы обнаружили объект, который имеет интерфейс IUnknown, перед вами COM+ объект. Например:

Таким образом можно установить, за какой функционал отвечает тот или иной объект, который используется программным обеспечением. При этом не нужно вникать в имплементацию и можно сразу разобраться в алгоритме приложения, прочитав описание объекта в интерфейсе COMView.
Статья подготовлена Александром Колесниковым в рамках курса «Reverse-Engineering. Professional». Если интересно узнать больше о программе и формате обучения на этом курсе, приходите на день открытых дверей онлайн, на котором вы также сможете познакомиться с преподавателем.
Технология COM
COM (англ. Component Object Model — объектная модель компонентов;) — это технологический стандарт от компании Microsoft, предназначенный для создания программного обеспечения на основе взаимодействующих компонентов, каждый из которых может использоваться во многих программах одновременно. Стандарт COM закрепился в основном на операционных системах семейства Microsoft Windows. В современных версиях Windows COM используется очень широко. На основе COM были реализованы технологии: Microsoft OLE Automation, ActiveX, DCOM, COM+, DirectX, а также XPCOM.
В технологии COM приложение предоставляет для использования своей службы, применяя для этого объекты COM. Одно приложение содержит как минимум один объект. Каждый объект имеет один или несколько интерфейсов. Каждый интерфейс объединяет методы объекта, которые обеспечивают доступ к свойствам (данным) и выполнение операций. Обычно в интерфейсе объединяются все методы, выполняющие операции одного типа или работающие с однородными свойствами.
Клиент получает доступ к службам объекта только через интерфейс и его методы. Этот механизм является ключевым. Согласно спецификации COM, уже созданный интерфейс не может быть изменен ни при каких обстоятельствах. Это гарантирует постоянную работоспособность приложений на основе COM, невзирая на любые модернизации.
Объект всегда работает в составе сервера COM, который может быть динамической библиотекой или исполняемым файлом. Объект может иметь собственные свойства и методы или использовать данные и службы сервера.
Для доступа к методам объекта клиент должен получить указатель на соответствующий интерфейс (для каждого интерфейса существует собственный указатель), после чего клиент может использовать службы объекта, просто вызывая его методы. Доступ к свойствам объектов осуществляется только через его методы.
Объект СОМ – это некоторая сущность, имеющая состояние и методы доступа, позволяющие изменять это состояние. СОМ-объекты можно создавать прямым вызовом специальных функций, но напрямую уничтожить его невозможно. Вместо прямого уничтожения используется механизм самоуничтожения, основанный на подсчете ссылок. Самым близким аналогом в объектно-ориентированных языках программирования является понятие объекта в языке Java. Так, в COM присутствует понятие класса. Класс в COM носит название CoClass.
Согласно правилам обозначения объектов COM, базовый интерфейс IUnknown, который имеется у любого объекта, обозначается как кружок, примыкающий к верхней стороне прямоугольника объекта. Остальные интерфейсы обозначаются справа и слева.
Взаимодействие между клиентом и объектом обеспечивается базовыми механизмами COM. При этом от клиента скрыто, где именно расположен объект: в адресном пространстве того же процесса, в другом процессе или на другом компьютере. Механизм обеспечения взаимодействия между удаленными элементами COM называется маршалингом (marshalling).



Рисунок 2.1 – Схема взаимодействия клиента и объекта COM
Любой объект COM является обычным экземпляром некоторого класса, описывающего его свойства и методы. Информация обо всех зарегистрированных и доступных в данной ОС классах COM собрана в специальной библиотеке COM, которая используется для запуска экземпляра класса – объекта.
Сначала объект обращается к библиотеке COM, передавая ей имя требуемого класса и необходимого в первую очередь интерфейса. Библиотека находит нужный класс и сначала запускает сервер, который затем создает объект – экземпляр класса. После этого библиотека возвращает клиенту указатели на объект и интерфейс. В последующей работе клиент может обращаться непосредственно к объекту и его интерфейсам.
После создания наступает очередь инициализации – объект должен загрузить необходимые данные, считать настройки из системного реестра и т.д. За это отвечают специальные объекты COM, которые называются моникерами (monikers). Они работают скрытно от клиента. Обычно моникер создается вместе с классом.
Довольно реальной представляется ситуация, когда одновременно несколько клиентов обращаются к одному объекту. При соответствующих настройках для каждого клиента создается отдельный экземпляр класса. За выполнение этой операции отвечает специальный объект COM, который называется фабрикой класса.
Объект COM
Центральным элементом COM является объект. Приложения, поддерживающие COM, имеют в своем составе один или несколько объектов COM. Каждый объект представляет собой экземпляр соответствующего класса и содержит один или несколько интерфейсов.
Любой объект является экземпляром некоторого класса, т.е. представляет собой переменную объектного типа. Поэтому объект обладает набором свойств и методов, которые работают с этими свойствами. К объектам применимы три основные характеристики: инкапсуляция (Инкапсуляция (encapsulation) — это механизм, который объединяет данные и код, манипулирующий зтими данными, а также защищает и то, и другое от внешнего вмешательства или неправильного использования. В объектно-ориентированном программировании код и данные могут быть объединены вместе; в этом случае говорят, что создаётся так называемый «чёрный ящик». Когда коды и данные объединяются таким способом, создаётся объект (object). Другими словами, объект — это то, что поддерживает инкапсуляцию.), наследование ( это процесс, посредством которого один объект может приобретать свойства другого) и полиморфизм (в языках программирования полиморфизм — возможность объектов с одинаковой спецификацией иметь различную реализацию.). Объекты COM всем этим требованиям удовлетворяют.
Применительно к объектам вообще понятие интерфейса объекта, как он был определен выше, не используется. В первом приближении можно считать, что все методы объекта составляют его единственный интерфейс, а указателем интерфейса является указатель на объект.
Объект COM может иметь любое число интерфейсов (если это число больше нуля), причем, каждый интерфейс обладает собственным указателем. Это первое отличие объектов COM от обычных.
У объектов COM имеется особенность еще в одном объектом механизме – наследовании. Вообще различают два способа наследования. Наследование реализации подразумевает передачу родителем потомку всего программного кода. Наследование интерфейса означает передачу только объявления методов, их программный код потомок должен предоставить самостоятельно.
Объекты COM поддерживают только наследование интерфейса, избегая тем самым возможного нарушения инкапсуляции родителя. Тем не менее, просто так выбросить наследование реализации нельзя. Вместо нее объекты COM используют механизм включения, т.е. при необходимости потомок вызывает нужный метод родителя. Также применяется механизм агрегирования, когда один или несколько интерфейсов одного объекта на время включаются в другой объект путем передачи указателей.
Component Object Model
Шаблон:Нет сносок COM ( Шаблон:Lang-en — объектная модель компонентов; произносится как [ком]) — это Microsoft, предназначенный для создания объектно-ориентированного программирования . Стандарт COM мог бы быть универсальным и платформо-независимым, но закрепился в основном на операционных системах семейства Microsoft Windows . В современных версиях Windows COM используется очень широко. На основе COM были реализованы технологии: ActiveX , DCOM, COM+, DirectX, а также XPCOM .
Содержание
История COM [ ]
Стандарт COM был разработан в OLE . Технология OLE 1.0 уже позволяла создавать т. н. « Шаблон:Lang-en ): например, в пакете Microsoft Office эта технология позволяла включать диаграммы Microsoft Excel в документы Microsoft Word.
Путаница в названиях [ ]
Некоторая путаница между понятиями OLE и ActiveX сохраняется и до сих пор, но речь идёт об одних и тех же COM-технологиях. Причём иногда даже путают понятия OLE и COM. Так, внедряемые OLE-объекты иногда называют COM-объектами, а OLE-контейнеры — COM-контейнерами, и т. п.
Принципы работы COM [ ]
Технологии, основанные на стандарте COM [ ]
Выпущенная в Шаблон:Lang-en — распределённая COM) основана на технологии CORBA .
Как DCOM, так и CORBA решают задачу вызова метода объекта, расположенного на другой машине, а также передачу ссылки на объект с одной машины на другую.
Сетевой уровень DCOM называется ORPC (Object RPC) и является объектно-ориентированным расширением DCE RPC.
Технология DCOM обеспечивает базовые установки безопасности, позволяя задавать, кто и из каких машин может создавать экземпляры объекта и вызывать его методы.
Microsoft Transaction Server был включен в Option Pack для Windows NT4 еще в 1997 году.
MTS/COM+ использовался внутри ряда версий веб-сервера MS ISAPI , так и скриптовых по технологии ASP (сама asp.dll есть ISAPI-приложение).
COM+ объединяет компоненты в так называемые приложения COM+, что упрощает администрирование и обслуживание компонентов. Безопасность и производительность — основные направления усовершенствований COM+. Некоторые идеи, заложенные в основу COM+, были также реализованы в Microsoft .NET .
.NET и будущее COM [ ]
В Microsoft .NET , которая на сегодняшний день объявлена Microsoft рекомендуемой основой для создания приложений и компонентов под Windows. По этой причине в .NET включены и средства, позволяющие обращаться к компонентам COM из приложений .NET , и наоборот. По словам представителей Майкрософт, COM (точнее, COM+) и .NET являются отлично взаимодополняющими технологиями.
DCOM через интернет и решение проблемы XP SP2 [ ]
В 2009 году DComLab опубликовал коммерческий продукт ComBridge. При использовании ComBridge для работы по DCOM через интернет не требуется CIS, не используется 135 порт, в локальной сети не требуются настройки dcomcnfg. ComBridge встраивается в транспортный уровень DCOM, полностью выделяя весь трафик созданного объекта и всех полученных из него объектов в отдельный поток.
Технология COM (Component Object Model)
До появления COM существовало множество разрозненных сервисов, выполняемых в среде MS Windows. Каждый из них выполнял или выполняет лишь свои узкие (или не очень) задачи. Чаще всего эти сервисы были совершенно несовместимы друг с другом и требовали от программиста знания сразу нескольких технологий (например Windows API, средства межпроцессорной связи, компоненты, разработанные для конкретной среды программирования).
Например, при статической компоновке с исполняемым модулем, запуске приложением другого приложения или вызовом программным модулем функций операционной системы, — везде используются принципиально разные механизмы доступа составных частей ПО друг к другу. Таким образом, из разрозненных частей, таких как Windows API, DDE, VBX и др., практически невозможно построить единую, устойчиво работающую систему, обеспечивающую реальный рефакторинг (повторное использование исходного кода).
С приходом COM всё изменилось. COM представляет собой универсальный способ взаимодействия программных модулей. В этой спецификации, разработанной компанией Microsoft, описаны требования, следуя которым становится возможным создание компонентов, предоставляющие свои сервисы единообразно. Причём вне зависимости от языка программирования или используемой ИСР (интегрированной среды разработки, IDE).
Модель COM определяет бинарный (двоичный) стандарт для построения компонентов приложений, а также принципов их взаимодействия друг с другом. Физическим воплощением является скомпилированный (в любой среде программирования!) двоичный модуль, полностью соответствующий требуемым стандартам.
Способ взаимодействия, который определяет COM, даёт программисту прочный фундамент для создания легко расширяемого, моудльного, переносимого программного обеспечения.
Многие службы ОС Windows основаны на использовании COM. Например, к Windows Explorer можно получить доступ через COM.
Основные понятия COM
- клиент — это программа, использующая возможности компонента;
- сервер — это программный модуль, содержащий компонент COM.
COM и DirectX
Компоненты DirectX, появившиеся в первых версиях этой бибилотеки, как правило, пытались скрыть свою COM-сущность (например, путём внедрения специальных функций, которые брали на себя всю работу по инициализации среды и созданию нужного интерфейса). Появившийся позднее DirectMusic и некоторые другие компоненты не имеют подобных функций, и для работы с ними требуется понимание основ используемой модели COM вцелом.
Все компоненты DirectX реализованы как внутрипроцессные серверы и физически содержатся в DLL-файле. Такой подход позволяет обеспечить самую высокую производительность. А всё из-за того, что при работе с интерфейсом отсутствуют посредники, выполняющие, например, преобразование адресов. Библиотеки DLL, содержащие компоненты DirectX, подключаются напрямую к адресному пространству процесса (выполняемого приложения).
В документации DirectX SDK прототипы методов для всех интерфейсов приведены в виде объявления методов классов. То есть указатель на экземпляр интерфейса для методов не указывается. В языках, отличных от C++, необходимо явно передавать методу указатель на его интерфейс.
Физическая реализация интерфейсов COM
COM — это двоичный стандарт, обеспечивающий построение компонентов. Физически двоичная структура интерфейса COM аналогична двоичной структуре, которую компиляторы C++ генерируют для абстрактного класса C++.
Абстрактный класс (в C++) — класс, содержащий только виртуальные функции-методы (методы, для которых отсутствует реализация). Причиной создания таких методов является возможность вызывать в базовом классе методы, которые будут определены лишь в производных классах. Невозможно создать экземпляр абстрактного класса. Каждый класс, производный от абстрактного класса, должен определить свою реализацию чисто виртуальных методов. Лишь после этого появляется возможность создания экземпляров производного класса. Чисто виртуальные методы, которые производный класс переопределяет, для него становятся просто виртуальными методами.
Для каждого класса, содержащего виртуальные методы, компилятор создаёт специальную таблицу, в которой содержатся указатели на конкретные реализации виртуальных методов. Если класс переопределяет виртуальный метод базового класса, то в таблицу заносится указатель на переопределённый метод. Физически, для класса, содержащего виртуальные методы, указатель на таблицу виртуальных методов (обычно называемую vtable) хранится в первых четырёх байтах конкретного экземпляра класса.
Структура класса, содержащего виртуальные методы, приведена на Рис. 2.
Библиотека COM содержит функции, которые выполняют наиболее распространённые и общие действия по созданию компонентов и управлению интерфейсами. Пример — запуск сервера клиентом. Обрати внимание на то, что это именно функции, а не методы, принадлежащие какому-либо интерфейсу. Большинство функций библиотеки COM выполняют специфичные действия и применяются лишь в очень редких случаях. Такие функции, как правило, всегда имеют в названии префикс Co, что указывает на их принадлежность к библиотеке COM.
Инициализация COM. Функции CoInitialize и CoInitializeEx
При использовании функции CoInitializeEx в многопоточном приложении, во втором параметре необходимо указать т.н. режим (модель) взаимодействия для корректной работы системы COM. Параметр dwCoInit может принимать следующие значения:
| ЗНАЧЕНИЕ | ОПИСАНИЕ |
|---|---|
| COINIT_APARTMENTTHREADED | При инициализации не создаётся нового клиентского подразделения. Все действия происходят в клиентском подразделении STA. Аналогично вызову CoInitialize. |
| COINIT_MULTITHREADED | При инициализации создаётся новое клиентское подразделение MTA. Инициализирует поток для работы в многопоточном режиме. |
| COINIT_DISABLE_OLE1DDE | Отключает DDE для поддержки OLE1. |
| COINIT_SPEED_OVER_MEMORY | При создании потока COM увеличивает объём используемой памяти для улучшения быстродействия. |
Самый нормальный флаг (значение параметра dwCoInit) здесь — COINIT_MULTITHREADED. 4
Клиентское подразделение в COM
Для большинства компонентов DirectX вызовы этих функций являются избыточными, так как их инициализация происходит внутри специальных "создающих" функций (например DirectSoundCreate). В то же время, во многих примерах DirectX SDK такая инициализация всё равно производится. Выполнять инициализацию библиотеки COM или нет, остаётся на усмотрение программиста.
