borland-crk

взлом борландии

крис касперски ака мыщъх, a.k.a. nezumi, a.k.a. souriz, no-email

начинающие хакеры обычно испытывают большие трудности при взломе программ, написанных на DELHI и BUILDER, поскольку классические трюки, типа бряк на GetWindowTextA,не работают и чтобы не пилить серпом по яйцам (не блуждать во тьмах) требуется учитывать особенности библиотеки VCL, которая только с виду кажется неприступной, а действительности ломается даже проще, чем «чистые» Си-программы!

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

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

Новый Год — семейный праздник и всякий уважающий себя хакер проводит его наедине с самым близким ему существом — с компьютером. Для создания атмосферы праздничного торча верхний свет выключить, зажечь свечи (не те, что от геморроя), послать всех девушек в /dev/nul, зарядить бурбулятор свежей порцией man'ов и начать маньячить. Ведь юзеры ждут подарков, а лучшего подарка чем новый кряк для компьютерщика, пожалуй, и не придумаешь!

Короче, надо хачить!

Рисунок 1 логотип декомпилятора DeDe

DeDe – это такой декомпилятор программ, написанных на DELPHI и BUILDER'е. Бесплатный и очень мощный. Мы будем использовать менее процента от его истинных возможностей. Кто там говорит, что это расточительство? Нет, расточительство это выбрасывать елку в мусор, не скурив ее всю вместе с гирляндой, серпантином и елочными игрушками.

Полная декомпиляция в нашу задачу не входит. Наша цель — локализация дислокации штаб-квартиры защитного механизма, то есть определение адресов процедур, проверяющих введенный пользователем регистрационный номер. Вот для этого нам и нужен DeDe, а все остальное можно сделать и руками. То есть дизассемблером. Вообще-то, в состав DeDe входит интегрированный дизассемблер в духе WIN32DASM, однако, по своему качеству он значительно уступает даже халявной версии IDA, не говоря уже о полном боекомплекте тяжелой артиллерии в лице IDA Pro + Soft-Ice. Это просто пи#дец какой-то! Это все равно что засунуть елочную ветку Стиву Б. в зад, даже круче! Намного круче!

Последняя известная мыщъх'у версия DeDe носит порядковый номер 3.50.02 и датируется серединой 2003 года. Похоже, что DaFixer полностью утратил интерес к своему детищу, решив похоронить DeDe на свалке истории. Полные исходные тексты версии 3.10b выложены в публичный доступ, однако, желающих продолжить благородное дело, что-то не наблюдается и потому DeDe обречен на медленное и мучительное вымирание. Программы, собранные новыми компиляторами от Багдада, DeDe либо вообще не переваривает, либо декомпилирует неправильно (вот потому, чуть позже мы рассмотрим как ломать борландию своими руками без посторонней помощи).

