Как ломают программы
Способы взлома программных защит ты и без меня знаешь (подчеркиваю,
что мы будем говорить о программных защитах, так как всякие хаспы
простому смертному кодеру с его программой «Яйца» не очень доступны). А
если не знаешь, то в двух словах: патчат двоичный код или пишут кейген.
Возможны и другие методы взлома, я тебе назвал два основных, знакомых
всем нам на практике. Чувствуешь, что эти два метода принципиально
разные? Каждый из них по отдельности может привести к необходимому
результату – несанкционированному использованию твоих «Яиц».
Значит, и защита должна состоять как минимум из двух более-менее
независимых компонентов (кто в курсах, это модель элементарной защиты с
двумя звеньями).
Первый компонент отвечает за целостность программы (ну или только
системы защиты – можно ведь контролировать целостность не всей
программы, а только защитного механизма). Мне захотелось этот компонент
назвать физической защитой. Реализовываться она может по-разному:
например, можно осуществлять превентивный контроль, запрещая любую
запись в exe-файл. Можно не разрешать использование модифицированных
файлов. То есть изменять изменяй, но ни в коем случае не используй.
Последний вариант мне показался более приемлемым, и я его и забабахал в
свой патент как часть способа защиты ПО от несанкционированного
использования. Но что-то мы отвлеклись, сегодняшняя наша цель – борьба с кейгенами!
Итак, второе звено - логическая защита. Это защита от тиражирования
одной легально купленной копии на много разных машин. Как ее можно
сделать? Можно попытаться спрашивать у пользователя его персональные
данные, отправлять их на сервер поставщика ПО, на их основе высчитывать
внешний серийный номер и возвращать его обратно. Наша программа на
основании вводимой фамилии пользователя вычисляет свой внутренний
серийный номер и сравнивает его с вводимым пользователем внешним
номером (который надо получать от поставщика). Таким образом, вроде,
все отлично: и учет пользователей ведется, и программы не тиражируются.
Схема защиты от тиражирования с помощью данных пользователя
Однако же такой подход не выдерживает никакой критики: пираты могут
купить один экземпляр программы и дальше тиражировать его с указанием
фиктивных имени и фамилии, которые нужно вводить при регистрации. И
заметь, при этом даже не надо ничего ломать!
Но такой метод нелегального распространения, конечно, почти никогда
не применяется - несолидно это в то время, когда в мире есть тысячи
хакеров, жаждущих славы и признания. Те садятся за свои суперкомпьютеры
и за короткое время выясняют, как же на основании слова «Пупкин»
вычисляется страшный серийный номер 111. Потом пишут кейген,
который работает по этому алгоритму, и вот юзеру уже не надо вводить
какие-то там фиктивные данные, вводи себе свои родненькие, а кейген, вместо поставщика ПО, сделает внешний серийник.
Что такое превентивная физическая защита?
Ясен перец, что готовый откомпиленный ехе-файл никогда не должен
изменяться. А тот, кто хочет его изменить, – подлец несчастный или
грязный вирус. А ну-ка придумай ситуацию, в которой для каких-то мирных
целей нужно изменить экзешник! Что, не выходит? Хе-хе, нету таких
ситуаций. Значит, надо подобное безобразие контролировать и упреждать.
Желательно это делать на уровне ОС, что нам опять же будет недоступно.
Хотя тут уже кто как захочет: пиши драйверок, работающий с высокими
привилегиями, запрещающий вносить изменения в ехе-файлы, - и готов
примитивный, но действенный файловый антивирус, который тоже можно
продать! Правда, как известно, на любой драйверок всегда найдется еще
более драйверистый драйверок :).
В образовательных целях запусти свой любимый антивирь и попробуй
изменить любой мирно лежащий экзешник, хотя бы открыв его блокнотом.
Все пройдет гладко и спокойно. Кто еще не верит, пускай напишет
программку, которая изменяет любой экзешник программно, и стартанет ее.
Сработает. Короче, не ловят популярные антивирусяги такие действия. А
зря.
Итак, превентивный контроль – это запрет внесения изменений в
исполняемые файлы (потому что они и так никогда не должны изменяться).
Как бороться: способ номер один
Что ж, давай подумаем, как можно избавиться от простейшего метода
распространения одной легально купленной копии твоих «Яиц». Такое
распространение возможно, потому что мы высчитываем серийник на
основании данных пользователя, а он, понятное дело, может указать
произвольные данные, то есть нас обмануть. Значит, логично будет
запрашивать персональные данные компьютера. Их-то пользователь
подделать не сможет!
Итак, мы будем производить привязку к программно-аппаратной среде
компьютера, на котором будет использоваться наша программа. Ну что это
могут быть за сведения? Например, серийные номера всяких компонентов ПК
(процессора, винчестера и пр.), особенности файловой системы, реестра и
т.д. Чем больше мы возьмем разных характеристик компьютера, тем меньше
вероятность их имитации. Но при этом возрастает частота обращений к нам
конкретного пользователя за сменой активационного кода. Подумай, ведь
если он заменит процессор, то нам придется заново выдавать ему
серийник! А если делать привязку к программной части, то это вообще
жесть. Количество контролируемых характеристик и их тип надо выбирать с
опорой на экономические расчеты (то есть ценность одной копии твоего
ПО). В защите информации почти всегда все решает не техника, а
экономика :-).
Итак, модифицированная схема защиты от тиражирования ПО выглядит
очень просто (смотри схему). Теперь тупо распространять одну копию с
фиктивными персональными данными не удастся. Мы осуществили очень
популярную привязку к аппаратной части ПК, которую я тебе предлагаю
делать еще и программно-аппаратной. Эффективный метод. Действительно,
не будет же товарищ взломщик распространять одну легально купленную
копию вместе с процессором и всеми потрохами, на которые была куплена
эта копия? :-D
Схема защиты от тиражирования ПО с привязкой к аппаратной части ПК
Но что-то все равно не радостно. От простого тиражирования-то мы
защитились. Но хакеры… они ж так и будут продолжать писать свои гадкие генераторы, из-за которых продажи «Яиц» падают ниже плинтуса. Что же делать?
Принцип написания генератора
Давай подумаем, как хакер пишет генератор. На основании каких сведений он это делает? Ему ведь надо знать, как поставщик высчитывает внешний серийный номер?
Смотрим внимательно на схемы. С чем сравнивается внешний серийник?
Правильно, с внутренним серийником. А по какому алгоритму высчитывается
внутренний серийник? По сугубо секретному алгоритму, который находится
в самой распространяемой программе. Стойкость такой защиты базируется
на секретности алгоритма, что, в общем-то, уже не очень хорошо.
Напоминаю, что стремиться нужно к такому способу защиты, при котором ее
стойкость основывается на секретности ключа – почитай правила Кирхгофа
для шифров.
Итак, полагать, что от взломщика можно скрыть какие-то сведения,
находящиеся в копии ПО на его стороне (то есть на его компе), - наивно
и даже глупо. Скрыть-то можно, зашифровав и выбросив ключ, но в таком
случае эти данные останутся лежать мертвым грузом в программе. Если же
надо в программе какие-то сведения использовать, то нужно предполагать
с вероятностью 100%, что эти сведения доступны не только нашей
программе, но и хакеру. И это не зависит от того, какого характера эти
сведения: исполнимый код или статические данные (например, ключ).
Следовательно, раз алгоритм создания внутреннего серийника должен
использоваться нашей программой, то получить к нему доступ сможет и
мазахакер. Насколько трудно это будет – это уже второй вопрос, но ты не
обольщайся. Даже если ты 100 раз зашифруешь алгоритм создания
внутреннего серийника, хакер только порадуется :-D. Ему, понимаешь ли,
в кайф вскрыть очередную защиту, просто-таки разложить по полочкам и со
спокойной совестью сдать написанный по изученному алгоритму генератор
на какой-нибудь крякерский форум. Дальнейшее развитие событий известно:
хакер идет пить пиво, а крякеры получают тонны зелени с продаж
нелегального ПО.
Как бороться: способ номер два
Ну, в общем-то, кто там что получает – это не наше с тобой дело. Наше дело - пресечь все мерзкие действия по написанию генератора.
Для этого надо как-то избавиться от алгоритма расчета внутренних
серийных номеров. После некоторых размышлений я решил применить
криптографический алгоритм доказательства при нулевом знании. В этом
случае копия ПО выступает в роли проверяющего, а поставщик ПО - в роли
доказывающего. То есть поставщик (через промежуточного агента –
пользователя ПО, что в принципе несущественно) должен доказать копии
ПО, что она имеет право запускаться на данном ПК. Теперь конкретнее.
Предлагаемая схема защиты от тиражирования без внутреннего серийника
Копия ПО собирает идентификационные данные среды, в которой она
будет работать, и отправляет их на сервер поставщика лицензий.
Поставщик с использованием своего секретного ключа генерирует цифровую
подпись полученных идентификационных данных и отправляет назад. Копия
ПО с помощью открытого ключа поставщика проверяет соответствие его
цифровой подписи идентификационным данным своей программно-аппаратной
среды.
Если проверка цифровой подписи прошла успешно, программа начинает
свою нормальную работу, в противном случае завершается. На практике
такие проверки надо осуществлять, естественно, не один раз, а
регулярно, допустим, при каждом запуске ПО.
В чем же преимущество предлагаемого подхода? А в том, что теперь нет
секретного алгоритма, заложенного в само ПО, доступного хакеру. Копия
ПО всего лишь должна проверить соответствие цифровой подписи
идентификационным данным компьютера и пользователя. А это делается, как
и в любой системе проверки подлинности, с помощью открытых ключей
поставщика по известному алгоритму. На основании открытого ключа
поставщика создать цифровую подпись нельзя, если, конечно, применяется
стойкий алгоритм цифровой подписи. Чужую подпись взять нельзя, так как
она зависит от характеристик данного ПК. Вот засада, правда? :)
Немного о преимуществах формализации
Ты мне можешь сказать, что такую систему проверки все равно можно
взломать, изменив двоичный код системы защиты (банальная смена условной
команды ассемблера на логически противоположную). Но ведь это
принципиально иной метод взлома!
Тут ты и попался! Суть предлагаемого мной общего формализованного
метода создания программных защит (любого назначения) заключается в
разбиении системы защиты на две части, и первая из них – физическая
защита от модификаций кода (посмотри-ка в раздел «Как ломают
программы»). Это ее функция – предохранять от изменений двоичный код
ПО. Как ты эту часть реализуешь - дело твое, но она должна
присутствовать в любой программной защите.
Защита же от тиражирования одной легально купленной копии на много
разных ПК относится ко второму классу – логическим защитам. Они должны
выполнять специфические функции, ради которых первоначально и
возводилась сама система защиты. Вот, например, если мы создаем защиту
от нелегального распространения ПО, надо с помощью этой логической
защиты запретить установку (тиражирование) одной легально купленной
копии на много разных ПК. А за целостность этой защиты, за то, что она
будет работать правильно и адекватно, будет отвечать звено физической
защиты.
Физическая защита без логической не имеет смысла, так как она следит
за целостностью самой системы защиты, а не выполняет какие-либо
смысловые действия для области применения системы защиты. Логическая
защита без физической не имеет смысла, так как ее элементарно ломануть
с помощью изменений двоичного кода.
Таким образом, предложена формализованная методика построения
программных защит. Два звена: логическое и физическое. Реализовываться
они могут по-разному.
Модель предлагаемой комплексной защиты
Чтобы тебе не показалось, что такая методика построения программных
защит притянута за уши только к системам защиты от пиратства, приведу
еще один пример. Вот разработал я систему программной биометрической
идентификации, которая следит за пользователем и контролирует, тот ли
это человек работает, или его подменили еще в роддоме (главное, чтоб
уже после снятия эталонных данных :-D). Эта система тоже построена по
подобной методике. Логическая защита снимает данные и сравнивает их с
эталоном, то есть выполняет те действия, ради которых выполнялось
построение всей системы защиты. Но это ж еще не все! Не надо забывать,
что нехороший человек может модифицировать программную систему
идентификации, изменив в ней самый последний перед выдачей вердикта
условный оператор. При таком изменении всего лишь одной команды
ассемблера вся многомесячная работа идет коту под хвост. Так вот я
прикрутил туда еще звено физической защиты, и теперь фиг там что-то
изменишь так просто, легче нанять себе двойника :-).
Что ж, подход простой. Два звена – защита от двух угроз,
соответственно. Хорошая у меня классификация угроз, большая :-).
Рекомендую ознакомиться и с другими классификациями угроз программному
обеспечению, предлагаемыми, например, Microsoft. Для этого ищи в инете
DREAD и/или STRIDE. Посмотри, сколько там угроз рассматривается. А
способствует ли это как-то созданию защит (в чем и заключается цель
любой классификации угроз) - решай сам.
Хочу только еще отметить, что многие угрозы на самом деле угрозами
не очень и являются. По моему мнению. Вот, например, угроза
исследования программного обеспечения с помощью дизассемблера или
отладчика. Ведь само по себе исследование не может повлечь негативные
последствия для твоего ПО. К ним может привести физическая модификация
или написание генератора ключей, которые следуют за
исследованием кода. Таким образом, трудно сказать, является ли
исследование кода с помощью дизассемблера угрозой его безопасности. Мне
вот кажется, что это не прямая угроза, а лишь предпосылка для
реализации прямой угрозы – модификации или создания генератора,
от которых мы и должны защищаться. Но я бы сказал, что это уже из
области терминологии. В общем, именно на основе правильной
классификации угроз строится любая система защиты, в том числе и
программного обеспечения от несанкционированного использования. Мне
хватило двух угроз, а ты разрабатывай свои собственные классификации. И
внедряйте, Шура, внедряйте.
Короче, Склифосовский!
Напомню, что основной целью статьи было рассмотрение способов борьбы со взломом путем написания генератора ключей. Надеюсь, мы успешно справились с этой задачей. Все замечания, критику и вопросы шли мне по почте. С радостью отвечу.
Кроме разработки всяких там антигенераторов и схем защиты, статья
призвана также немного взбудоражить общественность, вызвать жаркие
споры, шевеление серого вещества. Приветствуются любые мнения, даже
критика Меня. Особенно - ссылки на похожие методики защиты. Скажу
только, что перед подачей своего патента я долго рылся в русской (www.fips.ru), украинской (www.ukrpatent.org) и европейской (www.espacenet.com) базах патентов и ничего похожего на мою продвинутую схему не нашел. Поэтому надеюсь, что моя статья принесет кому-либо
реальную пользу.
|