computer,hack,and more others

Объявление

Нравится ли Вам наш форум?

Да, Очень!
Думаю Да!
Нет, не очень.
Нет.
Незнаю.

Добро пожаловать на наш форум!Здесь ты можеж поговорить на всякие разные темы,поделится советами,рассказать что нибудь,предложить чтонибудь сделать новенькое администрации форума,получить ценный совет или помощь!И многое другое!!!

Друзья сайта
http://stalker-nn.3dn.ru/ War style Тайны Смолвилля: Ролевая игра

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » computer,hack,and more others » Взлом » Сам себе шериф


Сам себе шериф

Сообщений 1 страница 2 из 2

1

Генератор лицензий для серийной защиты Sheriff

Во многих программах есть ошибки. Ошибки бывают разные. К примеру, то, что программа по каким-то причинам работает только 30 дней, я считаю ошибкой :). Ошибки надо исправлять. И тут на помощь к нам приходят отладчик с дизассемблером. Две милые девушки – Оля (OllyDbg) и Ида (IDA).

По долгу службы одному моему знакомому потребовалось использовать узкоспециализированную и дорогостоящую программу eFilm от Merge eMed. Денег на ее покупку нет. Сама же программа необходима исключительно в целях отладки; являясь клиентом, она помогает отлаживать собственноручно написанный сервер. 30 дней, что дается на пробу, для этого явно не хватит. Узкоспециализированность стала гарантом отсутствия широкоизвестных методов увеличения срока службы. А значит, пора доставать мой большой отладчик! [взломанный сайт]

0

2

Анализ

Не думаю, что установка программы может вызвать хоть какие-то затруднения. Собственно, пока все достойно работает. Но вот первый запуск, и нас уведомляют о том, что программу можно или попробовать, или зарегистрировать. Выбираем первое. Получаем предупреждение, что системное время менять не стоит. Замечательно. В пункте меню «Help -> Licensing...» видим запутанную систему лицензий. Похоже, что где-то здесь и находится та самая ошибка, которую надо исправить.

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

Запускаем eFilm из под Оли. При запуске в программе происходят исключения, с которыми она сама не справляется. Значит, придется понажимать <Shift-F9>. После полной загрузки заходим в «Help -> Licensing...» и делаем вид, будто все уже оплачено. Нажимаем Local. Нам дают какой-то Reference Key (запишем куда-нибудь!) и предлагают ввести License Key. Ну что же. Вводим классическое «111111111...» (сколько хочется единичек) и смело жмем OK. Программа ругается MessageBox'ом. Ставим брейкпоинт на MessageBox в Оле (bp MessageBoxW и bp MessageBoxA). Давим OK - наш брейкпоинт срабатывает.

Мы в kernel32, и теперь нам надо попасть к месту вызова этой стандартной процедуры. Просто трассируем программу до retn'а. Ага. Мы теперь мы в MFC. Трассируем до следующего retn'а. Опа. Мы в eFilm.exe. Поднимаем взор чуть выше только что выполненного call’а, и пытаемся понять, как же программа до него дошла. Иногда изменив пару логических условий, можно добиться совсем других последствий.

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

Избегая блока с руганью, меняя флаги процессора перед jmp'ами, трассируем программу дальше. Стандартные процедуры трассировать бессмысленно, поэтому перешагиваем через многочисленные вызовы из mfc, kernel32 и user32. А вот местные процедуры могут быть интересны, поэтому их мы трассируем с заходом. Оля показывает нам содержимое стека и регистров. И там мелькает имя нашей программы, интересный ключ в реестре и какой-то номер. По вызываемым функциям становится примерно ясно, что происходит (к слову, человеческие имена для mfc-процедур можно получить у Иды). Запоминая действия программы, и записывая данные на листочке, продолжаем дальше. Доходим до любопытного места, а именно вызова:

004FABB3 . FF50 14 CALL DWORD PTR DS:[EAX+14]; <JMP.&efSheriffLocal.?GetLicenseHandle@CSheriffLocal@@UAEKXZ>,

В нем Оля углядела функцию из библиотеки efSheriffLocal. Функция имеет, прямо скажем, заманчивое имя. В папке с программой как раз лежит такая библиотека. И еще там есть библиотека с довольно похожим именем: efSheriffRemote. Судя по всему, это разные части одного защитного механизма. Первая библиотека - для локального применения, а вторая - на случай, если у нас есть сеть и лицензии надо шарить. Но это только догадки, которые, однако, подтверждаются наличием кнопок Local, Client и Server в диалоге регистрации. Просим Иду дизассемблировать и их. Это происходит довольно быстро. И начиная анализ, обращаем внимание на странный факт, что имена многих функций в таблицах экспорта и импорта совпадают. Более того, импорт происходит из библиотеки slsLocal.dll(sllRemote.dll), и если efSheriffLocal написана на С++, то slsLocal - на С. Таким образом, библиотеки efSheriff* - объектные надстройки над библиотеками sls*. Жуть.

