Минимум SoftICe

Статья предоставлена TEAM | TSRh

Эта полезная прога облегчает
жизнь и программерам, и кракерам, которая
является продвинутым отладчиком,
работающим в RING0. Для нормальной работы тебе
необходимо знание ASM-a (рекомендую книгу"Assembler"
Зубкова С.В.).
Начнем с установки. При инсталляции SoftIce (рабочая
версия 4.0) добавит себя в autoexec. Для
активизации SoftIce, нужно нажать Ctrl + D -
увидишь консоль. Чтобы закрыть главное меню
и вернуться в систему, следует нажать F5.
Главное окно SoftIce состоит из нескольких
подокон, предназначенных для отображения
кода, дампа памяти, состояния регистров и т.д.
Все эти окна можно включать и выключать. Вот
несколько команд (чтобы получить краткую
справку по командам, надо набрать H или HELP):

WD - (on/off) окно данных
WC - (on/off) окно кода
WR - (on/off) окно состояния регистров
процессора
WF - (on/off) окно стека сопроцессора
WL - (on/off) окно локальных переменных
LINES n_of_lines - установка количества линия на
экране (25-128)
WIDTH n_of_col - установка количества столбцов на
экране (60-160)
SET ORIGIN x,y - установка левого верхнего гланого
окна в позицию x, y
Ctrl+Alt+стрелки - перемещение главного экрана
Ctrl+Alt+Home - перемещение в левый верхний угол
экрана
Ctrl+Alt+C - перемещение в центр
Ctrl+стрелки - прокрутка окна кода
Alt+стрелки - прокрутка окна данных

Теперь команды, который используются в
работе:

F1 - Help
F4 - показать содержимое экрана Windows
F5 - выйти
F6 - перевести курсор в окно кода или из него
F7 - выполнить команды от текущей строки до
курсора
F8 - трассировка с заходом в функцию
F9 - контрольная точка в текущей строке
F10 - трассировка без заходя в функцию
F12 - выполнить команды до ret

BPX xxx - поставить точку прерывания на адрес,
функцию API

BPM yyy - поставить точку прерывания на
обращение по адресу yyy памяти

BL - список всех установленных BP (Break Point)

BD n_of_bp - деактивировать BP

BE n_of_bp - активизировать BP

BC n_of_bp - удалить BP

n_of_bp - номер BP, который можно узнать командой
BL.

D addr - отобразить в окне данных память,
начиная с addr

DB,DW,DT,DD,DD - разновидности команды D,
отличающиеся только форматом отображения.

A addr - заменить команду по указанному адресу
в памяти

