Нахождение ключей для 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-сектора
|