Поиск

Что мы имеем? Защита организована в виде библиотек. Библиотеки имеют унифицированный интерфейс. В голову начинают лезть разные мысли:

   1. выяснив правильные ответы на запросы большого брата, можно было бы подменить библиотеки;
   2. защита явно не самодельная, а значит, где-то есть документация.

Опробуем вторую мысль. Гуглим по слову slslocal. Первая же ссылка ведет нас на сайт со звучным именем sheriff-software.com. Более того, она ведет нас прямо в help для тех, кто решил использовать эту защиту! Вот везение!

За комплект защиты для одной программы с нас просят всего $550 и $275 за каждую следующую. Эх... хорошо, что можно просто попробовать. Качаем SDK, щелкнув по кнопке Free evaluation (форму можно заполнять кривыми данными).

Честно говоря, на этом поиски можно было бы и закончить ввиду того, что в help'е достаточно подробно изложен принцип работы библиотеки, что позволило бы без труда написать подмену. Но мой взгляд приковала папка TOOLS. В ней лежат утилиты для работы с лицензиями. SlsAdmin -явно утилита для манипулирования существующими лицензиями. SlsGen - утилита для генерации лицензий по известным Product Name, Product ID, Product Secrets. Первое - тупо имя программы. Product ID - это 5 групп по 4 цифры. Группы разделены дефисами. Product Secrets - 4 строки, в каждой строке 4 группы по 4 цифры. Дальше в эту программу кидается Reference Key, и мы получаем Licence Key. Reference Key, по-видимому, индивидуален для каждой машины. И его нам выдали еще в самом начале.

Одна незадача - у нас нет ни Product ID, ни Product Secrets. Открываем мануал. Так. Product ID узнать просто - он в открытом виде передается многим процедурам (SLS_Request, например). Да и в реестре он светится, не говоря уже о том, что наша программа покажет его, если нажать кнопку View в меню «Help -> Licensing...». Вот он: 5366-8721-2229-7642-5711.

C Product Secrets все сложнее. Они бывают двух типов: обычные и зашифрованные. Эти ключи участвуют в проверке лицензий, поэтому они тоже передаются в одну из процедур. Но передаются они в зашифрованном виде, а для генератора они нам нужны в обычном. Собственно, вот они:

0x42 0x62 0x17 0x00 0x43 0xFC 0xC0 0x7F 0x8F

0xA2 0x9F 0x63 0x2E 0x86 0x19 0x28 0x35 0x62

0x41 0x61 0x6D 0x36 0x14 0x14 0x6D 0xB8 0x1D

0xCA 0x8B 0xCE 0x92 0xC4 0x0F 0x04 0x3B 0x39

0x43 0x63 0x39 0x6F 0x45 0xD5 0x41 0x11 0x43

0x41 0x13 0xA5 0x07 0xD2 0x04 0x8E 0xFB 0x9B

0x44 0x64 0x9A 0x49 0x97 0x8B 0x1C 0x15 0x64

0xB7 0x5D 0x0A 0x0F 0x0B 0xD9 0xFB 0x62 0x76

Остается еще одна программа в папке TOOLS - SlsPsn. Судя по описанию, человек покупает у Sheriff’ов некий номер (Product SN). Вводит в эту утилиту и получает Product ID и Product Secrets. Причем и в обычном, и в зашифрованном виде. Э-э-э... где-то здесь спрятан косяк. Либо программа уже знает все комбинации, либо генерирует их на лету по входному номеру. В любом случае внутри этой маленькой программки есть код, переводящий обычные Product Secrets в зашифрованные. Найдем его, затем обратим и получим код, переводящий зашифрованные Product Secrets в обычные.

Подмена

Для начала надо заставить SlsPsn вывести хоть что-нибудь. Суем ей «1111-1111-1111-1111». Ругается. Она права. Где там мой большой отладчик?! Ставим брейкпоинт на MessageBox. Жмем Generate. Брейкпоинт срабатывает. Отлично, теперь ищем место, где принимается роковое решение нас отвергнуть. В текущей процедуре решение уже принято, следовательно, надо искать выше. Вот вызов уровнем выше:

00403EF7 . 53 PUSH EBX ; /Arg3

00403EF8 . 6A 10 PUSH 10 ; |Arg2 = 00000010

