3.1.3 В отладчике
Wow! Работает! Теперь вы в SoftICE, в самом начале функции GetDlgItemTextA. Чтобы попасть туда, откуда она была вызвана, нажмите F11. Теперь Вы внутри модуля SGLSET.EXE. Если Вы не уверены - посмотрите на строчку между окном кода и окном командной строки, она должна выглядеть так:
----------SGLSET!.text+1B13----------
Сейчас Вы уже можете запретить реакцию на вызов функции:
:bd 0
Если Вам вдруг захочется снова разрешить ее, наберите:
:be 0
Первая строка в окне кода выглядит так:
CALL [USER32!GetDlgItemTextA]
Чтобы посмотреть строчки над ней, нажимайте Ctrl+Up ("стрелка вверх") до тех пор, пока не увидите нижеприведенный кусок кода. Если Вы ничего не понимаете в Ассемблере, я добавил комментарии которые могут Вам помочь.
RET ; Конец функции
PUSH EBP ; Начало другой функции
MOV EBP, ESP ; ...
SUB ESP, 0000009C ; ...
PUSH ESI ; ...
> LEA EAX, [EBP-34] ; EAX = EBP-34
PUSH EDI ; ...
MOVE ESI, ECX ; ...
PUSH 32 ; Макс. длина строки
> PUSH EAX ; Адрес текстового буфера
PUSH 000003F4 ; Идентификатор управления
PUSH DWORD PTR [ESI+1C] ; Идентификатор окна диалога
CALL [USER32!GetDlgItemTextA] ; Получить текст
Команды PUSH означают сохранение значений для последующего использования.
Я пометил важные строчки символом '>'. Глядя на этот код, мы видим, что адрес текстового буфера хранился в регистре EAX и что EAX был EBP-34h. Поэтому нам стоит взглянуть на EBP-34h:
:d ebp-34
Вы должны были увидеть текст, который вы ввели в диалоговом окне. Теперь мы должны найти место, где Ваш номер сравнивается с реальным серийным номером. Поэтому мы пошагово трассируем программу при помощи F10 до тех пор, пока не встретим что-нибудь о EBP-34. Не пройдет и нескольких секунд, как Вы наткнетесь на следующий код:
> LEA EAX, [EBP+FFFFFF64] ; EAX = EBP-9C
LEA ECX, [EBP-34] ; ECX = EBP-34
PUSH EAX ; Сохраняет EAX
PUSH ECX ; Сохраняет ECX
> CALL 00403DD0 ; Вызывает функцию
ADD ESP, 08 ; Удаляет сохраненную информацию
TEST EAX, EAX ; Проверяет значение функции
JNZ 00402BC0 ; Прыгает, если не "ноль"
Мне кажется, что это выглядит как вызов функции сравнения двух строк.
Эта функция работает так: на входе - две строки, на выходе - 0, если они равны и любое другое значание, если не равны.
А зачем программе сравнивать какую-то строчку с той, что Вы ввели в окне диалога? Да затем, чтобы проверить правильность Вашей строки (как Вы, возможно, уже догадались)! Так-так, значит этот номер скрывался по адресу [EBP+FFFFFF64]? SoftICE не совсем корректно работает с отрицательными числами и поэтому настоящий адрес следует посчитать:
100000000 - FFFFFF64 = 9C
Вы можете сделать это вычисление прямо в SoftICE:
:? 0-FFFFFF64
Число 100000000 слишком велико для SoftICE, а вычитание из 0 дает тот же
самый результат.
Наконец пришло время взглянуть, что же скрывается по адресу EBP-9C...
:d ebp-9c
В окне данных SoftICE Вы видите длинную строчку цифр - это серийный номер!
Но Вы помните, что я говорил Вам раньше? Два типа регистрации - два разных серийных номера. Поэтому после того, как Вы записали на бумажечку первый серийный номер, продолжайте трассировать программу при помощи F10. Мы дошли до следующего куска кода:
> LEA EAX, [EBP-68] ; EAX = EBP-68
LEA ECX, [EBP-34] ; ECX = EBP-34
PUSH EAX ; Сохраняет EAX
PUSH ECX ; Сохраняет ECX
> CALL 00403DD0 ; Снова вызывает функцию
ADD ESP, 08 ; Удаляет сохраненную информацию
TEST EAX, EAX ; Проверяет значение функции
JNZ 00402BFF ; Прыгает если не "ноль"
И что Вы видите по адресу EBP-68? Второй серийный номер!
:d ebp-68
Вот и все... Я надеюсь, что у Вас все получилось как доктор прописал? =)
3.2 Command Line 95 - легкая регистрация "имя-код", создание генератора ключей
Это программа - хороший пример, с легким алгоритмом генерации кода.
3.1.1 "Обследование"
Вы осмотрели программу и увидели, что это 32-битное приложение, требующее имя и код в окне регистрации. Поехали!
3.1.2 Прерывание программы
Мы поступаем так же, как и с Task Lock'ом - ставим брейкпоинты. Можно даже поставить сразу два брейкпоинта на наиболее возможные функции: GetWindowTextA и GetDlgItemTextA. Нажмите Ctrl-D, чтобы вызвать отладчик и наберите в окне команд:
:bpx getwindowtexta
:bpx getdlgitemtexta
Теперь возвращайтесь в прерванную программу, идите в окно регистрации и вводите имя и какой-нибудь номер (обыкновенное целое число - это наиболее вероятный код). Я написал примерно следующее:
Name: ED!SON '96
Code: 12345
Программа остановилась на GetDlgItemTextA. Так же, как и в случае с Task Lock'ом, мы нажимаем F11 чтобы вернуться в вызывающюю функцию. Просматриваем окно кода при помощи Ctrl+Up. Вызов функции выглядит так:
MOV ESI, [ESP+0C]
PUSH 1E ; Максимальная длина
PUSH 0040A680 ; Адрес буфера
PUSH 000003ED ; Идентификатор управления
PUSH ESI ; Идентификатор окна диалога
CALL [User32!GetDlgItemTextA]
Число 40A680 кажется нам интересным, поэтому мы проверяем этот адрес:
:d 40a680
Что же видно в окне данных, как не имя, которое мы ввели? =) А теперь взглянем на кусок кода под вышеприведенным:
PUSH 00 ; (не интересно)
PUSH 00 ; (не интересно)
PUSH 000003F6 ; Идентификатор управления
MOV EDI, 0040A680 ; Адрес буфера
PUSH ESI ; Идентификатор окна диалога
CALL [User32!GetDlgItemInt]
Функция GetDlgItemInt похожа на GetDlgItemTextA, но возвращает не строку, а целое число. Она возвращает его в регистре EAX, поэтому мы трассируем этот код (F10) и смотрим, что же у нас появилось в окне регистров после вызова функции... В моем случае оно выглядит так:
EAX=00003039
А что такое шестнадцатеричное 3039? Наберем:
:? 3039
И получим следующее:
00003039 0000012345 "09"
^ hex ^ dec ^ ascii
Как Вы видите (и, возможно, уже догадались) это код, который Вы ввели в диалоговом окне. Ok, что теперь? Посмотрим дальше:
MOV [0040A548], EAX ; Сохраняет рег. код
MOV EDX, EAX ; А также помещает его в EDX
0 комментариев