Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Исследование программы Xmcoder
Автор: Gas Man

Из сообщения информагентства: "Группа российских хакеров взломала защиту на главном сервере господа Бога и поставила себе бесконечные деньги и вечную жизнь".

Для того чтоб зарегистрировать программу ее следует изучить т.е. посмотреть ее реакцию на введение s/n, unlocking code или reg.no. Сообщения к-рые выдает программа на введение неверных ключевых данных лучше запомнить или записать - они нам еще понадобятся.

Используемые инструменты: SoftICE,WDasm89

Запускаем xmencoder. Жмем кнопку Buy now.Попали в экран User Registration - заполняем все поля информацией т.к. программа очень требовательна и не допускает пустых полей ;) Ok! Заполнили. Идем дальше. Предлагают купить Item(s) - проверяем кошелек если есть лишние $89 дальше лучше не читайте, а просто заплатите и все ;) (у меня не было :(( ) Идем далее. Предлагают выбрать способ оплаты. Мне понравилась Visa (т.к. не надо лишний раз тыкать мышОй) Пишете ваш номер кредитки если есть :), если нет то попробуйте подобрать любой подходящий ежели лень, то подсказываю: 13 шестерок проходит на УРА! Далее попадаем в форму для комментариев - вот где душу можно отвести и клаву потоптать! Но помните, скорее всего никто не прочтет ваши излияния ;)) После комментариев проходим еще один экран последнего подтверждения информации и ...