S нач_адресс L длина_поиска "образец" -
поиск указанного образца в памяти (образец
может быть как последовательность байт (без
кавычек), так и строкой символов, но в таком
случае она должна заключаться в кавычки.

Работа всех Windows-приложений основана на
вызове API-функций. Это очень удобно и
выгодно. Например, для вывода окна
сообщения с некоторым текстом достаточно
вызвать функцию MessageBoxA с адресом выводимой
строки в качестве аргумента. Замечательной
особенностью SoftICE является то, что Вы можете
устанавливать точки прерывания на вызовы
API-функций. Установив точку прерывания на
некоторую строку программы, Вы сообщаете
SoftICE, что при достижении этой строки
программа должна прервать свое выполнение
и возвратить управление отладчику.
Например, Вы установили точку прерывания на
выполнение команды по адресу 40А00020, а затем
запускаете программу с адреса 40А00000. Дойдя
до строки с адресом 40А00020, программа
прервется, управление вновь вернется в SoftICE,
и Вы сможете узнать содержимое регистров
процессора, участков памяти, а также, при
необходимости, что-то изменить. Точка
прерывания на вызов API-функции
устанавливается точно так же, как и на
выполнение команды по определенному адресу.
При вызове функции программа прерывается в
самом ее начале, и после этого Вы можете
выполнить необходимые Вам действия. Обычно
точку прерывания на вызов API-функции
устанавливают, когда хотят узнать, из
какого места программы она вызывается.
Допустим, в программе имеется следующий
фрагмент:

некоторый код
...

40200100 call MessageBoxA

40200105 cmp eax, 01

...
продолжение программы

Вы точно знаете, что вызывается функция
MessageBoxA, но не знаете, что это происходит по
адресу 40200100h. Для того, чтобы это выяснить мы
должны проделать следующее:
-- Активизируем SoftICE (Ctrl+D)
-- Устанавливаем точку прерывания на вызов
функции MessageBoxA (bpx MessageBoxA). При этом
происходит следующее: SoftICE устанавливает
точку прерывания на выполнение первой
команды указанной функции
-- Выходим в Windows (F5)
-- Выполняем те действия, в результате
которых произойдет вызов функции MessageBoxA
-- При вызове этой функции (сообщение в окне
команд) программа прерывается в модуле USER (указано
в низу окна кода) и активизируется SoftICE, при
этом курсор установлен на первой команде
функции MessageBoxA. Чтобы узнать, из какого
места произошел ее вызов, используем
команду p ret (быстрая клавиша F12) -
продолжение программы до выполнения
команды ret (команда возврата из
подпрограммы)
-- После этого, программа вновь прерывается
по адресу 40200105 (на этой строке установлен
курсор), а на предыдущей строке мы видим, что
происходит вызов MessageBoxA. Вот мы и нашли то
место, откуда вызывается функция MessageBoxA

Немного о Регистрах.

Регистры является составной частью
процессора. Они используются для
временного хранения информации.
Интенсивное использование регистров в
программе определяется тем, что скорость
доступа к ним намного больше, чем к ячейкам
памяти. 32-х битные процессоры имеют 16
регистров. Мы рассмотрим лишь основные и
наиболее часто используемые из них:
регистры общего назначения, указатель
инструкций, регистры сегментов и регистр
флагов.

Регистры общего назначения
32-х битные регистры общего назначения eax, ebx,
ecx, edx, esi, edi, ebp и esp могут хранить следующие
типы данных:
- Операнды для логических и арифметических
операций
- Операнды для рассчета адресов
- Указатели на ячейки памяти

Хотя для хранения операндов, результатов
операций и указателей Вы можете
использовать любой из вышеперечисленных
регистров, будте осторожны с регистром esp. В
нем хранится указатель вершины стека и
некорректное изменение этого значения
приведет к неправильной работе программы и
ее аварийному завершению.

Многие команды используют конкретные
регистры для хранения своих операндов.
Например, команды обработки текстовых
строк используют содержимое регистров ecx, esi
и edi в качестве операндов.

Основные случаи использования регистров
общего назначения:
- eax - используется для хранения операндов и
результатов операций
- ebx - как указатель на данные в сегменте ds
- ecx - как счетчик для строковых операций и
циклов
- edx - указатель для ввода/вывода
- esi - указатель на данные в сегменте ds, а
также как указатель на источник в командах
работы со строками
- edi - указатель на данные в сегменте es, а
также как указатель на приемник в командах
работы со строками
- esp - указатель вершины стека в сегменте ss
- ebp - указатель на некоторые данные в стеке

В регистрах, оканчивающихся на x, можно
обращаться к младщим 16-и битам (ax, bx, cx и dx
соответственно), которые в свою очередь
можно разделить на старший байт (ah, bh, ch и dh) и
младший (al, bl, cl и dl) и работать с ними, как с
регистрами длиной 8 бит. Регистры-указатели
esp (указатель вершины стека) и ebp (базовый
регистр), а также индексные регистры esi (индекс
источника) и edi (индекс приемника) допускают
только 32-битное обращение.

Регистры сегментов

Регистры сегментов (cs, ds, ss, es, fs и gs) хранят 16-ти
битные дескрипторы сегментов. Дескрипторы
сегментов - это специальные указатели,
определяющие расположение сегмента в
памяти. В защищенном режиме работы
процессора (Windows 95/98) все сегментные регисты
указывают на один и тот же сегмент, поэтому
обычно в программе они не используются.

Регистр флагов

Этот регистр представляет собой набор
флагов, устанавливаемых или сбрасываемых
по результатам выполняемых команд.

Флаг - это переменная длиной 1 бит,
используемая в командах условного перехода.
Если значение этой переменной равно 1, то
считается, что флаг установлен, если 0 -
сброшен. В первую очередь нас интересуют:
флаг нуля, флаг переноса и флаг знака. Флаг
нуля (zf) устанавливается в случае получения
нулевого результата при выполнении
очередной команды и сбрасывается при
остальных ненулевых значениях.
- Флаг переноса (сf) устанавливается при
переносе или заеме старшего бита в
арифметических операциях, в остальных
случаях сбрасывается.
- Флаг переполнения (оf) устанавливается,
если результат арифметической операции не
умещается в операнде-приемнике.
- Флаг знака (sf) устанавливается при
единичном значении старщего бита
результата - признаке отрицательного числа.

ПРАКТИКА.

Теперь попробуем осуществить все выше
описаные команды на конкретном примере.
Нашей целью будет регистрация всемирно
известной программы WinZip 7.0 (beta). В статье
рассматривается build 1243, для более новой
программы возможны некоторые отличия в
адресах.

Устанавливаем и запускаем WinZip. Сразу после
старта появляется окно, сообщающее о том,
что программа не зарегистрирована. Если
программу не зарегистрировать это окно
будет появляться при каждом новом запуске.
В меню Help выбираем пункт About WinZip... В
появившемся окне нажимаем кнопку Register.
Открывается окно регистрации. Вводим в поле
Имя имя, под которым хотим зарегистрировать
программу (например hack). В поле РН вводим
любую информацию (например 1212121212, чтобы
потом при необходимости его легко было
опознать) и нажимаем кнопку ОК. Появляется
окно, сообщающее, что введена неполная или
неверная информация. Обращаю Ваше внимание
на это окно. Это типичное окно MessageBox (окно
сообщения). Его отличительными чертами
являются:
- неактивная кнопка закрытия окна
- наличие внутри окна иконки (вид иконки
зависит от типа сообщения)
- наличие одной или нескольких кнопок (их
названия и количество также зависит от типа
сообщения)

В программе окно MessageBox может создаваться с
помощью четырех функций: MessageBox(), MessageBoxA(),
MessageBoxIndirect() и MessageBoxIndirectA(). Функции, не
оканчивающиеся символом A (MessageBox(),
MessageBoxIndirect()) используются преимущественно
приложениями Win16 (Windows 3.x) и на них мы будем
рассчитывать меньше всего. Остаются две
функции: MessageBoxA() и MessageBoxIndirectA(). Какая из них
используется программой, определяем
опытным путем:

- Закрываем окно сообщения
- Активизируем SoftICE (Ctrl+D)
- Устанавливаем точки прерывания на вызов
MessageBoxA() и MessageBoxIndirectA() (bpx MessageBoxA, bpx
MessageBoxIndirectA)
- Возвращаемся в Windows (F5)

Нажимаем кнопку ОК в окне регистрации,
программа прерывается при вызове функции и
передает управление SoftICE. В окне команд
сообщается, что программа прервалась при
вызове функции MessageBoxIndirectA() из модуля USER32. И
действительно в окне кода мы видим, что
курсор стоит на первой строке этой функции
и, что имя текущего модуля USER32 (написано
внизу окна кода). Дальше мы тоже знаем, что
делать:

- Нажимаем F12 (команда p ret), для продолжения
программы до выполнения команды ret. Перед
нами вновь появляется знакомое окно
сообщения, при нажатии в нем на кнопку ОК
программа прерывается и управление
передается SoftICE. Мы видим, что теперь
программа остановилась в модуле WINZIP32:

0137:00426920 FF15C4AF4700 call [USER32!MessageBoxIndirectA]

0137:00426926 EB14 jmp 0042693C <- в этой строке
находится курсор

Вот мы и нашли то место, где вызывается
функция MessageBoxIndirectA() и создается окно
сообщения. Теперь можно удалить
установленные точки прерывания (команда bc
*), т.к. они нам больше не понадобятся.
Итак, продолжим:
- Мы все еще находимся в SoftICE. Устанавливаем
точку прерывания на выполнение команды по
адресу 00407CA5 (команда bpx 407CA5).
- Выходим в Windows (F5) и вновь пытаемся
зарегистрироваться. При этом программа
прерывается при выполнении команды по
адресу 00407CA5, в окне команд SoftICE сообщается,
что программа остановилась на точке
прерывания по адресу 0137:00407CA5.
- Вводим команду db eax (показать в окне данных
содержимое памяти в виде байт, начиная с
адреса, содержащегося в регистре eax) и
переписываем 8 символов нашего
регистрационного номера (у меня это 62561061).
- Убираем не нужную уже точку прерывания (команда
bc *) и выходим в Windows (F5).

Наступает решающий момент. Вводим в поле РН
полученный регистрационный номер и
нажимаем кнопку ОК. Программа просит
подтвердить регистрационную информацию, и
после нажатия ОК Вы уже являетесь
владельцем личного WinZip'а.