скрыть

скрыть

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

Как сделать генератор PH, не зная алгоритма его вычисления


Едет программер с девушкой в троллейбусе. Девушка:
- Мечтаю съездить на могилку к Янке... Программер (немного подумав):
- А я мечтаю съездить на могилку к Биллу Гейтсу.

Что за бред, подумает читатель, прочитав название этой статьи. Как можно сгенерировать ключ, если алгоритм генерации полностью не известен? Но я гарантирую, что, прочитав эту статью, вы убедитесь, что и такое возможно... Итак приступим.

Мне понадобилось перевести несколько видеороликов в стандарт MPEG, а для сего я скачал с www.download.com XingMPEG Encoder 2.20 – во всех отношениях просто замечательную программу, кроме одного: это trial-версия (т.е. она работает только 30 дней), но главное – trial позволяет делать файлы не более 30 секунд. А поскольку большинство роликов заметно больше 30 секунд, мы займемся исправлением этого недоразумения.

Для начала с помощью SoftICE. При запуске программы появится окошко с логотипом фирмы и сообщением, что это не полная версия. Внизу окошка – бегунок, показывающий количество дней до конца халявы, а так же 3 кнопки: "Buy Now", "Try First" и "Cancel".

Нажимаем кнопку "Buy Now" и попадаем в окно регистрации, где заполним больше десятка полей всяческой ерундой. Пару раз щелкаем "Дальше". Попали в окошко, где надо вводить данные о кредитной карточке. Я заполнил поля так:


  Тип карточки	– American Express
  Card Number	– 1234 1234 1234 1234
  Expiration	– 11/11
  Name on card	– You!

Трижды щелкаем "Дальше", и попадем в окно с выбором платежа. Выберем "ORDER BY MAIL/FAX", т.к. все остальные отпадают по понятным причинам. Теперь, когда мы снова запустим программу и нажмем "Buy Now", мы попадем в само окно регистрации, где и необходимо ввести код, якобы присланный нам по почте после оплаты.

Теперь поставим в SoftICE контрольную точку на выполнение MessageBoxA(). Вводим в окно для кода любое число, но меньше 10 знаков (можно и 10, но тогда придется прокручивать страниц пять текста, чтобы найти команду перехода). Щелкаем "ОК" и попадаем в SoftICE. Жмем F12, "ОК" в окошке с сообщением о неверном коде, и попадаем обратно в SoftICE. Наблюдаем такую картину:


:10005635  call [user32!MessageBoxA]
:1000563B  mov ecx, [10031774] <--- Мы здесь.
:10005641  or eax, -01

Прокрутим код немного вверх, пока не натолкнемся на строчки:


:1000560C  repnz scasb
:1000560E  not ecx
:10005610  dec ecx
:10005611  cmp ecx, 0A <---- Проверка длины.
:10005614  jz 10005655 <---- Сюда bpx.
:10005616  lea edx, [esp+10]

Отключим предыдущие контрольные точки, и поставим новую на выполнение команды jz 10005655 (просто двойным щелчком по этой строке), вернемся в программу и введем теперь точно 10 цифр в окно для кода (а можно просто поменять значение регистра флагов Z) и снова попытаемся зарегистрироваться. Произойдет остановка на jz 10005655 (JUMP), протрассируем (F10) немного программу, пока не дойдем до места:


:10005698  push ecx
:10005699  push edx
:1000569A  push eax
:1000569B  call 1000B950 <---- Остановимся тут.
:100056A0  add esp, 0C

Не выполняя команду call, посмотрим что ей передается:


  d ecx – пусто
  d edx – крупненькая константа = Er5286RteWa2314HmN
  d eax – номер, у меня – 4872151134

Из всего этого можно сделать вывод, что следующая команда call запускает внешнюю функцию, которая сгенерирует правильный код.

Проверим это, выполнив call. Посмотрим, что теперь находится в ранее пустом ecx:


d ecx – регистрационный код, у меня – QLRHMLIRYR

На этом первая часть заканчивается. Теперь можно ввести код в окне регистрации – и полностью рабочий XingMPEG Encoder 2.20 у нас в руках.

Убрать регистрацию можно так:

  • Uninstall.
  • Удалить из реестра ключ HKEY_CLASES_ROOT\ultxfile\Format\MSHVVEN2 (или типа такого).
  • Переустановить программу.

