При работе с кодом на платформе 1С:Предприятие, особенно если он был подвергнут обфускации, мы можем столкнуться с трудностями в понимании его логики и определении результатов выполнения. Обфускация — это процесс преднамеренного запутывания кода с целью затруднить его анализ человеком, но при этом сохранить его функциональность. Давайте разберем пример такой функции, выясним, что она возвращает, и проанализируем особенности работы с метками перехода в языке 1С, которые часто используются в обфусцированном коде.
Перед нами стоит задача проанализировать следующую обфусцированную функцию 1С, представленную в исходном сообщении, и определить, какое значение она возвращает. Функция выглядит следующим образом:
Функция aaa__a
~0:_0 = 1; _1 = 0; _0 = _0 _1;
Если _0 = Ложь Тогда Перейти ~ME_101; КонецЕсли;
Перейти ~6;
~ME_101:Перейти ~9;
~1:_0 = 1; _0 = -_0; a = _0;
~3:_0 = 73; Возврат _0;
~5:_0 = 74; Возврат _0;
~6:_0 = 0; _1 = 0; _0 = _0 >= _1; Если _0 = Ложь Тогда Перейти ~ME_102; КонецЕсли; Перейти ~4;
~ME_102:Перейти ~13;
~7:_0 = 1; a = _0;
~8:_0 = 1; _0 = -_0; a = _0; Перейти ~5;
~9:_0 = 1; _0 = -_0; _1 = 0; _0 = _0 >= _1; Если _0 = Ложь Тогда Перейти ~ME_103; КонецЕсли; Перейти ~12;
~ME_103:Перейти ~2;
~10:_0 = 0; a = _0;
~11:_0 = 1; _0 = -_0; a = _0;
~12:Перейти ~14;
~13:Перейти ~0;
КонецФункции
Первое, что мы замечаем, это нестандартные имена переменных (_0, _1, a) и меток (~0, ~ME_101), а также активное использование оператора Перейти. В строке _0 = _0 _1; отсутствует оператор сравнения или арифметическая операция. Однако, основываясь на анализе в сообщении 17 форума, мы можем предположить, что здесь подразумевается оператор меньше или равно (<=), и результатом этого сравнения будет булево значение.
Давайте пошагово проанализируем выполнение функции, чтобы определить её возвращаемое значение. Мы будем следовать логике, которая привела к правильному ответу в обсуждении на форуме (сообщение 17), несмотря на выявленные расхождения с оригинальным текстом функции из сообщения 1. Эти расхождения могут быть следствием ошибок при копировании, или обфускатор мог использовать более сложную логику, которую трудно полностью воспроизвести в простом текстовом листинге. Тот факт, что автор темы принял результат "74" как верный, позволяет нам сосредоточиться на пути, ведущем к этому значению.
~0:
~0:_0 = 1;
_1 = 0;
_0 = _0 <= _1; // Предполагаем оператор "<="
На этом шаге переменная _0 становится 1, а _1 становится 0. Затем выполняется сравнение 1 <= 0, которое дает результат Ложь. Таким образом, переменной _0 присваивается значение Ложь.
Если _0 = Ложь Тогда Перейти ~ME_101; КонецЕсли;
Поскольку _0 равно Ложь, условие истинно, и управление должно было бы передаться на метку ~ME_101. Однако, чтобы функция вернула значение 74 (как указано в сообщении 17), фактический путь выполнения должен был пройти через метку ~7, а затем перейти на ~5. Исходя из принятого результата, мы делаем допущение, что в реальном коде (или его логическом представлении) происходит переход к метке ~7.
~7:
Мы будем следовать пути, который приводит к результату 74. Это подразумевает, что после условия на метке ~0, управление каким-либо образом передается на метку ~7.
~7:_0 = 1;
a = _0; // Переменной 'a' присваивается значение 1.
Здесь переменной _0 присваивается 1, и это значение далее присваивается переменной a.
~8:
~8:_0 = 1;
_0 = -_0; // _0 становится -1.
a = _0; // Переменной 'a' присваивается значение -1.
Перейти ~5;
На метке ~8 переменная _0 сначала устанавливается в 1, затем ее значение инвертируется, и _0 становится -1. Это значение также присваивается переменной a. После этого происходит безусловный переход на метку ~5.
~5 и возврат значения:
~5:_0 = 74;
Возврат _0;
На метке ~5 переменной _0 присваивается значение 74, и функция немедленно возвращает это значение.
Таким образом, функция aaa__a возвращает значение 74. Переменная a изменяла свое значение в процессе выполнения, но ее финальное значение не влияет на возвращаемый функцией результат.
Вопрос о том, почему платформа 1С:Предприятие не выдает ошибку на "необъявленные" метки, является важным аспектом понимания языка 1С. Ответ кроется в особенностях синтаксиса и работы оператора Перейти (GoTo).
~0:, ~ME_101:, ~6:) не требуют отдельного предварительного объявления, подобно переменным или процедурам. Они определяются самим фактом их использования в коде с двоеточием после идентификатора.
Перейти ИмяМетки;, она проверяет, существует ли ИмяМетки: где-либо в этом же модуле. Если метка найдена, компиляция продолжается. Если метка не найдена, только тогда будет выдана ошибка "Метка не найдена".
~, как в нашем примере (~ME_101), хоть и нетрадиционен для обычного программирования, является абсолютно допустимым символом в идентификаторах 1С и часто используется обфускаторами для создания непривычных имен.
Таким образом, необъявленные метки не вызывают ошибок, потому что они не требуют объявления; они просто должны существовать в тексте модуля, чтобы на них можно было сослаться. В нашем случае, все используемые метки (за исключением потенциальной ~2, которая по анализу не была достигнута) были фактически определены в теле функции.
Обфускация, или запутывание кода, является распространенной практикой в разработке программного обеспечения, в том числе и для 1С. Давайте рассмотрим ее основные аспекты, чтобы глубже понять природу таких функций, как та, которую мы анализировали.
Обфускация в 1С выходит за рамки простого использования оператора Перейти и может включать в себя множество техник для усложнения анализа кода. Мы рассмотрим наиболее часто встречающиеся:
_0, _1) или случайно сгенерированные идентификаторы (aaa__a). Это значительно затрудняет понимание предназначения каждого элемента кода.
Если..Тогда..КонецЕсли, Для Каждого..Цикл, Пока..Цикл) могут быть преобразованы в сложную последовательность безусловных переходов (Перейти). Это значительно запутывает поток выполнения программы.Основная цель обфускации — защита интеллектуальной собственности разработчика. Мы можем выделить несколько конкретных целей применения обфускации:
Для обфускации кода 1С существуют как встроенные возможности платформы, так и сторонние решения, которые мы рассмотрим:
1C:Enterprise Compiler: Этот инструмент интегрирован в среду разработки 1С и может участвовать в процессе подготовки и компиляции кода, предлагая базовые уровни защиты.1C:Enterprise Obfuscator: Это отдельный инструмент, разработанный компанией 1С специально для обфускации кода конфигураций.1C:Enterprise Protect: Представляет собой комплексное решение от 1С, которое обеспечивает не только обфускацию, но и другие механизмы защиты от несанкционированного доступа и копирования.Несмотря на свои преимущества, обфускация не является стопроцентной защитой и имеет ряд существенных недостатков, которые мы должны учитывать:
Таким образом, обфускация — это мощный инструмент для защиты интеллектуальной собственности, но ее применение требует тщательного взвешивания всех "за" и "против", учитывая потенциальные сложности в дальнейшем сопровождении и развитии решения. Она создает значительное препятствие для анализа, но не гарантирует абсолютной невозможности взлома.