IT-Блог о программировании и операционных системах

Взлом Delphi компонент на примере TAdvMemo от TMS Software

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



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

И вот ведь какая штука получается. Взламывать мы будем не компонент, а свою программу. То есть как бы частично, никаких лицензий мы не нарушаем – наша программа, захотим – покрасим.

Техника взлома

После установки компонента и компиляции с ним нашего проекта, запустите его, но только закройте IDE Delphi. Вы сразу увидите некое окно, намекающее нам о том, что компоненту нужно купить. После закрытия окна, программа продолжит выполнение в нормальном режиме. Но такого не случится, если запускать проект на выполнение через саму среду, или с запущенной Delphi. Почему? Давайте разберемся.

Компонент проверяет, запущена ли сейчас среда, или нет и в зависимости от этого, показывает, или не показывает нам окно. Было бы логично предположить, что делает он это через функцию FindWindow, пытаясь найти окна, класс которых соответствует классу окна самой IDE. Это хорошо видно, если смотреть программу под отладчиком. Отладчик может быть любой, IDA Pro, SoftICE или OllyDbg. Я выбрал последний. В нём, чтобы нам поставить брейкпоинт на какую либо API функцию нужно нажать Ctrl+N, выбрать нужную нам функцию (можно набить несколько первых букв на клавиатуре – это сократит время поиска) и выбрать в контекстном меню Toggle breakpoint on import. Запускаем программу на выполнение клавишей F9.

Отладчик остановится на необходимой нам функции, вернее внутри ее самой. Что бы узнать, откуда и почему она была вызвана, необходимо нажать Ctrl+F9 (выполнение до инструкции ret) и затем F8, чтобы выполнить ret и перейти туда, откуда вызывалась процедура. А вызывается она вот где:



Видно, что сначала компонента пытается найти окно класса TApplication, а затем, если окно найдено, пытается найти другое, с классом TAppBuilder, и если последнее обнаружено, то никаких окнон о том что компонента триальная мы не обнаружим. Кстати говоря, TApplication – фундаментальный класс, свойства и методы которого описывают основные характеристики Windows-приложения, так что, как вы понимаете, такое окно может присутствовать в системе с большой долей вероятности, если будет запущена какая либо программа написанная на Delphi, CPP Builder или Lazarus. Так что если вы будете трассировать программу с этого места, не удивляйтесь, что первая проверка прошла и выполнение не передалось на вывод сообщения. Намного интереснее вторая проверка, на класс TAppBuilder. Такой класс как раз и имеет главное окно среды Delphi ( я проверял на Delphi7 & 2010, но думаю, что у всех остальных он один ). Итог один: если программа найдёт классы TApplication & TAppBuilder, то сообщения нам не покажут.





Как бороться?

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

Вариант первый достаточно неказист, хоть и прост в реализации. Я не буду его рассматривать в силу его неинтересности. Остановимся лучше подробнее на втором варианте. Посмотрим ещё раз на код процедуры поиска окон. По адресу 48588С единица отнимается от двойного слова по адресу 48DC20, и затем если первый операнд был больше или равен второму. (оба операнда рассматриваются как числа без знака.), то управление передаётся на адрес 4858С8. Скажу сразу, что в памяти по этому адресу, перед выполнением инструкции:

 SUB DWORD PTR[48DC20],1

находится значение “00 00 00 00”. Получается, что если бы там была еденица или что либо отличное от нулей, то после выполнения инструкции вычитания переход по адресу 4858С8 был бы осуществлён, что нам и нужно.

Получается, можно пропатчить этот момент заменой одного байта! Меняем инструкцию SUB DWORD PTR[48DC20],1 на SUB DWORD PTR[48DC20],0. Проверяем. Работает. С первой проблемой разобрались, теперь надоедливого сообщения мы наблюдать не будем. Но есть и вторая проблема – копирайт на компоненте:


Как бы его убрать оттуда? Решение первое – забить эту строку пробелами в hex-редакторе. Попробуем этот вариант. Открываем наш файл в HIEW и переходим в hex-режим. Для поиска строки жмём F7, вбиваем начало искомой строки, после чего жмём Enter. HIEW находит следующее:



По клавише F3 включается режим редактирования, так вот эту строку нужно забить пробелами. Переход между редактированием шестнадцатеричных кодов и ascii данных производится по клавише TAB. Для сохранения изменений нужно нажать на F9. Конечным результатом будет то, что эти пробелы как бы будут выводиться, но мы их не увидим.


Что тут сказать? Этот способ работает, но есть ещё один и как мне кажется, он лучше. Давайте снова откроем нашу программу под отладчиком и поищем строку о копирайтах (контекстное меню дизассемблера, Search for, All referenced text strings, правая кнопка мыши, Search for text, выключить case sensitive, включить entire scope). На найденной строке кликаем два раза и оказываемся примерно в следующем месте:


