Анализ защиты регистрационным ключом в библиотеке S7-OPEN MODBUS/TCP
Разбираем вариант защиты программного обеспечения для контроллеров Siemens.
Содержание:
Описание
Получаем ключ отладкой
Выделяем код генерации ключа
Автономный генератор ключа
Описание
Защита применена в библиотеке COMM, функции MODBUSCP, предназначенной для обмена данными по протоколу S7-OPEN MODBUS/TCP.
Сама восстановленная функция MODBUSCP - здесь
Чтобы выполнить правильную регистрацию, необходимо выполнить следующие шаги (взято из официального руководтсва):
Если функция незарегистрирована, при работе контроллера получаем сообщения каждые 4 секунды, в буфере диагностики, об отсутствии лицензии и ошибки обращения к блоку данных.
Ошибка обращения к блоку данных, формируется строкой PT.IN:=DB0.DBX0.0;
Получаем ключ отладкой
Беглый обзор кода функции, показывает, что полученный REG_KEY сравнивается внутри кода посимвольно, что означает что правильный код генерируется внутри функции.
Попробуем найти этот сгенерированный код с помощью пошаговой отладки.
Получаем IDENT_CODE:
Задаем серийный номер как константу
(на симуляторе серийный номер CPU не читается).
Устанавливаем точку останова после генерации IDENT_CODE.
Находим IDENT_CODE в экземплярном блоке:
Находим REG_KEY:
Устанавливаем точку останова после генерации лицензионного ключа tAlicenseKey
Изменяем немного участок кода, чтобы ключ копировался в удобную для обработки область sSTATUS_CODE
Копируем результат:
Эта строка и есть сгенерированный ключ.
Проверяем результат:
Создаем блок данных, в который прописываем этот ключ.
Подаем ключ на вход блока:
Результат:
Выделяем код генерации ключа
Анализируя код генерации и последовательно упрощая довольно запутанный код, получаем упрощенный вариант (вариант на PHP).
$serialn:='SC-W0VK37682008';
$tSProductID='MODCP2XV94501MB00';
for
($i = 1;
$i <=17; $i++)
{
$IDENT_CODE_arr[$i]=(($serialn_arr[$i]
^ $tSProductID_arr[$i]) % 13) + 65;
}
$IDENT_CODE_arr[18]=50;
Генерация идентификационного кода IDENT_CODE
$sHoldingRegisterState_arr =
ARRAY(0,
223, 32,
240, 67,
135, 170,
11, 0,
96, 159,
159, 33,
38, 64,
53, 0,
0, 1,
0, 0,
0, 0,
0 );
for
($i = 1;
$i <=17; $i++)
{
$tALicenseKey_arr[$i]=$IDENT_CODE_arr[$i]
^ ($sHoldingRegisterState_arr[$i-1]
^ ($i));
$tALicenseKey_arr[$i]=($tALicenseKey_arr[$i]
% 26) + 65;
}
$tALicenseKey[18]=50;
Генерация регистрационного ключа REG_KEY
Как видно, ничего особо сложного нет.
Небольшой вывод: защита довольно слабая, хотя без шифрования кода функции и/или применения аппаратных ключей добиться большего вряд ли возможно.
Автономный генератор ключа
Введя здесь серийный номер вашего CPU можно получить код регистрации.