Обфускация кода 1С (приведение в нечитаемый вид) для платформы 1С:Предприятие 8.3.7




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

97 Comments

  1. Pavgorb

    Обновил до 8.3.7, запустил в режиме толстого клиента, конвертировал…

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

    Пока не понял в чем дело, но похоже «не любит» двойные кавычки, Экспорт и представление дат в явном виде.

    Reply
  2. Evil Beaver

    Замена идентификаторов на GUID (с добавлением «х», чтобы начиналось с буквы), это еще не обфускация.

    Reply
  3. masterkio

    (1) Pavgorb, Если есть возможность, можете прислать обработку, в которой такое происходит, что бы я смог исправить ошибку?

    Reply
  4. masterkio

    (2) Evil Beaver, предложите, что еще можно сделать используя только встроенный язык.

    Reply
  5. the1

    (3) у меня тоже возникли синтаксические ошибки. Пытался обфусцировать код формы Вашей обработки.

    Reply
  6. the1

    (2) Evil Beaver, Обфуска́ция — приведение исходного текста или исполняемого кода программы к виду, сохраняющему ее функциональность, но затрудняющему анализ, понимание алгоритмов работы и модификацию при декомпиляции. По моему, обработка подходит под определение.

    Reply
  7. masterkio

    (5) the1, Для формы не подходит, т.к. там заменяются переменные, которые являются реквизитами формы, поэтому возникают ошибки.

    В описании написано, что только для общих модулей и модулей объектов и модулей менеджеров.

    По формам думал, но к сожалению, обработкой не возможно пользоваться, если в конфигурации стоит режим совместимости, с версиями ниже 8.3.7, соответственно не получиться указать нужную форму, для анализа ее реквизитов. А т.к. сейчас львиная доля конфигураций еще в режиме совместимости, то я решил отказаться от этого в угоду универсальности обработки.

    Reply
  8. alex_4x

    Для модулей форм просто надо добавить таблицу, в которую сам пользователь (ну тот кто шифрует) вносит переменные, используемые на форме и они не шифруются.

    или другой вариант — после шифрации дается таблица, по которой эти реквизиты на форме руками переименовываются в «кривые» названия.

    Конечно это не полная автоматизация но выход.

    В твоей шифровалке обрабатываются дерективы препроцессора ?

    поток выполнения может быть запутан ?



    Хорошо бы порядок аргументов и их количество в вызываемых функциях менять, добавлять «контрольные» аргументы, при неправильном значении которых начинает происходить всякая дребедень — это будет некой защитой от отладки. Опять же область видимости переменных — с этим также можно устроить путаницу. так как в 1С нет ни строгой типизации типов — это еще один механизм, который можно применять для усложнения читаемости кода.

    Reply
  9. masterkio

    (8) alex_4x,

    Для модулей форм просто надо добавить таблицу, в которую сам пользователь (ну тот кто шифрует) вносит переменные, используемые на форме и они не шифруются.

    Так можно сделать, но вносить вручную что-то довольно трудоемко, но подумаю над этим.

    другой вариант — после шифрации дается таблица, по которой эти реквизиты на форме руками переименовываются в «кривые» названия.

    Такая таблица есть — кнопка «Посмотреть таблицу замены»

    В твоей шифровалке обрабатываются дерективы препроцессора ?

    Нет, а как и с какой целью их можно обрабатывать, не особо представляю.

    поток выполнения может быть запутан ?

    скорее нет, к этому можно отнести только вставку бессмысленных выражений в функции.

    Тут честно сказать даже не представляю как можно реализовать что-то более сложное.

    Хорошо бы порядок аргументов и их количество в вызываемых функциях менять

    это можно сделать, но получается все равно придется переопределять переменные прямо в начале функции. Не особо запутает, поэтому не знаю нужно ли это.

    добавлять «контрольные» аргументы

    не очень понял, что это.

    пять же область видимости переменных — с этим также можно устроить путаницу

    тоже не очень понял, как это можно применить.

    Reply
  10. Yashazz

    Согласен, не обфускация это в полном смысле слова. Вообще, интереснее всего делать такие преобразования, чтобы требовался некий «ключ», без которого код превращается в пусть и читабельную, но трудноотлаживаемую и незапускаемую «кашу». Т.е. потратив N времени, можно довести код до ума, но трудозатраты должны быть огромны. И вот элементарной заменой на этот ключ код превращался бы в работающий и правильный, вот это было бы круто.

    А это — извините, и автору самому потом с таким невозможно работать.

    Reply
  11. masterkio

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

    Reply
  12. logarifm

    Хорошая идея, автору однозначно +

    А идея насчет обратного прнобразования думаю тоже кто-то разработает, все в свое время…

    Reply
  13. МимохожийОднако

    (12) logarifm, всё гораздо проще. Для случаев разбора обработанного кода и необходимости правки вполне помогает отладчик, мозг и команда найти-заменить.

    Reply
  14. puzakov

    Интересно, и почему так много «больных» защитой своего кода разработчиков?

    Reply
  15. Оберон

    (14) puzakov, потому что жадность!!!

    Reply
  16. Трактор

    15 лет назад я такой же хренью страдал. Потом понял, что всё фигня.

    Reply
  17. masterkio

    (14) puzakov, потому что много не порядочных внедренцев.

    Reply
  18. infostart user

    боль….

    Reply
  19. so-quest

    Такое через регэкспы еще лет пять назад делали.

    Автор, твою бы энергию да в правильное русло… Эта задача проще решается через построение AST и последующий обход.

    А самое интересное — когда сделаешь, приходит понимание что глупость это все… И тратить время на то что бы приводить код к нечитаемому виду — в принципе! не стоит. Слишком просто разбирается назад.

    Построение преобразователя к конечному автомату — лучше, но дороже в исполнении, и там уже совсем другой объем знаний надо.

    По парсерам если будут интересны наработки — смотри тут https://github.com/wwall/disa_da

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

    Reply
  20. masterkio

    (19) so-quest,

    А самое интересное — когда сделаешь, приходит понимание что глупость это все… И тратить время на то что бы приводить код к нечитаемому виду — в принципе! не стоит. Слишком просто разбирается назад.

    Конечно разбирается, но тут то суть как правило в том, что трудоемкость, а как следствие стоимость этого обратного разбор больше, чем сам продукт.

    Может, конечно это и ерунда все, но я для себя не нашел другого — бесплатного и простого способа хоть как-то защитить конфигурацию. А просто отдавать без защиты — лишать себя денег.

    Reply
  21. so-quest

    >как следствие стоимость этого обратного разбор больше, чем сам продукт.

    Вы в принципе в вопросе не разобрались. Стоимость разбора вашего обработанного кода — ни о чем. Час работы на обход дерева, полчаса покурить. У вас ведь не меняется ничего, кроме синтаксического представления. Единственное чего нельзя будет восстановить — имена переменных и комментарии.

    Reply
  22. masterkio

    (21) so-quest,

    Вы в принципе в вопросе не разобрались

    в каком вопросе я не разобрался?

    Стоимость разбора вашего обработанного кода — ни о чем. Час работы на обход дерева, полчаса покурить. У вас ведь не меняется ничего, кроме синтаксического представления. Единственное чего нельзя будет восстановить — имена переменных и комментарии.

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

    1.5 часа для, например Москвы, это уже ~ 3000 рублей, т.е. все что дешевле уже не оправданно даже пытаться декодировать.

    Ну и, думаю, 1.5 часа это преувеличение, по крайней мере не каждый специалист сделает за такой срок. + там не только изменение синтаксического представления, есть и еще некоторые «запутки», пусть немного, но тоже усложнят дешифровку.

    Reply
  23. Evil Beaver

    (4) (6) the1 обычно еще добавляют запутывание control-flow. Добавляют неочевидные условия, goto-переходы и т.п. Но это, конечно отдельная сложная и интересная тема.

    Например. Если вы даже без переименования идентификаторов замените все условия и циклы на GOTO — уже никто разбираться не захочет. И для форм сработает, ибо идентификаторы целы.

    Reply
  24. so-quest

    > в каком вопросе я не разобрался?

    В вопросе построения обфусикаторов. В (23) тебе описали что надо. Решается все это весьма просто — берешь любой парсер 1С который тебе нравиться, или пишешь свой. Строишь по AST списки переходов, трансформируешь в новый автомат и на выходе — реально обфусицированный код. В котором никто даже разбираться не будет.

    ОФФ —

    Вот что мне нравиться в писателях всяких обфусикаторов — так это их непоколебимая уверенность что их код нужен кому-то, кроме них самих и одного/двух клиентов кому умудрились впарить свое творение.

    Reply
  25. masterkio

    (24) so-quest,

    В вопросе построения обфусикаторов. В (23) тебе описали что надо. Решается все это весьма просто — берешь любой парсер 1С который тебе нравиться, или пишешь свой. Строишь по AST списки переходов, трансформируешь в новый автомат и на выходе — реально обфусицированный код. В котором никто даже разбираться не будет.

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

    ОФФ —

    Вот что мне нравиться в писателях всяких обфусикаторов — так это их непоколебимая уверенность что их код нужен кому-то, кроме них самих и одного/двух клиентов кому умудрились впарить свое творение.

    Не понимаю такой агрессии, если не нужен — так ок, а если нужен, то отдавать его просто так по меньшей мере глупо.

    Разбираетесь в чем-то лучше? посоветуйте как лучше или просто промолчите. Зачем писать в какой-то уничижительной форме про других людей? Я думаю найдется куча народа, для которых и ваш код/работа/результаты труда будут никчемным.

    Reply
  26. so-quest

    Я высказал свое мнение. Оно не совпало с вашим. В этом проявление агрессии? Насчет лучше или нет — да, в вопросах анализа кода и обфусикации разбираюсь лучше. И выше указал что ваша разработка — пустая трата времени. Вы не согласились и попытались отстоять свою точку зрения. Не получилось. Среагировали на ОФФ и решили перевести обсуждение в выяснение личных отношений. В связи с чем вопрос — где в моем поведении агрессия? Чем я так вас обидел? Считаете что ваша обработка нужна — хорошо. Не хотите ее обсуждать — пусть будет так.

    Если обидел чем вас — простите. Не хотел я такого.

    Еще раз — простите

    Reply
  27. masterkio
    Я высказал свое мнение. Оно не совпало с вашим. В этом проявление агрессии?

    нет, конечно, только в том, что вы перешли на личности, написав что работа таких как я никому не нужна. Тут я с вами совершенно не согласен.

    Насчет лучше или нет — да, в вопросах анализа кода и обфусикации разбираюсь лучше.

    Именно это я и отметил, и признаю это.

    И выше указал что ваша разработка — пустая трата времени.

    нет не пустая, какая бы никчемная и глупая она ни была. + когда мне нужна была подобного рода штука, чтобы хоть как то защитить свой никому не нужный код, я не нашел НИЧЕГО (по крайней мере бесплатного), написанного людьми разбирающимися хорошо в этом вопросе, например, как вы. Нашел только обработку, которая выкладывалась тут же и она сделана в том же ключе как у меня, я занялся своей, т.к. в той не обрабатывался современный код и ее код был закрыт.

    И я надеюсь что моя обработка помогла тем, кто ее скачал.

    Вы не согласились и попытались отстоять свою точку зрения. Не получилось

    я даже не понимаю о какой моей точке зрения вы пишите, которую я защищаю.

    Среагировали на ОФФ и решили перевести обсуждение в выяснение личных отношений. В связи с чем вопрос — где в моем поведении агрессия? Чем я так вас обидел?

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

    Ваш комментарий сначала посчитал самым полезным, вы предоставили некие наработки, давали реальные советы… а потом занялись каким-то само восхвалением…печально.

    Reply
  28. herfis

    А я вот не совсем понимаю, в чем смысл защиты обфусцированием вообще.

    Защита авторских прав на код? Усложнить модифицирование кода?

    Чтобы можно было «вот вам версия типа без исходников», а если захотите сами дорабатывать — доплатите?

    Тут редкий раз вообще встретишь код, который можно дорабатывать без отвращения.

    Да и нечасто это требуется, как мне кажется. Если речь об обработках, так 99% используют их as is.

    С конфой, в принципе, тоже самое. Но конфу, если очень хочется, и так можно поставлять без исходников общих модулей, хотя опять таки непонятно — зачем.

    Спрятать «гениальные» приемы программирования? Не смешите мои тапочки.

    Чтобы кто-то не выдал твою конфу за свою? Это еще заслужить надо. Единицы добиваются такого ошеломительного успеха. И в этом случае доказать свое авторство обычно особой проблемы не составляет.

    Reply
  29. masterkio

    (28) herfis,

    Если кофа — то чем хуже поставка без исходных кодов?

    я лично использую и то и другое, т.е. делаю код не читаемым и потом модуль не включаю.

    Reply
  30. herfis

    (29) Простой вопрос — зачем?

    Reply
  31. herfis

    Хотя, если это работает как маркетинговый прием, тогда есть смысл.

    Типа с исходниками, это «all inclusive» и поэтому дороже. И народ такой — цена вопроса небольшая, так зачем брать с урезанными возможностями?

    Если это работает, тогда ладно.

    Reply
  32. antz

    (14) puzakov, многим стыдно за свой код.

    Reply
  33. adhocprog

    Плюс )

    Reply
  34. masterkio

    (31) herfis,

    Смысл простой.

    Есть у вас дополнение к конфигурации, вы продаете ее за деньги, если ни как её не защитить, то один купивший может раздать ее всем своим знакомым, например, или если купил внедренец, то он может поставить ее многим клиентам получив за это деньги, а вам не достанется ничего.

    Поэтому помещаете в какой-то модуль часть функционала, туда же запиливаете проверку по пинкоду, закрываете модуль и получаете, пусть небольшую, но защиту от незаконного копирования.

    Reply
  35. so-quest

    >а потом занялись каким-то само восхвалением…печально.

    Печально что вы так и не поняли о чем же тут вам говорили Для вас обфусикация — это маленькие желтые кругляшки именуемые деньгами. Но ни как не часть достаточно большой и интересной математической дисциплины о компиляции и анализе. Приложив хоть немного усилий к изучению которой вы бы добились больших результатов.

    Но ведь некогда… Какой-то подлый внедренец именно сейчас ворует ваш гениальный код и из-под полы в переходе метро продает его. И только вы можете с этим боротьбся. И только обфусикация кода с этим справиться.

    тьфу. Теорема БЖ-Соболя в действии

    Reply
  36. slawanix

    Я конечно понимаю, жадность там и все такое. Но когда такое делается в среде, изначально ориентированной на открытый код и возможность доработки любой конфигурации сторонними программистами… Ну вот тогда я не очень понимаю. Интересно, веб-разработчики свой код на яве и пхп тоже так стремятся защищать?

    Reply
  37. masterkio

    (35) so-quest, по-моему вас вообще не туда понесло… 🙂

    Reply
  38. masterkio

    (36) slawanix,

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

    Почти все партнерские решения имеют закрытый код, такова реальность.

    Reply
  39. slawanix

    (38) ну допустим я согласен с тем, что разработчики отраслевых конфигураций, с действительно оригинальными решениями, защищают свой продукт ключами, е-токенами и т.д. Но, если ты работаешь у франча, пишешь всякие там обработки на каждый день, отчеты и печатные формы… Не пойму, что действительно есть такая потребность в обфускации. Не догоняю, не опытный я в этих делах. Может подскажете, когда такая потребность возникает? И вот это вот:

    Почти все партнерские решения имеют закрытый код, такова реальность.

    Они поставляют конфигурации с закрытым или с обфуксированным кодом? Ведь это разные вещи.

    Reply
  40. masterkio

    (39) slawanix,

    Наверно, каждый сам определяет для чего ему это надо .

    Для меня

    Но, если ты работаешь у франча, пишешь всякие там обработки на каждый день, отчеты и печатные формы… Не пойму, что действительно есть такая потребность в обфускации

    — в этом случае не вижу смысла, скорее это даже вред и противоречие этике внедренцев/разработчиков 1С.

    я вижу использование только в коммерческих тиражных решениях, в сочетании с неким кодом защищающим от копирования.

    Они поставляют конфигурации с закрытым или с обфуксированным кодом? Ведь это разные вещи.

    — цель одна, скрыть от возможности редактирования часть кода. Просто обфускация + не включение модуля в поставку — это, пусть самая не надежная, но доступная и бесплатная возможность это сделать. Все остальные способы защиты, как правило, требуют дополнительных финансовых затрат.

    Reply
  41. herfis

    (34) Что-что?? Защита пин-кодом в обфусцированном коде? Seriously? Небольшая защита? Выложи на спор такую «защиту», замерим время на «взлом». ИМХО, защита не лучше консервной банки. Пока содержимое не нужно — вполне себе защищает.

    ЗЫ. Уточню свою мысль. С точки зрения защиты от несанкционированного выполнения кода, обфускация не дает ровным счетом НИЧЕГО. Кто утверждает обратное — не дружит с головой. Единственное, на что способна обфускация в принципе — защита авторских прав и некоторый уровень защиты от модификации кода.

    Reply
  42. masterkio

    (41) herfis,

    Что-что?? Защита пин-кодом в обфусцированном коде? Seriously? Небольшая защита? Выложи на спор такую «защиту», замерим время на «взлом». ИМХО, защита не лучше консервной банки.

    я же и не утверждал, что она очень надежная, но не подготовленному человеку, думаю, будет на так просто взломать. Честно сказать, сам никогда не занимался декомпиляцией, поэтому не знаю, что из себя представляет декомпилированный код модуля не включенного в поставку, может быть он такой же не читаемый… но если он нормальный, то дополнительная обфусикация модуля дополнительно усложнит дешифровку.

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

    С точки зрения защиты от несанкционированного выполнения кода, обфускация не дает ровным счетом НИЧЕГО. Кто утверждает обратное — не дружит с головой. Единственное, на что способна обфускация в принципе — защита авторских прав и некоторый уровень защиты от модификации кода.

    -она дает защиту модуля от модификации, в который можно встроить защиту от несанкционированного выполнения. Понятно, что не во всех случаях это возможно, но думаю для многих задач можно придумать такого рода защиту.

    Reply
  43. herfis

    (42)

    в который можно встроить защиту от несанкционированного выполнения

    Это иллюзия, которая не выдерживает банальной проверки здравым смыслом. Никаких навыков и опыта для этого не требуется. Можно вообще вчера 1С увидеть первый раз. Достаточно знать, что такое отладчик и азы информатики.

    Ну подумайте сами. Вы видите, что на определенном этапе выскакивает проверка пин-кода. Модуль где это происходит, хотя бы корневой — очевиден. Включаете пошаговую отладку и просто идете пока не выскочит окошко. С этого момента отследить, как дальше проходит алгоритм проверки и воткнуть его обход — ничего не стоит.

    Reply
  44. masterkio

    (43) herfis,

    Ну подумайте сами. Вы видите, что на определенном этапе выскакивает проверка пин-кода. Модуль где это происходит, хотя бы корневой — очевиден. Включаете пошаговую отладку и просто идете пока не выскочит окошко. С этого момента отследить, как дальше проходит алгоритм проверки и воткнуть его обход — ничего не стоит.

    Ну понятно, что там где это окошко выскакивает тоже должно быть в закрытом модуле, т.о. все сводится к взлому модуля, то что обсуждалось выше.

    Понятно что всю функциональность пихать в закрытые модули не корректно, но что-то ключевое, без чего вся доработка бессмысленна можно и нужно.

    Так что то, что вы пишите не совсем верно, опять же все сводится к взлому модуля.

    Reply
  45. alex_4x

    Мне кажется морально-этические нормы и цели обфускации кода — это отдельная тема, а техническая реализация — совсем другая тема. И зачем их обсуждать одновременно — непонятно.

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

    Какие этапы для этого нужно выполнить, чтобы:

    1. Гарантировать работоспособность этого кода (как минимум — не внесение новых ошибок, а лучше — контроль возможных ошибок перед модификацией и не добавление новых)

    2. Обеспечить высокую сложность автоматического анализа

    Для выполнения первого пункта хорошо бы сначала, перед тем как формировать некий обфусцированный код, провести статический анализ того кода, который есть изначально. Есть же статические анализаторы для С например, они проверяют такие вещи как определение переменных, которые не используются, условия, которые всегда будут иметь одно и то же значение

    А=Б; Если А=Б Тогда…. Циклы, из которых по определению никогда не выйдем… Для А < Б Цикл …. А=0 КонецЦикла, и множество потенциальных угроз. Статический анализ не гарантированно найдет все ошибки, но укажет потенциально небезопасные участки кода. Конечно это лучше работает в тех языках, где есть обязательное определение переменных и что мне кажется важнее — чёткая типизация переменных. В 1С поскольку нет строгой типизации переменных — ошибка, когда например А = 3, а потом А.Записать() — вроде как и не очевидна, только на этапе выполнения будет понятно, что для А — метода Записать() нет, так как это числовая переменная. И никто не мешает сделать А = 3; А = справочник.фигня.НайтиПоКоду(А); А.Записать(); Вот статический анализ бы мог тут пригодиться не только для написания обфускатора, а просто для анализа кода на возможные ашипки и очепятки.

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

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

    Reply
  46. herfis

    (44)

    все сводится к взлому модуля

    Вот именно! Вернее, не к взлому, а к обратной трансляции байт-кода в код 1С.

    Именно об этом я и говорю. Если уже используется поставка без исходных кодов, ваш вариант обфускации — абсолютно лишний. Он ничего не привносит, с какой стороны не глянь.

    При самостоятельном применении защиту от несанкционированного выполнения обфускация тоже не помогает реализовать.

    Ее имеет смысл использовать только в качестве некоторой защиты от изменений и авторских прав.

    Reply
  47. herfis
    Мне кажется морально-этические нормы и цели обфускации кода — это отдельная тема, а техническая реализация — совсем другая тема. И зачем их обсуждать одновременно — непонятно.

    Ну а мне непонятно, почему вы считаете странным обсуждать в комментариях к продукту его целевое назначение.

    Reply
  48. dgolovanov

    (47) herfis, прочитал все ваши комменты. Вам женщины не дают, всё в слова выливается?

    Reply
  49. Dach

    (27) речь про вот эту обработку?

    http://infostart.ru/public/15907/

    если про нее, то она прекрасно работает и с «современным» кодом.

    Протестировал ради интереса буквально только что — не смогла только обработать тип ОписаниеОповещения.

    Ну, неудивительно, это асинхронное выполнение кода, в рамках отказа от модальности, на момент написания обфускатора еще не применялось…

    Неужели Ваш код содержит везде асинхронные вызовы? Или нет? Большинство внедренцев, из тех, от кого собственно и надо бы защищать свои творения — толком то и не знают что это. )))

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

    Но когда таки навяжут — будет хорошо, считаю, но это тема для отдельной дискуссии.

    Кстати, у автора обработки все развилось в целый проект, видимо довольно успешный. Не сочтите за рекламу, но: https://netlenka1c.ru

    (сейчас сервис платный, бесплатный был при старте, года 2 назад).

    Если уж так нужно защитить свой код, то почему бы не купить абонемент? 4500 в год — не так уж дорого за возможность спать спокойно 😉 😉

    А если не хочется покупать абонемент и хочется разработать свое, то воспринимайте критику… Вам Evil Beaver и остальные уже надавали кучу советов… Насчет GoTo и запутывания.

    Reply
  50. alex_4x

    Интересно не «купить абонемент», а сделать самому 🙂

    Я с автором нетленки общался, но так как проект у него коммерческий, он даже по поводу разбора синтаксиса языка ничего не стал подсказывать. Ну это понятно, всё что приносит доход — ноу хау 🙂 Как я уже писал выше — мне интересно на данном этапе сделать статический анализатор кода.

    Вот вам одна смешная конструкция, для раздумий 🙂

    //Дерективы компилятора можно так поставить что например
    Функция
    //….
    #Для тонкого клиента
    //…
    КонецФункции
    #Для толстого клиента
    //…
    КонецФункции
    //Проверку синтаксического контроля не проходит, но работает 🙂
    

    Показать

    Reply
  51. so-quest

    (37) сложно что либо объяснять человеку, если кроме слова деньги он ничего не понимает. Тебе 40 постов пытаюсь объяснить что твоя обработка фигня бесполезная — ты упираешься в то что она якобы работает и даже от чего-то защищает. Тебе говорят как надо делать такой продукт — ты упираешься и говоришь что и так хорошо.

    (48) dgolovanov, А как коррелирует между собой сексуальная привлекательность и вопросы по этой обработке? herfis вполне нормальные вопросы задает. То что автор на них ответить не может и юлит — по моему никак не связано с женщинами вообще.

    (50) alex_4x, То что ты показываешь — не проблема. Сперва делается проход препроцессором, затем собственно парсер. То есть парсеров должно быть 2. Один для препроцессора, второй для самого языка.

    Если тебе что нужно подсказать по статанализу кода- идешь сюда — https://github.com/wwall/drracket-loxy (парсер и пример простого анализа после новогодних будет там). Если просто парсер нужен — то сюда http://oscript.io/ или сюда — https://github.com/wwall/disa_da

    Reply
  52. alex_4x

    Ну что вы, уважаемый so-quest так накинулись на парня! Он же не заставляет вас своей обработкой пользоваться. Ну сделал человек эксперимент, ему и обсудить это хочется и поддержку найти, а вы тут как научный руководитель в институте — всё у вас неправильно, идите перечерчивайте…

    Как вашим анализатором drracket-loxy пользоваться ? на чём это написано ? какая-то непонятная для меня мешанина файлов….

    http://oscript.io/ — я так понимаю на сях написан. И как это работает ? Ему надо что скармливать ? Модуль один или весь файл метаданных?

    Reply
  53. herfis

    (48) Кто о чем, а вы про «женщины не дают». Напомнили старую русскую поговорку про баню.

    Reply
  54. alex_4x

    herfis, дорогой, ну не устраивайте тут помойку из придирок.

    Давайте лучше по существу.

    Кто знает как сделать или уже сделал разбор кода 1С на самом 1С ? Понятное дело есть всякие специфические библиотеки, но давайте ограничимся функционалом 1С для удобства и понятности.

    Reply
  55. alex_4x

    herfis, спасибо за ваш полный сарказма и снобства совет. жаль что в нём нет даже намека на смысл.

    Теории — это всё замечательно, и конечные автоматы тоже. Как это всё реализовать на практике — вот вопрос.

    Анекдот…

    -Мама, вы хотите рыбы?

    -Ммм… ну да…

    -Ну так идите, купите и пожарьте!

    Теоретическая база такова:

    Так как программа на языке 1С по разному отрабатывается в разных режимах (на клиенте, на сервере, толстый клиент, com соединение), что обусловлено применением деректив компилятора, сначала надо из исходного кода выделить ту часть, которая будет отрабатываться в интересующем нас случае. Например на клиенте. Остальное просто выбросить.

    Далее модуль состоит из частей:

    Определение переменных

    Определение функций и процедур

    Тело модуля (аналог функции main())

    Сначала определяем все глобальные переменные модуля.

    Встречаем начало объявления функции — запоминаем что началась функция и дальше идут сначала параметры потом тело функции

    Встречаем конецфункции — функция закончилась.

    Внутри функции(процедуры) — в начале определяются переменные функции(процедуры), потом идет тело функции.

    Тело состоит из вызовов процедур

    ИмяПроцедуры(Параметры); Параметры — это список Выражений через запятую

    И присвоений

    ИмяПеременной = Выражение

    Вот и вся теоретическая база. Или я глубоко заблуждаюсь ?

    Reply
  56. so-quest

    (56) alex_4x, Очень глубоко заблуждаетесь, начиная со слова «Анекдот»

    Конечные автоматы, теория построения компиляторов и прочая прикладная математика необходима. Хотя если вы хотите повторить путь пройденый до вас и не достичь ничего нового — то не обязательно. Если вы откажетиесь от этого — поучитсья примерно то же самое что и у автора этой разработки — тяжелый, трудночитаемый, неподдерживаемый код. Без формальной грамматики языка — ничего не сделать. Точнее можно сделать, но будет очень грустно это читать/развивать.

    По поводу вашего вопроса «Как вашим анализатором drracket-loxy пользоваться ?» — пока никак. Это начинающийся проект. на данный момент там реализован только токенизире и интерфейс анализа потока токенов. Ссылку дал что бы вы могли посмотреть на один из вариантов реализации статического анализа кода. Аналогичные проекты есть для питона, джавы, сишарпа и прочих языков. У моего проекта язык реализции — schema (точнее drracket). Перегнать на 1С — труда не составит, там никаких сложных конструкций не используется.

    Reply
  57. Evil Beaver

    (35) so-quest, а посоветуйте мне, коллега, хорошую литературу по анализу кода, а? Если не затруднит, конечно.

    И за ссылку на oscript.io, отдельное спасибо, мне лестно 🙂

    Reply
  58. Evil Beaver

    (52) alex_4x,

    http://oscript.io/ — я так понимаю на сях написан. И как это работает ?

    А никак не работает. Это не парсер, а среда исполнения. В ней нет отчуждаемого анализатора кода, который можно просто взять и для обфускатора заюзать. Написан на C# — это сильно проще, чем С.

    Reply
  59. nikaleks

    Ребята, а зачем это нужно?

    Выкладывая обработку на открытом источнике, думать о непорядочных внедренцах? ерунда какая-то.

    Если уж так нужно, можно паролем защитить модуль, а так ерунда какая-то.

    Reply
  60. CyberCerber

    Автор, спасибо за обработку!

    Скажу, что мне обработка понадобилась. Для чего… Я — фрилансер, написал обработку, отправляю заказчику, деньги он мне еще не прислал. Был случай, когда меня так кинули. Вот решил попробовать отправить демоверсию, которая перестанет работать через некоторое время. Вставил условие в код и обфусцировал его.

    Но есть некоторые замечания, ошибки:

    1. Именно, защитный код, который нужен был мне, скрылся плохо. Т.е. код

    Если ТекущаяДата() > ‘20160101’ Тогда
    Возврат;
    КонецЕсли;

    таким же и остался.

    2. Возникает ошибка с директивами препроцессора. Код вида:

    #Если Клиент Тогда
    #КонецЕсли

    должен занимать отдельные строчки, а он идет в середине строки.

    3. Проблема с переменной в модуле обработки, которая является реквизитом обработки

    Например, есть реквизит обработки «Реквизит1». В одном методе пишу:

    Реквизит1 = 1;

    А в другом:

    Сообщить(Реквизит1);

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

    Желаю исправления этих ошибок и дальнейшего развития обработке!

    Reply
  61. masterkio

    (61) CyberCerber,

    Первые две проблемы понятны, постараюсь исправить в ближайшее время.

    По поводу третьей не очень понял.

    Если это одна и та же переменная или просто с одинаковым идентификатором, то если они заменяются на другое , не читаемое имя переменной, все равно все должно работать…

    Reply
  62. CyberCerber

    (62) Реквизит1 — это реквизит самой обработки, он не задан в коде внутри модуля, а добавлен в окне создания обработки. Такую переменную не надо переименовывать.

    Reply
  63. Evil Beaver

    (63) CyberCerber, по вашей задаче — не парьтесь и просто закройте код модуля паролем (или вообще не включайте код в поставку).

    Reply
  64. ekaruk

    На самом деле закрытие кода вещь достаточно полезная.

    Я сама всегда рассказывала, что в 1С закрытого кода быть не должно.

    Сейчас сама использую для закрытия и урезания функционала бесплатной Лайт версии платного отчета.

    Это позволяет без особого труда дать пользователю облегченную версию, чтобы показать, что именно отчет может.

    Поставка без кода + легкая обфускация байт-кода.

    По моей оценке, 95% программистов Инфостарта такую защиту за срок меньше недели не откроют, не говоря уже о рядовых бухгалтерах.

    А те 5%, что откроют, такой фигней заниматься не будут.

    Reply
  65. CyberCerber

    (64) Evil Beaver, пароль, слышал, вскрывается проще простого. А вот про поставку мало знаю… Этот метод можно применить к внешней обработке?

    Reply
  66. masterkio

    (63) CyberCerber, Понятно, эта проблема уже обсуждалась. Постараюсь ее как-нибудь решить.

    Reply
  67. ekaruk

    (66) CyberCerber, Можно применить к отчету, но для этого его нужно встроить в конфигурацию.

    Как вариант, можете ограничиться обфускацией текста обработкой в этой публикации + обычный пароль.

    Для пользователя этого более чем достаточно.

    Reply
  68. CyberCerber

    (68) ekaruk, так и сделал: обфусцировал и паролем закрыл. Но решил, гулять так гулять, и хотел всеми стандартными способами воспользоваться. 🙂

    Reply
  69. izidakg

    исключение модуля очень фиговая защита

    лично я ее вскрываю ровно за время открытия соответствующего инструмента

    Reply
  70. ekaruk

    (70) izidakg, Для рядового пользователя этого более чем достаточно.

    Reply
  71. Evil Beaver

    (66) CyberCerber, про пароль я не интересовался, по-моему он не очень просто снимается. А вот декомпилировать обратно можно, да. Но awa, например, знает, как защитить от декомпиляции. Имхо, это надежнее, чем просто замена идентификаторов.

    Reply
  72. masterkio

    (61) CyberCerber, По вашим вопросам вроде бы поправил. Публикация обновлена.

    Единственное с литералами даты не стал заморачиваться, но сделал, что в строковых константах цифры кодируются, т.е. если в вашем случае написать Дата(«20160101»), то в явном виде её видно не будет.

    Reply
  73. master-73

    Ошибка. Если в модуле присутствует примерно такая строка:

    ОбластьПодвал = Макет.ПолучитьОбласть(«Подвал|_» + Ширина);
    Reply
  74. MRAK

    Автор, молодец.

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

    Если кому-то не разу не приходилось сверлить стены, то он тоже будет утверждать, что дрель не нужна, и кто ее изобрел — тот дурак 🙂

    Не стоит на таких людей излишне обращать внимание 🙂

    Reply
  75. masterkio

    (74) master-73, Проверю, спасибо за замечание.

    Reply
  76. capitan

    Задумка хорошая.

    Но у меня не взлетела.

    Появляются строки типа:

    структура ( sdferwrrwerwrwer(«҄ҙқҧҟҰҦҔҦ

    Они видны и на принтскрине автора.

    На них — затык, модуль не компилируется без ошибок.

    А http://infostart.ru/public/15907/ работает на ура.

    Reply
  77. masterkio

    (77) capitan, если есть возможность, пришлите пример кода, который не компилируется.

    Reply
  78. FractonKireyev
    Reply
  79. vasyS
    Reply
  80. masterkio

    (80) vasyS,

    Проверьте по этому пункту в описании:

    «Требуется платформа не ниже версии 8.3.7, в конфигурации не должен быть установлен режим совместимости, поэтому для использования обработки лучше всего создать пустую конфигурацию и запустить её в толстом клиенте обычном приложении, в конфигураци необходимо включить возможность использования модальных окон.»

    Reply
  81. webandroid

    текст в ковычках тоже обфусцирует. Зачем??? «҇ҫҜҦүҖҔҦҰ ҁѸ҅»

    Reply
  82. masterkio

    (82) webandroid, Тексты запросов + по комментария можно найти фрагмент кода.

    Reply
  83. for_sale

    (10), код, который превращается или не превращается в кашу — это уже компиляция налету. Т.е. Выполнить(). И тогда, во-первых, вы можете без всякой обфускации найти какую-то шифровалку строк с кодом доступа, даже в онлайне, а у себя в коде прописать функцию дешифрации и получить что-то вроде Выполнить(Дешифровать(Каша, Код)). Но во-вторых, любая такая дешифровка по коду доступа уже даёт любому купившему вашу нетленку возможность получить её чистенький код. А смысл обфускации как раз в том, чтобы сделать кашу, которая бы работала именно в виде каши, без всякой дешифровки.

    Reply
  84. for_sale

    (14) а что вас смущает?

    Есть разные схемы монетизации разработок. Работа на распиловом проекте очередной госкорпорации или допиливание отчётов для бухгалтера, чтобы вместо точек в цифрах были запятые — это ещё не вся жизнь программиста 1С. Есть вещи, которые предоставляются бесплатно, например, но монетизируются за счёт трафика. Или даже просто продаются конечному пользователю не за стоимость разработки, а гораздо ниже, но окупаемость достигается за счёт массовости.

    И почему, спрашивается, я, потратив стотыщмиллионов часов на разработку, должен отдавать свой код любому, кто хочет продавать мой же товар в своей обёртке да ещё и этом составлять мне же конкуренцию?

    Reply
  85. for_sale

    (14) и, кстати, почему-то в других сферах и средах разработки это само собой разумеется — закрытый исходных код, а в 1С это считается «болезнью». Идиоты из микрософта, огрызка и прочих осей зла, видимо, не прониклись высокими идеалами 1С.

    Reply
  86. for_sale

    (36)

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

    Сказки — они, конечно, хороши, но реальность другая. Есть кто-то, кто тратит время, разрабатывает и продаёт, а есть кто-то, кто ворует и продаёт.

    (36)

    Интересно, веб-разработчики свой код на яве и пхп тоже так стремятся защищать?

    не поверите, но во всех сферах и средах это стандартная ситуация — закрытый исходный код. И только 1С, а за ней и гениальные программисты 1С, как обычно, имеют на всё своё особое мнение, которое, как обычно, не очень много общего имеет с реальностью. Напишите в Майкрософт, пусть вам исходники винды вышлют. Или каких-нибудь энгрибёрдс. Ну чтобы вы просто скомпилировали и пользовались бесплатно, да ещё и другим продавали.

    И там как раз другая ситуация — там, если ты хочешь, можешь отдельно поставлять исходники, тебе никто не запрещает. А ВЫНУЖДАТЬ поставлять исходники — ну это как обычно 1С-стайл.

    Ну и как всегда интересна вообще психология людей на форумах. Человек разработал вещь, довольно неплохую. В комментариях — ни одного дельного совета, ни одного дельного замечания и подсказки. Одни говном поливают, другие своё «фе!» самой идее высказывают, третьим интересно, как это вообще люди существуют, которым нужно то, что не нужно им самим?

    Reply
  87. ture

    (0) Я часто сталкиваюсь с людьми, которые учат писать код правильно (словно все вокруг не умеют). У меня нет своих принципиальных правил, как нужно говнокодить в 1С. Однако автор этой публикации меня покорил, и, на мой взгляд, заслужил приз за лучший говнокод.

    Reply
  88. masterkio

    (88)Просто ради интереса, вы про код самой обработки?

    Reply
  89. nomadon

    два вопроса…

    1. Как вернуть все обратно? ))

    2. Те кто плохо высказываются могут предложить лучшее решение не за деньги?

    Reply
  90. Serega-artem

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

    Reply
  91. Kyrales

    А в управляемых формах сделать не судьба?

    Reply
  92. Vovan1975

    (87)

    не поверите, но во всех сферах и средах это стандартная ситуация — закрытый исходный код.

    ну зачем врать? Опенсорсного софта — навалом. Вон тот же линукс на память первым приходит. Никакой «стандартной ситуации» нет.

    Reply
  93. for_sale

    (94) вы вначале вникните в суть сказанного мной, а потом обвиняйте меня во лжи. Я что, сказал, что нет опенсорсного софта? Я сказал, что в нормальных сферах и средах, в отличие от 1С, ЕСТЬ ВСЁ НЕОБХОДИМОЕ для поставки скомпилированных программ без исходного кода. Что из этого — враньё?

    И другой вопрос — а наличие линукса и другого опенсорса отменяет наличие ещё большего количества программ с закрытым исходным кодом?

    Reply
  94. Horex

    Скачал обработку v4 и сразу выпадает куча ошибок:

    {ВнешняяОбработка.СтайерОбфускацияКода_v4.Форма.Форма.Форма(323,61)}: Переменная не определена (НаправлениеПоиска)

    ПозицияНачалоПеременной = СтрНайти(стрОбработанныйКод,» «,<<?>>НаправлениеПоиска.СКонца,ПозицияПеременная,2);

    ///////////////////

    {ВнешняяОбработка.СтайерОбфускацияКода_v4.Форма.Форма.Форма(480,21)}: Процедура или функция с указанным именем не определена (СтрНайти)

    ПозицияПробела = <<?>>СтрНайти(стрОбработанныйКод,» «,,КоличествоСимволовВСтроке);

    Жаль потраченных мани

    Reply
  95. FractonKireyev

    (96)

    «Как много нам открытий чудных…» несёт простое прочтение инструкции. Ну, или можно почитать комментарии в этой ветке (например: (81) ).

    Reply
  96. buganov

    8.3.10

    ВнешняяОбработка.СтайерОбфускацияКода_v4.Форма.Форма.Форма(388)}: Ошибка при вызове метода контекста (ОтметитьЭлементы)

    Если сзИменаПеременных.ОтметитьЭлементы(«Идентификаторы для замены») Тогда

    по причине:

    Использование модальных окон в данном режиме запрещено!

    Reply
  97. masterkio

    (99)

    Цитата из описания

    Требуется платформа не ниже версии 8.3.7, в конфигурации не должен быть установлен режим совместимости, поэтому для использования обработки лучше всего создать пустую конфигурацию и запустить её в толстом клиенте обычном приложении, в конфигураци необходимо включить возможность использования модальных окон.
    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *