# Взлом программ, или Крэкинг

Дзен-крэкинг

Вспомогательные программы

Отладчики и дизассемблеры

Декомпиляторы и узкоспециализированные отладчики

Распаковщики и утилиты для дампинга процессов

Утилиты анализа файлов

Шестнадцатеричные редакторы и редакторы ресурсов

API-шпионы и другие утилиты мониторинга

Прочие утилиты

Заключение

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

Настоящая статья вовсе не является руководством к действию с конкретными примерами, более того — в ней не будет ни одного примера взлома и ни одного указания на конкретную утилиту для взлома. Она посвящена теории крэкинга и методам, которыми руководствуются при взломе программ.

Прежде всего рассмотрим понятие «крэк» (крак, кряк), представляющее собой кальку с английского слова crack, которое имеет множество значений, но ближе всего к теме нашей статьи значения «решать трудную задачу» и «раскалываться, давать трещину, ломаться». Впоследствии в Интернете так стали называть программы для взлома защиты, а крэкингом — сам процесс взлома.

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

## Дзен-крэкинг

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

Кроме того, в обоих случаях, конечно же, необходимо знание команд ассемблера, способов передачи параметров в процедуры и функции, системных вызовов ОС, различных компиляторов и т.п. Без этого изучать крэкинг бесполезно — нельзя понять, как устроен монитор, если смотреть на изображение, которое он показывает. Поскольку для успешного взлома программы не всегда необходимо знание всех ее внутренних функций, во многих случаях можно обойтись очень приблизительным пониманием и анализом встроенной защиты, чтобы не ковырять код до потери пульса. Первый метод позволяет более быстро и эффективно получить искомый результат. Второй требует огромных усилий и, что самое главное, времени. Безусловно, когда происходит «правильный» взлом, то есть взлом по второму методу, количество ошибок, а также вероятных багов при работе с программой в дальнейшем будет значительно меньше, но разбирать каждую программу по винтику по силам лишь профессионалам высокого класса. К тому же для подробного анализа необходимы опыт и знания, которых у начинающих крэкеров нет. И тут возникает парадокс: для приобретения опыта необходимо успешно взламывать программы, однако для успешного взлома необходим опыт. Поэтому первый метод — исследовать программы, исходя из предположений, которые, в свою очередь, строятся на наблюдении за внешними эффектами, производимыми программой, — наиболее распространен среди крэкеров. В этом случае крэкер не выясняет, что и как происходит в недрах кода программы, а сначала строит предположения, на что это может быть похоже, как это может быть реализовано и как бы он добился такого эффекта на месте автора программы. Как ни странно, при использовании этого метода успех зависит не только от знаний, но и от того, насколько богато у крэкера воображение. Поэтому в данном случае эффективность дзен-крэкинга зависит прежде всего от наблюдательности и смелости предположений крэкера. Поскольку надеяться на то, что авторы средств защиты применяют шаблонные и избитые приемы, не стоит, необходимо подходить к процессу взлома творчески, ставя себя на место автора программы.

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

Представим, что есть программа, которая выполняет некое действие. К примеру, она отказывается запускаться по истечении 15 дней с момента ее первого запуска. При этом появляется окошко с предупреждением — это и есть первое наблюдение. Если при переводе системной даты назад программа все равно не запускается, из этого следует еще один вывод: программа каким-то образом проверяет текущую дату, но при этом не основывается на показаниях часов операционной системы. Можно предположить, что программа либо сделала пометку о том, что запуск больше невозможен, либо все-таки определяет время другим способом. Здесь есть два пути: представить себя на месте программиста и подумать, какие варианты определения времени он мог использовать, или искать в системном реестре либо в исполняемых файлах ссылку на запрет запуска. Однако сначала необходимо понаблюдать за производимыми программой действиями, которые являются признаками той или иной реализации защиты. Если программа не просто «задумывается» при запуске, но еще и шуршит винчестером, вероятность того, что она проверяет файлы на дату/время создания, увеличивается. В противном случае необходимо уже непосредственно разбирать, какие условные переходы, связанные с этим окном, происходят, и к каким функциям в это время происходит обращение.

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