Попадаем в экран выбора способа оплаты Выберите OREDER BY PHONE и дальше. Теперь спрашивают unlocking code :)) Введите любой бред. Получите сообщение типа Sorry, that unlocking code .... что-ж, не угадали :(( Теперь поищем эту строку в директории с Xing MPEG Encoder'ом Вуаля - Есть вхождение в rsagnt32.dll

Дизассемблируем его, и находим 4 ссылки на эту строку


* Reference To: USER32.GetDlgItemTextA, Ord:00F5h
:1000466A FF15A4850310 Call dword ptr [100385A4] ;читаем unlocking code
:10004670 B9FFFFFFFF mov ecx, FFFFFFFF
:10004675 2BC0 sub eax, eax
:10004677 F2 repnz ;вычисляем длину
:10004678 AE scasb
:10004679 F7D1 not ecx
:1000467B 49 dec ecx
:1000467C 83F90A cmp ecx, 0000000A ;если не равно
:1000467F 743E je 100046BF ;10 то выдаем
:10004681 A164F20210 mov eax, dword ptr [1002F264] ;сообщение
* Possible StringData Ref from Data Obj ->"Sorry, that unlocking code is "
->"not valid for this program."
:10004686 6818150210 push 10021518

(такая же конструкция находится по адресу 10001F03; какая исполняется очевидно зависит от выбранного способа оплаты) Нам надо поменять условный переход на безусловный т.е.


:1000467F EB3E jmp 100046BF 

и параллельно


:10001F25 7440 je 10001F67 

на


:10001F25 EB40 jmp 10001F67 

Можно конечно и не менять а ввести любую белиберду из 10 знаков Оппа! Вторая часть полученного сообщения наводит на мысль о том, что программа защищена Release Software Agent Но первая часть осталась неизменной Sorry, that unlocking code ...

Что-ж, смотрим далее


* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001FCA(C)
:10002288 A164F20210 mov eax, dword ptr [1002F264]
* Possible StringData Ref from Data Obj ->"Sorry, that unlocking code is"
->"not valid for this program."
:1000228D 6818150210 push 10021518

(аналогичная конструкция по адресу :1000474D).

Посмотрим на условный переход, который нас сюда приносит с адреса 10001FCA


:10001FBA 6860FE0210 push 1002FE60 ;заносим в стек
:10001FBF 51 push ecx ;параметры ф-ции
:10001FC0 E89BDC0100 call 1001FC60 ;вызывается ф-ция
:10001FC5 83C408 add esp, 00000008 ;корректируется стек
:10001FC8 85C0 test eax, eax ;проверяется возвращаемое знач-е
:10001FCA 0F85B8020000 jne 10002288 ;если не 0 то выдаем уже знакомое нам сообщение 

Если посмотреть на ф-цию по адресу 1001FC60, то там можно увидеть


:1001FC60 55 push ebp ;сохраняем индексный регистр
:1001FC61 8BEC mov ebp, esp ;сохраняем позицию стека
:1001FC63 57 push edi
:1001FC64 56 push esi
:1001FC65 53 push ebx
:1001FC66 8B750C mov esi, dword ptr [ebp+0C] ;берем один параметр ф-ции
:1001FC69 8B7D08 mov edi, dword ptr [ebp+08] ;берем другой параметр ф-ции
:1001FC6C 8D05688C0210 lea eax, dword ptr [10028C68]
:1001FC72 83780800 cmp dword ptr [eax+08], 00000000
:1001FC76 753B jne 1001FCB3 ;по этому переходу мы тоже будем проверять строки, но немножко по-другому, очевидно, это зависит от продукта к-рый регистрируем
:1001FC78 B0FF mov al, FF ;загружаем в eax
:1001FC7A 8BC0 mov eax, eax ;начальные данные
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:1001FC88(C), :1001FCA8(C)
:1001FC7C 0AC0 or al, al ;начало цикла сравнения
:1001FC7E 742E je 1001FCAE ;если нечего сравнивать уходим
:1001FC80 8A06 mov al, byte ptr [esi];берем символ из одной строки
:1001FC82 46 inc esi ;увеличиваем счетчик первой строки
:1001FC83 8A27 mov ah, byte ptr [edi];берем символ из другой строки
:1001FC85 47 inc edi ;увеличиваем счетчик второй строки
:1001FC86 38C4 cmp ah, al ;сравниваем
:1001FC88 74F2 je 1001FC7C ;если равно, то на начало цикла
:1001FC8A 2C41 sub al, 41 ;преобразуем в нижний регистр
:1001FC8C 3C1A cmp al, 1A ;один символ
:1001FC8E 1AC9 sbb cl, cl
:1001FC90 80E120 and cl, 20
:1001FC93 02C1 add al, cl
:1001FC95 0441 add al, 41
:1001FC97 86E0 xchg al, ah
:1001FC99 2C41 sub al, 41 ;а теперь другой
:1001FC9B 3C1A cmp al, 1A
:1001FC9D 1AC9 sbb cl, cl
:1001FC9F 80E120 and cl, 20
:1001FCA2 02C1 add al, cl
:1001FCA4 0441 add al, 41
:1001FCA6 38E0 cmp al, ah ;сравним и если равно
:1001FCA8 74D2 je 1001FC7C ;то на начало цикла
:1001FCAA 1AC0 sbb al, al ;если нет, то очищаем al
:1001FCAC 1CFF sbb al, FF ;заносим в al 1
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1001FC7E(C)
:1001FCAE 0FBEC0 movsx eax, al
:1001FCB1 EB6F jmp 1001FD22 ;на выход (в eax результат сравнения) 

Нам надо, чтоб ф-ция выдавала всегда 0 в eax, для этого есть много способов, я выбрал следующий:


:1001FCAC 33C0 xor eax, eax 

В результате ф-ция всегда вернет нам 0 в eax - что нам и надо :))

