Защищайтесь, господа разработчики!
Вопросы защиты своей интеллектуальной собственности все еще остаются большой проблемой. В статье описаны основные принципы защиты разработок на MQL4, используя которые можно если не совсем побороть воровство результатов многодневного труда разработчика злоумышленником, то, по крайней мере, настолько усложнить вору его «труд», чтобы ему просто не захотелось заниматься этим.
Введение
Когда я только начинал знакомиться с MQL, через розовые очки начинающего MQL-программиста мне виделась «приятная во всех отношениях» картина: мне толково рассказывают, как надо торговать. Я не менее толково пишу соответствующую программу, после этого каждый получивший ее себе для работы с первой, заработанной с ее помощью прибыли, перечисляет мне часть своего первого заработка как благодарность за качественно написанный продукт.
Начинающий трейдер, заработавший первый раз 5 баксов на первом депозите в 20$, восторженно перечисляет мне 2$, а какой-нибудь зубр от торговли, в очередной раз сняв 2К, благодарит аж на целых 200$. Все выглядело вполне честно: я делаю работу, которую не может сделать трейдер-непрограммист, который с ее помощью зарабатывает большечащелегчепостоянее, чем без нее. Вместе мы сработали успешно и вместе получили отличный финансовый результат, который можно разделить по справедливости. Я даже придумал для этого специальные условия распространения — FairWare.
Каково же было мое удивление, когда, несмотря на достаточно приличное число скачиваний моих первых инструментов и постоянные вопросы-консультации по ним, я за год получил всего один платеж на 3$, в котором человек явно сослался на мои условия FairWare. В общем, с честностью неизвестного мне качальщика и пользователя моих продуктов обнаружились явные проблемы, и я решил установить хотя бы какую-то минимальную планку оплаты за использование моих инструментов на реальных счетах.
Для этого пришлось вставить в них защиту и перейти на принципы Shareware. По мере «взросления» моих инструментов все более взрослыми становились и пожелания к их защите, и на сегодняшний день у меня накопилось несколько проверенных способов, которыми я решил поделится с собратьями по MQL-кодингу. Все мы в той или иной степени проходим описанный мною в начале этой статьи путь, и собранная в едином месте информация по этой проблеме наверняка многим очень сильно облегчит «защитные страдания».
Итак, приступим: от простого к сложному.
Защита строковых констант
Первое, что хочется защитить, — это свое авторство. Не только для того чтобы погордиться и похвастаться, что это я, мол, такой крутой программер написал такую вещь, но еще и для того, чтобы пользователи имели возможность обратной связи с автором-разработчиком. Как гласит закон Мэрфи, «всякая найденная вами последняя ошибка на самом деле является предпоследней», и вполне вероятно, что не вы наткнетесь на нее при тестировании, а другой пользователь обнаружит то, что проскользнуло мимо вас. В этом случае надо сделать так чтобы текст строки, которую выводит ваш эксперт с вашим e-mail или адресом сайта, остался неизменным. Возьмем простейший код:
Все честно, открыто. Сброс скрипта выводит ваш комментарий. Однако заглянув вовнутрь файла ex4 мы видим все тексты в открытом виде.
Любой HEX-редактор позволит без труда заменить видимые тексты на какие-то свои, и модифицированный скрипт будет выдавать уже совсем не ваш копирайт.
Теперь давайте задумаемся: что такое текстовая строка? Это последовательность сцепленных друг с другом символов. Кто мешает написать нам такую операцию «посимвольно»?! Однако прежде чем делать это, подготовим сборщик закодированных строк. Вот его текст:
Алгоритм работы, я надеюсь, очевиден: вписываем комментарий, чтобы видеть, что закодировали, и пристегиваем к нему символ за символом код сборки строки из отдельных символов. Полученную строку выводим в лог, чтобы оттуда скопировать его для вставки в исходный текст.
Чтобы понять, как это сработает, давайте посмотрим на исходник с закодированной строкой.
Как мы видим, сначала объявляем строковый массив из всех возможных 256 символов основной таблицы и заполняем каждый его элемент соответствующим символом. Затем вставляем вместо исходной строки тот закодированный текст с комментарием, который мы скопировали из лога на закладке Эксперты окна Терминал, компилируем и смотрим результат.
В результате содержимое оказалось зашифрованным, и мы уже нигде не видим нашей закодированной строки. Ведь ее уже нет — вместо нее есть набор команд, которые ее собирают. Оставшиеся незашифрованными строки — это константы из #property copyright и #property link — их, к сожалению, так закодировать нельзя, поскольку они задаются именно строками, и там никакие коды сборки недопустимы.
Вот так, теперь каждую строку, которую мы хотим защитить от возможного изменения HEX-редактором, можно закодировать таким образом. Для этого нужно только с помощью скрипта Protect-002.mq4 получить ее зашифрованный вид. При использовании такой сборки нужно иметь в виду, что такая операция сцепления символов занимает определенное время. Поэтому нельзя такие конструкции напрямую вставлять в тело эксперта, чтобы не дергать их по сто раз на каждом тике. Достаточно объявить нужные строковые переменные и проинитить их один раз такой закодированной сборкой при ините индикатора или эксперта и в дальнейшем пользоваться уже этими переменными.
Защита от несанкционированного использования
Ну вот, свое авторство мы защитили и подошли к другой проблеме. Написанный вами советник может быть кем то скопирован без вашего ведома (например, когда вы отлучились от компьютера в торговом зале ДЦ), и в дальнейшем он начинает свою жизнь без вашего ведома. Если вы собирались пользоваться им только лично для себя или продавать его, такая «утечка» будет, конечно же, не в ваших интересах.
Механизмов защиты от несанкционированного использования существует достаточно много: от простых генераторов серийных номеров, до защит с использованием онлайн сервисов иили электронных ключей защиты. Последний способ — самый надежный, но одновременно и самый трудоемкий. Однако у терминала MetaTrader есть определенная, только ему присущая, специфика, которая вместе со спецификой самого объекта защиты позволяет использовать более простой, но, тем не менее, надежный способ.
Реально нужно сделать так, чтобы копия вашего советника или индикатора работала только у того, кому вы ее передали или продали. Для однозначного определения владельца у нас есть совершенно уникальная для каждого пользователя вещь: номер его рабочего счета. А в паре с именем торгового сервера он вообще становится уникальным «электронным паспортом» владельца эксперта.
Вот пример простейшего кода, реализующего эту схему защиты:
Здесь мы воспользовались нашим предыдущим способом скрытия номера счета и названия торгового сервера в виде зашифрованных строк и можем быть относительно уверены, что ваш ex4 нельзя будет «поправить» так, чтобы он работал на других счетах и серверах.
Вопрос организации такой защиты (каждый раз пересобирать эксперта под каждого разрешенного клиента или придумать какую-то универсальную схему защиты с использованием механизма закодированных строк) выходит за рамки этой статьи. Да и нельзя открыто обсуждать логику работы таких универсальных защит. Ведь знакомиться с ней будут не только разработчики, но и взломщики — ну а зачем нам облегчать им работу по взлому наших программ?
Защита по времени
Другим способом защиты своего эксперта может быть ограничение его работы по времени. Вы можете позволить ему работать ему только до определенной даты на любом счете или сервере. После окончания демо-периода эксперт перестанет работать, и пользователь должен будет обратиться к вам за нормально защищенным вариантом эксперта.
Вот текст скрипта с этим механизмом защиты.
В нем так же используется шифрование строки даты окончания демо-периода, чтобы нельзя было его «продлить», поправив ex4-файл вручную.
Защита от декомпиляции
К сожалению, все эти способы успешно работают только тогда, когда взломщик не имеет доступа к исходному коду эксперта. Однако, как говаривал небезызвестный дядя Степан из кинофильма «Формула любви»: что один построил — другой завсегда поломать может. В сети гуляет утилита для декомпиляции ex4-файлов. Ее авторы даже снабдили ее собственной защитой и продают ее.
Но дядя Степан был прав — и их утилиту тоже взломали и теперь каждый, кто ухитрился ее раздобыть, может декомпилировать вашего эксперта и получить его исходный код. В этот декомпилированный код можно внести нужные правки (например, просто выбросить блок анализа дат, счетов и серверов) и, перекомпилировав его, получить полностью беззащитный вариант вашего советника.
Разработчики компилятора MQL4 как могут борются с этой проблемой. Детали этой борьбы, естественно, наружу никогда не будут вынесены. Но, к сожалению, зачастую исходник все таки можно восстановить. Правда текст его будет несколько неудобочитаем: все идентификаторы вместо осмысленных имен будут называться механически созданными именами. Это, конечно же, сильно затрудняет процедуру разбора и восстановления алгоритма работы. В больших по объему файлах, со множеством функций, это может стать практически нерешаемой задачей. Однако когда эксперт небольшой, его можно восстановить практически до исходного состояния.
И здесь на первое место выходит искусство программиста. Задача разработчика системы защиты состоит в том, чтобы зная, в каком виде декомпилятором будет восстановлен исходный текст, написать его так, чтобы возможность нахождения и отключения защиты была для взломщика максимально затруднена. Эта часть статьи конечно уже не будет подробно излагаться — методы такой защиты вам придется придумывать самим.
Самые общие рекомендации — разброс кода защиты по всему модулю. Взломщика нужно умотать работой по анализу вашего кода так, чтобы ему не захотелось возиться со взломом. Значения контрольных переменных нужно собирать в разных местах исходного кода, причем, чем неожиданнее место, тем труднее будет догадаться, что это кусочек защитного кода.
Например, сборку даты окончания можно разбить на два оператора: год задать в самом начале эксперта, а месяц, день и время — дописывать по ходу вычислений торговых сигналов. Сам анализ нарушений тоже можно сделать в одном месте кода, а действия по его результату (досрочный выход или ограничение функциональности) — в другом.
Существующий декомпилятор ex4-файлов не умеет восстанавливать имена переменных, но имена функций он все-таки восстанавливает. Точнее, они, в отличие от имен переменных, просто есть в ex4-файле, откуда и выбираются декомпилятором. Поэтому, если вы используете функцию IsDemoMode(), то тем самым вы даете прямое указание, где искать отключалку вашей защиты.
Если мы немного перепишем наш скрипт с проверкой демо-периода по дате вот так «неправильно»:
то декомпилятор выдаст нам вот такой текст:
Как видим строка с датой зашифрована, и понять с ходу что и как проверяется — нельзя. Однако, по тексту совершенно очевидно, где и что нужно поправить в функции IsDemoMode, чтобы защита отключилась.
MQLEnigma — кодировщик MQ4 текстов
Для того чтобы бороться с существующим декомпилятором, нам придется научиться заменять имена используемых функций. Сделать это средствами MQL4 практически невозможно (ну разве что вы сами контекстной заменой замените нормальные названия на откровенную белиберду). Поэтому мне пришлось написать программу-кодировщик на языке VB.NET.
Почему на нем? Просто потому, что последние несколько лет я на основной работе очень интенсивно программирую на VBA и VB.NET, поэтому на нем я смог это сделать максимально быстро и комфортно. К тому же сборка производилась в Express редакции Visual Studio, на которую не нужно приобретать лицензию.
Единственное неудобство для будущих пользователей этой программы — необходимость иметь установленным в системе .NET FrameWork версии 3.5. Но он, несмотря на свой приличный объем, может быть уже установлен на современных машинках с современным софтом, который зачастую пишется на .NET и устанавливает его при своей инсталляции. Если в вашей системе его нет, вы можете загрузить его здесь и установить самостоятельно.
MQLEnigma — это консольное приложение. Ему передается один обязательный параметр — имя файла для кодирования. После этого с текстом производятся следующие манипуляции:
Вставляются все include-файлы. Если у вас есть глобальные переменные, которые используются в разных файлах в других экспертах, их нужно собрать в один общий, чтобы замена коснулась только сборки одного этого конкретного эксперта, а другие — продолжали использовать включаемый файл с незашифрованными именами.
Из полученного общего текста вырезаются все комментарии (чтобы не нарваться на какой-нибудь // int i=0;).
Очищенный текст разбивается на две части: отдельно вырезаются и анализируются тела функций, и отдельно остаются все внешние переменные и define, а также объявления функций.
Из блока внешних текстов удаляются все описания импортируемых функций. Их имена заданы снаружи и кодировать их нельзя.
В обоих блоках текстов (внутреннем и внешнем) находятся описания стандартных типов int, string, . из них удаляются инициализации переменных и размерности массивов.
В конструкциях define удаляется ключевое слово define и назначение параметра так, чтобы осталось только определяемое имя. Также удаляются зарезервированные слова (чтобы вы не заменили случайно название цвета Magenta на какой-то мусор).
В результате всех обработок остаются только имена переменных, внутренних функций и объявленных констант. Эти имена собираются в общий список, из него удаляются дубли (описание int i=0; может встретиться внутри нескольких функций). По ходу создаются «мусорные» имена переменных для замен и определяются длины найденных идентификаторов, чтобы выполнять замены начиная с самых длинных. Иначе, при наличии двух переменных str и str2str, может получиться неправильное имя у более длинного str2str, если сначала в нем будут заменены две его «части» str.
Собственно все: в отдельный файл с суффиксом Open пишется очищенный полный текст файла эксперта со всеми вставленными в него инклюдами. После этого выполняется замена идентификаторов. В отдельный файл с суффиксом Encodings выводится табличка соответствий имен найденных идентификаторов и записывается закодированный файл с суффиксом Encoded. Именно этот файл вы должны будете откомпилировать и распространять полученный из него ex4.
Новые имена можно собирать как угодно, лишь бы они были бессмысленны и уникальны. Я использовал простой способ: взял максимальное целое число, приписал к нему слева допустимый, но «невидимый» символ с кодом 160 (неразрывный пробел) и для увеличения мусорности слева и справа основного числа добавил случайные числа. При формировании очередного имени из предыдущего основного числа вычитается единичка (чтобы гарантировать уникальность имени) и снова дописывается мусор и невидимый пробел.
Чтобы не заменять имена переменных в текстовых константах типа:
я использовал такой прием: перед заменой переменных после каждого символа внутри символьной константы я вставлял символ с кодом 3. Его нельзя просто набрать на клавиатуре и, значит, его не может быть в вашем тексте. В результате константа «LotSize = » превратилась в » #L#o#t#S#i#z#e# #=# #» (где # означает это самый символ с кодом 3). Теперь если я буду искать подстроку для замены LotSize в строковой константе я ее просто не найду и она так и останется незамеченной. После того, как все замены настоящих переменных будут выполнены, я просто повырезаю все символы с кодом 3 и исходный текст строковых констант восстановится.
Когда мы заменили в тексте из предыдущего примера найденные переменные по вот такому списку (первая цифра — это количество найденных вхождений идентификатора в исходном тексте):
то получили вот такой файл
Занятной возможностью использования такого кодирования исходного текста может получиться вот такое его применение: от вас требуется исходный текст эксперта, но вы не хотите его отдавать. Но теперь вы можете отдать этот закодированный текст и получится, что исходник вы все таки отдали, но секрет своего алгоритма так и не раскрыли.
После его декомпиляци получается вот такой текст:
В нем уже не осталось ни одного осмысленного имени (ну кроме зарезервированного start да стандартных имен функций) и хотя разобраться с этим файлом-примером, наверно, можно без особого напряга, но более сложный текст с массой переменных будет совершенно неадекватен. За его взлом запросят такие деньги, что пользователю будет дешевле и проще купить нормальный эксперт у самого автора эксперта, получив при этом от него официальную поддержку.
Заключение
Скажу честно, текст MQLEnigma писался мною в худших традициях Extreme-программирования. Я рассчитывал на то, что исходный текст, подаваемый ему на вход, является синтаксически «правильным». Ну, например, там не может быть незакрытых скобок функций, объявлений типов без имен переменных (int 😉 и т.п. Алгоритм вырабатывался «по ходу» — я взял свой самый объемный проект и на нем постепенно вырезал все лишнее, глядя на получавшийся текст, в котором, в конце концов, должны были остаться только имена переменных. Поэтому я не вставлял многочисленные обработки исключительных ситуаций и возможных ошибок.
Кроме того, предстоящий выход MQL5 превратил эту работу в одноразовую, которая очень скоро «пойдет в корзину». По этой же причине был выбран VB.NET — я на нем (точнее на VBA) почти ежедневно буквально щелкаю программки как орешки, и писать на нем мне было легче, быстрее и комфортнее.
Несмотря на этот разгильдяйский способ написания, MQLEnigma получилась рабочей программой, и пока что мне не удалось нарваться на исходник, который был бы как то неправильно обработан, чтобы его компиляция приводила бы к ошибкам. Но это не означает, что он абсолютно правильный. Именно поэтому я даю его исходный текст. Если у вас MQLEnigma сработает неправильно, вы сможете сами выяснить причину и, при необходимости, самостоятельно поправить ее (если такое произойдет, не забудьте пожалуйста оповестить о сделанной вами модификации в обсуждении этой статьи).
Приведенные в этой статье способы — это только вершина айсберга, которая, тем не менее, позволяет достаточно эффективно защищать свои разработки. Возвращаясь к тому, о чем я писал в самом начале статьи, я могу сказать то же самое, что писал в заключении своей самой первой лицензии FairWare: «Автор, как мог, помог вам, написав эти программы, которые вы может никогда бы сами не придумали и не написали. Теперь — ваш очередь помогать Автору, так как можете вы 🙂«.
В коде MQLEnigma могут быть некоторые логические ошибки, которые не проявились на тех текстах, которые были у меня под рукой для тестирования при его написании и отладке. Если вы найдете их, сообщите мне об этом, чтобы я мог внести правки и обновить файл, приложенный к этой статье. Если вы знаете другие способы защиты, которые могут быть открыто опубликованы без того, чтобы стать помощью для взломщиков, оставьте комментарий к этой статье. Я и другие члены нашего MQL4-сообщества будут вам только признательны за ваш вклад в «наше общее дело».
Ну и совсем уж в заключение: тема защиты исходного кода своих разработок — очень непростая. Делиться всеми секретами открыто нельзя, потому что тем самым вы объясняете потенциальным взломщикам, как можно с вами бороться. Я решил опубликовать эту статью только потому, что для декодеров ничего нового я не открываю. Однако это первые, всем известные способы защиты, которые достаточно эффективно работают и могут быть полезны, особенно начинающим MQL-программистам.
https://www.mql5.com/ru/articles/1572