Наиболее подходящими для крэкеров дырами являются глобальные переменные, в которых хранятся сведения о состоянии программы («зарегистрирована — не зарегистрирована»); функции, возвращающие критичное для защиты значение (число запусков или дней до истечения испытательного срока, результат проверки серийного номера на правильность), и процедуры, выводящие сообщение об успешной или неуспешной попытке регистрации, а также об истечении триального срока программы. В некоторых случаях изменение 0 на 1 делает программу зарегистрированной и полностью работоспособной — конечно, необходимо найти эту прореху, что и является главной задачей крэкера. Поэтому поиск констант (количество дней) и их изменение — наиболее оптимальное решение, поскольку в этом случае действует правило минимального вмешательства в сам код программы.

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

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

Описанные выше приемы взлома применяются в большинстве случаев, однако в некоторых ситуациях защита встроена в установщик, которым инсталлируется программа, так как большая часть программ поставляется в виде инсталляционного пакета. В нем, кроме файлов, которые требуется установить на машину пользователя, содержится сценарий инсталляции, то есть некий скрипт, описывающий алгоритм инсталляции. Поскольку написание собственного инсталлятора — дело трудоемкое, для большинства небольших программ используется один из готовых продуктов. Инсталляционный скрипт описывает, в каком режиме устанавливается тот или иной файл (добавление, замена, замена с предварительной проверкой версии и т.п.), какие данные необходимо внести в реестр или в файлы конфигурации, какие программы запускаются до, в процессе и после инсталляции, а также многое другое. В это «многое другое» могут входить и такие интересные вещи, как проверка серийных номеров, создание записей в реестре, а также распаковка и запуск программ. Поэтому защиту от запуска незарегистрированной или триальной со сроком действия версии следует искать именно в инсталляционном файле. При этом реализация защиты может быть совершенно различной — от простых меток в реестре до создания точки отсчета времени от системной библиотеки самой операционной системы. В качестве метки, по которой программа будет проверять ограничения по времени или по числу запусков, может использоваться какой-либо файл, создаваемый в процессе инсталляции, особенно если этот файл спрятан где-нибудь глубоко в системных директориях, но при этом активно применяется программой. Самый надежный способ нахождения подобных функций защиты — декомпиляция инсталляционного файла и последующий разбор его по байту. Однако эта операция требует времени и опыта. Зато в случае, если инсталляционная программа произведена сторонним разработчиком, можно написать универсальный патч для обхода защиты всех программ, которые используют эту версию инсталляционного пакета. Исходя из метода наименьшего сопротивления применяется прием мониторинга системы в процессе инсталляции. В этом случае, не углубляясь в код инсталляционного файла, можно обнаружить запросы к файлам, а также создание ключей в реестре. Подобные утилиты мониторинга за ОС позволяют делать слепки системы на разных этапах ее инсталляции, а путем сравнивания исходных значений с полученными можно выяснить результат действия инсталляционного пакета. Стоит отметить, что далеко не все инсталляционные пакеты отличаются широкими возможностями, очень часто встречается простое решение — запуск либо самой программы после инсталляции, либо дополнительной программы на фоне процессов, которая и создает защиту.

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

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

## Вспомогательные программы

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

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

### Отладчики и дизассемблеры

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

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

### Декомпиляторы и узкоспециализированные отладчики

С ростом мощности ЭВМ широкое распространение получили компиляторы, создающие не «чистый» машинный код, а некий набор условных инструкций, который выполняется при помощи интерпретатора. Интерпретатор может поставляться отдельно или быть прикрепленным к самой программе. Интерпретаторами являются практически все инсталляторы (в их основе лежит интерпретатор инсталляционного скрипта, хотя процесс создания такого скрипта может быть скрыт визуальными средствами). Создавать код могут также компилирующие языки, однако его прямой анализ весьма затруднителен. Для анализа таких программ используются специализированные утилиты, переводящие код, понятный лишь интерпретатору, в форму, более удобную для понимания человеком. Некоторые декомпиляторы также могут извлекать информацию об элементах интерфейса, созданных визуальными средствами. В любом случае не следует ожидать от декомпиляторов восстановления исходного текста программы; если декомпилированная программа успешно компилируется и сохраняет работоспособность — это исключение, а не правило.

### Распаковщики и утилиты для дампинга процессов

