Dаrоvа, хацкеры!
Сегодня мы рассмотрим взлом всеми любимой сжималки
WinZip 8.0. А точнее мы её незаконно зарегистрируем %-). Для этого нам понадобится:
1. Отладчик SoftIce.
2. Знание АСМа.
Воспользуемся меню программы с пунктом Help. Как мы видим, здесь используется схема регистрации "ИМЯ - КОД". Диалог регистрации в программе WinZip построен следующим образом:
1. Пользователь вводит ИМЯ и КОД, пользователь "подтверждает" окончание ввода нажатием на кнопку "ОК".
2. Программа получает введенную информацию, программа проверяет правильность информации.
Теперь выполним следующее, в редактор текста для имени вводим: someone, вводить можно любое значение, удовлетворяющее условиям:
- не пустое;
- "не очень" короткое и длинное;
Эти условия программы часто проверяют, прерывая свою работу, когда условия не выполняются.
Кода вводим: 1234554321, условия для кода аналогичны ограничениям для имени.
Кнопку "ОК" нажимать пока еще не нужно!
Теперь нам надо перехватить API функцию, которая будет получать из редакторов текста введённые вами значения.
В отладчике (переключаемся, нажимая CTRL+D (стандартная настройка SoftIce)),
вводим команды установки точек прерывания на вызов функций:
bpx GetDlgItemTextA
bpx GetWindowTextA
Т.к. заранее точно не известно, какой функцией пользуется программа, то мы пытаемся перехватить вызовы всех возможных функций (ну, почти).
В программе нажимаем на кнопку "ОК", после чего снова попадаем в отладчик, но преимущество в том, что мы теперь находимся в том месте программы, где она получает из редакторов текста введенные значения ИМЕНИ и КОДА, для выполнения в скором будущем проверки правильности регистрации.
Прежде всего, заметим, что, попав в отладчик, мы оказались не в самой программе, а внутри перехваченной функции, поэтому, нажав F12 (команда: возврат из процедуры) в отладчике, мы вернемся в программу сразу за местом вызова функции.
Листинг программы на ассемблере:
....
407F5Fh: mov edi, 48CD78h !;адрес буфера, куда помещается ИМЯ
push 29h
push edi
push 0C80h
push ebx
call GetDlgItemTextA !;программа получает введенное ИМЯ
После 1-ого срабатывания прерывания и нажатия на F12, мы оказываемся здесь:
....
mov esi, 48CDA4h !;адрес буфера, куда помещается КОД
pop ecx
push 0Bh
push esi
push 0C81h
push ebx
call GetDlgItemTextA !;программа получает введенный КОД
После 2-ого срабатывания прерывания и нажатия на F12, мы оказываемся здесь:
....
cmp [48CD78h], 0 ;проверка ?ИМЯ не введено (пусто)
....
jz 408005h ;прерывание работы алгоритма по ошибке ввода ИМЕНИ
cmp [48CDA4h], 0 ;проверка ?КОД не введен (пуст)
jz 408005h ;прерывание работы алгоритма по ошибке ввода КОДА
....
call 4079D5h !;функция проверки правильности регистрации
test eax, eax ;проверка ?регистрация ошибочна
jz 408005h ;прерывание работы алгоритма по ошибке
;неправильные регистрационные данные
....
jmp 408035h
408005h:
....
call 430025h ;вывод сообщения об ошибке на экран
....
jnz 40812Ch ;прерывание работы алгоритма по ошибке
....
408035h:
....
call EndDialog ;завершение диалога
jmp 40812Ch ;завершение работы алгоритма
....
Комментарии к листингу программы:
-отметим, что прерывание на функцию GetWindowText() не потребовалось;
-отметим, что call 4079D5h это функция проверки правильности регистрации сделан постфактум;
Главное в листинге, это фрагмент кода, отвечающий за вызов функции GetDlgItemText(), т.к. нам становится известно, где в памяти хранятся ИМЯ и КОД, которые программа проверяет:
48CD78 - адрес памяти, где находится ИМЯ
48CDA4 - адрес памяти, где находится КОД
Что же программа будет делать с этими значениями, чтобы установить факт выполнения правильной регистрации? Самый простой способ проверки это:
- сгенерировать для введенного ИМЕНИ ПРАВИЛЬНЫЙ КОД регистрации
- сравнить правильный код с введенным КОДОМ.
Вывод:
1. В программе должен быть алгоритм генерации правильного кода для любого допускаемого ею имени;
2. В программе должен быть алгоритм проверки введенного кода с генерированным правильным кодом;
3. Правильный код хранится в открытом виде.
Методика поиска правильного кода регистрации:
мы здесь не ставим целью себе выяснить, как программа по ИМЕНИ генерирует правильный код, наша цель узнать его значение. Уязвимым местом программы, где можно посмотреть правильный код, является как раз алгоритм его сравнения с введенным кодом, т.к. мы "знаем", где хранится КОД
(48CDA4).
Средства поиска: отладчик SoftIce позволяет устанавливать точки прерывания по обращению к адресам памяти следующими командами:
bpm 48CDA4 - прерывание по обращению к одной ячейке памяти
bpr 48CDA4 48CDA4+9 - ... по обращению к диапазону ячеек памяти длиной 10
Методика поиска: в отладчике вводим команду установки прерывания на обращение к памяти:
bpm 48CDA4
Вывод: этап "подготовка перехвата обращения к КОДУ" выполнен.
Нажимаем F5 (команда: продолжение выполнения программы), теперь мы будем каждый раз попадать в отладчик, как только программа будет обращаться к значению введенного кода:
1. Попав после срабатывания прерывания в отладчик, будем анализировать код в этой точке на наличие инструкций сравнение данных.
2. Если таких "рядом" нет, то нажимаем F5 и возвращаемся к п.1.
3. Если такие существуют, то нужно определить что с чем сравнивается, пытаясь найти искомый правильный код.
Вернуться к п.1.
- через несколько повторений (4-5 раз) мы наткнемся на участок кода:
....
4692F0h: mov al, [esi] ;esi=48CDA4-адрес введенного кода
;al-очередной символ кода
inc esi ;переход к следующему символу
mov ah, [edi] ;edi=79F68C-адрес правильного кода
;ah-очередной символ правильного кода
inc edi ;переход к следующему символу
cmp ah, al ;проверка ?совпадают символы
jz 4692ECh ;продолжение сравнения кодов
....
Вводим команду просмотра содержимого памяти по адресу:
d 79F68C
по этому адресу располагается правильный код в открытом виде:
B91808B8 - правильный код для имени someone
если продолжить методику поиска, то можно выяснить и второй код:
47384223 - правильный код для имени someone
теперь можно командой bd * (команда: запретить точки прерывания) отключить все точки прерывания, по F5 вернуться в программу.
Ну, теперь дело осталось за малым. В программе вводим правильный код и нажимаем кнопку "ОК" и убеждаемся в выполнении регистрации на введенное имя.
Вывод:
регистрационные данные:
ИМЯ: someone
КОД: B91808B8
или:
ИМЯ: someone
КОД: 47384223
Вот и весь, как говорится, взлом =-)….