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

-  Техника отладки приложений без исходных кодов (Статья о SoftICE)  427 Кб скачать: (doc) - (doc+fbd)  читать: (полностью) - (постранично) - Крис Касперски

Книга в формате doc! Изображения и текст могут не отображаться!


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

редактирования) окну посылается сообщение 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 равна нулю, вывести ругательный диалог). Как определить где именно этот x инициализируется? В большинстве случаев перекрестные ссылки автоматически восстанавливаются ИДОЙ, однако разработчик защитного механизма может легко ослепить ее, но едва ли он справится с командой "bpm x" (установить точку останова на доступ к переменной x). А вот другой вариант: изменили мы пару байтиков в программе, а она, обнаружив факт своего взлома, отказалась работать. Чтобы найти процедуру проверки целостности кода достаточно установить одну или несколько точек останова на модифицированные