Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Нахождение ключей для JPEG Optimizer v2.02 (взлом без Soft-Ice)

Автор: Fess
WEB сайт: vallkor.chat.ru

Target: JPEG Optimizer v2.02

Tools:
Some brains
Win32Dasm 8.93

Все, кроме мозгов, можно найти на www.exetools.com

Вступление

Как это начиналось:

Принесли мне компакт от какой-то книги издательства Питер, кажется книга про Web. Там валялись всякие проги для работы с графикой и html, не долго думая, я решил скопировать все это на свой хард, чтобы потом поразобраться...

Спустя неделю ко мне в руки попал компакт с огромным количеством картинок в формате jpg. При не очень большом разрешении их размер достигал 500 кило, и это меня не обрадовало. Их было так много, что я сразу отбросил мысль об использовании IrfanView'а (очень рулезная прога, всем рекомендую www.irfanview.com). Тут я вспомнил о компакте, где были проги для работы с графикой, а точнее оптимизаторы. Так я вышел на эту прогу. К моему сожалению, она просила за регистрацию $29 и это была ее главная ошибка. Приступаем

Что за прога:

Очень хорошая прога для сжатия графики, позволяет обрабатывать файлы в автоматическом режиме. Короче мне понравилась, я ее себе даже русифицировал, если кому интересно, то напишите на мыло. Размер в архиве примерно 400Kb. Единственный недостаток - регистрация, который мы сейчас исправим.

Начало

Взглянув на ресурсы, я понял, что программа написана на Delphi и это хорошо (присутствуют bmp файлы всегда вставляющиеся Delphi). Запускаем ее, заходим в раздел Register и вводим произвольный пароль. На это нам выплевывается надпись Incorrect Registration Code. Это будет главная зацепка.

Кидаем программу в Win32Dasm. И в секции строк ищем нашу. Нашли. Нажимаем на нее два раза и оказываемся тут


:00427F8E 50            push eax
:00427F8F FF4E1C        dec [esi+1C]
:00427F92 8D45F8        lea eax, dword ptr [ebp-08]
:00427F95 BA02000000    mov edx, 00000002
:00427F9A E891D10100    call 00445130
:00427F9F 59            pop ecx
:00427FA0 84C9          test cl, cl
:00427FA2 0F84B7000000  je 0042805F
:00427FA8 66C746102C00  mov [esi+10], 002C

* Possible StringData Ref from Data Obj ->"JPEG Optimizer"
                           |
:00427FAE BA6D9B4700    mov edx, 00479B6D
(всякий мусор выкинут)
:00427FF0 8D4DEC        lea ecx, dword ptr [ebp-14]

* Possible StringData Ref from Data Obj ->"Code"
                           |
:00427FF3 BA7C9B4700    mov edx, 00479B7C
(здесь выкинут код отвечающий за запись правильного кода в реестр)
:00428040 8BC3          mov eax, ebx
:00428042 E8054A0200    call 0044CA4C
:00428047 6A40          push 00000040

* Possible StringData Ref from Data Obj ->"Message"
                           |
:00428049 B9AA9B4700    mov ecx, 00479BAA <- Выводится сообщение о правильной регистрации.

* Possible StringData Ref from Data Obj ->"Thank you for registering JPEG "
                                       ->"Optimizer"
                            |
:0042804E BA819B4700    mov edx, 00479B81
:00428053 A104F54700    mov eax, dword ptr [0047F504]
:00428058 E843A80300    call 004628A0
:0042805D EB16          jmp 00428075

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00427FA2(C) <- Вот оттуда переход на првильный или неправильный
|
:0042805F 6A30          push 00000030

* Possible StringData Ref from Data Obj ->"Error"
                                  |
:00428061 B9CE9B4700    mov ecx, 00479BCE

* Possible StringData Ref from Data Obj ->"Incorrect Registration Code"
                                 |
:00428066 BAB29B4700    mov edx, 00479BB2
:0042806B A104F54700    mov eax, dword ptr [0047F504]
:00428070 E82BA80300    call 004628A0

Вроде бы проверка в процедуре call 445130. Но меня смутила строка 427F9F (она выделена). А потом я просек в чем дело, взглянув чуть выше, строка 427F8E. Я уж не знаю, сами ли программеры решили так нас обмануть, а может компилятор. Скорее всего второе. Теперь смотрим повыше


:00427F75 BA6C9B4700  mov edx, 00479B6C

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00427F73(U)
|
:00427F7A 52         push edx
:00427F7B E8380A0000 call 004289B8
:00427F80 59         pop ecx
:00427F81 84C0       test al, al     <- Проверяем
:00427F83 7504       jne 00427F89    <- Если все тип-топ (al<>0), то переход

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00427F68(C)
|
:00427F85 33C0       xor eax, eax
:00427F87 EB05       jmp 00427F8E

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00427F83(C)
|
:00427F89 B801000000 mov eax, 00000001

