winrar.crk

взлом архиватора WinRAR

крис касперски ака мыщъх

обучаться взлому лучше всего на простых защитах, таких как, например, архиватор WinRAR, который мы сегодня захачим по полной программе, заодно научившись пользоваться hex-редактором, API-шпионом и дизассемблером, а с отладчиком познакомимся в следующий раз

Свежескаченная версия WinRAR'а работает 40 дней, а потом вопит о регистрации, выбрасывая противный NAG-screenпри каждом запуске, что очень аноит и возникает естественное желание его отломать.

Мы будем хачить последую стабильную версию 3.42, на которую ведет ссылка http://www.rarsoft.com/rar/wrar342.exe. Все остальные ломаются аналогичным образом, только смещения «защитных» байт будет другими.

Рисунок 1 противный NAG-Screen

Еще нам понадобиться любой HEX-редактор (например, HIEW), API-шпион Kerberos, дизассемблер IDA Pro и редактор ресурсов (например, Microsoft Visual Studio). Различные версии hiew'а имеют различную раскладку «горячих» клавиш, что создает некоторую путаницу. Мы будем использовать бесплатную версию 6.04 без функциональных ограничений. Последние версии hiew'а распространяются на коммерческой основе, а коммерция и хакерство не совместимы!

Всякий диалог выводится не сам по себе (это ведь не кошка), а отображается некоторой API-функцией. Перехватив API-функцию, выводящую NAG, мы сможем дизассемблировать защитный код, который ее вызывает, и проанализировать условия, определяющие появление NAG'а на экране.

Существует множество API-функций, связанных с диалогами: CreateDialog, DialogBox, MessageBox и т. д. Какую из них использовал разработчик rar'а? Чтобы не гадать, воспользуемся API-шпионом. Он все покажет. Только сначала настроим фильтр, чтобы Kerberos отбрасывал малоинформативные API-вызовы, захламляющие файл отчета. Откроемke_spy.txt и закомментируем следующие функции: TlsGetValue, DefWindowProcA, DispatchMessageA, GetFocus, GetMessageA, SendMessageA, SendMessageW, TranslateAcceleratorA, TranslateAcceleratorW и TranslateMessage (чтобы закомментировать функцию перед ее именем вставляется знак ';'). Для усиления фильтрации имеет смысл зайти в Опции (кнопка «options») и взвести флажок «reportonly .execalls», чтобы собирать API-вызовы только из winrar.exe, но не из загружаемых им DLL. Если этого не сделать, ничего страшного не произойдет, но файл отчета получится слишком большой и удручающе ненаглядный.

Рисунок 2 настойка фильтра перед запуском шпиона

Теперь нажимаем Browse, указываем путь к rar'у и давим Inject. Дождавшись появления NAG'а на экране, выходим из rar'а и открываем файл отчета WinRAR.rep, находящийся в одном каталоге с rar'ом.

Рисунок 3 API-шпион kerberos, готовый к работе

Изучение файла-отчета (см. листинг 1) лучше начинать с конца (ведь NAG-screen появляется в последнюю очередь, когда основной интерфейс уже инициализирован). Только слепой не обнажит вызов функции DialogBoxParamA, выводящей диалог с грозным именем «REMINDER» (то есть «напоминатель»). Она-то этот противный диалог и создает. Да… с фантазией у разработчиков защит всегда былоинапряги.

WinRAR.exe|0044B030|LoadAcceleratorsA(00400000, 00496BA8: «VIEWACC») returns: 001E006F

WinRAR.exe|00440F73|DialogBoxParamA(400000,495FE1:«REMINDER»,70094,444FF4,0) returns:0

WinRAR.exe|00440F9B|WaitForSingleObject(00000110, 0000000A) returns: 00000102

Листинг 1 фрагмент файла отчета

Kerberos (вот умница!) даже сообщает адрес возврата из функции — 440А73h, ведущий прямо к защитному коду. Заглянем сюда дизассемблером? Загружаем winrar.exe в IDA PRO идавим <G> (Jump to address), «440A73», <Enter>.

Рисунок 4 защитный код, исследуемый в дизассемблере IDA PRO

Отчетливо виден вызов DialogBoxParamA, выше которого находится следующий дизассемблерный код:

00440F1Dcmpdword_4B3A90, 0

00440F24jnzshort loc_440F73

00440F26cmpbyte_495A60, 0

00440F2Djnzshort loc_440F73

00440F2Fcmpbyte_4B7E00, 0

00440F36jnzshort loc_440F73

00440F38cmpbyte_49F9BC, 0

00440F3Fjnzshort loc_440F73