Архив DeDe.3.10b.realy.complete.src.zip (который, в частности, можно скачать с http://www.wasm.ru/baixado.php?mode=tool&id=55) на самом деле не совсем полон и в нем отсутствует пара компонентов: RxLib_v2.75 плюс VCLZip и прежде, чем DeDe удастся собрать, их необходимо найти в Интернете. Если же ты не собираешься заниматься доработкой DeDe, то лучше скачать архив без исходных текстов с http://www.xakep.ru/post/18513/default.asp который на два метра короче.

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

Ладно, не будем впадать в депрессию. Ведь Новый Год на дворе! И пока остальные рвут петарды, мы будем рвать свой хвост напополам, используя его как аркан для защищенных программ. Все очень просто! Берем программу, загружаем ее в DeDe, давим на кнопку «процесс» и сидим себе курим в ожидании пока DeDe потрошит дамп памяти. Лучше всего делать это под VM Ware, а то среди защищенных программ есть всякие твари, начиненные AdWare и прочей малварью.

Все, хватит курить! Хватит курить, я сказал!!! Щелчком отправляем бычок в раскрытое окно, дышащее свежим морозным воздухом и вникаем в полученный результат. Обычно долго вникать не приходится и приход наступает с первой же хапки. Сознание расширяется до границ адресного пространства и наступает просветление, граничащее с суицидом. Поубивал бы тех, кто придумал механизм идентификации типов в рантайме, благодаря которому названия классов не уничтожаются при компиляции (как в классическом Паскале и Си), а попадают непосредственно в исполняемый файл (как в Visual Basic'е). Взлом упрощается настолько, что ломать становится не в кайф. Никакого тебе интеллектуального поединка. Все равно что ломом добивать попавшую в капкан мышу.

Но мы же не садисты и не маньяки какие ни будь. Оставим мышу любоваться праздничным салютом, а сами вернемся к DeDe (после того как покурим). Самая левая (можно даже сказать радикально левая) вкладка с именами классов не содержит для нас ничего интересного (см. рис. 2). Вкладки «Units Info» и «Forms» так же отправляются в /dev/nul или куда поглубже. А вот вкладка «Procedures» это уже то, что нужно.

Рисунок 2 вкладка «Classes Info» декомпилятора DeDe

Открываем ее и смотрим. Ага, здесь перечислены юниты со всеми процедурами в них содержащимися. Причем, и сами юниты, и имена классов и названия событий (events) даны в символьном виде. То есть, если в программе есть диалоговое окно регистрации, то DeDe покажет что-то типа: fRegister  TfrmRegister  bOKClick (см. рис. 3). Как нетрудно догадаться — «bOKClick» и есть имя процедуры, получающей управление при нажатии на кнопку «ОК» и занимающуюся проверкой валидности введенного юзером серийного номера. Тут же, в колонке RVA, DeDe показывает ее относительный виртуальный адрес, по которому функцию легко найти в файле.

Рисунок 3 вкладка «Procedures» декомпилятора DeDe

А можно и не искать! Двойной щелчок по имени функции открывает окно с интегрированным дизассемблером, перемещая наш хвост непосредственно на зловредный защищенный код (см. рис. 4), что особенно полезно при анализе упакованных файлов, которые бесполезно загружать в ИДУ. DeDe дизассемблирует дамп памяти и потому упаковщики идут лесом. Как вариант, можно заюзать Soft-Ice, установив по заданному адресу аппаратную точку останова (команда «BPM адрес X»), необходимо только помнить, что RVA – это относительный виртуальный адрес, а Soft-Ice требует абсолютный. Чтобы перевести относительный виртуальный адрес в абсолютный достаточно загрузить файл в HIEW, нажать <F8> (header), посмотреть на базовый адрес загрузки (base address) и сложить его с RVA-адресом, сообщенным DeDe.

Рисунок 4 интегрированный дизассемблер декомпилятора DeDe

Ураганный артиллерийский огонь декомпилятора DeDe накрывает практически весь Багдад, ставя моджахедов по стойке смирно, а всех несогласных отправляет на север, где они рубят пихтовый лес и гонят драп, чтобы у всех плановых жителей было по елке. В смысле ПО «Елки», программное обеспечение т. е.

Недостатков у DeDe как минимум два. Первое — ломать автоматом это не в кайф и вообще не попонятиям. Настоящие хакеры так не поступают, предпочитая во всем разбираться самостоятельно с помощью кедрового отвара из хрюнделя (в просторечии называемого hiew'ом) и топора. Второе – как уже говорилось, DeDe обречен на вымирание и скоро он исчезнет с жестких дисков за ненадобностью, как в свое время исчезли динозавры и мамонты.

А потому, во многих ситуациях ручной взлом оказывается _намного_ предпочтительнее, а бывает так, что это вообще единственно возможный вариант. Короче, кто как, а мыщъх сразу в кусы и за демократию! Любовь, трава и IDA Pro — во! Трава желательно голландская. IDA Pro – любой версии. Шампанское — по желанию. На счет любви сказать затруднительно. С другой стороны, если мы себя не полюбим, нас никто не полюбит! Но это мы отвлеклись.

Берем, значит ИДУ, переходим в начало сегмента данных (View\Open subviews\Segments или <Shift-F7>) и прокручиваем его вниз до тех пор пока не встретим текстовые названия элементов управления с прилегающими к ним ссылками. Дизассемблерный текст должен выглядеть так, как показано в листинге 1.

.data:0040E88B word_40E88Bdw 0Bh; DATA XREF: .data:0040E614↑o

.data:0040E88Ddw 11h

.data:0040E88Fdd offset _TForm1_FormCreate

.data:0040E893db 10,'FormCreate'

.data:0040E89Edw 12h

.data:0040E8A0dd offset _TForm1_FormDestroy

.data:0040E8A4db 11,'FormDestroy'

.data:0040E8B0dw 17h

.data:0040E8B2dd offset _TForm1_Comm1ReceiveData

.data:0040E8B6db 16,'Comm1ReceiveData'

.data:0040E8C7dw 13h

.data:0040E8C9dd offset _TForm1_Button1Click

.data:0040E8CDdb 12,'Button1Click'

.data:0040E8DAdw 13h

.data:0040E8DCdd offset _TForm1_Button4Click

.data:0040E8E0db 12,'Button4Click'

.data:0040E8EDdw 13h

.data:0040E8EFdd offset _TForm1_Button2Click

.data:0040E8F3db 12,'Button2Click'

.data:0040E900dw 12h

.data:0040E902dd offset _TForm1_Timer1Timer

.data:0040E906db 11,'Timer1Timer'

.data:0040E912dw 13h

.data:0040E914dd offset _TForm1_Button3Click

.data:0040E918db 12,'Button3Click'

.data:0040E925dw 13h

.data:0040E927dd offset _TForm1_Button5Click

.data:0040E92Bdb 12,'Button5Click'

.data:0040E938dw 13h

.data:0040E93Add offset _TForm1_Button6Click

.data:0040E93Edb 12,'Button6Click'

.data:0040E94Bdw 13h

.data:0040E94Ddd offset _TForm1_Button7Click

.data:0040E951db 12,'Button7Click'

.data:0040E95E aTform1db 6,'TForm1'; DATA XREF: .data:0040E61C↑o

Листинг 1 названия методов класса формы в исполняемом файлы прямым текстом

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

Перемещаем курсор на название функции, автоматически назначенное ИДОЙ на основе текстовой строки (например, «_TForm1_Button3Click») и нажимаем на <Enter>, переходя на ее тело, откуда мы видим, что функция расположена по адресу, ну, скажем, 040286Ch. Загружаем файл в hiew, нажимаем <Enter> для перехода в шестнадцатеричный режим, давим <F5> (goto) и вводим адрес перехода (в данном случае «.040286C»). Точка в начале адреса сообщает hiew'у, что это действительно адрес, а не смещение (по умолчанию). Активируем режим редактирования по <F3> (Edit) и пишем «CC» – опкод точки останова, соответствующий машинной команде INT 03h. Сохраняем изменения по <F9> и выходим.

Рисунок 5 а вот так выглядит листинг 1 в hiew'e

Запускаем программу, вызываем обозначенную форму и давим на все кнопки по очереди. Когда мы надавим Button3 на экран выскочит системное сообщение о том, что у программы рвет крышу и сейчас она будет аварийно завершена в добровольно-принудительном порядке. Так и должно быть. В отсутствии отладчика команда INT 03h приводит к критической ошибке, что позволяет нам довольно быстро найти необходимые нам кнопки, после чего останется только хакнуть соответствующие им функции.

Естественно, ручной просмотр секции данных непроизводителен и ненадежен. Так легко проглядеть нужные нам формы, особенно если программист обозвал методы классов короткими и невыразительными именами в стиле «a», «b», «c», особо не бросающимися в глаза. Как быть тогда?! Очень просто! Указатель на структуру, приведенную в листинге 1, передается библиотечной VCL-функции Forms::TApplication::CreateForm(System::TMetaClass *,void*) в качестве одного из аргументов. IDA распознает VCL функции по сигнатурам, автоматически назначая им неразмангленные имена. Применительно к нашему случаю это будет: @Forms@TApplication@CreateForm$qqrp17System@TMetaClasspv. Просто находим эту функцию и смотрим все перекрестные ссылки, ведущие к местам ее вызова из программного кода. Ни одна форма не уйдет незамеченной!!!

Хорошо, а как быть, если в нашем распоряжении нету ИДЫ, а есть только hiew? Первая мысль: идти топиться — отметается как идеологически неправильная. Топиться в Новый Год это по меньшей мере негуманно. У всех людей праздник, настроение соответствующие и тут — бац! Дохлый труп в ванной с порезанными венами. Не эстетично! Таким путем мы приходим ко второй мысли — бедность это не порок, а естественное студенческое состояние и все, что не убивает — делает нас сильнее. Хорошо подумав головой, мы сумеем обойтись одним hiew'ом. Хотя, почему бы не подарить себе любимому лицензионную ИДУ на Новый Год как подарок?

ОК, hiew — так hiew. Это только с виду кажется, что hiew беспонтовая программа. На самом деле это очень даже мощный зверь типа гепард. Сильный и шустрый. К тому же компактный. Правда, увы, с некоторых пор далеко не бесплатный. Но найти hiew намного проще, чем ИДУ. Да и стоит hiew непропорционально дешевле, чем IDA Pro (это при его-то возможностях).

Короче, пока над нашими головами разрываются петарды и реактивная китайская пиротехника залетает через открытое окно форточки, мы загружаем ломаемую программу прямо в hiew, нажимаем <Enter> для перехода в шестнадцатеричный режим, давим <F8> (Header), говорим <F7> (Import) и в списке импортируемых функций находим imp_@Forms@TApplication@CreateForm$qqrp17System@TMetaClasspv, поставляемую динамической библиотекой vclXX.bpl, где «XX» – номер версии, например, «60». По <Enter> переходим к таблице «переходников» на импортируемые функции, состоящую из множество команд jmp. Убедившись, что курсор стоит на функции imp_@Forms@TApplication@CreateForm$qqrp17System@TMetaClasspv (что вовсе не факт, поскольку тут у hiew'а глюк и чтобы его обойти приходится выбирать соседнюю функцию, а потом поднимать курсор руками), нажимаем <F6> (Ref) для поиска перекрестных ссылок и видим код типа приведенного в листинге 2. Соответственно, <Ctrl-F6> (NexRef) означает поиск следующей ссылки на процедуру создания формы. Вот мы и будем жать <Ctrl-F6> пока не найдем все формы какие только есть.

.0040193A: 8B0DE01F4100movecx,[00411FE0]

.00401940: 8B15FCE54000movedx,[0040E5FC]

.00401946: E8B9BF0000call@Forms@TApplication@CreateForm$qqrp17System@TMeta

.0040194B: A134B65900moveax,@Forms@Application ;vcl60

Листинг 2 поиск указателя на структуру формы в hiew'e

Разумеется, это работает только с непожатыми программами, использующими статическую линковку, коих большинство. Если программа пожата, то прежде, чем мы доберемся до таблицы импорта ее предстоит распаковать, а если разработчик задействовал динамическую компоновку, то один или несколько вызовов imp_@Forms@TApplication@CreateForm$qqrp17System@TMetaClasspv останутся незамеченными, что есть бэд. В таких случаях выгоднее прибегнуть к отладчику, установив точку останова на imp_@Forms@TApplication@CreateForm$qqrp17System@TMetaClasspv, но об этом мы скажем ниже, а пока разберется с аргументами.

Главным образом нас интересует аргумент, загружаемый в регистр EDX и указывающий на структуру по смещению 18h от начала которой расположен указатель на вложенную структуру типа приведенной в листинге 1.

Самые сложные случаи взлома — это упакованные программы, загружающие VCL библиотеку на лету и не использующие никаких вразумительных имен в методах классов. Ломать такие защиты в дизассемблере — означает напрасно тратить время и здесь будет лучше воспользоваться отладчиком, в роли которого может выступать не только тяжелая (Soft-Ice) но и легкая артиллерия в лице OllyDebbuger.

Загружаем программу в Olly, в списке модулей (<Alt-E>) находим «VCLxx.bpl», давим на <Enter> и, просматривая список импорта (<Ctrl-N>), находим желаемое имя и давим <F2> для установки программной точки останова или <Enter>, <Shift-F10>, «Breakpoint», «Hardware, on execution» для установки аппаратной точки останова соответственно. Аппаратные точки намного надежнее, но… увы, их всего четыре, а вот количество программных точек останова ничем не ограничено.

Рисунок 6 установка точек останова в OllyDebbuger

Остается только выбрать подходящие функции для бряканья, краткий перечень наиболее важных из них (с точки зрения хакера) представлен ниже:

  1. @TControl@GetText$qqrv ; TControl::GetText(void):
    1. аналог API-функции GetWindowTextA — считывает текст из элемента управления в буфер;
  2. @Mask@TCustomMaskEdit@GetText$qqrv:
    1. еще одна функция для чтения текста в буфер (применяется довольно редко, но все-таки применяется);
  3. @Controls@TControl@SetText$qqrx17System@AnsiString:
    1. установка текста (т.е. копирование текста из буфера в элемент управления);
  4. @System@@LStrCmp$qqrv ; System:: LStrCmp(void):
    1. сравнение двух текстовых строк (например, расчетного серийного номера с эталонным — очень важная хакерская функция);
  5. @System@@LStrCopy$qqrv ; System::LStrCopy(void):
    1. функция копирования строк;
  6. @Sysutils@StrToInt$qqrx17System@AnsiString ; Sysutils::StrToInt(System::AnsiString):
    1. функция преобразования текстовой строки в число (достаточно часто используется защитами);

Как видно, во взломе программ из Багдада ничего сложного нет и они хакаются со свистом пробки, вылетающей из бутылки шампанского. Даже еще быстрее! Так что подарок к Новому Году по любому будет обеспечен!