Литвек - электронная библиотека >> Крис Касперски >> Статьи и рефераты и др. >> Техника отладки приложений без исходных кодов (Статья о SoftICE) >> страница 3
адрес возврата).

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


Техника отладки приложений без исходных кодов (Статья о SoftICE). Иллюстрация № 5
Рисунок 5. Определение адреса, по которому записывается считанный пароль.

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

Отсюда еще не следует, что точки останова на данные бесполезны, просто они сильны совсем в другой области. Вот, например, мы выяснили, что переменной x содержится флаг регистрации. Как именно выяснили, не суть важно. Допустим, встретили код типа: cmp [x],0/jz nag_screen (если переменная x равна нулю, вывести ругательный диалог). Как определить где именно этот x инициализируется? В большинстве случаев перекрестные ссылки автоматически восстанавливаются ИДОЙ, однако разработчик защитного механизма может легко ослепить ее, но едва ли он справится с командой «bpm x» (установить точку останова на доступ к переменной x). А вот другой вариант: изменили мы пару байтиков в программе, а она, обнаружив факт своего взлома, отказалась работать. Чтобы найти процедуру проверки целостности кода достаточно установить одну или несколько точек останова на модифицированные ячейки. Да много чего можно придумать, главное — фантазию иметь!

Раскрутка стека

Внешние проявления защитного механизма засечь очень легко. Как правило, это либо окошко с надписью «trial expired», либо форма для ввода серийного номера. Установить точку останова на WM_COMMAND легко, но что это дает? Мы окажемся внутри оконной процедуры, в глубоких недрах которой зарыт защитный код. Можно, конечно, и потрассировать, но это же — сколько времени уйдет? Вот бы узнать — какие команды исполнялись до этого? Обратить выполнение программы вспять и посмотреть — какой именно код определят факт регистрации программы. Некоторые отладчики поддерживают механизм обратной трассировки (back trace), запоминая все выполняемые команды и складывая их в специальный буфер, однако это сильно замедляет выполнение программы и выводит антиотладочные приемы на оперативный простор. Мы поступим иначе. Soft-ice поддерживает шикарную команду «STACK», раскручивающую стек и выводящую адреса всех материнских функций. Не совсем равноценная замена обратной трассировки, но для большинства случаев ее вполне хватает.

В нашем случае ответ отладчика выглядит так:


:STACK

0012E138 77E155B5      oorwiz!.text+0001AC5E

0012E168 77E15A3B      USER32!DefWindowProcW+0105

0012E188 77E1FB52      USER32!SendMessageW+0043

0012E214 77E1E6C3      USER32!WINNLSGetIMEHotkey+0E15

0012E254 77E1E561      USER32!EditWndProc+0075

0012E278 77E198DF      USER32!ScrollWindow+0096

0012E29C 77E13EB0      USER32!ShowCursor+0057

0012E2BC 77E16469      USER32!SetTimer+0435

0012E2E0 77E164E5      USER32!SetRect+0065

0012E300 00F7A1B6      USER32!CallWindowProcW+0019

0012E320 00F7A403      oorwiz!.text+000191B6

0012E33C 00F7BC02      oorwiz!.text+00019403  ; _AfxPostInitDialog

0012E39C 00F7BC92      oorwiz!.text+0001AC02  ; AfxWndProc

0012E3BC 77E13EB0      oorwiz!.text+0001AC92  ;

0012E3DC 77E1591B      USER32!SetTimer+0435

Листинг 2. Раскрутка стека в soft-ice.


Десять первых вызовов относятся к библиотеке USER32.DLL и не представляют для нас никакого интереса (soft-ice неправильно определил принадлежность вызова 12E138h, приписав его к oorwiz, но oorwiz не может располагаться по адресам 77E155B5 — эта зона принадлежит USER32). А вот одиннадцатый вызов 12E320, ведущий к адресу F7A403 весьма интересен. Заглянув сюда дизассемблером, мы обнаружим следующий код:


.text:1001A3E6                call dword ptr [eax+10Ch]

.text:1001A3EC                test eax, eax

.text:1001A3EE                jnz  short loc_1001A406

.text:1001A3F0                push [ebp+arg_8]

.text:1001A3F3                mov  eax, [esi]

.text:1001A3F5                push [ebp+arg_4]

.text:1001A3F8                mov  ecx, esi

.text:1001A3FA                push [ebp+arg_0]

.text:1001A3FD                call dword ptr [eax+110h]

.text:1001A403                mov  [ebp+var_4], eax   ; адрес возврата

.text:1001A406

.text:1001A406 loc_1001A406:         ; CODE XREF: CWnd::WindowProc()+24^j

.text:1001A406                mov  eax, [ebp+var_4]

.text:1001A409                pop  esi

.text:1001A40A        leave

.text:1001A40B                retn 0Ch

Листинг 3. Фрагмент дизассемблерного листинга, с подозрительным условным переходом.


Функция 1001A3FD: call dword ptr [eax+110h] — та самая, к которой ведет адрес возврата. Именно она и выводит противный регистрационный диалог. Прокручивая экран дизассемблера вверх, легко найти условный переход, расположенный по адресу 101AEE, который прыгает за диалог возврата. Изменив jnz на jmp short, мы навсегда уберем диалог с экрана. Конечно, такая мера еще не зарегистрирует программу, но это все-таки кое-что!

Отладка динамических библиотек

Loader32 (символьный загрузчик soft-ice) как бы позволяет загружать динамические библиотеки, но отлаживать их в автономном режиме не позволяет, что, собственно говоря, и не удивительно, ведь всякая такая библиотека — просто набор функций, вызываемых из основного процесса. Возьмем библиотеку oorwiz.dll, экспортирующую тройку функций с заманчивыми именами: RegWiz_InitReadOnly, RegWiz_InitTrial, RegWiz_InitLicMgr. Как их отладить?

Заходим в Loader32, выбираем пункт File ―> Load Export, указываем имя библиотеки (oorwiz.dll). В списке «Loader Symbols» немедленно появляется новое имя. Теперь загружаем основной исполняемый файл (в данном случае oodled.exe) и устанавливаем точки останова на интересующие нас функции («bpx RegWiz_InitReadOnly», «bpx RegWiz_InitTrial», «bpx RegWiz_InitLicMgr»), заставляя отладчик всплывать при их вызове.


Техника отладки приложений без исходных кодов (Статья о SoftICE). Иллюстрация</div></main></div><div class='read_navi'><form class='sec_tab' action='/br/539694' method='get'><label>Страница: <input size='3' class='mz5 p5 s09' type='text' name='p' value='3'></label><input class='mz5 fff s11' style='border:0px' type='submit' value='GO'></form><ul style=
  • 1
  • 2
  • 3
  • 4