00440F41moveax, dword_004B43C8

00440F46cmpeax, 28h

00440F49jgshort loc_440F4F

00440F4Btesteax, eax

00440F4Djgeshort loc_440F73

00440F4F

00440F4F loc_440F4F:; CODE XREF: sub_4408C8+681↑j

00440F4Fmovbyte_495A60, 1

00440F56push0; dwInitParam

00440F58pushoffset sub_444FF4; lpDialogFunc

00440F5Dpushdword_4B161C; hWndParent

00440F63pushoffset aReminder; lpTemplateName

00440F68pushhLibModule; hInstance

00440F6EcallDialogBoxParamA

00440F73 loc_440F73:; CODE XREF: sub_4408C8+65C↑j

00440F73; sub_4408C8+665↑j …

00440F73cmpdword_4B3A90, 0

Листинг 2 дизассемблерный листинг защитного механизма (фрагмент)

Как мы видим, функция DialogBoxParamA вызывается когда выполняется условный переход: cmp eax, 28h/jg loc_440F4F (прыжок, если eax > 28h). В десятичной системе 28h равно 40. Это и есть срок демонстрационного периода, положенный нам по праву. Теперь становится понятен «физический» смысл переменной dword_004B43C8, содержащей количество дней, прошедших с момента установки программы.

Открываем свежее пиво! Штаб-квартира защитного механизма найдена! Как мы будем действовать? Чтобы заблокировать NAG, можно, например, изменить cmp eax,28h (83 F8 28) на xor eax,eax/nop (33 C0/90), тогда eax всегда будет равен нулю независимо от того какой день сейчас за окном, ну а команда nop понадобилась нам для того, чтобы скомпенсировать уменьшение длинны инструкции (cmp занимает три байта, а xor только два).

Запускаем hiew, загружаем winrar.exe, дважды нажимаем на <ENTER> чтобы перейти в ассемблерный режим, давим <F5> (goto) и пишем «.440F46» — адрес инструкции cmp, ну а точка здесь затем, чтобы сообщить hiew'у, что это именно адрес, а не смещение в файле. Нажимаем <F3> для перехода в режим редактирования (edit), а затем <ENTER> для ввода ассемблерной инструкции. В появившемся диалоговом окне пишем «xor eax,eax» <ENTER> «nop» ESC>. Сохраняем все изменения в файле нажатием <F9> и выходим.

Рисунок 5 три байта, блокирующие NAG

Запускаем winrar. Теперь NAG уже не выводится! Весь взлом не занял и десяти минут! Как вариант, можно заменить mov eax, dword_004B43C8 (A1 C8 43 4B 00) на mov eax, 6 (B8 06 00 00 00) и тогда rar будет считать, что с момента регистрации всегда прошло ровно шесть дней. Почему именно шесть? Ну, не шесть так девять. Какая нам разница?! Главное, чтобы не больше 40! А еще можно заменить jg short loc_440F4F (7F 04) на jmp short loc_440F73 (EB 28), тогда безусловный переход будет перескакивать диалог независимо от текущего времени.

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

Несмотря на то, что раздражающий NAG успешно убран, программа остается незарегистрированной и честно пишет в заголовке окна: «evolutioncopy». А если нажать «About», мы увидим «40 daystrialcopy». И хотя никаких ограничений в демонстрационной версии нет, чисто психологически работать с зарегистрированной копией намного приятнее.

Известно, что регистрация осуществляется с помощью ключевого файла с электронной подписью, сгенерированной на криптографической основе с таким расчетом, чтобы подделка ключа была невозможной. Все это так, но ведь нам не нужен ключ! Мы хотим установить флаг регистрации! А как его найти? Вернемся к листингу 2.Выше уже известной нам инструкции «cmpeax, 28h» ополчилась целая серия условных переходов при определенных обстоятельствах перепрыгивающих через этот противный диалог. Очевидно, один из них принадлежит флагу регистрации (ведь у зарегистрированных пользователей NAG не выводится), но как определить какой из них какой?

Будем действовать по плану (план — эта такая шутка, что растет во дворе). Назначение переменной byte_495A60 определяется сразу. При выводе диалога сюда записывается 1, то есть диалог уже выведен и повторно выводить его не нужно. С переменной dword_4B3A90 разобраться гораздо сложнее. Чтобы узнать кем она используется и для чего (alt: чтобы узнать за каким хреном она используется), необходимо просмотреть перекрестные ссылки. Подводим курсор к имени переменной, вызываем контекстное меню и выбираем пункт «jumptoxref to operand» или просто нажимаем <X>. Появляется следующее окно (см. рис. 6):