00403EFA . 68 60234200 PUSH SlsPsn.00422360 ; |Arg1 = 00422360 ASCII "Invalid Product Serial Number"

00403EFF . E8 DF4F0100 CALL SlsPsn.00418EE3 ; \SlsPsn.00418EE3

Теперь надо его избежать. Видимо, условный прыжок чуть выше «00403EC2 75 7E JNZ SHORT SlsPsn.00403F42» нам поможет.

И действительно! Заменив его безусловным, мы добились того, что SlsPsn отработала, выдав нам необходимую информацию. Информация на самом деле бесполезная... Но! Давай теперь внимательно посмотрим, что там происходит. Нам был нужен код, который из обычных Product Secrets делает зашифрованные. Заново жмем кнопку Generate и с нашего патчика начинаем трассировать программу. Видно, как с помощью каких-то алгоритмов и вшитых констант программа вычисляет Product ID. А по Product ID... считается Product Secrets. Следовательно, зная Product ID, мы можем вычислить Product Secrets! Вот это косяк!

Ситуация упрощается. Попробуем подменить только что сгенерированный Product ID уже известным нам «5366-8721-2229-7642-5711». Вдумчивое наблюдение показывает, что в первый раз Product ID мелькает здесь:

00403F95 8D4424 70 LEA EAX,DWORD PTR SS:[ESP+70]

Тут-то мы его и подменим! Находим его в дампе и пишем туда «53668721222976425711» вместо «52468953169332006300». Алгоритм отрабатывает, и на выходе мы имеем Product Secrets. Причем обрати внимание, что «зашифрованный» вариант этих секретов мы уже где-то видели.

Копируем открытый вариант Product Secrets в SlsGen. Заполняем остальные поля. Запускаем eFilm. Регистрируемся. Получаем Reference Key. Генерируем себе лицензию. Вставляем в eFilm. Работает! А значит, генератор лицензий у нас есть! И можно идти дальше пить кефир и жевать жвачку.

Немного кодинга

Работает на ура. Но для полной гегемонии хотелось бы избавиться от извращений с SlsPsn. Мало ли в мире жертв Sheriff software. Надо приготовить инструмент для быстрой генерации секретных ключей. Безусловно, можно выдрать из SlsPsn нужные алгоритмы и быстро склепать нужный tool. Но стоит ли забивать свою голову глупыми алгоритмами, если есть другой способ - просто исправить ошибки в SlsPsn.

Для начала отредактируем интерфейс. Здесь нам поможет редактор ресурсов. Сделаем поле ввода, текст «Product SN:» и кнопку Help невидимыми - все равно они не нужны. А удалять не стоит - могут посыпаться ошибки, например, от кода инициализации диалога. Передвинем остальные поля чуть повыше. Свойство Read Only поля Product ID выставляем в False. Теперь Product ID можно редактировать. В качестве фона можно повесить свою фотографию. Ну или фотографию Джоанны Рутковской. Тру-хакерский интерфейс готов, теперь приступаем к редактированию кода.

Чтобы много не думать, мы припоминаем, где мы подменяли Product ID. Имеет смысл делать это там постоянно. Только теперь нам нужно вытаскивать код из EditBox'а и класть его в ss:[esp+70]. Обычно для этого я использую GetDlgItemText. Но этой функции нет в таблице импорта SlsPsn. С таблицей импорта разбираться не хочется. К тому же есть обходной маневр:

GetWindowText( GetDlgItem(hDlg, nIDDlgItem), buffer, buffer_length);

И обе функции у нас есть. На роль буфера подходит SS:[ESP+70] с максимальной длиной, скажем, 5 * 4 (5 групп по 4 цифры) + 4 (4 дефиса) + 1 (для нуля) = 25 = 19h. nIDDlgItem подскажет любой редактор ресурсов, а hDlg мы можем подглядеть в одном из вызовов SetDlgItemText. Или другим, более умным путем. mfc - библиотека объектная. Следовательно, для вызовов применяется соглашение __thiscall, и указатель на текущий экземпляр класса (this) передается в регистре ecx. Мы находимся в одном из методов mfc-диалога, а значит... В любом случае правильный ответ - [ecx+1c], только вот ecx сначала сохраняется в ebp. Поэтому - [ebp+1c].

Нам остается найти место для нашего патча. Под нашим исправленным джампом как раз образовалось много мертвого кода:

00403EC2 EB 7E JMP SHORT SlsPsn.00403F42

; здесь имеется ввиду

00403F41 . C3 RETN ; этот retn включительно

Так. Места у нас тоже вагон. Приступим к самому веселому!

Циничный патчинг

