- Codesys Software PLC Solution
- Contents
- Introduction
- Codesys on Linux
- Requisites for supporting Codesys on Linux
- Codesys Partner Demo Container
- Codesys Partner Demo Image
- Licensing Information
- Исследование безопасности: CODESYS Runtime — фреймворк для управления ПЛК. Часть 1
- Фреймворк
- Описание объекта исследования: CODESYS Runtime
- Связка продуктов компании CODESYS Group
- Архитектура
- Компоненты
- Структура компонентов
- Структура интерфейсов взаимодействия
- Настройка компонентов
- Адаптация
- Реализация
- Файл — установщик
- Файл конфигурации
- Исполняемый файл
- Запущенный процесс
- Информация в открытых источниках
Codesys Software PLC Solution
Contents
Introduction
Programmable Logic Controllers (PLCs) have been around since the late 60´s. They are basically digital computers adapted to industrial automation needs and are largely used in the most diverse manufacturing plants.
Our partner Codesys has a software PLC solution that can be deployed on our ARM-based System on Module families (Colibri and Apalis) in order to transform the module into a PLC solution. It is the perfect fit for use cases where the device end-user must have the capacity to program the device behavior. See the list of Devices using Codesys (you see some famous PLC brands like Beckhoff, Wago, and Eaton).
Codesys System provides several advantages for devices implementing PLC-like solutions. For licensing information please check here.
Codesys can run on Linux or Windows Embedded Compact, please see below for more information.
Codesys on Linux
Codesys can run in a variety of operating systems and hardware platforms including Linux and ARM-based devices.
Requisites for supporting Codesys on Linux
In order to run Codesys Control on Linux, you have to provide support for the OSADL real-time extension. The information on how to do this you find here.
Codesys Partner Demo Container
Learn how to run an evaluation of CODESYS on TorizonCore with the Partner Demo Container — Codesys.
Codesys Partner Demo Image
Attention: This Partner Demo Image is not available anymore. Toradex and CODESYS developed a Partner Demo Container as a replacement, which you can read more on Partner Demo Container — Codesys.
Steps to run the Codesys demo on the Colibri iMX6DL:
Download the pre-build image (tar.bz2 or zip) and extract its contents to a FAT formatted SD card. For Windows users, a program such as 7-zip can be used; if you are a Linux user:
Use the SD card to flash the Colibri iMX6DL module. Insert the card on the Carrier Board and stop the booting process. If your module is booting from Eboot (Windows CE), you will have to flash the U-Boot bootloader using the recovery mode. If your module already has the U-Boot bootloader, follow the steps for flashing Linux described here, which in most cases consists on stopping the boot process and running:
Install the Toradex-Device on the Codesys Development tool.
On the Codesys Development open Tool > Device Repository.
Codesys instruction 1
Download the device description hardware here. Change the file extension from .txt to .xml.
On the Device Repository window click on the Install button and select the file downloaded on the previous step.
After the process is finished you are ready to start a new project.
Codesys instruction 2
Download missing libraries in Library Manager menu entry.
Follow the procedure on the video below:
Licensing Information
If you want to License Codesys on Toradex hardware you can get in touch with our partners 3S-Smart Software Solutions GmbH or Nexo. For licensing information, check CODESYS Licensing page.
Источник
Исследование безопасности: CODESYS Runtime — фреймворк для управления ПЛК. Часть 1
Исследование безопасности технологий, которые используются разработчиками систем автоматизации и имеют потенциал применения на промышленных объектах по всему миру, является одним из приоритетных направлений работы Центра реагирования на инциденты информационной безопасности промышленных инфраструктур «Лаборатории Касперского» (Kaspersky ICS CERT).
В этой статье мы продолжаем рассказ об исследовании популярных OEM-технологий, входящих в состав продуктов большого количества производителей. Уязвимости в таких технологиях с большой вероятностью сказываются на безопасности многих, если не всех продуктов, в которых они используются. Иногда это могут быть сотни продуктов, используемых на производстве и в критической инфраструктуре. Именно так обстоит дело с CODESYS Runtime ® — фреймворком для разработки и выполнения программ автоматизированного управления технологическим процессом от компании CODESYS.
Согласно официальной информации от компании-разработчика, CODESYS Runtime уже адаптирован для более чем 350 устройств от различных вендоров, которые используются в энергетики, промышленном производстве, системах интернета вещей и промышленного интернета вещей и т.д. Отметим также, что в реальности эта цифра значительно больше, так как устройства множества компаний, которые используют фреймворк CODESYS Runtime для своих ПЛК, не находятся в официальном списке. Количество таких устройств постоянно растет — в 2016 году их было всего 140, — и мы не будем удивлены, если оно продолжит расти и в будущем.
Фрагменты технической информации были удалены в связи с требованием CODESYS Group. Более подробную информацию можно запросить по адресу security@codesys.com.
Фреймворк
В современном мире использование готового программного кода в своем продукте — скорее правило, чем исключение. Это позволяет разработчикам нового продукта не заниматься «изобретением велосипеда» и сокращает время на разработку.
Степень влияния стороннего кода на использующий его программный продукт и степень влияния на безопасность системы, в которой этот продукт используется, может быть различной.
Сторонний код часто используется для реализации конкретной функции или набора функций, таких как, отрисовка изображения, отображение пользовательского интерфейса, печать на принтере или сохранение данных в БД. Мы уже проводили исследования безопасности и обнаруживали уязвимости в различном стороннем коде. Например, в 2017 году — для части программно-аппаратного комплекса контроля соблюдения лицензионных соглашений и защиты приложения от «взлома» SafeNet Sentinel, а в 2018 — для библиотеки OPC UA от OPC Foundation.
С фреймворком CODESYS ситуация другая: разработчик ПЛК на основе CODESYS адаптирует фреймворк для работы на своих аппаратных комплексах и разрабатывает при необходимости дополнительные модули, используя предоставляемые CODESYS сервисные функции. Конечный пользователь ПЛК (инженер) разрабатывает при помощи среды разработки CODESYS код программы автоматизации технологического процесса. И поток выполнения разработанных дополнительных модулей и программы автоматизации технологического процесса контролируется на ПЛК адаптированным под него вариантом CODESYS Runtime.
Контроль фреймворком потока программы означает, что использование фреймворка накладывает ограничения на уровне архитектуры — на этапе проектирования продукта. Иначе говоря, фреймворк представляет собой уже созданный сложный механизм,
а пользовательский код должен стать винтиком в этом механизме.
С точки зрения обеспечения безопасности при использовании фреймворка разработчику необходимо ответить на следующие вопросы:
- Что внутри этого фреймворка?
- Как он работает?
- Как мне сделать свое ПО безопасным, если уязвимость не в моем коде, а во фреймворке?
Данная статья посвящена исследованию безопасности CODESYS Runtime. В ней мы дадим ответы на первые два вопроса: что происходит внутри этого фреймворка и как он работает. Также мы продемонстрируем один из способов обнаружения уязвимостей без возможности анализа исходного кода.
Описание объекта исследования: CODESYS Runtime
Прежде чем говорить о результатах исследования безопасности объекта, необходимо разобраться в том, что он из себя представляет. Техническое описание CODESYS Runtime, приведенное в этой главе, было сформировано нами в ходе его изучения.
Связка продуктов компании CODESYS Group
Компания CODESYS Group разрабатывает два основных продукта:
- Среда разработки — CODESYS Development System
- Среда исполнения — CODESYS Runtime
Оба продукта работают в связке. CODESYS Development System представляет собой IDE для разработки программ управления устройствами, на которых запущен CODESYS Runtime. В среду включено множество инструментов для упрощения процесса разработки и тестирования.
В контексте нашего исследования важно, что CODESYS Development System — это кастомизируемая среда разработки. На её основе созданы IDE SoMachine от компании Schneider Electric, TwinCAT от компании Beckhoff Automation, IdraWorks от компании Bosch, Wagilo Pro от компании WAGO, одноименные IDE CODESYS от компаний Owen, STW Technic, prolog-plc и другие IDE.
Для программирования контроллера с помощью IDE CODESYS Development System, на нем должен быть запущен CODESYS Runtime. Для корректного запуска CODESYS Runtime на конкретном устройстве его необходимо адаптировать под выбранную операционную систему и железо. Согласно информации на официальном сайте CODESYS, сами разработчики CODESYS адаптировали CODESYS Runtime только для 15 устройств. Дистрибьютерами же CODESYS Runtime был адаптирован для более чем 350 устройств.
Среди адаптированных CODESYS Runtime есть версии:
- Для одноплатных компьютеров с операционной системой Linux, такие как Raspberry Pi, UniPi, BeagleBone;
- Для Soft PLC на Windows и Linux;
- Для ПЛК компаний ASEM S.p.A, exceet electronics AG, Hitachi Europe GmbH, Hans Turck GmbH & Co. KG, elrest Automationssysteme GmbH, Janz Tec AG, Kendrion Kuhnke Automation GmbH, Beijer Electronics, ifm electronic gmbh, Nidec Control Techniques Limited, Advantech Europe B.V, WAGO Kontakttechnik GmbH & Co. KG, KEB Automation KG, Berghof Automation GmbH и многих других.
Архитектура
Компоненты
CODESYS Runtime основан на компонентно-ориентированной архитектуре, то есть представляет собой набор компонентов — модулей, на которые разделена каждая логическая или функциональная часть CODESYS Runtime.
Каждый компонент ответственен за свою задачу и область действия — например, отвечает за логирование, за сетевое взаимодействие, за взаимодействие по серийному кабелю, за распределенную нагрузку на ядрах, за отладку программы и т.д.
Компонентно-ориентированная архитектура CODESYS Runtime (источник)
Среди всех компонентов CODESYS Runtime можно выделить основные:
- ComponentManager, илиCM — компонент для запуска и инициализации всех остальных компонентов в системе;
- SystemComponents — группа компонентов для описания взаимодействий с операционной системой и с железной составляющей. Компоненты из этой группы отвечают за взаимодействие с физическими портами, с файловой системой, с работой по динамическому и статическому выделению памяти и т.д.
- CommunicationComponents – группа компонентов для взаимодействия с внешним миром, например по сети или через последовательный кабель;
- Applicationcomponents — компоненты управления программой ПЛК;
- Corecomponents — компоненты для управления ПЛК и его состоянием.
У разработчика есть несколько способов расширить CODESYS Runtime:
- Заменить существующие компоненты;
- Написать собственные компоненты;
- Написать собственные компоненты, которые будут расширять функциональность уже существующих компонентов.
Структура компонентов
Компоненты CODESYS — это динамические библиотеки (аналог *.dll в ОС Windows и *.so в ОС Linux). Все компоненты загружаются компонентом Component Manager.
CODESYS Runtime может иметь статическую и динамическую сборку.
Если CODESYS Runtime имеет статическую сборку, то программный код компонентов содержится в самом исполняемом файле.
Если же CODESYS Runtime имеет динамическую сборку, то в конфигурационном файле указывается список загружаемых компонентов, а файлы компонентов находятся отдельно от исполняемого файла.
Структура самого файла компонента не являлась объектом данного исследования, однако можно с уверенностью сказать, что в этой структуре содержится:
- Программный код компонента;
- Название компонента, имя автора, версия и описание компонента;
- Различные контрольные суммы и магические значения.
Структура интерфейсов взаимодействия
Более интересным, чем структура файла компонента, для исследования является то, каким образом CODESYS Runtime взаимодействует с внешними компонентами, и как внутренние компоненты взаимодействуют друг с другом.
Каждый компонент обязан содержать следующие функции: функцию инициализации, функцию экспорта, функцию импорта, функцию обработки событий, функции удаления и создания своей сущности. Также компонент обязан иметь свой уникальный числовой идентификатор.
Функции удаления и создания своей сущности — опциональны. Они оказались пустыми для большинства компонентов. Поэтому мы не станем здесь их рассматривать. Остальные же функции будут рассмотрены далее.
Реализация функции инициализации
Функция инициализации — аналог entry point для PE и ELF файлов, с той лишь разницей, что непосредственную работу компонента она не начинает. Вызов этой функции осуществляется компонентом Component Manager.
Декомпилированный код функции инициализации компонента CmpBlkDrvUdp из группы Communication
Функция ModuleCmpBlkDrvUdp_entry — функция инициализации. Аргумент для этой функции структура INIT_STRUCT. Обычно эта функция вызывается с использованием Component Manager для заполнения структуры. Функция инициализации заполняет поля в структуре, среди которых — все вышеперечисленные функции и идентификатор компонента, который для компонента CmpBlkDrvUdp равен 7.
Реализация функции обработки событий
Следующая интересная функция — это функция обработки событий. Для компонента CmpBlkDrvUdp этой функцией является ModuleCmpBlkDrvUdp_hook. Эта функция определяет по полученному идентификатору события, что от неё требует выполнить Component Manager.
Идентификаторы основных событий:
- CH_INIT_SYSTEM — идентификатор 1. В случае, если компонент относится к группе системных компонентов (SystemComponents), то ему необходимо инициализироваться;
- CH_INIT — идентификатор 2. Компоненты должны инициализировать все локальные переменные;
- CH_INIT2 — идентификатор 3. Компонент должен инициализироваться;
- CH_INIT_TASKS — идентификатор 5. Компонент может запустить свои потоки выполнения;
- CH_INIT_COMM — идентификатор 6. Компонент может начать коммуникацию;
- CH_EXIT_COMM — идентификатор 10. Компоненту необходимо завершить все каналы коммуникаций;
- CH_EXIT_TASKS — идентификатор 11. Компоненту необходимо остановить и завершить все созданные им потоки выполнения;
- CH_EXIT2 — идентификатор 13. Компоненту необходимо сохранить все данные перед вызовом CH_EXIT;
- CH_EXIT — идентификатор 14. Компоненту необходимо освободить память;
- CH_EXIT_SYSTEM — идентификатор 15. В случае если компонент относится к группе системных компонентов (SystemComponents), то ему необходимо освободить память;
- CH_COMM_CYCLE — идентификатор 20. Вызывается каждый цикл. Используется для созданных потоков выполнения.
Сравнение жизненного цикла работы компонента CODESYS с циклом работы динамически подключаемой библиотеки Windows (Dynamic Link Library)
События для обработки компонентом, как и события вызова DLL Windows, созданы «зеркальными» парами: [СH_INIT_SYSTEM — CH_EXIT_SYSTEM], [СH_INIT — CH_EXIT] и т.д.
Декомпилированный код функции ModuleCmpBlkDrvUdp_hook, в котором продемонстрирована обработка событий компонентом CmpBlkDrvUdp
На примере функции ModuleCmpBlkDrvUdp_hook видно следующее:
- Компоненты могут пренебрегать предусмотренными правилами работы с событиями и объединять обработку нескольких событий в одном обработчике, как это сделано, например, в рассматриваемой функции: при обработке события CH_INIT_COMM происходит одновременно инициализация потока выполнения и его непосредственный запуск, хотя для последней задачи предназначено событие CH_INIT_TASKS;
- Компоненты не обязательно должны обрабатывать все события. В том числе, компонентам не обязательно обрабатывать оба «симметричных» события, если одно событие из «зеркальной» пары уже было обработано — например, компонент CmpBlkDrvUdp не обрабатывает событие CH_EXIT, хотя им было обработано событие CH_INIT.
Реализация функций импорта и экспорта
Функция экспорта и функция импорта используют механизм, который в совокупности дает эффект работы экспортируемых и импортируемых функций в динамических библиотеках ОС Windows и Linux. Главная разница функций экспорта и импорта с библиотеками ОС Windows и Linux в том, что во время работы этих функций происходит регистрация экспортируемых функций и инициализация указателей на импортируемые функции.
Псевдо-код функции экспорта компонента CmpRasPi (есть исключительно в CODESYS Runtime for Raspberry PI)
Функция CMRegisterAPI использует в качестве первого аргумента указатель на заполненный массив, содержащий сведения об экспортируемых функциях, а в качестве последнего — идентификатор компонента. Для примера экспортируемой функции: на строке 10 есть заполненная структура exported_function с указателем на функцию sub_84e5bc0, именем функции “raspiyuv”, хешем 0xF81Fd05 и версией 0x3050400.
Таким образом компонент CmpRasPi предоставляет API для взаимодействия с модулем камеры на устройстве Rapsberry PI для всех остальных компонентов СodeSys и прикладных программ. Пример использования этого API продемонстрирован в примере проекта Camera.project для CODESYS Control for Raspberry Pi.
Код программы проекта Camera.project
Функция импорта в компонентах пытается найти функции, экспортируемые другими компонентами, и запомнить их местоположение.
Функция импорта модуля CmpApp
Функция CMGetAPI2 ищет функцию, которая была зарегистрирована другим компонентом. Первый аргумент — это имя функции, второй — значение, куда сохранить полученный указатель на функцию, третий — это ожидаемый хеш функции, если передается, и последний — ожидаемая версия.
Перед этим все эти функции были зарегистрированы компонентом SysTarget.
Фрагмент массива с экспортируемыми функциями
Механизм импорта и экспорта функций предоставляет разработчикам основную функциональность для создания собственных компонентов или расширения возможностей существующих.
Настройка компонентов
Механизм настройки компонентов демонстрирует, как работает часть архитектуры CODESYS Runtime. Поэтому он будет рассмотрен здесь как заключительная часть главы про архитектуру CODEYS Runtime.
Пользователю CODESYS Runtime предоставляется возможность управления компонентами через конфигурационный ini-файл. Конфигурационный ini-файл — это обычный текстовый файл, в котором находятся ключи и параметры для настройки компонентов.
Фрагмент файла конфигурации для CODESYS Control for Raspberry Pi
Component Manager инициализирует все компоненты. В первую очередь он инициализирует системные компоненты, такие как CmpMemPool, CmpLog, CmpSettings и SysFile и т.д.
Фрагмент лога запуска исполняемого файла CODESYS Control for Raspberry Pi
Среди системных компонентов есть компонент CmpSettings. Он интересен нам тем, что функция экспорта этого компонента регистрирует API, которыми пользуются все остальные компоненты для получения параметров из файла конфигурации.
Фрагмент массива экспортируемых функций компонента CmpSettings
Функции SettgGetIntValue и SettgGetStringValue используются большинством компонентов для определения параметров своей работы. По перекрестным ссылкам вызовов этих функций можно определить, какие компоненты могут быть настроены через файл конфигурации, и какие ключи необходимо указать в файле конфигурации.
Используя метод поиска вызовов функции SettgGetIntValue, по перекрестным ссылкам можно найти ключ DemoTimeUnlimited для настройки компонента ComponentManager:
Ключи настройки компонента ComponentManager
Адаптация
Возможность адаптировать CODESYS Runtime под любое железо и операционную систему — несомненно, главная его особенность. На разработчиках продукта с использованием фреймворка лежит ответственность по адаптации системных компонентов CODESYS Runtime под нужды и требования конкретного применения, включая тип технологического процесса. Адаптированный фреймворк CODESYS Runtime должен уметь взаимодействовать с аппаратными интерфейсами, Ethernet, освобождать и выделять память, работать с таймером, событиями, межпотоковым взаимодействием и т.д.
Системные компоненты из компонентно-ориентированной архитектуры CODESYS Runtime
Адаптация системных компонентов происходит путем экспортирования функций, которые требуют остальные компоненты (этот путь описан в предыдущей главе).
Проведя анализ нескольких вариантов CODESYS Runtime, мы выяснили, что системных компонентов всего 25.
Список основных системных компонентов:
После обеспечения работоспособности системных компонентов разработчик должен создать собственные модули CODESYS Runtime для ПЛК со специфичной функциональностью.
Реализация
В декабре 2016 вышла первая версия CODESYS Control for Raspberry Pi. В июне 2018 года — версия для Linux (CODESYS Control for Linux SL). Помимо этого, еще есть эмулятор CODESYS Control для Windows, который входит в пакет программ CODESYS Development System. Все эти реализации однотипны с реализацией CODESYS Control for Raspberry Pi и имеют схожие или полностью идентичные элементы реализации.
В этой главе мы рассказываем о реализации CODESYS Runtime на примерах CODESYS Control for Raspberry Pi и CODESYS Control for Linux SL.
Файл — установщик
CODESYS Development System передает на устройство Raspberry Pi установщик CODESYS Control, используя SSH client. Сам установщик представляет собой .deb-файл (Debian binary package).
Основными элементами .deb-файла являются файл конфигурации и исполняемый файл.
Файл конфигурации
Файл конфигурации содержит огромное количество различных параметров конфигурации для CODESYS Control. По содержимому этого файла можно сделать следующие выводы:
- CODESYSControlforRaspberryPi способен работать в качестве веб-сервера;
- CODESYS Control for Raspberry Pi использует OpenSSL;
- Есть параметры логирования для компонента CmpLog;
- Параметры компонента CmpSettings могут ссылаться на другие файлы;
- Для компонента SysProcess есть ключ Command.%d, значение параметра которого совпадает с именем системной утилиты shutdown в ОС Linux.
Содержимое файла конфигурации CODESYS Control For Raspberry Pi v3.5.14.10
Исполняемый файл
Параметры защиты файла
Первичный анализ исполняемых файлов, как правило, включает в себя проверку опций компиляции на предмет установки параметров защиты. Инструмент checksec показывает эти значения параметров защиты для исполняемых файлов.
Результат обработки утилитой checksec исполняемых файлов CODESYS Control for Raspberry Pi v3.5.14.10
По результатам работы утилиты видно, что исполняемые файлы CODESYS Control for Raspberry Pi v3.5.14.10 были скомпилированы без дополнительной защиты, которая могла бы усложнить эксплуатацию бинарных уязвимостей.
Чуть лучше ситуация с компиляцией файла CODESYS Control for Linux SL, потому что в этом файле содержится установленная опция PIE.
Результат обработки утилитой checksec исполняемых файлов CODESYS Control for Linux SL v3.5.14.10
Состояние исполняемого файла
Статический анализ исполняемого файла с помощью инструмента IDA Pro показывает, что этот файл на 99% состоит из данных (зеленый цвет), а не из машинного кода:
Состояние запокованного исполняемого файла CODESYS Runtime For Raspberry Pi
Обычно такое состояние характерно для исполняемых файлов, машинный код которых был запакован. Тем не менее, для всех исполняемых файлов обязательным атрибутом является наличие точки входа (Entry point). Для исполняемого файла CODESYS Runtime for Raspberry Pi точкой входа является функция start. С этой функции можно начать анализ.
Ассемблированный код функции start
Код функции start нормально распознается, и IDA Pro подсказывает, что функция sub_86a0840, она же функция main, также содержит валидный программный код.
Декомпилированный псевдокод функции sub_86a0840
Функция main записывает в глобальные переменные количество аргументов командной строки и указатель на их значения (строки 3:4). Затем она вызывает функцию mprotect (строка 5), которая изменяет параметры доступа к области памяти. Первый аргумент — указатель на функцию start или же начало сегмента .text. Второй аргумент — размер памяти, параметр доступа к которой будет изменен. Размер памяти также должен указывать на конец сегмента. Последний аргумент — это параметры доступа к памяти, на которые меняются исходные параметры. Его значение равно 7, то есть суммарному значению параметров PROT_READ | PROT_WRITE | PROT_EXEC.
Иначе говоря, строка 5 готовит область памяти к распаковке и возможности выполнения программного кода в этом участке памяти. Затем вызывается следующая функция (строка 6) и в качестве аргумента передается указатель на участок памяти, которым является переменная dword_86A0460, – это указатель на оригинальную функцию main после распаковки.
Таким образом, для дальнейшего исследования файла необходимо его распаковать.
Запущенный процесс
CODESYS Runtime for Raspberry Pi и for Linux выполняет трассировку своего процесса, то есть CODESYS Runtime for Raspberry Pi и For Linux занимается отладкой самого себя. Данный механизм используется в двух случаях: для перехвата системных вызовов (syscalls) и для реализации простейшей защиты от отладки: к запущенному процессу CODESYS Runtime нельзя присоединиться, используя сторонние инструменты отладки, такие как gdb, IDA Pro, radare или же strace.
Трассировка
Запуск утилиты strace с ключом –f на исполняемый файл CODESYS Control For Raspberry Pi v3.5.14.00
Из лога запуска утилиты strace с ключом -f видно, что CODESYS Runtime меняет параметры доступа к памяти (строка 06), что, как известно из предыдущего пункта, нужно для распаковки программного кода.
Далее syscall clone создает дочерний процесс (строка 13). Родительский процесс имеет идентификатор 4289. Созданному дочернему процессу присвоен идентификатор 4290. Из-за наличия ключа -f strace пытается трассировать дочерние процессы, поэтому на строке 14 происходит оповещение о подключении к созданному дочернему процессу.
Далее родительский процесс пытается возобновить работу остановленного дочернего процесса вызовом функции ptrace с аргументом PTRACE_CONT (строка 17). Дочерний процесс в это время выполняет ptrace с аргументом PTRACE_TRACEME (строка 20), обозначив этим, что этот процесс должен быть трассирован родительским процессом.
Однако, результат выполнения функции указывает на то, что процесс не может быть трассирован родительским процессом. Из-за этого дочерний процесс завершает свою работу (строки 21:22). После этого родительский процесс получает ответ от функции ptrace (строка 23) и узнает, что дочернего процесса уже нет в системе. Далее родительский процесс пытается еще раз обратиться к дочернему процессу (строка 28) и, снова не обнаружив его, завершает свою работу (строки 29:30).
На этом утилита strace завершает свою работу.
Отладка
Аналогичная ситуация возникнет, если попробовать запустить исполняемый файл под отладчиком gdb.
Запуск отладчика gdb на исполняемый файл CODESYS Control For Raspberry Pi v3.5.14.00
Для отладки дочернего процесса для gdb необходимо выставить соответствующий режим set follow-fork-mode child (строка 17). После этого запустить CODESYS Runtime (строка 18). Далее создается дочерний процесс (строка 22), и спустя некоторое время программа самозавершается (строки 26:27).
Таким образом, для исследования исполняемого файла после распаковки его нужно привести в состояние, способное к отладке.
Необходимо сказать, что существует возможность сэмулировать успешно созданный процесс трассировки файла, указав в качестве переменной окружения LD_PRELOAD библиотеку, которая будет содержать функции fork, ptrace, getppid и getsid. Однако на этом этапе это не будет иметь особой эффективности.
Потоки
CODESYS Runtime — многопоточное приложение. Помимо того, что запущенный процесс клонируется и выполняет трассировку дочернего процесса, дочерний процесс порождает огромное количество потоков. Системные утилиты Linux ps и htop получают список потоков, созданных процессом.
Получение списка потоков, порожденных процессом исполняемого файла CODESYS Control for Raspberry Pi v3.5.14.00
По результату выполнения утилиты ps и фильтрации вывода утилитой grep видно, что дочерний процесс имеет идентификатор 5405 (строка 03).
Результат выполнения команды htop для процесса 5405 (строка 06) выводит потоки, созданные дочерним процессом (строки 09:18).
Из имен потоков частично узнаются имена компонентов группы коммуникации (компонент BlkDrvTcp, компонент BlkDrvUdp), имя индустриального протокола OPC UA.
Сетевые коммуникации
По результатам работы утилиты netstat, CODESYS Runtime слушает следующие порты:
Список прослушивающих портов, открытых процессом исполняемого файла CODESYS Control for Raspberry Pi v3.5.14.00
CODESYS Runtime слушает как TCP, так и UDP порты. TCP порт 11740 (строка 2) используется для TCP-связи между CODESYS Runtime и CODESYS Development System.
UDP порт 1740 (строка 7) используется для этой же цели, только общение осуществляется по UDP-протоколу.
Также CODESYS Runtime слушает UDP порт 1740 на широковещательном адресе (строка 6). Широковещательные адреса на стороне клиентов обычно слушаются для возможности обнаружения этих клиентов серверами, т.е. в качестве discovery service. TCP порт 4840 (строки 4:5) используется в качестве discovery service OPC UA.
Информация в открытых источниках
Поиск информации в открытых источниках — неотъемлемая часть исследовательской работы. Нами было найдено:
- Удалено по требованию вендора. Содержит технический обзор архитектуры CODESYS Control.
- Удалено по требованию вендора. Содержит много полезной информации для статического анализа, например, аргументы и назначения функций.
- Руководство по адаптации CODESYS Control (удалено по требованию вендора). Описывает базовый подход по портированию CODESYS Runtime на устройство без ОС.
К сожалению, вся обнаруженная документации датируется концом 2015 года. Однако её изучение было необходимо: несмотря на устаревшие версии документов, они дали множество подсказок на вопросы, которые возникали во время исследования протокола общения между CODESYS Development System и CODESYS Runtime.
Источник