В этой теме хочется затронуть тему Защита от взлома!
Крэкинг: практика взлома и теория защиты.
Здравствуй, дорогой читатель! Сегодня мы поговорим на столь интересную и важную тему как КрЭк и методы защиты от него. ??звините, что приходится писать старомодным литературным языком. Просто писать всё современным программерским сленгом я побоялся из-за возможного не прохода статьи в «свет». Поэтому даже смайлыков вы в ней почти не увидите. Ладно, поехали…
Для начала немного теории. Само название «КрЭк» (а в разговорном «КрЯк») переводится как «Трещина», а в разговорном английском как «Кража со взломом». Перевод говорит сам за себя(Прим. Автора – для чайников: крЭкинг – это взлом шароварного(платного, от слова «Shareware») софта(программного обеспечения), с целью получения полнофункциональной версии, разблокировки ограничений, обусловленных нелицензионной или незарегистрированной копией, а также продление/снятие триального (от слова Trial – испытательного) периода или просто убирание надоедающего окна, в котором при каждом запуске вам напоминают о регистрации). Само занятие крЭкинг появилось с появлением первого платного софта. Соответственно сразу нашлись люди(так сказать Робин-Гуды), которым очень не понравилось, что за какое-то программное обеспечение разработчики начали ещё и брать деньги. Они не просто ради практики начали ломать софт, а и свободно распространять свои «КрЯки» в интернете, наверно чтобы принести всеобщую радость халявы в мир (или чтобы дать разработчикам понять, что они смело могут полностью отказаться от всех своих защит, потому что не было ещё не сломанной защиты). Ладно, перейдём к делу…
Чтобы изучить теорию защиты от взлома ПО нужно изучить все тонкости самого взлома. Так что мы сначала начнём именно с него. Возьмём пару программ и походу разберёмся как, что и куда. Вот. В альтернативу всем остальным статьям по крЯкингу я возьму не зарубежный софт, а наш советский, то бишь софт стран бывшего СССР. Кстати, т.к. в России/Украине больше крЭкеров, чем в остальных странах, то в основном наши умельцы действительно очень хорошо защищают свой софт. Но, как известно, из всех правил всегда существуют исключения. Всё. К делу…
Начнём с самого простого. Правда не совсем с самого, потому что брать для примера такие программы, в которых пароль для её регистрации спокойно лежит в текстовых ресурсах, я не собираюсь, так как это полный примитив. Поэтому возьмём для начала такую советскую прогу, в которой постоянно просят ввести пароль, а иначе программуля совсем откажется работать.
Я взял действительно нужную программу «Зодчий», которая представляет собой менеджер базы данных СНиПов(строительные нормы и правила) и ГОСТов для архитекторов. В доказательство, что она настолько полезна, я поискал в интернете на неё уже сделанный крЯк. ?? очень удивился, когда не нашёл ни одного бесплатного крЯка, а самый дешёвый из них стоил порядка 312грн. Что всё равно гораздо дешевле чем лицензия(уж поверьте). Кстати, не спешите качать с ??нтернета все подряд крЯки на интересующий вас софт, т.к. кроме угрозы «нахватать» вирусов существуют ещё и просто «лохотроны»(пустышки), в которых вам взамен на в будущем высланный вам код вы обязуетесь пополнить крЯкеру телефонный счёт или ещё что-то на подобии этого. Не ведитесь.
Ладно, вернёмся к нашему делу. По нажатии на кнопку «Зарегистрировать» появляется поле с уже введённой половиной пароля и предложение ввести вторую половинку. Давайте попробуем ввести неправильный (вдруг программа и так запустится). К сожалению прога по нажатию на Enter тут же закрылась. «Что ж тут делать?», спросите вы. А я вам отвечу. В данном случае есть 7 подходов. Перечислим каждый из них:
Можно открыть редактор ресурсов (ResHacker, Restorator), попробовать найти там диалог Регистрации, удалить и посмотреть не будет ли тупо прога его пропускать передавая управление главной форме. Можно найти адрес команды, которая открывает именно окно регистрации и попробовать заNOPпить(заменить её ассемблерной командой nop (no operator), то есть пустой командой) её. Что в принципе тоже может привести к пропуску. По текстовой ссылке найти заголовок главной формы, примерно вычислить адрес точки входа на неё и используя адрес, который мы получили в прошлом пункте(прямо перед окном регистрации), перескочить с него на адрес главной формы. Это можно осуществить командами «прыжков» jcc . Они делятся на безусловные переходы(прыжки) jmp (от англ. jump «прыжок») и условные ( je,jne …). Детальное описание к ним вы можете получить в самоучителе по ассемблеру. Так же найдя адрес команды, открывающей окно регистрации (методом поиска по тексту, трассировки и отладки с использованием брЭйкпоинтов ( breakpoint – точка остановки)) можно идти вручную «вверх» по течению программы(то есть полностью проследить ход её развития в обратном направлении) до тех пор, пока мы не найдём сравнение/опрос данных о регистрации. То есть при запуске программа ведь тоже «смотрит» зарегистрирована ли она или нет. ?? переключить эту «развилку». Тогда без всяких паролей программа будет «думать», что она зарегистрирована. Узнать сам пароль. Это возможно(но далеко не всегда) сделать прогонкой проги и постоянным наблюдением за регистрами процессора, оперативной памятью и стэком (от англ. stack – «кипа»). Но в большинстве случаев пароль шифруется или просто обрабатывается так, что отладчик его не может увидеть. Ну и самый распространённый метод – это метод переключения «развилки» проверки правильности пароля. То есть перехват выполнения кода(или просто поиск по заголовкам элементов управления) в том месте, где прога именно сравнивает введенный пароль с правильным паролем. Если мы эту развилку переключим на обратную, то можно будет ввести любой пароль (соответственно кроме правильного). Ну и самый крайний метод. Это перехват выхода программы и его отмена. То есть в нашем случае по нажатии на Enter с неправильно введённым паролем программа даёт команду выхода. Что нам мешает перехватить её, узнать откуда она была вызвана и «произвести» отмену её вызова. Недостатком остаётся то, что придётся постоянно вводить любой пароль для работы с программой.
Вот. Чтобы осуществить крЯк хоть одним из этих методов нужно посмотреть не сжата ли программа внешним упаковщиком. Программы часто сжимают в основном из-за защиты, из-за сохранения авторских прав и просто из-за улучшения компактности программы. Самые распространённые пакеры (от англ. pack – «упаковывать»): UPX, AsPack(и AsProtect), PECompact, WinUPack, Telock, NeoLite, Yoda, PE-Shield, Armadillo… Они сжимают как и все(или не часть) ресурсы так и сам код программы, что приводит к невозможности её дизассемблирования (декомпиляции в исходный код ассемблера), отладки(трассировки) и даже редактированию ресурсов. Поэтому перед крЯком обязательно нужно проверить подопытную прогу на «сжатость».
Есть немало программ узнающих чем именно сжата программа и много анпакеров(то есть распаковщиков). Я предпочитаю 2 самых, по моему мнению, лучших из них. Это: PEiD и PE-scan . У каждого из них своя «изюминка»: PEiD может даже показать на каком языке программирования написана прога, а в PE-scan даже встроены некоторые стандартные распаковщики.
Как видим наш «Зодчий» (его исполняемый файл имеет имя ARM_ARH.EXE) ничем не сжат. А PEiD даже показывает нам, что он написан на языке Borland Delphi. Также они оба могут показать наглядную информацию о структуре файла, в которую вам вникать вовсе не обязательно. Т.к. наш файл ничем не сжат мы можем смело приступать ко всему остальному.
Давайте попробуем начать с самого простого, с проверки шифруется ли пароль. Для этого нам понадобится дЭбаггер(от анлг. Debugger – «отладчик»). Я поклонник «OllyDBG». Так как считаю, что эра SoftICE’а уже в прошлом(но он ещё актуален для отладки драйверов). Открываем в нём наш ARM_ARH.EXE, ждём пока Оля («Olly») проанализирует весь код и начинаем отладку. Жмём F9 (Run) , наш Зодчий запускается без exception’ов (от англ. exception – «исключение»). Это означает, что на него «не поставили» никакой анти-отладочной защиты.
Вводим вместо 2-ой половины пасса(пароля) что угодно и скрестив пальцы молимся, что сейчас отловим требуемый пароль. Жмём на Enter, перед нами «предстаёт» окно Olly, в статусной панели которого мы можем прочитать, что возник экзэпшн по адресу 0EEDFADE. В принципе это нам и надо. Теперь «шарим» взглядом по дампу памяти(правое нижнее окно). Тут мы видим всё, что произошло с программой с момента её запуска(переход по адресам, загрузка модулей, строк, вызов функций и возврат из них). Но, к сожалению, пароля мы тут так и не нашли. Но не расстраивайтесь, не всё уж так плохо.
Попробуем такую теорию, а что если полный пароль загружается только тогда, когда мы вводим пароль заново полностью, а не только 2-ю половину. Для этого жмём радио-кнопку «Повторно на этой ПЭВМ» и перед нами появляется абсолютно пустой TEdit(поле для ввода). Вводим снова что попало и жмём Enter. Опять таки вылетает exception с тем же адресом. Ошибка, скорее всего, обусловлена запросом программы на выход. Снова «проматываем» весь дамп в поисках паролей. ??… натыкаемся на очень любопытные строки:
Хм. Не трудно увидеть, что ASCII-строка “75ZS8H2238859” очень смахивает(по длине) на вторую половину. Стоит попробовать. ??… Поздравляю, у нас всё вышло! Скриншот можете посмотреть ниже.
Ну вот. С одним простым крЯком мы справились. Теперь у нас есть пароль, который мы можем продавать за 312грн. Но у нас есть ещё и мозги, поэтому мы его и сохранять не будем, т.к. знаем, что эти действия припадают под статью УК Украины. Поэтому эта статья рассматривается только как наглядный пример, в котором показывается насколько слаба бывает защита у программного обеспечения. ?? за любое неправомерное использование данного материала ответственность несёт только сам читатель.
Так перейдём к более сложному крЯку. Возьмём очень популярный на сегодняшний день плЭер: Light Alloy. Его сделала наша советская компания-разработчик Softella ( http://www.softella.com/ ).
Для регистрации разработчики предлагают нам отгадать одну из загадок. Но если нам очень тяжело каждый раз их угадывать, то мы можем написать крЭк. Также при запуске сначала показывается NUG-окно. То есть окно, с сообщением о демо-версии:
На заголовке окна LA красуется неприятная надпись UNREGISTERED. А сама регистрация проходит в таком виде:
Ну что ж, как вы уже догадались, нам следует искать «развилку» проверки пароля. Начнём. Сначала проверим не запакован ли чем-то наш LA.exe. Отправляем в PEiD и… видим, что он нагло сжат самым популярным пакером UPX.
Чтобы распаковать его лезьте в нЭт по линке http://upx.sourceforge.net/ и качайте распаковщик UPX’а или скачайте его вместе с GUI (графический интерфейс), мой называется UPX X-Shell 1.02 (http://www.urixsoft.nm.ru/). Откройте его в нём и нажмите кнопку «Распаковать». Если на статусной панели появится надпись «… БЕЗ ОШ??БОК», значит всё в порядке.
Теперь вы увидите, что размер LA.exe увеличился с 894КБ аж до 2,75МБ и рядом с файлом появилась резервная копия LA.ex~ со старым размером. Отлично, распаковали.
Теперь к делу. Загружаем наш плЭер в Олли и запускаем( F9 ). Сразу же вылетает экзэпшн. Это первая противоотладочная защита. Но она легко пропускается Олли по нажатию Shift+F9.
Теперь ищём текстовые ссылки (string rпосле eferences), которые соответствуют смыслу. Для этого в главном окне отладки с ярлыком «С» и заголовком «CPU – main thread, module LA» нажмите правую кнопку мыши ->Search for->All referenced text strings и проматывайте в поисках чего-нибудь. Я напал на такую строку: ASCII “Registration is successful. Please restart application.”
Двойной клик и мы переносимся именно на тот адрес команда которого подгружает этот текст. По логике, развилка должна быть выше. ??дём вверх и видим команду сравнения test и прыжок сразу же неё.
Слово short означает – короткий, то есть недалёкий прыжок. Видим что он осуществляется (это показывает маленькая галочка слева от шестнадцатеричного представления команды) и что он перепрыгивает в этом же файле(LA) на адрес 0050417А. Сама команда je означат jump if equal, то есть прыжок при равности. С адреса 0050417А идут команды присвоения/помещения mov и помещение в регистр общего предназначения edx строки о неправильности кода.
Это означает, что в будущем она по любому вызовется, скорее всего в процедуре которая вызывается командой call (от англ. call – «вызывать») по адресу 00504186. Вот. Тогда пробуем «переключить» стрелку (условный прыжок). То есть мы прыгнем на сообщение «Access code is not valid» уже тогда, когда мы введём именно правильный пароль. А при вводе любого другого пароля программа продолжит своё выполнение вниз по коду и дойдёт до требуемого «Registration is successful». Это самый стандартный и самый простой метод крЯкинга.
Сначала завершим предыдущую сессию отладки нажав Ctrl+F2. Щёлкаем дважды по строке с нашим прыжком (адрес 0050415D) и переименовываем je в jne (jump if not equal). ?? снова жмём Run (F9).
Увы… Как это ни странно LA показывает всё то же сообщение о неправильности пароля. А это значит, что программа там даже и не проходит… А это просто программистский обман.
Ну что ж, мы не сдаёмся. Стрелки « > », слева от кода команд, означают, что на команду по этому адресу возможен переход программы с какого-то удалённого адреса. То есть на меченый стрелкой адрес совершается прыжок или вызов процедуры.
Тогда давайте попробуем поставить брЭйк(breakpoint) на команду с адресом 0050418B. Для этого нужно «подсветить» мышкой или клавой эту команду и нажать F2. Адрес подсветится выделяющимся цветом. Жмём Ctrl+F2 и снова F9.
Программа всё так же запускается, но при вводе неправильного пароля останавливается именно так, где мы поставили брЭйк и передаёт управление в отладчик. А это значит, что мы с вами не ошибались и что всё-таки мы на правильном пути. Значит нужно подниматься ещё выше дабы найти «настоящий» участок сравнения и прыжок следующий за ним.
Находим ближайшие(впрочем и единственные в этой подпроцедуре, в которой мы находимся) условные переходы:
На обоих стоят маленькие галочки(просто они не скопировались как символ). Смело ставим брЭйки на них и перезапускаем отладку. При нажатии кнопки подтверждающей ввод пароля у нас «вылетает» наш брЭйк. То есть всё идёт по плану.
Теперь чисто для теста мы меняем его с je на jne и трассируем методом Step over (покомандная отладка программы без входа в подпроцедуру) . Когда доходим до нашего второго jump’а мы видим, что он тоже «собирается» прыгнуть (Jump is taken). А если он прыгнет мы снова попадём на «… code is invalid». То есть мы столкнулись с двойной перепроверкой пароля.
Это показывает на наличие большего числа извилин у разработчиков чем одна. Хм, но нам то что. Смело меняем jnz (всё равно, что jne ) на обратный ему je и наслаждаемся результатом:
Теперь надо сохранить наши изменения в исполняемый файл. Для этого жмём правую->Copy to executable-> All modifications. Откроется окно «D», нажмите «закрыть» его. ?? вам предложат сохранить его. Введите что- то на подобии LA(cracked).exe.
Теперь давайте проверим на работоспособность нашу сохранённую программу. Запускаем и опа… Программа «выбивает» две ошибки. Но ведь в отладчике у нас всё работало. А это значит, что разработчики поставили ещё и двойную проверку подлинности пароля при запуске. Для этого они и просили перезапустить программу. Под видом, что она так не может обновиться.
Ну ладно. Загружаем уже LA(cracked) в Олли. Запускаем. Натыкаемся на два exception’а, пропускаем их через щифт и… перед нами красуется всё то же окно с надписью «UNREGISTERED».
Хм… А ведь почему бы не «оттолкнуться» именно от него. Рыщем в текстовых ссылках и находим:
005558A1 |. B9 6C5B5500 mov ecx,LA_c.00555B6C ; ASCII ” – UNREGISTERED”
БрЭйк можно не ставить, т.к. программа точно проходит тут(эта ссылка только одна) . ??дём вверх в поисках возможных полезных развилок, которых по идее должно быть две…
В данном случае маленькие галочки(которые обозначают эквивалентность) показывают нам, что прыжок не состоится. А значит программа «спустится» до «UNREGISTERED». Следовательно нам надо совершить эти прыжки. Меняем их на je , сохраняем изменения и запускаем уже сохранённый файл.
Всё супер. Перед нами предстаёт окошко Light Alloy’я без всяких UNREGISTERED. Отличная работа!
Так. Следующие примеры я буду описывать немного быстрее. Всё-таки вы ж уже тоже опытные…
Возьмём ещё одну советскую прогу SlyControl. Это программа для дистанционного управления компьютером со всевозможных устройств (WinLIRC, Tekram M205, FlyRC2…). Русским, или людям знающим русский язык эту программу можно регистрировать каждый месяц (кстати, куда вводить полный код я так и не нашёл), но мы ж максималисты. КрЯкнем её…
За что мы зацепимся? Хм. Отладчик распознаёт только латинские буквы. Поищем в текстовых ссылках мыло(e-mail) разработчика… Нету.
О, кнопка xUSSR. ??щем… Есть! То, что надо. Но их есть две. Ставим брЭйк на обе.
В принципе, программа полнофункциональна, остаётся только лишить её этого NUG’а(сообщения, напоминающего о регистрации). Трассируем… Пропускаем пару экзэпшнов и «натыкаемся» на первый брЭйк(для интереса можете убедиться в том, что прога не будет проходить через второй брЭйк). Но окно регистрации ещё не появилось. Так что трассируем дальше, что бы найти именно его вызов. ?? доходим до:
В данном случае лучше пойти вверх и переключить «развилку», чем просто заполнить вызов Рег.Формы NOP’ами. Да и на главной форме красуется надпись:
Так что идём вверх… ?? видим одну очень примечательную структурку:
Ведь это спокойно может быть сравнение. ??зменяем. К нашей с вами радости не появляется ни какого NUG’а, а заголовок формы очень изменился в лучшую сторону:
Вот так вот мы поломали пару советских программ.
А теперь я хочу вам показать как делаются NO-CD. То есть крЯки игр с целью их запуска без диска и обеспечения их полнофункциональности. Возьмём уже далеко не советскую игру «Heroes of Might and Magic V» версии 1.0 от издателя 1С. Установим. Запустим:
Как видите игра «просит» диск. Если у вас здоровенный винт и вам не в лом вставлять полтора гигабайтовый виртуальный диск, то можете ничего и не делать. Но мы её попробуем крЯкнуть.
Программа ничем не сжата и написана на «Micorsoft Visual C++ 7.0 Method2 [Debug]». Загружаем её в Олли и… из-за здорового размера (11,26Мб) Олли переглючивает и он виснет на 97,7 процентах анализа файла.
Может через пол дня он и догрузится, но я со своим PIV 640 3,2GHz решил, что 10 минут хватило, чтобы понять, что он уже не загрузится.
Тогда решаемся использовать более примитивный софт для крЯка, такой как W32Dasm и HIEW. Когда-то я «сидел» только на них. Dasm(disassembler) тужится, но буквально через 3 минуты всё-таки полностью загружает и анализирует наш H5_Game.exe.
Нажимаем Ctrl+L (Load) вместо F9 (Олли) и видим снова окошко с предупреждением о вставке диска. Переключаемся на Дасм, жмём Паузу (кнопкой или пробелом) и видим, что управление не передалось сразу Дасму.
Ну ничего, жмём на повтор и видим как Дасм нам сразу показал адрес MessageBox’а, в котором мы только что нажали «Повтор»:
Походу тут конструкция cmp/jne ответственна за наш выбор нажатия кнопок («Повтор» или «Отмена»), но сам факт, что диалог уже вызван присутствует. Значит идём вверх и натыкаемся на такие строки:
Прыжки jbe и jne можете проверить, но ничего не получится. Это значит что сюда программа «прыгает» из другого участка проги. А с какого нам показывают две строчки: Referenced by a… Jump at Addresses:
и 3 адреса прыжков, с которых может быть совершён прыжок сюда, к нашему MessageBox’у.
??щем их в асм-листинге(можно промоткой, а можно через «Перейти» Shift+F12) и ставим на все 3 прыжка брЭйки. Буквы «(C)» и «(U)» означают «Conditional»(от англ. условный) и «Unconditional»(безусловный).
?? «гоним» прогу дальше(F9). Видим, что срабатывает первый(самый верхний) брЭйк, потом несколько раз прыгает на 2-ой, но в конечном случае на MessageBox прыгает всё-таки с самого нижнего.
Пробуем его поменять. ГыгЫ ) Не вышло?! 😉 Правильно, потому что W32Dasm не предназначен для динамического редактирования декомпилированного файла.
Для этого открываем его в 16-ричном дизассемблерном редакторе HIEW. Я лично переименовываю файл в H5_Game(c).exe.hiew и выбираю HIEW в «открыть с помощью».
Когда открывается HIEW нажмите Enter 2 раза. Это переведёт его в режим дизассемблера.
Переходим на адрес нижнего прыжка. Для этого нажмите F5 и введите адрес с точкой: .004011F8 .
Нажимаем F3(правка) и если вы хорошо разбираетесь в 16-теричной системе счисления, то можете просто заменить 5 на 4 в 2-х байтах: 75 25. А если вам тяжело это помнить, то можете нажать ещё и F2 и править саму ассемблерную команду. Сохраняем(F9). Теперь копируем с переименовкой файл H5_Game(c).exe.hiew в H5_Game(c).exe и запускаем. Но перед нами снова появляется всё то же сообщение…
Снова просматриваем код. ?? видим, что прыжок:
:0040121D 7533 jne 00401252.
Должен перепрыгивать через MessageBox. Значит он не осуществляется.
Так давайте переключим его. Снова в HIEW. С 7533 в 7433. Сохраняем(F9). Переименовываем. ?? запускаем. Гы. ??гра начинает загружаться.
Теперь возьмём достаточно похожий случай. ??гра:«FIFA2007» (Вы скажете: «Так она у меня и так без диска идёт!». Это значит, что у вас скорее всего новая версия с русскими комментаторами или ваша игра от другого издателя). Устанавливаем, запускаем:
Посмотрим что мы сможем с этим сделать. Действуем как и в прошлый раз. PEiD нам говорит, что fifa07.exe ничем не сжат. Тут, по моему, само реально пойти самым распространённым методом отладки: ставить брЭйки на WinAPI функции, вызывающие диалог или показывающие окно. Ну, для этого их нужно знать. Вот пару самых распространённых: MessageBoxA, MessageBoxW, ShowWindow, ShowWindowEx .
Загружаем Ф??ФУ в Олли. Открываем, если не открыт по умолчанию, плагин « Command line » (Plugins->2. Command line). Пишем туда « bpx MessageBoxA », жмём Enter. ?? точно так же проделываем с MessageBoxW…
Если вы захотите выбрать брЭйк из всего списка API-функций, используемых в приложении, вы можете написать в плагин: « bpx “что угодно”». То есть не правильную API. Например: « bpx dfgsdfg ». ?? из списка через правую поставить брЭйк куда хотите ничего не вводя. Теперь в окне «(B) Breakpoints» появится список ваших поставленных брЭйков. В нём вы можете приостановить работу одного из брЭйков или удалить любой из них. Значит брЭйки мы поставили.
??дём дальше. Запускаем программу и надеемся, что «вылетит» хоть один наш брЭйк. F9 и… УРА! Один из самых распространённых:
В окне дампа мы можем посмотреть как по частям загружалось содержимое диалога:
Теперь идём вверх(можете попробовать прыжки, но они не перепрыгивают вызов сообщения) и натыкаемся на первую строчку этой подпроцедуры. Выделим эту строчку и в статусной строке видим:
Local calls from 005EFD12, 005F0595, 005F066D, 005F0694, 005F0D6A, 005F0ED3.
Это нам показывает, что наша подпрограмма вызывалась call ’ами с перечисленных адресов. Теперь остаётся поставить брЭйки на все эти call ’ы и поотменять вызов этой подпроцедуры. Для этого попереходим на каждый адрес вызова и понаставим брЭйки. Копируем первый адрес, жмём Ctrl+G , вставляем и жмём Enter. Олли сразу прыгнет на введённый адрес. Жмём F2 (брЭйк) и точно так же проделываем со всеми остальными call ’ами.
Теперь завершим прошлую отладку нажав Ctrl+F2 (Reset). ?? запустим снова ( F9 ). Видим, что выскочил брЭйк по адресу 005F0D6A . Возможно, что будут ещё и после проверки, так что не следует ещё сил