Что ж идем в процедуру и попробуем разобраться в коде.


:004289B8 55       push ebp
:004289B9 8BEC     mov ebp, esp
:004289BB 83C4F8   add esp, FFFFFFF8
:004289BE 53       push ebx
:004289BF 8B4508   mov eax, dword ptr [ebp+08]
:004289C2 8D5DF8   lea ebx, dword ptr [ebp-08]
:004289C5 8A10     mov dl, byte ptr [eax]     <-
:004289C7 8813     mov byte ptr [ebx], dl     <-
:004289C9 8A4801   mov cl, byte ptr [eax+01]  <-
:004289CC 884B01   mov byte ptr [ebx+01], cl  <-
:004289CF 8A5002   mov dl, byte ptr [eax+02]  <-
:004289D2 885302   mov byte ptr [ebx+02], dl  <- Копируем 6 байт регистрационного кода
:004289D5 8A4803   mov cl, byte ptr [eax+03]  <- в другое местов оперативной памяти
:004289D8 884B03   mov byte ptr [ebx+03], cl  <-
:004289DB 8A5004   mov dl, byte ptr [eax+04]  <-
:004289DE 885304   mov byte ptr [ebx+04], dl  <-
:004289E1 8A4005   mov al, byte ptr [eax+05]  <-
:004289E4 884305   mov byte ptr [ebx+05], al  <-
:004289E7 0FBE0B   movsx ecx, byte ptr [ebx]  <-
:004289EA 51       push ecx
:004289EB E8AC240400  call 0046AE9C
:004289F0 59       pop ecx
:004289F1 83F851   cmp eax, 00000051  <- Проверка кода 1 символа пароля с кодом буквы Q
:004289F4 7544     jne 00428A3A       <- Если не правильно, то переход
:004289F6 0FBE4301 movsx eax, byte ptr [ebx+01]
:004289FA 50       push eax
:004289FB E89C240400  call 0046AE9C
:00428A00 59       pop ecx
:00428A01 83F84F   cmp eax, 0000004F  <- Проверка кода 2 символа пароля с кодом буквы O
:00428A04 7534     jne 00428A3A       <- Если не правильно, то переход
:00428A06 0FBE5302 movsx edx, byte ptr [ebx+02]
:00428A0A 83FA37   cmp edx, 00000037  <- Проверка кода 3 символа пароля с кодом символа 7
:00428A0D 752B     jne 00428A3A       <- Если не правильно, то переход
:00428A0F 0FBE4B03 movsx ecx, byte ptr [ebx+03]
:00428A13 83F930   cmp ecx, 00000030  <- Проверка кода 4 символа пароля с кодом символа 0
:00428A16 7522     jne 00428A3A       <- Если не правильно, то переход
:00428A18 0FBE4304 movsx eax, byte ptr [ebx+04]
:00428A1C 83F831   cmp eax, 00000031  <- Проверка кода 5 символа пароля с кодом символа 1
:00428A1F 7519     jne 00428A3A       <- Если не правильно, то переход
:00428A21 0FBE5305 movsx edx, byte ptr [ebx+05]
:00428A25 83FA32   cmp edx, 00000032  <- Проверка кода 6 символа пароля с кодом символа 2
:00428A28 7510     jne 00428A3A       <- Если не правильно, то переход
:00428A2A C605F0EC470001 mov byte ptr [0047ECF0], 01
:00428A31 E85AAEFDFF  call 00403890
:00428A36 B001      mov al, 01  <- Вроде как код введен правильно
{В итоге для того, чтобы пройти эту проверку нужно написать код QO7012}
:00428A38 EB18      jmp 00428A52

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004289F4(C), :00428A04(C), :00428A0D(C), :00428A16(C), :00428A1F(C)
|:00428A28(C)
|
:00428A3A 53       push ebx
:00428A3B E8501A0000  call 0042A490
:00428A40 59       pop ecx
:00428A41 84C0     test al, al
:00428A43 7404     je 00428A49
:00428A45 B001     mov al, 01
:00428A47 EB09     jmp 00428A52

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00428A43(C)
|
:00428A49 C605F0EC470000 mov byte ptr [0047ECF0], 00
:00428A50 33C0     xor eax, eax

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00428A38(U), :00428A47(U)
|
:00428A52 5B       pop ebx
:00428A53 59       pop ecx
:00428A54 59       pop ecx
:00428A55 5D       pop ebp
:00428A56 C3       ret

И вроде бы, код найден, но меня заинтересовала процедура call 0042A490 (она выделена). После нее AL тоже устанавливается в единицу. И я решил проверить.