Дизассемблировать запакованную или зашифрованную программу невозможно, но если очень хочется получить хоть какой-то листинг, то можно попытаться извлечь из памяти компьютера дамп программы в момент ее работы. Этот дамп уже можно более или менее успешно дизассемблировать. Более того, на основе дампа можно воссоздать исполняемый файл программы, причем этот файл будет успешно загружаться, запускаться и работать. Именно на этом принципе и основана работа большинства современных распаковщиков: подопытная программа запускается под управлением распаковщика; распаковщик ждет некоторого события, свидетельствующего о том, что программа полностью распаковалась, тут же «замораживает» программу и сбрасывает ее дамп на диск. Защитные системы нередко пытаются противодействовать получению работоспособного дампа при помощи манипуляций с сегментами и таблицами импорта-экспорта. В этих случаях приходится использовать PE-реконструкторы, то есть утилиты, обнаруживающие в дампе некорректные ссылки на функции и пытающиеся их восстановить. Многие продвинутые дамперы и распаковщики имеют встроенные средства восстановления секций импорта.

### Утилиты анализа файлов

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

### Шестнадцатеричные редакторы и редакторы ресурсов

Это, несомненно, наиболее древние (по идее, но необязательно по исполнению) из программистских инструментов, ведущие свою историю с тех времен, когда программисты еще умели читать и править исполняемый код, не прибегая к помощи дизассемблеров. Редакторы ресурсов, в принципе, занимаются тем же самым, но по отношению к прилинкованным к исполняемому файлу ресурсам. Именно при помощи редакторов ресурсов выполняется значительная часть работ по «независимой» русификации программ и доработке интерфейсов. Наряду с редакторами используются всевозможные патчеры, которые позволяют создать небольшой исполняемый файл, автоматически вносящий изменения в оригинальный файл программы либо в код этой программы непосредственно в памяти.

### API-шпионы и другие утилиты мониторинга

Зачастую бывает нужно узнать, какие именно действия выполняет та или иная программа, откуда она читает и куда записывает данные, какие стандартные функции и с какими параметрами вызывает. Получить эти сведения помогают утилиты мониторинга. Они делятся на две большие группы: отслеживающие сам факт возникновения каких-либо событий и позволяющие выявить один или несколько специфических типов изменений, произошедших в системе за некий промежуток времени. К первой группе относятся всевозможные API-шпионы, перехватывающие вызовы системных (а более продвинутые — и не только системных) функций, хорошо известные утилиты Reg, File, PortMon и т.д., перехватчики системных сообщений и многие другие. Эти утилиты, как правило, предоставляют подробную информацию об отслеживаемых событиях, но генерируют весьма объемные и неудобные для анализа логи, если отслеживаемые события происходят довольно часто. Вторая группа представлена всевозможными программами, создающими снимки реестра, жесткого диска, системных файлов и т.п. Эти программы позволяют сравнить состояние компьютера до и после некоего события, построить список его различий в этих состояниях и на основе этого списка сделать определенные выводы. Основная проблема при работе с такими утилитами хорошо описывается афоризмом: «После — не значит вследствие».

### Прочие утилиты

Существует также огромное количество утилит, не вписывающихся в рассмотренные выше категории или попадающих в несколько категорий сразу. Поскольку крэкинг — занятие весьма многогранное, столь же многогранны используемые для него инструменты. Более того, некоторые утилиты, которые могут быть полезны для крэкера, создавались для совершенно иных целей (хорошим примером может служить программа GameWizard32, которая, вообще-то, предназначена для того, чтобы мухлевать в компьютерных играх, но оказалась полезной при вскрытии программы с ограничением на максимальное число вводимых записей). Как невозможно объять необъятное, так и нельзя описать все программы, которые применяются для крэкинга.

## Заключение

Напоследок отметим, что крэкеры делятся на три группы: на тех, для кого крэкинг — хобби, на тех, кто занимается этим в качестве самообразования, и на тех, кто зарабатывает на взломе защиты программ. Поскольку в России пиратство распространено широко, во многих случаях крэкинг обеспечивает неплохой доход.

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

P.S. При подготовке данной статьи автор брал материалы из открытых источников и сам имеет очень отдаленное отношение к крэкингу. Существует множество практических руководств и пособий по взлому программ, в настоящей же статье рассматривались лишь методы крэкинга — его теория.

КомпьютерПресс 3'2007