Эта статья посвящена достаточно актуальной в настоящее время тематике — защите программ от взлома и нелегального копирования. Этой теме посвящено много статей, одна из наиболее интересных (из тех, которые попались мне) — статья «Защита shareware-программ» Владимира Каталова в Компьютерре Online#240. Он привел ряд советов по написанию shareware программ и я не хочу повторяться — сходите, почитайте.
Рассмотрим некоторые тонкости организации защиты на достаточно популярном примере — предполагаем, что программа защищена некоторым кодом (серийным номером, паролем), который сообщается пользователю после соблюдения им определенных условий. До регистрации в этой программе заблокирован ряд каких либо полезных функций, используется надоедливая реклама или ограничен строк работы. После ввода этого кода производится его проверка и при положительном исходе проверки программа начинает нормально работать.
По неизвестной мне причине в большинстве современных программ данная защита сделана однообразно и для ее снятия необходимо 10-15 минут. В этой статье я постараюсь поделиться опытом в построении систем защиты. Могу сразу предупредить — хорошему хакеру противостоять практически бесполезно, да и не нужно — при желании любая защита может быть взломана, это вопрос времени.
Ни один хакер мира не может взломать эту защиту. Абсолютная защита вашего компьютера.
Инструментарий хакера
Современный хакер имеет в своем арсенале набор разнообразных утилит для взлома.
- Отладчики. Позволяют прерывать выполнение программы при достижении заранее заданных условий, производить пошаговое выполнение программы, изменять содержимое памяти и регистров и т.п. Наиболее популярным, удобным и мощным является отладчик SoftICE, который при достаточно примитивном интерфейсе обладает приличными возможностями и весьма стабильно работает.
- Дизассемблеры. Производят дизассемблирование программы для дальнейшего изучения полученного кода. Один из наиболее мощных и популярных — IDA. От дизассемблера достаточно легко защититься — зашифровать или заархивировать программу. Тогда дизассемблируется только архиватор или кодировщик. Однако тот-же IDA имеет мощный встроенный скриптовой язык, позволяющий производить расшифровку программы
- Средства мониторинга. Это набор утилит, отслеживающих операции с файлами, реестром, портами и сетью.
- Средства пассивного анализа программы. Показывают разную информацию о программе — извлекают ресурсы, показывают связи, используемые библиотеки. Классический пример — утилита DEPENDS.EXE из комплекта Visual Studio. Она показывает, какие библиотеки используются программой и какие функции импортируются.
- Прочие утилиты. Их великое множество (можно найти на диске типа «Все для хакера», причем в изобилии). Это разнообразные редакторы, анализаторы .
- FileMon — утилита, позволяющая вести мониторинг всех операций с файлами. Имеет удобный фильтр, может сохранять отчет в файле. Поэтому нет смысла делать «секретные» файлы где-нибудь в Windows/System — их элементарно найти.
- RegMon — аналог FileMon, только ведется мониторинг всех операций с реестром. Аналогично файлам, бессмысленно создавать в реестре «секретные» ключи — они сразу бросаются в глаза.
- PortMon — мониторинг работы с портами ввода/вывода
- TCP_VIEW — монитор соединений по TCP-IP
- RegUtils — набор утилит для контроля за реестром — делает копии реестра, позволяет сравнивать копии и просматривать изменения.
Основы построения защиты — шаг за шагом
Как ввести регистрационный код. Ввод пароля или регистрационного номера является ответственным делом — хакер постарается отловить адрес памяти, в который будет записан пароль. Затем на обращение по этому адресу ставится точка останова (команда BPM в SoftICE), что позволяет поймать начало процедуры проверки регистрационного кода. Если для ввода используются стандартные элементы ввода Windows, то алгоритм действий хакера можно формализовать и выглядит он примерно так:
Как защитить свой код на Python от ВЗЛОМА
- Устанавливает точку останова на считывание текста из стандартного элемента ввода (функции GetWindowText, GetGlgItemText модуля KERNEL32)
- При вызове этой функции анализируем ее параметры и таким образом определяем, по какому адресу будет размещено считываемое значение и ставим обращение к этой области памяти точку останова. А достоверности определенного адреса легко убедиться — после выполнения функции там появится введенная строка
- При срабатывании этой точки останова мы попадаем в анализатор введенного значения и либо делаем генератор регистрационных ключей, либо ломаем процедуру проверки. И то, и другое весьма просто сделать — достаточно только изучить ассемблер и API
Набор этих действий стандартен и мне не раз попадались подробные руководства типа «Взлом Windows программ — шаг за шагом», ориентированные на продвинутого пользователя.
Рассмотри несколько решений, которые могут затруднить взлом на этом этапе.
Совет _0. Старайтесь как можно меньше применять стандартные функции (особенно API-шные) и компоненты VCL. Так что Assembler, Assembler и еще раз Assembler .
Сущность этого совета надеюсь очевидна — современные дизассемблеры умеют распознавать стандартные процедуры высокоуровневых языков, а API — вообще отдельный разговор — SoftICE обладает изумительной возможностью — загружать символьные имена для любых указанных библиотек (особенно для KERNEL32.DLL) — отладка резко упрощается, т.к. мы видим имена вызываемых функций и можем ставить точки останова на вызов функций по их имени.
Совет 1. Применяйте нестандартный способ ввода пароля.
Наипростейший путь — написать свой визуальный компонент для ввода регистрационного кода. Он конечно должен будет обрабатывать события от клавиатуры, но момент считывания кода нельзя поймать избитыми методами. Это уже что-то, но есть второй способ взлома, основанный на поиске введенного кода в памяти. Для этого в SoftICE есть удобная команда «S стартовый адрес L длина ‘образец'» , которая позволяет найти введенное значение в памяти.
Совет 2. Не храните введенный код в одном месте !
Если введенный код или регистрационный номер хранить в одном месте, то достаточно легко установить точку останова на эону памяти, в которой зазмещен введенный код.
Совет 3. Не храните введенный код открытым текстом !
Итак, что же следует сделать. Для начала необходимо завести в программе 5-10 переменных типа STRING и после ввода кода переписать введенное значение в них. Делать это лучше всего не в одном месте, а распределить по программе. Таким образом поиск даст кучу адресов, по которым будет находиться введенный код.
Я в таком случае поступаю так — по таймеру создаю в динамической памяти новую строковую переменную, пишу в нее код. Затем на следующем срабатывании таймера создаю новую переменную, переписываю в нее код, а старую уничтожаю. При определенном навыке можно заполонить память значениями введенного кода и сделать поиск почти бесполезным. Причем такое копирование можно совместить с проверкой кода или эмуляцией этой проверки. Затем с эти строками неплохо поделать какие-либо операции — сравнить с чем-нибудь .
Советы 3 и 1 можно объединить — создать свой компонент, который позволит вводить код нестандартным способом с его одновременной шифровкой.
Анализ регистрационного кода. Итак, код введен и приняты меры для того, чтобы его было непросто найти (хотя найти то его можно, но это время, навык . ). Теперь следующий шаг — анализ. Поэтому сразу совет:
Совет 4. Ни в коем случае не анализируйте код сразу после его ввода .
Чем дальше ввод кода от его анализа, тем лучше. Самое разумное — после ввода кода поблагодарить пользователя за сотрудничество и сообщить, что со временем будет выполнена , дата и время доступа. Хорошим решением может быть также стороннее приложение проверки целостности кода.
Вот только против опытных взломщиков и этого недостаточно
Игры с паролями и ссылками тут бесполезны, против опыта и мастерства можно играть лишь теми же картами. Изобретать что-то новое бессмысленно (тем более, если раньше не имели дело с задачами по защите), требуется помощь профессионалов. В недрах глобальной паутины можно найти большое количество как бесплатных, так и платных протекторов кода, шифровщиков и обфускаторов. Некоторые из них способны сделать ваше приложение почти неуязвимым, другие же лишь создают подобную видимость для разработчика. Впрочем, это уже другая история.
Сейчас лишь несколько процентов программ остаются не взломанными. Даже мировые гиганты IT-индустрии, вкладывая в безопасность миллионы, не могут гарантировать полную защиту своих изделий, что уж говорить о простых разработчиках. Поэтому думайте прежде всего о том, чтобы оправдать ожидания потенциальных пользователей. А неплохо заработать, как показывает практика, можно и на бесплатном дистрибутиве.
Следующая статья через неделю. Поговорим об обфускации: что, как и зачем. Не переключайтесь.
А тех, кто определился с тем, что хочет стать программистом, ждет профессия «Веб-разработчик».
Источник: gb.ru
Как защитить свою программу от взломщиков
Я решил написать статью о том, как защитить свои программы от взлома. Оговорюсь сразу, практически невозможно создать такую защиту, которая могла бы противостоять опытному взломщику. Но можно попытаться создать такую защиту, которая окажется не по зубам около 90% взломщиков. Все мои идеи по защите основаны на личных наблюдениях, и они могут не быть достоверными, но могут быть полезными против большинства новичков и продвинутых взломщиков. Сейчас я расскажу, какие инструменты использует средний взломщик:
Во-первых, самый незаменимый инструмент это дебагер, то есть программа, которая позволяет трассировать код чужой программы в живую. Список этих программ варьируется от простого debug’а до продвинутого Soft-Ice’а.
Во-вторых, программа дизассемблер, которая превращает байты программы в команды ассемблера, тем самым позволяет просмотреть, где и как действует защита. Причем хороший дизассемблер показывает еще и где, какие строки используются в программе. Далее идут всевозможные утилиты, для мониторинга реестра, файлов, определители компилятора и упаковщика, распаковщики, дамперы памяти, генераторы кряков и т.д. Ну и конечно самое главное это мозги взломщика, ведь во многом результат взлома зависит от его сообразительности или идиотизма.
Короче наша задача, обмануть все эти средства, и самое главное запутать взломщика. И вот как мы это сделаем, я буду идти по приведенному списку и буду объяснять, как защитится от этих средств и от взломщика. Начнем с дебагеров.
Вообще-то, многие взломщики недолюбливают VB, потому что он работает благодаря своим библиотекам, и естественно взломщику потребуется очень много времени, чтобы разобраться, где код программы, а где вызовы библиотечных функций (проверено на опыте). Но это случается, только тогда когда программа была скомпилирована в P-код, то есть в псевдокод.
Значит первое кольцо защиты, должно быть компилирование в псевдокод. Если вы думаете, что на этом все закончилось, то глубоко ошибаетесь. На свете есть дебагер именуемый P-Code Loader, и он позволяет фильтровать вызовы библиотек и показывать непосредственно код программы. Конечно, не у всех он есть, но если есть, то не стоит слишком надеяться на то, что взломщик откажется от взлома.
Поэтому P-код не должен быть главной ставкой программиста. Конечно, с псевдокодом придется таскать кучу библиотек но, как говориться здоровье дороже.
Иногда программы используют различные приемы против дебагеров, основанные на их свойстве выполнять команды до их фактического выполнения. То есть теоретически можно создать команду, которая отправит дебагер в тартарары, в то время как процессор проигнорирует эту команду из-за системы прогнозирования переходов. Я не умею это делать, поэтому упоминаю это только потому, что однажды встретился с этим приемом.
Копаясь с АПИ справочнике, я обнаружил замечательную функцию IsDebuggerPresent, которая возвращает True, если в системе стоит системный дебагер типа SofIce’а.
Функция работает, начиная с NT и Win98:
Declare Function IsDebuggerPresent Lib «kernel32» () As Long
Далее, дизассемблеры. В инструментарии взломщика дисассемблер занимает почетно место. Редко взломщик изучает программу без дизассемблера.
Дизассемблер дает не только информацию о коде программы, но и показывает имена используемых функций и строковые выражения, использующиеся в программе, а также предоставляет удобную навигацию по вызовам функций и прыжкам. Дизассемблер можно обмануть несколькими путями. С начала, что значит обмануть? Обмануть значить не дать дизассемблеру показать истинный код программы. Этого достигнуть можно следующим способом, программу можно упаковать каким-нибудь упаковщиком типа Aspack, UPX и т.п.
В этом случае дизассемблер сможет показать разве что код упаковщика и более ничего. Но ведь существуют и распаковщики, поэтому всегда есть вероятность того, что у взломщика найдется подходящий распаковщик, и он получит готовенький код вашей программы. Что бы предотвратить это, нет никаких способов. Разве что пользоваться несколькими упаковщиками или использовать нестандартный, мало кому известный упаковщик. Это серьезно затруднит взломщиков, но особенно настырных это не сможет остановить (ведь теоретически можно найти то место где упаковщик передает программе управление и провести кое-какие манипуляции с кодом).
Кроме того, есть ещё один способ усложнить взломщику жизнь. Для этого я расскажу, как производится обычный взлом с помощью дизассемблера. Берется жертва, дизассемблируется. Первое на что смотрит взломщик, это какие строки использует программа. Допустим, программа при вводе неверного серийного номера показывает что-то типа «Сорри, но ваш серийник не подходит нам».
Взломщик первым делом ищет эту строчку, и если находит, то у него уже появляется точка старта взлома, так как он сможет в большинстве случаев найти, то место где вызывается это сообщение, и соответственно найти место проверки серийника. Значит, наша задача убрать эту возможность для взломщика, то есть убрать все важные сообщения из программы.
Это можно сделать, если вынести все сообщения во внешний файл и читать их оттуда во время рантайма. В этом случае дизассемблер покажет разве что имя вызываемого файла. Особенно хорошо загрузить сообщения в начале программы, чтобы взломщик не смог связать их с каким-нибудь важным местом в программе. Ну и я думаю понятно, что самая глупая ошибка это писать прямо в программе правильный пароль. Это сводит на нет всю защиту.
Есть ещё один способ повысить безопасность программы, правда я не знаю, как это сделать на VB, но смысл состоит в следующем: Надеюсь всем известно о компьютерных регистрах. Также вам известно, что на ассемблере можно вызвать процедуру по адресу находящемуся в регистре.
Так вот, дизассемблер не может сказать какое значение будет в регистре в тот или иной момент, поэтому можно вызвать окно с сообщением через регистр, и тогда ни один дизассемблер не сможет сказать, откуда вызвана та или иная функция. Иногда я замечал, что некоторые программы подвешивали дизассемблер при попытке чтения файла.
Я не знаю, как это делают, но подозреваю, это происходит из-за несущественно испорченной структуры файла. Как обмануть мониторы реестра и файлов я не знаю, но могу посоветовать спрятать иголку в стогу сена (опять же встречались случаи падения мониторов при запуске некоторых программ). То есть запрятать чтение данных пользователя в кучу ненужных вызовов.
Также желательно не давать очевидных имен типа «Code» или «User Name». Вообще чтение данных, является слабым местом любой защиты, так как большинство программистов полагают раз прочтенные данные правильные, то значит, все в порядке и бросают все свои силы на защиту процедуры подсчитывания пароля, забывая о том важном месте, где программа устанавливает, куплена она или нет.
Поэтому настоятельно советую не забывать ни об одном месте, где программа делает решающий выбор. Кстати подавляющее число программ использует одну и туже функцию для этой цели. Это оказалось фатальным для этих программ. Нельзя, повторяю ни в коем случае нельзя пользоваться одной и той же функцией. Её легко вычислить и тогда она теряет свой смысл.
Помните самая хорошая защита, это защита которую нельзя обнаружить. Желательно пользоваться разными функциями, причем желательно рабочими (чтобы их корректировка привела к не работоспособности программы). Также лучше пользоваться разными переменными, чтобы нельзя было отследить адрес в памяти. Далее сверяйте переменные, и если они не равны, то лучше программе аварийно выйти, чем дать взломщику продолжить работу.
Поставьте таймер, который проверяет каждые 10 минут право пользователя на работу. Причем если вы используете чистые проверки (без мусора), то взломщик может заметить это, и использовать это. Поэтому проверяйте пользователя в месте с мусором, чтобы ваша проверка не бросалась в глаза. Кстати тот же таймер (или другой с меньшим интервалом) подскажет вам, трассируют ли вашу программу или нет.
Дело в том, что во время трассирования программы, время в Windows останавливается (системный таймер блокируется), то есть вы засекаете время, и если через 20 секунд оно не сдвинулось, то это означает, что либо материнская плата полетела, либо вашу программу взламывают. Кстати есть смысл хранить данные зашифрованными в реестре или файле, чтобы взломщик не сразу вычислил, где вы храните их. И конечно очень глупо записать где-нибудь строчку типа Registered=0, я думаю, что даже младенец поймет, что надо сделать. Но это можно использовать это как прикрытие, то есть если Registered=1, то можно показать сообщение типа и форматнуть ему комп (шутка). Но, в самом деле, идея не плохая.
Вообще все чем я вам пудрю мозги, рассчитано на то, чтобы запутать взломщика.
Но это были цветочки, теперь ягодки.
Как вам известно, проверка пароля самая важная в защите, так как именно ей приходится выдерживать удары тяжелой артиллерии и поэтому у нее должна быть защита, как у банковского сейфа.
Для начала я объясню, как взломщик начинает взлом. У него обычно есть два выбора начать с начала или с конца. Это значит, что он может начать исследовать программу с самого ввода пароля или начать с того момента, когда программа показывает сообщение о неверном пароле. У обоих методов есть свои плюсы и минусы.
Если идти с начала, то можно узнать, где хранится введенное имя и пароль, и что с ним делают. Но с другой стороны приходится фильтровать кучу мусора, чтобы найти что-то стоящее. Если идти с конца, то есть шанс посмотреть код вышестоящий вызова сообщения или если это отдельная процедура выйти к месту проверки.
Но и здесь есть свои трудности, иногда программа не использует стандартные функции показа сообщений, поэтому её нельзя поймать, или после показа сообщения программа не возвращается туда, откуда оно вызывалось, и поэтому тоже не узнаешь, что там случилось. Наша задача сделать так чтобы взломщик не понял где вообще проверка и не смог её подсмотреть.
Так как в большинстве случаев взломщики идут первым путем, то и мы пойдем их путем. Я не вижу способа прочитать имя и пароль без вызова hmemcpy, эта стандартная функция Windows которая вызывается всюду без нашего разрешения, так что здесь у взломщика есть преимущество. Но кто сказал, что нам обязательно проверять пароль, тут же не отходя от кассы. Мы можем сказать и спокойно записать данные где-нибудь, и тут же использовать вышеописанный таймер и если нас просматривали, то выходим без лишних сообщений. Если нет то, где-нибудь через 20 кликов мышки, проверить тихо мирно чего нам подсунули.
Желательно закодировать и имя и пароль по какому-нибудь крепкому алгоритму и сверить результаты. Причем сверять надо по букве, чередуя с мусором, а то программа типа Smartcheck запишет и если их не спрятать, то можно догадаться, где это творится. Кстати если результат не верный то не надо ругаться, можно спокойно продолжать работу, так как взломщик может подловить на этом сообщении программу. И как я уже говорил, используйте разные функции всюду.
Кстати, я недавно прочитал книжку по хакингу, крэкингу, и фрикингу. Так вот там автор утверждал, что надежность защиты определяется надежностью её самого слабого звена. Это утверждение применимо и в нашем деле. Насколько я понимаю самая слабая точка в защите, это то место где программа решает как её вести себя дальше, то есть купили её или нет.
Это является очень критической точкой, так как большинство начинающих и ленивых взломщиков, часто трассируют огромные куски кода ради вышеописанного места в программе. Значит надо внимательно следить за этим, и лучше завести несколько дублей переменной и сверять их.
Иногда программы используют CRC, то есть число уникальное для каждой программы которое определяет её целостность. Его можно хранить где-нибудь и подсчитывать заново каждый раз, и если числа не совпадают, то или на компе вирус или взломщик копался в коде программы. Если копался то лучше выйти. И ещё лучше выйти без сообщений.
Я советую вообще воздержаться от каких либо сообщений по поводу защиты. А все потому что нельзя давать взломщику хоть малейший шанс подловить программу на чём либо. Функций для показа сообщений не так уж и много и они довольно известны, а вот функция, которая используется для выхода программы, не очень известна, и есть шанс, что взломщик не поймет что делать.
Я перечитал то что написал и понял что так и не объяснил что, значит, подловить программу. Сейчас объясню. Программы бывают большими, и защита бывает тоже не маленькая. Поэтому чтобы не ворочать зря горы, взломщики используют точки останова.
То есть в VB допустим, чтобы показать сообщение msgbox используется функция rtcMsgBox, взломщик может сказать дебагеру (если знает эту функцию), останови программу, если она вызовет rtcMsgBox. И когда ваша программа возмутится из-за неверного пароля, взломщик сможет начать свое исследование гораздо ближе к важному месту защиты, чем надо. Поэтому я считаю, что лучше всего вообще не давать взломщику лишнего шанса, проникнуть в программу.
Часто взломщики не просто банально меняют нужный код, а исследуют алгоритм создания пароля и пишут генераторы серийных номеров. Поэтому необходимо хорошо защитить этот алгоритм. Желательно использовать какой-нибудь криптостойкий алгоритм типа RSA или MD5. В Интернете можно найти методы работы с ними.
Также, чтобы затруднить взломщика желательно разбить генерирование пароля на несколько этапов, разбить по функциям (желательно рабочим, чтобы чаще вызывались не только из-за пароля), и в промежутках между вызовами этих функций проверять на исследование вашу программу. И ещё помните что когда ваша программа под дебагером, она не может выполнять параллельно несколько вещей, то есть если она проверит на наличие дебагера, взломщик может это заметить и выключить. Поэтому не давайте никому этого шанса, относитесь к каждому пользователю как к потенциальному взломщику. Ну вот и все, что я хотел рассказать
Я написал эту статью по нескольким причинам:
- Мне захотелось поделиться с людьми своими знаниями.
- Мне нечего было делать.
- Мне надоело смотреть, как все кому не лень издеваются над слабыми защитами программистов, которые используют схемы защит 20-летней давности, и я решил по мере своих сил исправить положение.
- Я заметил, что когда объясняешь кому-нибудь, что-то, то начинаешь сам лучше понимать.
Все приведенные методы используйте, как хотите. Ну и конечно тому, кому лень защищать свое детище, или он отмахивается тем, что программу все равно сломают, не стоило даже и читать эту статью.
Источник: codenet.ru