:0042A490 55      push ebp
:0042A491 8BEC    mov ebp, esp
:0042A493 53      push ebx
:0042A494 8B5D08  mov ebx, dword ptr [ebp+08] <- В ebx адрес памяти с введенным кодом
(какой-то мутный код)
:0042A4B1 33D2    xor edx, edx <- Обнуляем edx
:0042A4B3 8BC3    mov eax, ebx <- В eax указатель на введенный код

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0042A4BD(C)
|
:0042A4B5 803093   xor byte ptr [eax], 93 <- Ксорим все символы введеного кода с 93h
:0042A4B8 42       inc edx                <- Увеличиваем счетчик
:0042A4B9 40       inc eax                <- Увеличиваем указатель
:0042A4BA 83FA06   cmp edx, 00000006      <- Сравниваем счетчик с 6
:0042A4BD 7CF6     jl 0042A4B5            <- Если меньше, то повторяем цикл
:0042A4BF 0FBE0B   movsx ecx, byte ptr [ebx]  <- Берем 1 символ отxorенного кода
:0042A4C2 83F9D8   cmp ecx, FFFFFFD8          <- Сравниваем с
:0042A4C5 7545     jne 0042A50C               <- Если не равно, то в пролете
{Значит надо, чтобы было равно этим мы вычислим символ, который надо написать в коде,
можно, конечно, попробовать угадать в дебаггере или написать программу, но мы попробуем
посчитать все в ручную. Как, надеюсь, вам известно, что функция xor обратима, поэтому
ее часто используют для шифрования. Функция устанавливаем бит в единицу, если один
операнд единица, а второй ноль, иначе будет ноль. Переводим 93h в двоичную систему,
это можно сделать с помощью простого виндового калькулятора, можно тетрадами, а можно
в ручную.
93h - 10010011           93h - 10010011            93h - 10010011
D8h - 11011000           D9h - 11011001            A4h - 10100100
--------------           --------------            --------------
      01001011 -> 4Bh(K)       01001010 -> 4Ah(J)        00110111 - 37h(7)
и так далее. В итоге получаем KJ7246}
:0042A4C7 0FBE4301 movsx eax, byte ptr [ebx+01]
:0042A4CB 83F8D9   cmp eax, FFFFFFD9
:0042A4CE 753C     jne 0042A50C
:0042A4D0 0FBE5302 movsx edx, byte ptr [ebx+02]
:0042A4D4 83FAA4   cmp edx, FFFFFFA4
:0042A4D7 7533     jne 0042A50C
:0042A4D9 0FBE4B03 movsx ecx, byte ptr [ebx+03]
:0042A4DD 83F9A1   cmp ecx, FFFFFFA1
:0042A4E0 752A     jne 0042A50C
:0042A4E2 0FBE4304 movsx eax, byte ptr [ebx+04]
:0042A4E6 83F8A7   cmp eax, FFFFFFA7
:0042A4E9 7521     jne 0042A50C
:0042A4EB 0FBE5305 movsx edx, byte ptr [ebx+05]
:0042A4EF 83FAA5   cmp edx, FFFFFFA5
:0042A4F2 7518     jne 0042A50C
:0042A4F4 C605F0EC470001  mov byte ptr [0047ECF0], 01
:0042A4FB C60500F4470001  mov byte ptr [0047F400], 01
:0042A502 E88993FDFF       call 00403890
:0042A507 B001     mov al, 01 <- Если все хорошо
:0042A509 5B       pop ebx
:0042A50A 5D       pop ebp
:0042A50B C3       ret

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0042A4C5(C), :0042A4CE(C), :0042A4D7(C), :0042A4E0(C), :0042A4E9(C)
|:0042A4F2(C)
|
:0042A50C 33C0     xor eax, eax  <- здесь не есть хорошо
:0042A50E 5B       pop ebx
:0042A50F 5D       pop ebp
:0042A510 C3       ret

Ну вот и все, найдены два кода QO7012 и KJ7246. Чем они отличаются, честно говоря не знаю. Но все-таки думаю, что второй код приоритетней, т.к. он был замудрован посильнее первого (хотя и не очень сильно).

Спасибо за интерес к моему творчеству!

Удачи в Reversing Engeneering!

Послесловие

Спасибо авторам за предоставленный для исследования продукт. Он мне очень помог при переделывании картинок.

Господа Авторы: "Худшая защита месяца" только так можно охарактеризовать то, что я увидел в этой программе. Перед тем, как делать защиту можно было и почитать мануалы, написанные в этом направлении. Извините меня, но $29 для России это не дела. Крэкеров в Росии много. Россия рулез!

Братья Крэкеры: Не стоит сильно ругать авторов, они там за бугром не ведают, что творят.

Автор: Fess
Все ругательства отправлять в null
Все остальное на lomovskih@yandex.ru

P.S. Запомните все материалы публикуются только в учебных целях и автор за их использование ответственности не несет!!

P.P.S. Возможно имеют место опечатки, заранее извините!

Самые последние мои статьи можно найти на vallkor.chat.ru

With best wishes Fess Member of the group PTDS

И да пребудет с вами великий дух bad-сектора

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