Рисунок 6 исследование перекрестных ссылок

Фу! Куча перекрестных ссылок по чтению ® и записи (w), разбросанных по всему телу программы, среди которых доминируют dec и inc. На флаг регистрации это мало похоже. Скорее это какой-то дикий семафор, использующийся для организации взаимоблокировок. В общем, запчасть от интерфейса. К переменной byte_4B7E00, ведут три перекрестные ссылки, две из которых находятся в непосредственной близости от функции DoDragDrop, так что их можно сразу откинуть.

А вот переменная byte_49F9BC — это настоящий клад. К ней ведет множество перекрестные ссылок на чтение и запись, но все записываемые значения возвращаются либо функцией sub_40DB5C, либо функций sub_44A278. И только одна ссылка ведет к команде mov byte_49F9BC, 0, принудительно сбрасывающей переменную в ноль.

При первом же взгляде на sub_44A278 бросаются в глаза текстовые строки «rarkey», заботливо оформленные дизассемблером как комментарии. Ага! Держи мыщъх'а за хвост! Похоже это и есть процедура, ответственная за регистрацию. Подводим курсор к ее началу, нажимаем <N> и переименовываем ее в «DoRegister».

Рисунок 7 дизассемблерный листинг функции DoRegister, выдающей себя текстовыми строками «rarkey»

С функцией sub_40DB5C разобраться тоже несложно. Достаточно проанализировать код, находящийся в самом начале DoRegister:

DoRegisterproc near

0044A299callsub_40DB5C

0044A29Etestal, al

0044A2A0jzshortloc_44A2B6; продолжение регистрации

0044A2A2moval, 1

0044A2A4movedx, [ebp+var_11C]

0044A2AAmovlarge fs:0, edx

0044A2B1jmploc_44A40D; на вход из функции

Листинг 3 загадочная функция sub_40DB5C

Если sub_40DB5C возвращает ноль, функция DoRegister продолжает регистрацию. Ненулевое значение приводит к немедленному выходу из функции. Логично предположить, что sub_40DB5C просто сообщает статус регистрации: ноль — не зарегистрирован, не ноль — зарегистрирован. Подведем курсор к началу sub_40DB5C и переименуем ее в «IsRegistered».

А давайте заставим IsRegistered всегда возвращать ненулевое значение! Тогда программа будет признана зарегистрированной, несмотря на то, что ключевого файла, заверенного электронной подписью, у нас нет (да и откуда бы ему взяться)!

Запускаем hiew, дважды нажимаем <ENTER> для перехода в дизассемблерный режим, давим <F5>, вводим «.40DB5C» (адрес функции IsRegistered), затем <F3> для перехода в режим редактирования и <ENTER> xor eax,eax <ENTER> inc eax <ENTER> retn <ESC> (обнулить регистр eax, тут же увеличить его на единицу и свалить из функции на хрен). Записываем изменения клавишей <F9> и выходим из hiew'а.

Надпись «evaluationcopy» в заголовке окна послушно исчезает, а в окне About появляется строка «Registeredto» (см. рис. 8)

Рисунок 8 как демонстрация версия стала зарегистрированной

Правда, после добавления любого файла в архив, rar регистрация загадочным образом исчезает. А все потому, что мы забыли исправить команду «mov byte_49F9BC, 0», расположенную по смещению 44D049h на «mov byte_49F9BC, 1». Сделаем это и тогда надпись evaluationcopy никогда не появится!

Надпись «Registeredto» это, конечно, хорошо, только не понятно на кого именно программа зарегистрирована. Первое, что приходит на ум, найти этот «Registeredto» в программе (он там находится по смещению 50DBA4h) и заменить его на «hackedbyKPNC», однако, более длинный ник вместить уже не удастся, поскольку предельно допустимая длина строки жестко ограничена сверху. Лучше найдем тот код, который эту строку выводит!

Запускаем Kerberos, загружаем winrar.exe, открываем «About», закрываем winrar.exe и лезем в протокол, в конце которого содержится строка, DialogBoxParamA(400000, 496005: «ABOUTRARDLG», 001200AA, 00444618, 00000000), вызываемая по адресу 441D1Ch. Ага, это наш AboutRarDialog и есть! Возвращаемся в ИДУ и переходим по указанному адресу.

00441D01pushoffset sub_444618; lpDialogFunc

00441D06pushdword_4B161C

00441D0Cpushoffset aAboutrardlg

00441D11pushhLibModule

00441D17callDialogBoxParamA

Листинг 4 код, создающий About-диалог