Помнится здесь мы подменяли Product ID:

00403F95 8D4424 70 LEA EAX,DWORD PTR SS:[ESP+70]

00403F99 52 PUSH EDX

00403F9A . 50 PUSH EAX

Что ж... подменим теперь код:

00403F95 ^E9 2AFFFFFF JMP SlsPsn.00403EC4

00403F9A . 50 PUSH EAX

О ужас! Мы затерли один push. Не беда, конечно, но забыть о нем нельзя! Компилятор в целях выгоды не использовал стандартный кадр стека, и все стековые переменные адресуются относительно очень непоcтоянного esp. Дополнительная сложность. Теперь по адресу 00403EC4 надо расположить наш код. Я тут набросал кое-что:

PUSH ECX ; сохраняем ecx

PUSH EBX ; сохраняем ebx

PUSH EDX ; сохраняем edx

; далее аргументы GetDlgItem в обратном порядке - таково соглашение __stdcall

PUSH 3E9 ; это nIDDlgItem

PUSH DWORD PTR DS:[EBP+1C] ; это hDlg

CALL DWORD PTR DS:[<&USER32.GetDlgItem>] ; USER32.GetDlgItem

LEA EDX,DWORD PTR SS:[ESP+7C] ; buffer

; 70 сменилось 7С ввиду того, что кадр стека поплыл за счет трех push'ей наверху

; 3 * 4 байта = 12 байт = Ch байт

PUSH EDX ; кидаем в стек buffer (смотри ниже)

PUSH 18 ; buffer_length

PUSH EDX ; buffer

PUSH EAX ; в eax - результат GetDlgItem, то есть искомый HWND

CALL DWORD PTR DS:[<&USER32.GetWindowTextA>] ; USER32.GetWindowTextA

POP EAX ; edx, засунутый чуть выше, идет в eax

; мы ведь потерли LEA EAX,DWORD PTR SS:[ESP+70],

; а этой комбинацией мы восстановили справедливость

POP EDX ; восстанавливаем edx

POP EBX ; восстанавливаем ebx

POP ECX ; восстанавливаем ecx

PUSH EDX ; мы обещали не забыть об этом push'е

JMP SlsPsn.00403F9A ; прыжок назад, точно на push eax

Отлично! Вбиваем патч в Олю и запускаем программу. Call'ы нужно вбивать, опираясь на значения в таблице импорта, а не на конкретные смещения! То есть не call 7E4247FE, а CALL DWORD PTR DS:[41C2D4]. Значения можно легко подсмотреть в Иде. Вбили - проверяем.

И вот первый косяк - кнопка Generate задизейблена. Причем не на уровне ресурсов, а программно. Что же нам делать? Давай размышлять! Кнопка - элемент диалога, а значит, у нее есть номер. Чтобы выполнить любую операцию над кнопкой, надо в стек засунуть ее номер. Причем наша кнопка уникальна во всех смыслах, то есть в циклах ее обрабатывать не будет. Номер нашей кнопки 1004 = 3ech. Поищем push 3ec в Иде. Так и есть – нашелся. И как раз рядом с вызовом ShowWindow. Обратим внимание, что чуть выше в стек кладется ноль:

00403DF1 . 33D2 XOR EDX,EDX

[...]

00403DFE 52 PUSH EDX

Этот ноль - аргумент для ShowWindow. Причем когда он нулевой, это значит «выключить», а когда ненулевой – «включить». Места, чтоб изменять edx, у нас нет. К тому же его потом опять придется восстанавливать - скорее всего, этот ноль где-то еще используется. Но ведь есть же регистр, который всегда ненулевой! Указатель стека esp, к примеру.

00403DFE 54 PUSH ESP

Перезапускаем. Применяем патчи. Работает! Это странно, но очень радостно. Осталось лишь сохранить изменения, и генератор готов.

Впрочем, тут еще есть, над чем поработать. К примеру, можно добавить фильтры для входящей строки, допуская любые комбинации: «XXXXXXXXXXXXXXXXXXXX», «XXXX-XXXX-XXXX-XXXX-XXXX» и даже «XXXX XXXX XXXX XXXX XXXX». Стоит сделать простую защиту от дурака...

Заключение

Итак, налицо метод получения генераторов лицензий для любых программ, защищенных с помощью Sheriff v3.0. Хтрость защиты строится на неведении алгоритмов и запутанной системе лицензий, разобраться в которой может торговец, но не математик. Такая защита себя не оправдывает, алгоритмы узнаются, либо обходятся, а систему всегда можно обыграть по ее же правилам.

0


Вы здесь » computer,hack,and more others » Взлом » Сам себе шериф