Видно, что какая то подпрограмма принимает в качестве параметра ту самую строку. Якорь мне в горло, если эта процедура не отвечает за рисование этих копирайтов. Если зайти в эту процедуру двойным кликом, и прокрутить немного вниз, то мы увидим что функция ExtTextOutA этим и занимается. Что нам мешает занопить (NOP) вызов этой подпрограммы? Да ничего, так и сделаем. Встаём на инструкцию CALL 00421E3C (у вас кстати может быть и другой адрес), жмём правую кнопку мыши, затем Binary и Fill with nop's. Всё, взлом закончен, осталось сохранить результаты работы. 

Как сохранять:
После того как вы изменили нужные вам байты, выполните следующие действия:
ПКМ -> Copy to executable -> All modifications -> Copy all -> ПКМ->Save file

Заключение

Техника взлома таких компонент если и отличается, то очень незначительно. По крайней мере я думаю что все разработки TMS страдают такими изъянами. Да, взломать просто, но ещё проще приобрести данный продукт, тем более в его качестве усомниться точно нельзя. Так что, если вы зарабатываете на жизнь разрабатывая программные продукты, вы должны понимать разработчиков платных компонент. Что-то я рассусолил. Короче, лучше купить ПО, особенно если позволяют финансы, а не ломать их, если не позволяет совесть.




9 комментариев:

  1. Отличная статья. Автору большой +, конечно не за взлом компонента, а за рассказ о технике взлома.Спасибо.

    ОтветитьУдалить
  2. Спасибо и вам за хорошие слова и за прочтение моего труда. Будем стараться и дальше радовать вас интересными заметками.

    ОтветитьУдалить
  3. Найти ж готовые исходники не проблема =))
    Что так незаконно, что так незаконно пользоваться

    ОтветитьУдалить
  4. Лешик, и много вы нашли исходников платных разработок? И все они как говориться up to date? Не уверен...

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

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

    ОтветитьУдалить
  5. Для многих Ваша статья и будет как раз руководством к действию. Я не верю в благородных пиратов-робингудов.

    Лучше бы написали о том, как создать что-нибудь хорошее, а не о том, как украсть.

    ОтветитьУдалить
  6. Ну что тут сказать. Отчасти вы правы. Но у нас тоже есть некоторые аргументы на этот счёт:

    Заметка написана не о том, как сломать, а о том, как НЕ защищать.

    Созидание чего-то хорошего так или иначе связано с изучения лучшего. Человек грамотный учится на чужих ошибках, а не на своих. Это к слову о том что: - "Лучше бы написали о том, как создать что-нибудь хорошее, а не о том, как украсть."

    Пират - Робин-Гуд. Любой разработчик опенсорс или фривар. Он так или иначе частично ворует чужие мысли и наработки, добавляет массу своих и отдает народу.

    Всеобщая декларация прав человека. Статья №18. Цитата: "Каждый человек имеет право на свободу мысли, совести и религии...". Так что, каждый вправе думать об этой статье так, как считает нужным, и применять свои знания, насколько ему позволяет его совесть.

    ОтветитьУдалить
  7. 1. Я считаю, что тема как защищать или как не защищать - это очень специфическая тема, касающаяся очень небольшого количества разработчиков.
    2. Выводы из статьи совершенно неочевидны. В статье даётся техника взлома, а под конец идут "рассусоливания" на тему того, что это может быть наверное иногда плохо.
    3. Любой разработчик опенсорс не ворует код, он может заимствует и развивает идеи, алгоритмы, но не ворует чужой код.

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

    ОтветитьУдалить
  8. 1. Если тема защиты Вас никогда не касалась - вы вправе считать так, как считаете.

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

    3. Взломщик тоже ничего плохого с кодом не делает. Он его исследует на предмет уязвимых мест.

    А про бомбу - это исключительно ваши мысли :)

    ОтветитьУдалить
  9. Спасибо за комментарии.

    Вставлю своих 5 копеек.

    1. Воровства компонента не было. Компонент использовался для написания программы как он есть. Как позволяет его использовать автор(ы). Насчет взлома большой вопрос. Программный код компоненты не ломался. Правился код собственной программы. Ничего криминального в последнем я не вижу. Хотя вполне возможно глубоко заблуждаюсь)
    2. Взлом и воровство это действительно плохо. Никто не побуждает и не пропогандирует данные вещи. В данном блоге точно.
    3. "Все аналогии лживы. Они говорят лишь о их авторе"(с) С. Лукьяненко
    4.
    >Любой разработчик опенсорс не ворует код, он может заимствует и развивает идеи, алгоритмы, но не ворует чужой код.
    Буковки набранные на клавиатуре, важнее алгоритма?
    Патенты на алгоритмы чудным образом испарились со страниц мировой истории?
    С Вашей бы энергией да в ближайший офис MS. Рассказывать, что их патенты это бумажки для wc.

    С Уважением)

    ОтветитьУдалить