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

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Едет программер с девушкой в троллейбусе. Девушка:

— Мечтаю съездить на могилку к Янке… Программер (немного подумав):

— А я мечтаю съездить на могилку к Биллу Гейтсу.

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

Мне понадобилось перевести несколько видеороликов в стандарт 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 стоит правильный РН. Ну что, смог я вас убедить?

{/codecitation}

Добавить комментарий