Взлом
TDC’s CrackME #6 Password Protection.
Автор:
@
Pest
Всем привет! Это
мой первый (и надеюсь не последний)
тутор, поэтому не судите строго, а к
опытным кракерам просьба не смеяться…
Дано:
очень простой крякмис (найти можно
здесь: http://www.reversing.be/index.php?topic=crackmes&page=2
).
Найти:
один единственный верный пароль,
который вводим в поле Password
:-D. НЕ
ПАТЧИТЬ!
Инструменты:
Olly
Debugger.
Перед копанием в коде я всегда
осматриваю прогу на предмет
запакованности с помощью PEid.
В этот раз он ничего не показал, но
посмотрев прогу в Restorator’е
(можно ResHacker)
я понял, что она не пакована и написана
на ассемблере.
Все это очень хорошо, поэтому
запускаем Ольку и грузим в нее нашу
подопытную. Жмем Ctrl+N
и смотрим, какими функциями
пользуется крякмис. Нам нужна та, что
читает содержимое окон. Ищем GetWindowTextA
или GetDlgItemTextA(стандартные
функции чтения содержимого окна).
Находим GetDlgItemTextA,
кликаем на этой строке левой кнопкой
крысы, затем правой и выбираем Set
breakpoint
on
every
reference.
Таким образом, мы установили точку
останова(breakpoint). Закрываем окно c заголовком Name
in
<имя проги> и нажимаем F9(или
кнопку с синим треугольником). Мы
запустили крякмис на исполнение.
Вводим в поле Password
строку 1234567890 и жмем Check.
Ага! Прога прервалась на вызове
функции GetDlgItemTextA.
Жмем F8,
пока не дойдем до этого места:
004010B3
. 84C0
TEST AL,
AL
; Если поле Password
пустое,
004010B5
. 74 5D
JE SHORT pass.00401114 ;то
перейти по адресу 00401114
004010B7 .
3C
0D CMP AL,0D
;Если длина строки равна или
больше 13,
004010B9
. 74 59
JE SHORT pass.00401114 ;то
перейти по адресу 00401114
004010BB . E8
B0000000 CALL
pass.00401170 ;
What is it!?
В последней строке
идет вызов какой-то нестандартной
функции. Нажимая F7
заходим в эту функцию и смотрим, что
она делает:
00401170 $
BAE0314000 MOV EDX, pass.004031E0
; ASCII "1234567890"
00401175 > 8A0A MOV CL, BYTE PTR DS:[EDX]
00401177 . 84C9 TEST CL, CL
00401179 . 74 0D JE SHORT pass.00401188
0040117B . 80F9 30 CMP
CL, 30
0040117E .
7C
63 JL SHORT pass.004011E3
00401180 . 80F9 39 CMP CL, 39
00401183 . 77 5E JA SHORT pass.004011E3
00401185 . 42
INC
EDX
00401186 .^EB ED JMP SHORT pass.00401175
В этом куске
происходит проверка пароля на то, что
он состоит только из чисел. Если это не
так, то нехорошо, иначе все ОК и
продолжаем дальше:
00401188
> BAE0314000
MOV EDX, pass.004031E0
; ASCII "1234567890"
0040118D > 8A0A
MOV CL, BYTE PTR DS:[EDX]
0040118F
. 84C9 TEST CL,
CL
00401191 . 74 21
JE SHORT
pass.004011B4
00401193 . F6D1 NOT CL
00401195 . 66:C1E1
08 SHL CX, 8
00401199 . 80F5 FA
XOR CH,
0FA
0040119C
. 80F5 34
XOR CH, 34
0040119F
. F6D5
NOT CH
004011A1 . 80F5 21
XOR CH, 21
004011A4 . F6D5
NOT CH
004011A6 . 80F5 FA
XOR CH, 0FA
004011A9 . 66:C1E9
08 SHR
CX, 8
004011AD . F6D1
NOT CL
004011AF . 880A MOV BYTE PTR DS:[EDX],CL
004011B1 . 42 INC EDX
004011B2. ^EB D9 JMP SHORT pass.0040118D
Этот кусок
генерирует символьное представление
из введенного нами пароля, а затем
происходит сравнение полученной
строки с правильной:
004011B4 > 68
E0314000 PUSH
pass.004031E0 ;String = "$'&! #"-,%";0
004011B9 .E8
6C000000 CALL
<JMP.&kernel32.lstrlenA>
004011BE .BA E0314000
MOV EDX, pass.004031E0 ; ASCII "$'&! #"-,%"
004011C3 .813A
2621242C
CMP DWORD PTR DS:[EDX],2C242126
;1
004011C9 .75 18
JNZ
SHORT pass.004011E3
004011CB .817A 04 >CMP
DWORD PTR DS:[EDX+4],20222D24 ;2
004011D2 .75
0F
JNZ SHORT
pass.004011E3
004011D4 .66:817A
>CMP
WORD PTR DS:[EDX+8],2724 ;3
004011DA .75 07
JNZ SHORT
pass.004011E3
004011DC .B8 01000000
MOV EAX, 1
004011E1 .EB 04
JMP SHORT
pass.004011E7
004011E3 > 33C0 XOR EAX, EAX
004011E5 .EB 00
JMP SHORT
pass.004011E7
004011E7 > C3 RETN
В строке №0
содержится символьное представление
нашего пароля, а в строках №1,№2,№3 –
правильного пароля. Смотрим в ASCII-таблицу
и находим, что в строке №1 содержится
“ &!$, ” в строке №2 – “ $-“пробел ” в
строке №3 – “ $’ ”. В уме составляем
следующую таблицу из чисел пароля и
соответсвующих им символов
полученного символьного
представления:
Число
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
0
|
Символ
|
$
|
‘
|
&
|
!
|
пробел
|
#
|
“
|
-
|
,
|
%
|
Теперь смотрим, что
на самом деле было в строках №1, №2 и
№3:
№1 -> 3419
№2 -> 1875
№3 -> 12
Вводим эти числа в
поле для пароля друг за другом без
пробелов и вот ОНО, сообщение об
успешной регистрации, тьфу, то есть о
верном пароле!!!
Ответ:
3419187512.
В принципе «задачку» можно было
решить несколько иначе, пропустив
символьное представление правильного
пароля через функцию генерации этих
символов, но, перевернув ее, т.е. начать
с конца процесс генерации. Однако мне
понравилось то, как я сделал «решение».
Цель достигнута!
Если я в чем-то ошибся, то
напишите мне, пожалуйста, сюда Pest_87
[@] mail.ru.
До
новых встреч ;-D!!!
© @
Pest,
2006
|