Техника отладки приложений без исходных кодов (Статья о SoftICE) [Крис Касперски] (fb2) читать постранично, страница - 3


 [Настройки текста]  [Cбросить фильтры]

(см. рис. 1). Как это сделать? Очень просто! Установить точку останова на сообщение! В Windows весь интерфейс построен на сообщениях (об этом хорошо написал Петзолд в «Программировании для Windows 95»). В частности, при нажатии на элемент управления (или изменении окна редактирования) окну посылается сообщение WM_COMMAND. Вот на него-то мы и поставим точку останова, но прежде определим дескриптор (handle) окна.


Рисунок 4. Диалоговое окно, на которое мы поставим бряк.

Это можно сделать либо любым Windows-шпионом (например, Spy++, входящим в состав Microsoft Visual Studio), либо средствами самого soft-ice, а конкретно — командой «HWND», выводящей список всех оконных элементов. Если в ответ на «HWND» soft-ice выплюнет «Unable to find a desktop window», необходимо переключить контекст командой «ADDR».

Левая колонка содержит дескрипторы оконных элементов, правая — имена модулей, которым эти элементы принадлежат. Имя модулей не всегда совпадают с именами процессов, если окно принадлежит динамической библиотеке, то soft-ice пишет имя DLL, а не основного процесса. В данном случае диалог обрабатывается библиотекой oodlrwrs, о чем можно узнать с помощью команды MOD, а фрагмент отчета выглядит так:


Handle   Class               WinProc    TID   Module

--------------------------------------------------------

010098   VMDropTargetClass   00403810   138   VMwareUser

010096   VMDropTargetClass   00403810   138   VMwareUser

010094   VMDropTargetClass   00403810   138   VMwareUser

010090   VMDropTargetClass   00403810   138   VMwareUser

01001C   NDDEAgnt            0100BC04    F8   winlogon

120124   #32770 (Dialog)     00F7BC5E   2BC   comctl32

220132   #32770 (Dialog)     00F7BC5E   2BC   oodlrwrs

1F00FE   Button              00F7BC5E   2BC   oodlrwrs

200102   Button              00F7BC5E   2BC   oodlrwrs

1B00F0   Button              00F7BC5E   2BC   oodlrwrs

320130   Static              00F7BC5E   2BC   oodlrwrs

210138   Static              77E19AA4   2BC   oodlrwrs

230116   Static              77E19AA4   2BC   oodlrwrs

24014C   Static              77E19AA4   2BC   oodlrwrs

1700F8   Static              00F7BC5E   2BC   oodlrwrs

20013A   Static              77E19AA4   2BC   oodlrwrs

1F0122   Static              77E19AA4   2BC   oodlrwrs

Листинг 1. Определение дескрипторов окон и элементов управления.


Мы видим, что три наших кнопки принадлежат диалогу #32770 с дескриптором 220132. В принципе, можно поставить точку останова и на 120124 — адрес оконной процедуры (WinProc) у них одинаков. Говорим: «BMSG 220132 WM_COMMAND» и выходим из soft-ice. Нажимаем на кнопку «Далее >» и… отладчик послушно всплывает! Остается только немного протрассировать оконную процедуру в поисках кода, обрабатывающего это нажатие.

Точки останова на данные

Чаще всего бывает так, что ключевой файл/регистрационные данные извлекаются в одном месте, а обрабатываются совсем в другом. Установив точку останова на GetWindowTextA, мы перехватим код, считывающий введенный нами регистрационный номер, но как найти то место, где он сравнивается с оригиналом? Это легко!

Открываем MSDN, смотрим прототип функции GetWindowText, ага: указатель на возвращаемую строку находится во втором аргументе слева, значит на момент вызова GetWindowTextA он будет располагаться по адресу ESP + 8 (четыре байта на hWnd и еще четыре — на адрес возврата).

Говорим: «bpx GetWindowTextA», выходим из отладчика, вводим серийный номер в окно редактирования, нажимаем «ОК» — отладчик всплывает (ну, будем считать, что всплывает, в действительности он может и не всплыть — все зависит от того, какую API-функцию использовал программист, так что тут возможны варианты). Даем команду «d esp->8» (если окно дампа отключено, перед этим необходимо дать команду «wd»), а затем «p ret» — в окне появляется введенная нами строка (cм рис. 5):


Рисунок 5. Определение адреса, по которому записывается считанный пароль.

Все, что нам нужно — это ее адрес, равный в данном случае 2F46E0. Логично — чтобы сравнить пароль с оригиналом, защита должна его считать из памяти. И в этом момент из кустов появляется мы (в смысле, мыщъх и отладчик). Команда «bpm 2F46E0» устанавливает точку останова на адрес 2F46E0, заставляя soft-ice всплывать при каждом чтении/записи этой ячейки. Звучит прекрасно, но на практике срабатывает далеко не всегда. Вовсе не факт, что в первое же всплытие отладчика выведет нас к защитному коду. Скорее всего, здесь будет библиотечная функция, копирующая пароль в локальный буфер, передаваемый по цепочке другим функциям. И хорошо, если по ссылке! Зачастую буфер передается по значению, т. е. копируется в другой буфер целиком. На каждый из таких буферов приходится ставить точку останова, а количество точек останова равно четырем. Это не ограничение отладчика, это просто архитектура у Пня такая.

Отсюда еще не следует, что точки останова на данные бесполезны, просто они сильны совсем в другой области. Вот, например, мы выяснили, что переменной x содержится флаг регистрации. Как именно выяснили, не суть важно. Допустим, встретили код типа: cmp [x],0/jz nag_screen (если переменная x равна нулю, вывести