| |
SoftIce для начинающих
Тебе
никогда не хотелось иметь у себя программу, с помощью которой можно ломать
игрушки, shareware и trial программы и вообще все, что запускается на компьютере?
Я думаю, что хотелось. А такая программа существует! И уже достаточно давно.
Это SoftICE от NuMega Software. Просто считается, что ее использование это
удел избранных программистов, разбирающихся в архитектуре процессора, устройстве
железа, в ассемблере и принципах действия операционных систем. Но на самом
деле и минимальных знаний достаточно для работы с этой программой. Сначала
введу тебя в курс дела.
SoftICE является самым мощным отладчиком на сегодняшний день (т.е. прогой,
которая может разобрать по кирпичику любую другую прогу и каждый этот кирпичик
изменить как захочется). А это значит, что с его помощью можно исследовать
все: от ядра Windows до программ на С++. Создавался он для отладки 32-битных
приложений, драйверов под Win NT и Win 95/98 и других программ под Win и
Dos (так по крайней мере говорят его разработчики ;). Но люди со всего мира
нашли ему дополнительное применение :)) Ведь что собой представляет какая-нибудь
Trial-программа? Не что иное, как 32-битное WIN приложение. А ее отладка?
Правильно - устранение защиты: или проверки времени, или проверки наличия
Key-файла, или еще чего-нибудь.
В связи с тем, что многие программы уже были взломаны с помощью SI, производители
ПО стали вшивать в свои творения части кода, проверяющие наличие SI в системе
и, в случае его обнаружения, не дающие программе вообще работать (они думали,
что это поможет, - вот наивные!). Поэтому тебе могут понадобиться несколько
программ, скрывающих этот отладчик от чужих глаз. Я тебе советую посетить
сайт www.dore.ru, а точнее его отдел www.dore.ru/files/debuggers, где представлено
много полезных прог, а именно сам SI под WIN 95/98 и под WIN NT, примочки,
мешающие другим прогам определить наличие SI в системе, дополнительные плагины
к нему, делающие работу с ним приятнее и удобнее. Если же тебе нужен SOFTICE
для Win ME, Win 2000 или Win XP, то перепиши соответствующий апдейт с сайта
производителя: www.numega.com/drivercentral/icecentral.asp. Под каждым апдейтом
написано, как его устанавливать. Итак, если у тебя уже есть проинсталлированный
SoftICE, можешь пропустить следующий раздел, если нет, то прими его к сведению.
Установка
В установке нет ничего сложного, просто после нее НАДО ВНЕСТИ ИЗМЕНЕНИЯ
в файл winice.dat (он должен находиться в каталоге, куда ты установил SI),
а именно раскомментировать в нем несколько строк:
; ***** Examples of export symbols that can be included for Windows 95 *****
;Change the path to the appropriate drive and directory
EXP=c:\windows\system\kernel32.dll - эти;
EXP=c:\windows\system\user32.dll - строки надо;
EXP=c:\windows\system\gdi32.dll - раскомментировать;
Это нужно для того, чтобы видеть имена Win API функций (стандартные функции,
используемые программами при работе под Win). А именно на них мы и будем
ловить программы, но об этом позже.
Что реально может делать SoftICE и как им управлять?
Вообще SoftIce состоит из нескольких окон: регистров, данных, кода и команд.
В окне кода ты видишь текст программы на ассемблере, а в окно команд вводишь
команды управления SI. Перемещаться между окнами удобно с помощью мышки,
но можно и без нее, хотя это сложновато для начала.
Основные команды (очень важный момент)
BPX адрес/имя функции - установить в указанный адрес или на вызов функции
точку останова (еще ее называют брэйк опинтом).
BPM адрес - установить точку останова на адрес памяти.
BL - вывести список всех установленных точек останова (каждая имеет свой
номер).
BD номер точки останова - сделать точку с соответствующим номером не активной.
BE номер точки останова - команда, обратная предыдущей.
BC номер точки останова - удалить точку останова.
Фактически, другие команды нам с тобой не понадобятся. Итак, с помощью SI
можно заморозить все программы в любой момент (например, будет вызвана стандартная
функция или выполнена команда по определенному адресу). Когда ты взламываешь
прогу, тебя можно сравнить с хирургом, ковыряющимся во внутренностях человека,
твой компьютер - с операционным столом, а SI - со скальпелем, ножницами
и наркозом.
Если ты хочешь сломать какую-то программу, то твоя основная задача состоит
в том, чтобы узнать, в какой момент нужно вызвать SI (если продолжить аналогию,
то в каком месте резать :), и поковыряться в программе-пациентке. Поэтому
нам с тобой потребуется установить ловушки, чтобы поймать в них программу,
когда она либо сравнивает твой серийный номер с правильным, либо смотрит,
какое сегодня число (чтоб сказать: "Ага! Срок моего действия истек.
Зарегистрируйся, а то я обижусь и не буду работать!").
Ловушки. И собственно сам взлом
Итак, нам надо выбрать момент, когда перехватить управление у программы.
Проще всего ломаются проги, использующие Win API функции. (Это стандартные
функции, облегчающие программирование под WIN. Например, если тебе нужно
создать окно на рабочем столе, то ты просто вызываешь какую-то функцию с
параметрами, а не пишешь код, создающий окно с нуля.) То есть тебе нужно
будет определить, на вызов какой из этих функций будет реагировать SI. Алгоритм
твоих действий должен быть следующим:
1. Решить, на что ты будешь ловить свою программу. На какую API функцию.
2. Установить на ее вызов точку останова (bpx имя функции).
3. Запустить свою прогу и спровоцировать вызов этой функции.
4. Нажав F11, перейти к тому месту в программе (на тот адрес), откуда она
вызывалась.
5. Установить точку останова на выполнение команд строки с этим адресом.
6. Снова спровоцировать вызов этой функции.
7. Просмотрев регистры, узнать необходимые тебе данные (к примеру, серийный
номер) или адрес той строки, в которой обрабатываются результаты вызова
функции (это могут быть какие-либо команды ассемблера: cmp или jump).
8. Запустив HIEW или что-то похожее, внести необходимые изменения (cmp можно
заменить пустой командой nop, а какую-нибудь разновидность команды условного
перехода - на безусловный jmp и тот же адрес). Именно из-за последних нескольких
пунктов считается, что знание ассемблера является очень желательным при
работе с SI.
Самыми часто используемыми Win API функциями являются:
MessageBoxIndirect - работа с окном сообщений. Используется в 16-битных
приложениях.
MessageBox - работа с окном сообщений. Используется в 16-битных приложениях.
MessageBoxA - то же самое, но 32-битное приложение.
MessageBoxIndirectA - то же самое, что и MessageBoxIndirect, но 32-битное
приложение.
GetWindowText - обычная строка ввода типа Windows Edit. Используется в 16-битных
приложениях.
GetWindowTextA - то же самое, но 32-битное приложение. Строки используются
однобайтовые.
GetDlgItemText - примерно то же, что и предыдущая функция, отличия в деталях.
Используется в 16-битных приложениях.
GetDlgItemTextA - то же самое, но 32-битное приложение. Строки используются
однобайтовые.
Следует заметить, что GetWindowTextA и MessageBoxA очень часто используются
при проверке серийного номера. Перед взломом рекомендую посмотреть свойства
ломаемой программы и выяснить ее разрядность (щелкни на ее ярлыке правой
кнопкой мыши, появится окно Свойств, там в левом верхнем углу обычно написано
"16" или "32 бит", это и есть разрядность приложения).
Практика
Вроде теорию я тебе всю изложил. Теперь практика: классический пример. Возможно,
пример немного трудноват, но даже если ты запомнишь хотя бы малую часть,
то сможешь почувствовать себя настоящим хирургом-маньяком, ищущим себе все
новые и новые жертвы. Итак прога-пациент называется TaskLock. Будем ловить
на GetWindowTextA (команда ":bpx getwindowtexta"). Ты можешь проверить,
установилась ли точка останова командой ":bl". В результате увидишь
что-нибудь типа: "00) BPX USER32!GetWindowTextA C=01". Далее жми
F5. Продолжим. Попробуй ввести какое-нибудь значение в окне регистрации
и нажми OK. Ты получишь дурацкое сообщение о том, что код был неправильным.
Значит, это была не функция GetWindowTextA. Попробуем GetDlgItemTextA. Удали
старый брейкпоинт ":bc 0" (0 - это номер брейкпоинта в списке
брейкпоинтов) и установи новый ":bpx getdlgitemtexta". Вводи номер
заново. Теперь ты в SoftICE, в самом начале функции GetDlgItemTextA. Чтобы
попасть туда, откуда она была вызвана, нажми F11. Теперь ты внутри модуля
SGLSET.EXE. Сейчас ты уже можешь запретить реакцию на вызов функции ":bd
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? Второй серийный номер! Вот и все...
|