1. Вы находитесь в архивной версии форума xaker.name. Здесь собраны темы с 2007 по 2012 год, большинство инструкций и мануалов уже неактуальны.
    Скрыть объявление

Взлом delphi-программ с помощью idr

Тема в разделе "Исследование софта на уязвимости, crackme", создана пользователем Dr. MefistO, 6 июн 2011.

  1. Dr. MefistO

    Dr. MefistO Крывіч Глобальный модератор

    Регистрация:
    3 авг 2008
    Сообщения:
    152
    Симпатии:
    254
    Баллы:
    0
    Доброго времени...
    Сегодня мы научимся взламывать программы, написанные в среде программирования Delphi (от Delphi 2, до Delphi 2010) с помощью IDR (Interactive Delphi Reconstructor). Взлом будем делать программы, написанной мной самим.

    В моем кракмисе организована защита следующими методами:
    • лицензионный файл;
    • логин-пароль;
    • наг-скрин;
    • закрытие программы через рандомное количество минут;
    • недоступен пункт меню.

    Для работы нам понадобятся:

    Итак, первым делом запустим PEiD, и узнаем, на чем же написана наша программа?
    [​IMG]
    1) это наш exe-файл;
    2) это собственно упаковщик. Анализатор показал, что программа запакована UPX-ом.

    Для того, чтобы распаковать UPX можно воспользоваться самим упаковщиком. Для этого необходимо выполнить следующую команду:
    Код:
    [B]upx.exe cridr.exe -d[/B]
    Теперь снова анализируем нашу программу:
    [​IMG]
    Ага, как я и думал: программа написана на Delphi 7)))

    Теперь откроем IDR, а в нем - наш exe-файл. Подождем окончания анализа:
    [+] Рисунок №3 - довольно большой (показать);
    [​IMG]

    [свернуть]

    1) это вкладки для перехода между модулями, классами и формами приложения;
    2) эти кнопки помогают перемещаться к началу программы, и по ранее просмотренным кускам кода. Чуть правее жирным шрифтом указано имя данного участка кода;
    3) основное тело процедуры (код процедуры, имя которой отображается в пункте 2);

    Переключимся на вкладку Forms:
    [+] Рисунок №4 - довольно большой (показать);
    [​IMG]

    [свернуть]

    Переключите флажок 1, как на рисунке, два раза нажмите мышкой по имени формы в списке слева - 2, и отобразится главное окно формы - 3.

    Давайте же посмотрим, наконец, как ведет себя программа при запуске... Она выдает нам два сообщения, и закрывается. Значит можно предположить, что основные действия происходят на FormCreate, т.е. при создании формы. Значит нужно узнать: какой же код выполняется? Для этого жмем правой кнопкой мыши на пустом месте показанной на предыдущем рисунке формы:
    [​IMG]
    1) место, где, например, можно нажать мышкой;
    2) пункт меню, который нас интересует. Нажмем по нему мышкой;

    Появится следующий код:
    [​IMG]
    Цифрами я отметил интересующие нас участки кода:
    1) это собственно то сообщение, что выдается при запуске программы. Будем его убирать;
    2) TTimer.SetEnabled - установка свойства Enabled таймера на True. Уберем и это, а то в свойствах программы, описанных в начале, указано, что она закрывается через какое-то время. Можно предположить, что на форме есть таймер, который отсчитывает время;
    3 и 4) из названия процедуры, и интересного имени файла в пункте 3 можно предположить, что идет проверка наличия файла. Скорее всего файл должен находиться в каталоге с программой (об этом мы еще узнаем). Проверку наличия файла попробуем пройти, не пропуская ее;
    5) можно предположить, что затем идет загрузка текста из файла...;
    6) ...и присваивание этого текста какой-то переменной;
    7) LStrLen получает длину строки, значит догадываемся, что идет получение длины текста в файле и сравнение (CMP) ее с 0F, что равно 15 в десятичной системе.
    JL - это переход на адрес, если сравниваемое значение МЕНЬШЕ эталона, т.е. в нашем случае - меньше 15;
    8 и 9) что-то с чем-то сравнивается, но новичку это будет сложно пояснить - как же распознать в будущем подобные команды, но я подскажу, что здесь идет сравнение 15-го символа в файле с символом b, и 5-го - с цифрой 6;
    [​IMG]
    1-4) это процедуры завершения программы: Application.terminate; Они выполняются в случае несоответствия предыдущих условий;

    Теперь, когда с основными моментами разобрались, давайте модифицируем нашу программу так, чтобы главное окно программы все же появилось. Запустим Olly Debugger, и откроем в нем нашу программу.
    Заметка: на всех предыдущих рисунках с кодом в левом столбце отображаются адреса команд - поэтому нам будет легче их искать;

    Сначала мы уберем надоедающее уведомление, что программа находится в демо-режиме. Для этого узнаем адрес этой процедуры, перейдем на это место в дебагере, и заменим эти команды пустышками.
    Подскажу, что адрес команды, которая выводит сообщение при старте программы: 453FBB
    Жмем в Olly Debugger клавиши Ctrl+G для перехода к нужному адресу, вводим его и жмем ОК.
    [​IMG]
    Красным выделены команды, которые выводят сообщение. Давайте их уберем. Для этого жмем правой кнопкой мыши->Binary->Fill with NOPs на каждой из команд:
    [​IMG]
    Не обращайте внимания, что число строк увеличилось - на самом деле размер программы остался тот же.
    Давайте проверим что же получилось: правая кнопка мыши->Copy to Executable->All modifications, Copy All. В этом окне жмем правой кнопкой->Save File. Запускаем получившийся файл.

    Круто!!! От одного окна избавились, теперь идем дальше...
    Таймер убирается точно так же. Адрес процедуры, которая его активирует: 453FE1. Тоже NOP'им и сохраняем.

    Файл lic.key : давайте узнаем, где его создавать. Для этого смотрим адрес процедуры FileExists (453FF8) и переходим по этому адресу в Olly Debugger. Теперь установим точку останова (прерывания), чтобы узнать какой же путь передается этой процедуре. Жмем кнопкой F2 на данной строчке:
    [​IMG]
    Адрес выделится красным. Теперь запустим программу клавишей F9.
    Программа остановится на нашей точке останова. Смотрим справа сверху значения регистров:
    [​IMG]
    Как мы видим, никакого дополнительно пути не дописывается, значит лицензионный файл должен быть размещен в каталоге с программой. Создадим этот файл. Перед этим нажмем Alt+F2, чтобы закрыть нашу программу в отладчике, и загрузим уже сохраненную копию после последних изменений, которые мы сделали.

    Как я писал выше, программа проверяет длину текста в файле. Она должна быть равна 15. Давайте же напишем чего-нибудь туда. Я написал "aaaaaaaaaaaaaaa". Пробуем запустить программу (не в отладчике). Программа закрывается? Значит просто текста в 15 символов недостаточно! Я говорил ранее, что проверяется 5 и 15 буквы, но мы это обойдем. Для этого в пункте (8) картинки с кодом заметим команду сравнения CMP и последующий переход при неудачном сравнении на адрес процедуры Application.terminate;
    Значит просто заNOPим этот переход (вы уже знаете как это делается, а адрес - 454040).
    Теперь второе сравнение (адрес: 454049). Здесь все наоборот: при удачном сравнении программа пропускает процедуры завершения. Значит сделаем так, чтобы завершение (переход туда) на данном куске кода не выполнялся вообще.
    [​IMG]
    Щелкаем два раза по данной строке, появляется окно ассемблерной команды:
    Код:
    [B]JE SHORT 0045407D[/B]
    Исправим его на:
    Код:
    [B]JMP SHORT 0045407D[/B]
    И сохраним изменения. Проверяем теперь запуск программы. Круто, не правда ли?!=)

    Теперь настал черед регистрации пользователя, т.е. подбор необходимых для регистрации программы данных.
    Впишем что-нибудь в поля для ввода и нажмем Check - программа без предупреждений закроется.
    Значит нужно узнать, какой код выполняется по нажатию кнопки. По рисунку вы все поймете:
    [​IMG]
    Жмем правой кнопкой по (1), и жмем на меню (2). Видим совершенно непонятный код. Попробуем разобраться...
    [​IMG]
    Видим процедуры TControl.GetText, значит в них происходит получение текста из какого-то объекта. Предполагаем, что это наши поля ввода, и программа берет из них текст. Мы не будем разбираться в премудростях преобразований введенных значений, а просто посмотрим что еще из кода кнопки можно вытянуть:
    [​IMG]
    Серый код не значит для ровным счетом ничего, и выполняет какие-то служебные команды. Нас же интересует переход на процедуру, которая закрывает программу при неверном вводе ключа. Видим почти в конце кода идет вызов (адрес: 454217) какой-то процедуры, которая находится вне кода кнопки (по адресу: 453F88). Что же там может быть? Давайте узнаем. Для этого жмем правой кнопкой на этом вызове, нажмем GoTo Adress и нажмем OK. Ага!

    [​IMG]
    Видим наш Application.Terminate, но перед ним какой-то переход, в случае успешной проверки переадресовывающий нас в конец данной процедуры, пропуская Terminate. Значит меняем переход на безусловным (JMP) и сохраняем файл. Проверяем... Отлично!!! Теперь при нажатии на кнопку Check программа не вылетает.

    Остается самое малое. Активировать пункт меню. Для этого нам понадобится Restorator, либо другой редактор ресурсов. Открываем в нем наш файл:
    [​IMG]
    Заходим в ресурс главной формы. Переключаемся в режим редактирования файла:
    [​IMG]
    и ищем в тексте ниже что-то, что относится к меню:
    [​IMG]
    Я выделил свойство, которое отвечает за доступность пункта меню, прямо там и пишем вместо False (ложь) слово True (Истина). Жмем F8, чтобы применить изменения, и сохраняем файл. Теперь запускаем программу...
    И - ВУАЛЯ! Все работает)))​


    Исходник программы, которую я ломал:


    Автор: Dr. MefistO

    Добавлено через 14 часов 13 минут
    Anvil, я взялся за Ольку еще до того, как начал изучать ассемблер) Так, по всяким руководствам, статьям обучался)
     
    Последнее редактирование: 7 июн 2011
    5 пользователям это понравилось.

Поделиться этой страницей