Функция sub_444618, как и подсказывает IDA, представляет собой диалоговую процедуру, ответственную за вывод диалога. Заглянем, что там? Ой-ой-ой, сколько всяких вызовов! Это же крышей поехать можно пока разберешься что к чему! Мы видим множество вызовов SetDlgItemTextA. Какой из них наш? Чтобы ответить на этот вопрос, требуется выяснить идентификатор соответствующего элемента управления.

Запускаем MicrosoftVisualStudio (или любой другой редактор ресурсов), говорим «openfile», в «типе файлов» выбираем «все файлы», а в «openas» – «resources» (если этого не сделать, файл будет открыт как двоичный, что совсем не входит в наши планы). В дереве ресурсов находим ветку «Dialogs», а в ней «ABOUTRARDLG». Щелкнем по нему мышью. Дважды. Или нажмем ENTER. Запустится редактор ресурсов. Находим строку «40 daystrialcopy» на месте которой в зарегистрированной версии выводится «Registeredto» и, вызвав контекстное меню определяем ее ID, равным в данном случае 102 (или 66 в hex-представлении).

Рисунок 9 определение идентификатора поля вывода в MicrosoftVisualStudio

Просматривая дизассемблерный листинг, ищем такую функцию SetDlgItemTextA, чьим аргументом будет идентификатор 66h и находим ее в конечном счете по адресу 4447ECh:

004447E6callsub_4113DC

004447EBpusheax; lpString

004447ECpush66h; nIDDlgItem

004447EEpush[ebp+hDlg]

004447F1callSetDlgItemTextA

Листинг 5 код, выводящий строку «Registeredto»

Функция sub_4113DC возвращает указатель на выводимую строку, которая тут же передается SetDlgItemTextA. Исследовать саму sub_4113DC мы не будем. Имя зарегистрированного пользователя берется из ключевого файла, над которым можно просидеть всю оставшуюся жизнь. Лучше внедрить свою строку в исполняемый файл и подменить указатель. Внедрятся мы будем в секцию данных, в хвосте которой практически всегда имеется свободное место. Размещать выводимую строку в секции кода нельзя, поскольку rar требует, чтобы она была доступа на запись.

Рисунок 10 каталог секций

Открываем hiew, однократным нажатием на <ENTER> переходим в hex-режим, давим <F8> для отображения заголовка файла и вызываем таблицу объектов (objecttable) клавишей <F6>. За секций .data расположена секция .tls. Подгоняем сюда курсор и нажимаем на ENTER, а затем перемещаемся на несколько строк вверх, следя за тем, чтобы не залезть в значимые данные, которые начинаются там, где кончается цепочка нулей. В нашем случае этот будет адрес 49D7B0h (хотя при желании так же можно выбрать 49D7AEh, 49D7AFh и т.д). Нажимаем <F3> для перехода в режим редактирования и записываем «registeredversionhackedbynezumi» (nezumi это мыщъх по-японски).

Рисунок 11 создание подложной строки с именем зарегистрированного пользователя

Теперь переходим по адресу 4447E6h, возвращаясь к нашей диалоговой процедуре (см. листинг 5) и заменяем call sub_4113DC (E8 F1 CB FC FF) на mov eax, 49D7B0 (B8 B0 D7 49 00), где 49D7B0h – адрес хакнутой строки. Сохраняем изменения в файле и…

Рисунок 12 полностью хакнутая версия, зарегистрированная на мыщъх'а

Это работает! Теперь хакнутая версия ничем не отличается от легально зарегистрированной! Разумеется, это еще не означает, что теперь rar'ом можно пользоваться и ничего за него не платить (законов ведь никто не отменял), поэтому сразу же после экспериментов взломанный файл должен быть удален с жесткого диска.

версияадрес IsRegisteredадрес mov flag,0адрес lpString
3.0 stable (rus)40BA4C441384439740
3.42 stable (eng)40DB5C44D0494447E6
3.50 beta 5 (eng)40DE2C44E5EA4457B0
3.42 stable (rus)40DB5C44D0494447E6

Таблица 1 адреса хакаемых байт в различных версиях rar'a

Многие разработчики используют электронные подписи и прочие криптографические механизмы, надеясь, что они уберегут их от зловредных хакеров. Как бы не так! Криптография, конечно, мощная штука, но к ней нужен свой подход. Если программа опирается на флаг регистрации (а так поступает большинство программ), она элементарно взламывается правкой нескольких байт, на поиск которых уходит совсем немного времени.

Зачем искать в сети краки (большинство из которых работают с устаревшими версиями или не работают совсем)? Гораздо быстрее взламывать программы самостоятельно!