А теперь о главном: как сделать генератор РН, не зная алгоритма его вычисления?

Для примера возьмём все тот же XingMPEG Encoder v2.20 (как найти правильный РН с помощью SoftICE я объяснять здесь не буду, об этом мы уже говорили в первой части, да и о нахождении большинства необходимых данных можно прочитать там же).

Поставив нужную контрольную точку, мы наткнёмся на процедуру генерации РН:


:10005698  51           push ecx
:10005699  52           push edx
:1000569A  50           push eax
:1000569B  E8B0620000   call 1000B950
:100056A0  83C40C       add esp, 0C

Обращаем внимание на то, что процедура эта находится в rsagnt32.dll. Также уделяем внимание EIP, из которого можно сделать вывод, что rsagnt32.dll грузилась по стандартному адресу 10000000. Так что несложно будет вычислить адрес и самой функции: 1000В950h – 10000000h = В950h. Самое время посмотреть, какие функции являются в rsagnt32.dll экспортируемыми (для этой цели я использовал DumpBin).

Вот собственно и есть эти функции:


Ordinal  Hint     RVA             Name

   1      0     00002A40     SAAddProductItem
   2      1     00011590     SAChargeTax
   3      2     00011580     SACheckEnable
   4      3     00002B70     SACleanup
   5      4     00002930     SAInitialize
   6      5     0000E350     SAPurchaseOrderEnable
   7      6     000085B0     SAPurchaseOrderSetFaxNumber
   8      7     0000E360     SAPurchaseOrderSetInstParagraph
   9      8     0000E3C0     SAPurchaseOrderSetOrderInfoParagraph
  10      9     00010660     SAReceiptSetNoSerialNumber
  11      A     00010600     SAReceiptSetParagraph
  12      B     000115A0     SASelectTransMethod
  13      C     000029E0     SASetHelpDir
  14      D     000088E0     SASetMailInstruction
  15      E     00008930     SASetNoWaitMail
  16      F     00002980     SASetScreenText
  17     10     00008580     SASetVendorName
  18     11     000012E0     startSalesAgent

И что же мы видим? А ничего. Экспортируемой функции с RVA=0000В950 просто нет!

Вот теперь мы перейдём к самому интересному. А что если нам написать программку (я использовал С++), которая будет делать следующее:

  • Загружать rsagnt32.dll. Можно использовать HINSTANCE hInst=LoadLibrary(rsagnt32), при этом hInst - не что иное, как RVA самой DLL (как 10000000, см.выше).
  • Вычислять адрес этой функции. Чтобы получить адрес функции, нам нужно к hInst прибавить В950h. Теперь у нас есть адрес функции (далее KeyMaker()), которую мы будем вызывать, осталось только найти нужные параметры.
  • Вызывать эту функцию, передав ей нужные параметры. Для этого вернемся ещё раз к самой функции из SoftICE:

:10005698  51          push ecx         <----- Buffer
:10005699  52          push edx         <----- Const
:1000569A  50          push eax         <----- PersonalCode
:1000569B  E8B0620000  call 1000B950    <----- Вызов ф-ции
:100056A0  83C40C      add esp, 0C      <----- Правка стека

  • Мы видим, что функции передаются три параметра: Buffer, Const и PersonalCode. Buffer - то место, куда запишется правильный код, Const имеет вид Er5286RteWa2314HmN, а PersonalCode берётся из rsagent.ini. (или из окошка в программе регистрации).

Теперь к самой программе:


char* Const="Er5286RteWa2314HmN";
char Buffer[10];
char* PersonalCode="4872151134" //PersonalCode можно читать из rsagent.ini
                                // используя GetPrivateProfileString()

Саму же функцию нам придётся вызывать с помощью Ассемблера, т.к она не является экпортируемой, после вызова будет неправильно выставлен стек, что приведёт непосредственно к сбою системы.


_asm

{
push offset Buffer
mov eax, [Const]
push eax
mov eax, [PersonalCode]
push eax
call dword ptr [KeyMaker]       // KeyMaker это и есть адрес функции, который мы вычислили
add esp, 0x0C
}

После всего этого в Buffer стоит правильный РН. Ну что, смог я вас убедить?






Copyright © 2004-2016 "Delphi Sources". Delphi World FAQ




Группа ВКонтакте   Ссылка на Twitter   Группа на Facebook