Патчим rsagnt32.dll, запускаем xmcoder и ... получаем сообщение Application Error : Important application files are missing or corrupted :(( Значит программа вычисляет контрольную сумму rsagnt32.dll. Поищем эту строку в каталоге программы.

Нашли в xmcoder.exe Дизассемблируем его и увидим 2 обращения к этой строке в одной и той же ф-ции, вот ее текст


:004033D0 56 push esi
:004033D1 6A00 push 00000000
:004033D3 6A00 push 00000000
:004033D5 E816FAFFFF call 00402DF0
:004033DA 83C408 add esp, 00000008
:004033DD 83F801 cmp eax, 00000001 ;проверка значения возвращаемого
:004033E0 7433 je 00403415 ;ф-цией если не 1 то получаем MessageBox
:004033E2 6810200000 push 00002010
* Reference To: USER32.MessageBoxA, Ord:0195h
|
:004033E7 8B3548C54200 mov esi, dword ptr [0042C548] ;заносим адрес MessageBoxA в esi и в стек параметры вызова
* Possible StringData Ref from Data Obj ->"Application Error"
|
:004033ED 6884844100 push 00418484
* Possible StringData Ref from Data Obj ->"Important application files are "
->"missing or corrupted."
|
:004033F2 6834844100 push 00418434
:004033F7 6A00 push 00000000
:004033F9 FFD6 call esi ;непосредственно вызов MessageBoxA
:004033FB A100F14100 mov eax, dword ptr [0041F100]
:00403400 50 push eax
:00403401 E86A450000 call 00407970
:00403406 83C404 add esp, 00000004
:00403409 6A00 push 00000000
:0040340B E880870000 call 0040BB90
:00403410 83C404 add esp, 00000004
:00403413 EB06 jmp 0040341B
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004033E0(C)
|
* Reference To: USER32.MessageBoxA, Ord:0195h
|
:00403415 8B3548C54200 mov esi, dword ptr [0042C548] ;в esi заносим адрес MessageBoxA
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00403413(U)
|
:0040341B E8B0E8FFFF call 00401CD0 ;вызов ф-ции
:00403420 85C0 test eax, eax ;проверка возвращаемого значения
:00403422 752B jne 0040344F ;и если eax=0 получаем MessageBox с ошибкой если eax=0 идем на ret
:00403424 6810200000 push 00002010 ;в стек параметры вызова MessageBox'а
* Possible StringData Ref from Data Obj ->"Application Error"
|
:00403429 6884844100 push 00418484
* Possible StringData Ref from Data Obj ->"Important application files are "
->"missing or corrupted."
|
:0040342E 68E4834100 push 004183E4
:00403433 6A00 push 00000000
:00403435 FFD6 call esi
:00403437 A100F14100 mov eax, dword ptr [0041F100]
:0040343C 50 push eax
:0040343D E82E450000 call 00407970
:00403442 83C404 add esp, 00000004
:00403445 6A00 push 00000000
:00403447 E844870000 call 0040BB90
:0040344C 83C404 add esp, 00000004
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00403422(C)
|
:0040344F 33C0 xor eax, eax
:00403451 5E pop esi
:00403452 A3D8F24100 mov dword ptr [0041F2D8], eax
:00403457 A3A0C94100 mov dword ptr [0041C9A0], eax
:0040345C A3DCF24100 mov dword ptr [0041F2DC], eax
:00403461 C3 ret 

Изменим 2 условных перехода на безусловные и запустим xmcoder


:004033E0 EB33 jmp 00403415
:00403422 EB2B jmp 0040344F 

Уверенно жмем Buy now, проходим уже знакомые экранные формы и .... получаем поздравительное рукопожатие (одна из этих рук на картинке точно моя ;)))! Поздравляю! После минутного процесса получаете полнофункциональный XING MPEG Coder. Правда я не проверял - не моя специфика, но все вроде выглядит достоверно :)) 2Release Software Agent: Фуфло гоните ребята! Хоть бы строки зашифровывали!

Подводим итоги :


Xing MPEG Coder cracked by Gas
rsagnt32.crk
1325 74 EB
3A7F 74 EB
1F0AC 1C 33
1F0AD FF C0 

xmcoder.crk
27E0 74 EB
2822 75 EB

P.S. Прошу не ругать за корявый язык написания статьи
Время crack'а=10 min
Время написания статьи = 1 hour
Видите - старался!

Примечание от Zet'а.

Есть еще один метод взлома этой программы. В ассемблерном листинге есть код, загружающий библиотеку RSAGENT32.DLL. Эта библиотека служит для 'защиты' программы. Достаточно найти в листинге вызов, возвращающий статус программы - зарегистрирована/незарегистрирована и поменять соответсвующие переходы так, чтобы программа считала, что она зарегистрирована. Этот метод более общий, а также более простой - изменяем один файл, не надо искать схему, проверяющую целостность файлов.

Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay