Можно ли надежно защитить код внешних обработок 1С без использования внешних компонент?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Вопрос защиты интеллектуальной собственности в среде 1С:Предприятие всегда стоит остро для разработчиков тиражных решений. Мы часто сталкиваемся с дилеммой: использовать неудобные в поддержке внешние компоненты (Native API) или пытаться скрыть алгоритмы средствами самой платформы. В данной статье мы разберем реальный кейс тестирования самописной системы защиты (СЛК) и выясним, почему защита кода, исполняемого непосредственно платформой 1С, является уязвимой.

Постановка задачи: защита без DLL

Традиционный подход к защите "нетленки" (тиражного продукта) заключается в выносе критической бизнес-логики во внешние компоненты (DLL), написанные на C++, C# или других компилируемых языках. Это надежно, так как злоумышленнику приходится иметь дело с машинным кодом, а не с байт-кодом 1С.

Однако поддержка внешних компонент накладывает ряд ограничений:

  1. Необходимость компиляции под разные операционные системы (Windows, Linux) и архитектуры (x86, x64, ARM).
  2. Сложность передачи контекста базы данных внутрь компоненты.
  3. Проблемы с регистрацией компонент на клиенте или сервере.

В рассматриваемом нами случае была предпринята попытка создать защиту, которая хранит код в зашифрованном виде внутри макета или двоичных данных, и распаковывает его "на лету" для выполнения платформой, не используя при этом классические внешние компоненты для сокрытия логики.

Анализ уязвимости: как платформа работает с кодом

Давайте разберемся, что происходит, когда 1С запускает внешнюю обработку или отчет. Даже если файл обработки (epf/erf) зашифрован или защищен паролем, для его исполнения платформа должна выполнить следующие действия:

  1. Прочитать файл с диска или из хранилища.
  2. Расшифровать содержимое, если оно защищено.
  3. Разместить исполняемый код (модуль объекта, модуль формы) в оперативной памяти процесса (1cv8.exe или rphost).
  4. Скомпилировать исходный код в байт-код (внутреннее представление 1С) для исполнения виртуальной машиной.

Именно на третьем и четвертом этапах кроется фундаментальная уязвимость любых защит, основанных на "скрытии" кода внутри самой платформы.

Методика обхода защиты через дамп памяти

В ходе эксперимента защита была взломана сообществом примерно за 15 минут. Давайте проанализируем, как именно это было сделано. Злоумышленнику не нужно пытаться расшифровать алгоритм старым способом (брутфорс пароля или анализ файла на диске). Достаточно позволить платформе сделать всю работу за него.

Алгоритм действий при взломе:

  1. Запускается штатная платформа 1С.
  2. Инициируется открытие защищенной обработки (через Файл - Открыть или программно).
  3. В этот момент срабатывает механизм защиты автора: он проверяет лицензию, расшифровывает код и передает его платформе для подключения.
  4. Платформа загружает расшифрованный модуль в оперативную память.
  5. Исследователь использует специализированное ПО (дампер памяти) для сканирования адресного пространства процесса 1С.

Поскольку обработка была успешно инициализирована, её исходный код (или байт-код, который легко декомпилируется) неизбежно оказывается в памяти в открытом виде.

Рассмотрим пример того, как код подключается в 1С. Обычно используется конструкция вида:


// Пример программного подключения внешней обработки
Адрес = ПоместитьВоВременноеХранилище(ДвоичныеДанныеОбработки);
ИмяОбработки = ВнешниеОбработки.Подключить(Адрес, "ЗащищенныйМодуль", Ложь);
// В этот момент код уже в памяти и доступен для дампа
Объект = ВнешниеОбработки.Создать(ИмяОбработки);

Участники тестирования отметили, что найти код удалось, зная адрес подключения внешней обработки или просто просканировав память на наличие характерных строк кода 1С.

Проблема очистки памяти

Можно предположить, что решением было бы мгновенное удаление кода из памяти после выполнения. Однако мы должны учитывать особенности работы менеджера памяти 1С и операционной системы.

Платформа 1С:Предприятие не гарантирует немедленную очистку памяти (Garbage Collection) после уничтожения объектов. Даже если вы программно закроете обработку, её след (фрагменты кода) может оставаться в оперативной памяти неопределенное время, пока этот участок памяти не будет перезаписан другими данными.

Как было замечено в обсуждении: "Чертова 1С не чистит память за собой". Это делает атаку через дамп памяти (Memory Dump) крайне эффективной против любых защит, написанных на самом языке 1С.

Существующие альтернативы и выводы

На основе проведенного анализа мы можем сформулировать следующие рекомендации по защите конфигураций и обработок:

  1. Внешние компоненты (Native API). Это по-прежнему самый надежный способ. Логика пишется на C++/Rust/Delphi, компилируется в DLL/SO. В 1С передаются только входные данные, а возвращается результат. Вскрыть такую защиту требует навыков обратной разработки (Reverse Engineering) уровня Ассемблера, что на порядок сложнее дампа памяти 1С.
  2. Вынос логики на Web-сервер. Самый надежный метод. Обработка 1С превращается в "тонкий клиент", который отправляет JSON/XML на ваш сервер, где происходит расчет, и получает ответ. Код алгоритмов вообще не попадает к клиенту.
  3. Обфускация. Если использование DLL или Web-сервисов невозможно, стоит применять обфускацию. Это не шифрование, а запутывание кода (замена имен переменных на П1, П2, удаление форматирования, добавление мусорного кода). Это не спасет от кражи кода (его так же достанут из памяти), но сделает его разбор и модификацию экономически нецелесообразными для пиратов.
  4. Собственные интерпретаторы. Существует теоретический подход (упоминаемый как методика OneScript или Gonec), когда внутри 1С пишется свой интерпретатор защищенного скрипта. Тогда в памяти 1С лежит только "движок", а бизнес-логика выполняется этим движком. Это усложняет анализ, но требует колоссальных трудозатрат на разработку.

Итог

Попытка создать "бесплатный СЛК" без использования внешних компонент обречена на провал, если противником выступает квалифицированный специалист. Любой код, который платформа 1С может исполнить, должен быть ею прочитан, а значит, он доступен для извлечения из оперативной памяти в момент работы.

← На главную