Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

articles:debug.tech [2017/09/05 02:55] (текущий)
Строка 1: Строка 1:
 +====== debug.tech ======
 +<​sub>​{{debug.tech.odt|Original file}}</​sub>​
 +
 +====== техника отладки приложений без исходных кодов ======
 +
 +крис касперски ака мыщъх, no-email
 +
 +**практически все знают, что программы взламываются отладчиком,​ но не все знают как. на самом деле, ничего сложного в этом нет. достаточно выучить несколько простых приемов и уже можно начинать ломать.**
 +
 +===== введение в отладку =====
 +
 +Отладчик — невероятно мощный инструмент в руках взломщика,​ однако,​ к нему нужен свой подход. Большинство начинающих хакеров начинает отлаживать программу с точки входа и… умирает в цикле выборки сообщений. Пошаговое исполнение программы (так же называемое трассировкой) слишком трудоемкий и крайне неэффективный процесс. Событийно-ориентированные приложения,​ (а к ним относятся практически все Windows-приложения),​ так не отлаживаются. Допустим,​ мы трассируем MFC-приложение,​ доходим до вызова AfxWinMain и… оказываемся глубоко внутри MFC42.DLL, откуда уже и вызывается весь пользовательский код, но прежде чем трассировка доберется до него, мы успеем состариться!
 +
 +Но ведь отлаживать всю программу целиком совершенно необязательно! Опытные хакеры трассируют только отдельные части защитного кода. Но как же мы найдем его в миллионах машинных инструкций исполняемого файла? Существует множество методик:​ точки останова,​ раскрутка стека, перекрестные ссылки,​ условная трассировка,​ прямой поиск паролей/​серийных номеров в памяти и т. д. Расскажем обо всем этом поподробнее.
 +
 +Мы будем курочить программу Drive LED от компании O&​O Software,​ 30-дневую демонстрационную версию которой можно скачать с сайта: http://​www.oo-software.com/​en/​download/​index.shtml;​
 +
 +===== дизассемблер и отладчик в одной упряжке =====
 +
 +Дизассемблер содержится в каждом отладчике (мы же ведь не собираемся отлаживать программу непосредственно в машинном коде, верно?​),​ но тот дизассемблер,​ что находится внутри soft-ice или OllyDbg, слишком примитивен и ненагляден. IDA PRO намного мощнее. Она автоматически распознает имена библиотечных функций,​ определяет типы локальных переменных и делает множество других полезных вещей, в частности,​ позволяет комментировать листинг и назначать символьные метки для инструкций и данных. Исследовать защищенные программы с ее помощью — настоящее удовольствие. Однако,​ вызовы типа call [ebx+64h] приводят хакеров в бешенство,​ особенно если функция вызывается из различных мест с различным ebx. На выяснение значения ebx в дизассемблере можно ухлопать целый день, а в отладчике просто "​подсмотрел"​ его и все!
 +
 +Или вот вызывается что-то по адресу 77E92B8D, лежащим где-то внутри операционной системы (при дизассемблировании дампов памяти такие адреса встречаются сплошь и рядом). В отладчике достаточно просто дать команду "​u 77E92B8D"​ и мы тут же увидим,​ что это CreateFileA.
 +
 +Бессмысленно спорить,​ кто круче отладчик или дизассемблер. Эти инструменты взаимно дополняют друг друга. Реконструкцию алгоритмов лучше поручить дизассемблеру,​ а все непонятные места уточнять в отладчике.
 +
 +Загрузка символов в отладчик осуществляется довольно противоестественным образом,​ на котором спотыкаются многие начинающие.
 +
 +{{debug.tech_Image_0.png?​553}}
 +
 +Рисунок 1 загрузка символьной информации в loader32
 +
 +Сначала исследуемый файл пропускается через ИДУ. Затем, в меню "​File"​ выбирается пункт "​Produceoutputfile  ProduceMAPfile"​ (причем,​ имя MAP-файла должно совпадать с именем самого дизассемблируемого файла). В появившемся диалоговом окне взводим все три галочки:​ Segmentation information (информация о сегментах),​ Autogenerated names (автогенерируемые имена) и Demangle names (размагленные имена). Полученный MAP-файл скармливается утилите idasym (которую можно скачать с сайта www.idapro.com) и конвертируется в sym-формат. Под воздействием утилиты nmsym, входящий в комплект поставки soft-ice, sym-файл преобразуется в nms. Уф! Половина работы сделана,​ теперь,​ пока запускается NuMegaSymbolLoader можно и передохнуть. В меню File выбираем пункт Open, открываем nms-файл и говорим Module  Load (загрузить). Появившаяся надпись "​SymbolsforC:​\TEMP\SIMPLE.NMSsuccessfullyloaded"​ говорит о том, что все прошло успешно. Теперь можно открыть и сам исполняемый файл (File  Open и Module  Load).
 +
 +Сравните,​ как выглядит экран отладчика с символами и без:
 +
 +{{debug.tech_Image_1.png?​552}}
 +
 +Рисунок 2 отладка файла без символьной информации
 +
 +{{debug.tech_Image_2.png?​552}}
 +
 +Рисунок 3 отладка файла с символьной информацией,​ автоматически сгенерированной IDA PRO
 +
 +Без символьной информации назначение функций 401234h и 401124h совсем не очевидно и на них отладку можно угробить несколько часов лучших лет своей жизни, а с символами все ясно и так. К тому же, символьные имена можно использовать в точках останова,​ например:​ "​bpx _fgets"​ (установить точку останова на функцию чтения пароля) или "​bmp aMygoodpassword"​ (установить точку останова на код, обращающийся к эталонному паролю).
 +
 +===== точки останова на API-функции =====
 +
 +Точки останова (они же breakpoint'​ы или просто бряки) — основное оружие хакера в борьбе с защитными механизмами. Наибольшей популярностью пользуются точки останова на API-функции. Чтение содержимого окна часто (но не всегда) осуществляется API-функцией GetWindowTextA,​ открытие файла — CreateFileA,​ загрузка динамической библиотеки — LoadLibraryA и т. д. Установка точки останова на эти функции заставить отладчик "​всплывать"​ всякий раз, когда защита пытается сделать что-то нехорошее. Этим она демаскирует свое расположение в исследуемом коде, выводя на след.
 +
 +Проблема в том, что API-функций очень много и угадать каким именно способом защита манипулирует с окном, не так-то просто. Обычно используется либо "​тупой"​ перебор всех возможных API-функций одна за другой,​ либо API-шпионы,​ показывание что происходит под капотом отлаживаемой программы (см. статью "​взлом архиватора WinRAR"​).
 +
 +Для установки точки останова на API-функцию достаточно нажать <​Ctrl-D>,​ и дождавшись появления отладчика на экране,​ написать "​bpx имя_функции"​. В soft-ice точки останова носят глобальный характер. Если мы устанавливаем бряк на функцию CreateFileA,​ отладчик всплывает при каждом открытии/​создании какого бы то ни было файла. Вот радость! Чтобы ограничить пыл отладчика,​ необходимо использовать условные точки останова. Допустим,​ мы хотим всплывать на "​keyfile.key"​. Открываем MSDN и смотрим прототип функции CreateFile. Видим, что lpFileName передается в крайнем левом аргументе,​ а поскольку аргументы API функций заносятся в стек справа налево,​ указатель на имя открываемого файла окажется на вершине стека и выше него будет только адрес возврата.
 +
 +Таким образом,​ в момент вызова CrateFile, lpFileName будет лежать по смещению 4, относительно ESP и условная точка останова будет выглядеть так: "​bpx CreateFileA if (*(esp‑>​4)=='​keyf'​)"​. Имя файла, заключенное в кавычки,​ автоматически преобразуется отладчиком в 32-разроядную константу и потому его длина не должна превышать 4х байт, причем,​ отладчик чувствителен к регистру ('​keyf'​ и '​Keyf'​ для него не одно и тоже), а вот файловая система — нет. В большинстве случаев частичного сравнения имени оказывается вполне достаточно. Если же нет, можно прибегнуть к оператору AND и сравнивать несколько 4х битных подстрок за раз. Синтаксис условных точек останова подробно описан в документации на soft-ice, так что не будем на этом останавливаться.
 +
 +Многие защиты противостоят точкам останова,​ например,​ начиная выполнение API-функции не с первого байта, и в таких случаях приходится прибегать к установке бряков на native-API — своеобразному фундаменту операционной системы,​ ниже которого находятся только порты ввода/​вывода и драйвера. Описание native-API функций можно найти в InterruptList'​е Ralf'​а Brown'​а или "​TheUndocumentedFunctionsMicrosoftWindowsNT/​2000"​ от Tomas'​а Nowak'​а. В частности,​ NtCreatrFile используется для создания/​открытия файлов.
 +
 +Отладчик OllyDbg поддерживает намного более мощный механизм условных точек, позволяющий отслеживать практически любые ситуации. Например,​ EAX == "​mypswd"​ — всплывать,​ когда регистр EAX указывает на строку с паролем/​серийным номером который мы ввели при регистрации. Это универсальный способ взлома,​ подходящий практически ко всем защитам. Каким бы образом программа не извлекала содержимое окна редактирования,​ в какой-то момент она неизбежно засунет указатель в регистр. Вот тут-то мы и всплывем! Процедура проверки соответствия пароля будет где-то неподалеку. Конечно,​ этим регистром не обязательно должен быть EAX. Вполне вероятно,​ что компилятор задействует EBX, ESI или что-то еще. Документация на OllyDbg заявляет о поддержке выражения R32 == "​mypswd",​ где R32 – любой регистр общего назначения,​ однако,​ в текущих версиях отладчика эта конструкция не работает и все регистры приходится перебирать вручную (благо,​ можно написать свой плагин,​ автоматизирующий этот процесс).
 +
 +Поимо точек останова на API, можно брякать библиотечные функции. В приложениях,​ написанных на DELPHI/​BUILDER/​MFC/​Visual BASIC прямые вызовы API используются редко. И хотя никакое дело без API-функций,​ конечно же не обходится,​ их анализ мало что дает, особенно,​ если используется динамический обмен данных с окном (DDX) и другие навороченные технологии,​ обмазывающие API-функциями несколькими мегабайтами кривого кода. Это же сдохнуть можно! Но мы не будем! Библиотечные функции легко опознаются ИДОЙ и брякаются как обычные API-функции только с той разницей,​ что точка останова носит локальный характер,​ воздействующий только на отлаживаемое приложение. А это значит,​ что после нажатия <​Ctrl-D>​ мы должны переключить контекст управления,​ чтобы попасть в адресное пространство отлаживаемого приложения. Это осуществляется либо командой "​ADDR имя_процесса",​ либо установкой точки останова на любую API-функцию,​ вызываемую отлаживаемым приложением. Например,​ SendMessageA. Жмем, <​Ctrl-D>,​ пишем "​bpx MeggsageBoxA",​ выходим из sof-ice, дожидаемся пока он всплывет (если не всплывает,​ можно дернуть мышью или щелкнуть по отлаживаемому окну), если в правом нижнем углу отладчика находится имя нашего процесса — все ок, в противном случае выходим из отладчика и ждем его всплытия опять.
 +
 +===== точки останова на сообщения =====
 +
 +Допустим,​ у нас есть окно с несколькими элементами управления (меню, флажок или кнопка) нажатия на которые мы хотим отследить (см. рис. 1). Как это сделать?​ Очень просто! Установить точку останова на сообщение! В Windows весь интерфейс построен на сообщениях (об этом хорошо написал Петзолд в "​Программировании для Windows 95"). В частности,​ при нажатии на элемент управления (или изменении окна редактирования) окну посылается сообщение WM_COMMAND. Вот на него-то мы и поставим точку останова,​ но прежде определим дескрпитор (handle) окна.
 +
 +{{debug.tech_Image_3.png?​514}}
 +
 +Рисунок 4 диалоговое окно, на которое мы поставим бряк
 +
 +Это можно сделать либо любым Windows-шпионом (например,​ Spyxx, входящим в состав MicrosoftVisualStudio),​ либо средствами самого soft-ice, а конкретно командой "​HWND",​ выводящий список всех оконных элементов. Если в ответ на "​HWND",​ soft-ice выплюнет:​ "​Unabletofindadesktopwindow",​ необходимо переключить контекст командой "​ADDR"​.
 +
 +Левая колонка содержит дескрипторы оконных элементов,​ правая — имена модулей,​ которым эти элементы принадлежат. Имя модулей не всегда совпадают с именами процессов,​ если окно принадлежит динамической библиотеке,​ то soft-ice пишет имя DLL, а не основного процесса. В данном случае,​ диалог обрабатывается библиотекой oodlrwrs, о чем можно узнать с помощью команды MOD, а фрагмент отчета выглядит так:
 +
 +HandleClassWinProcTIDModule
 +
 +010098VMDropTargetClass00403810138VMwareUser
 +
 + ​010096 VMDropTargetClass00403810138VMwareUser
 +
 + ​010094 VMDropTargetClass 00403810138VMwareUser
 +
 + ​010090 VMDropTargetClass 00403810138VMwareUser
 +
 +01001CNDDEAgnt0100BC04F8winlogon
 +
 +120124#​32770 (Dialog)00F7BC5E2BCcomctl32
 +
 + ​__220132#​32770 (Dialog 00F7BC5E2BCoodlrwrs__
 +
 +** 1F00FEButton 00F7BC5E2BCoodlrwrs**
 +
 +** 200102Button 00F7BC5E2BCoodlrwrs**
 +
 +** 1B00F0Button 00F7BC5E2BCoodlrwrs**
 +
 + ​320130Static 00F7BC5E2BCoodlrwrs
 +
 + ​210138Static 77E19AA42BCoodlrwrs
 +
 + ​230116Static 77E19AA42BCoodlrwrs
 +
 + ​24014CStatic 77E19AA42BCoodlrwrs
 +
 + ​1700F8Static 00F7BC5E2BCoodlrwrs
 +
 + ​20013AStatic 77E19AA42BCoodlrwrs
 +
 + ​1F0122Static 77E19AA42BCoodlrwrs
 +
 +Листинг 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)
 +
 +{{debug.tech_Image_4.png?​552}}
 +
 +Рисунок 5 определение адреса по которому записывается считанный пароль
 +
 +Все, что нам нужно — это ее адрес, равным в данном случае 2F46E0. Логично,​ чтобы сравнить пароль с оригиналом,​ защита должна его считать из памяти. И в этом момент из кусов появляется мы (в смысле мыщъх и отладчик). Команда "​bpm 2F46E0"​ устанавливает точку останова на адрес 2F46E0, заставляя soft-ice всплывать при каждом чтении/​записи этой ячейки. Звучит прекрасно,​ но на практике срабатывает далеко не всегда. Вовсе не факт, что в первое же всплытие отладчика выведет нас к защитному коду. Скорее всего здесь будет библиотечная функция,​ копирующая пароль в локальный буфер, передаваемый по цепочке другим функциям. И хорошо если по ссылке! Зачастую буфер передается по значению,​ т. е. копируется в другой буфер целиком. На каждый из таких буферов приходится ставить точку останова,​ а количество точек останова равно четырем. Это не ограничение отладчика,​ это просто архитектура у Пня такая.
 +
 +Отсюда еще не следует,​ что точки останова на данные бесполезны,​ просто они сильны совсем в другой области. Вот, например,​ мы выяснили,​ что переменной x содержится флаг регистрации. Как именно выяснили не суть важно. Допустим встретили код типа: cmp [x],​0/​jz nag_screen (если переменная x равна нулю вывести ругательный диалог). Как определить где именно этот x инициализируется?​ В большинстве случав,​ перекрестные ссылки автоматически восстанавливаются ИДОЙ, однако,​ разработчик защитного механизма может легко ослепить ее, но едва ли он справится с командой "​bpm x"​ (установить точку останова на доступ к переменой x). А вот другой вариант:​ изменили мы пару байтиков в программе,​ а она, обнаружив факт своего взлома,​ отказалась работать. Чтобы найти процедуру проверки целостности кода достаточно установить одну или несколько точек останова на модифицированные ячейки. Да много чего можно придумать,​ главное — фантазию иметь!
 +
 +===== раскрутка стека =====
 +
 +Внешние проявления защитного механизма засечь очень легко. Как правило,​ это либо окошко с надписью "​trialexpired",​ либо форма для ввода серийного номера. Установить точку останова на WM_COMMAND легко, но что это дает? Мы окажемся внутри оконной процедуры,​ в глубоких недрах которой зарыт защитный код. Можно, конечно,​ и потрассировать,​ но это же сколько времени уйдет! Вот бы узнать какие команды исполнялись до этого! Обратить выполнение программы вспять и посмотреть какой именно код определят факт регистрации программы. Некоторые отладчики поддерживают механизм обратной трассировки (backtrace),​ запоминая все выполняемые команды и складывая их в специальный буфер, однако,​ это сильно замедляет выполнение программы и выводит антиотладочные приемы на оперативный простор. Мы поступим иначе. soft-ice поддерживает шикарную команду "​STACK",​ раскручивающую стек и выводящую адреса всех материнских функций. Не совсем равноценная замена обратной трассировки,​ но для большинства случаев ее вполне хватает.
 +
 +В нашем случае,​ ответ отладчика выглядит так:
 +
 +:STACK
 +
 +0012E138 77E155B5oorwiz!.text+0001AC5E
 +
 +0012E168 77E15A3BUSER32!DefWindowProcW+0105
 +
 +0012E188 77E1FB52USER32!SendMessageW+0043
 +
 +0012E214 77E1E6C3USER32!WINNLSGetIMEHotkey+0E15
 +
 +0012E254 77E1E561USER32!EditWndProc+0075
 +
 +0012E278 77E198DFUSER32!ScrollWindow+0096
 +
 +0012E29C 77E13EB0USER32!ShowCursor+0057
 +
 +0012E2BC 77E16469USER32!SetTimer+0435
 +
 +0012E2E0 77E164E5USER32!SetRect+0065
 +
 +0012E300 00F7A1B6USER32!CallWindowProcW+0019
 +
 +0012E320 00F7A403oorwiz!.text+000191B6
 +
 +0012E33C 00F7BC02oorwiz!.text+00019403 ; _AfxPostInitDialog
 +
 +0012E39C 00F7BC92oorwiz!.text+0001AC02 ; AfxWndProc
 +
 +0012E3BC 77E13EB0oorwiz!.text+0001AC92 ; 
 +
 +0012E3DC 77E1591BUSER32!SetTimer+0435
 +
 +Листинг 2 раскрутка стека в soft-ice
 +
 +Десять первых вызовов относятся к библиотеке USER32.DLL и не представляют для нас никакого интереса (soft-ice неправильно определил принадлежность вызова 12E138h, приписав его к oorwiz, но oorwiz не может располагаться по адресам 77E155B5 – эта зона принадлежит USER32). А вот одиннадцатый вызов 12E320, ведущий к адресу F7A403 весьма интересен. Заглянув сюда дизассемблером,​ мы обнаружим следующий код:
 +
 +.text:​1001A3E6calldword ptr [eax+10Ch]
 +
 +.text:​1001A3ECtesteax,​ eax
 +
 +.text:​1001A3EEjnzshort loc_1001A406
 +
 +.text:​1001A3F0push[ebp+arg_8]
 +
 +.text:​1001A3F3moveax,​ [esi]
 +
 +.text:​1001A3F5push[ebp+arg_4]
 +
 +.text:​1001A3F8movecx,​ esi
 +
 +.text:​1001A3FApush[ebp+arg_0]
 +
 +.text:​1001A3FDcalldword ptr [eax+110h] ​
 +
 +.text:​1001A403mov[ebp+var_4],​ eax ; адресвозврата
 +
 +.text:​1001A406
 +
 +.text:​1001A406 loc_1001A406:;​ CODE XREF: CWnd::​WindowProc()+24↑j
 +
 +.text:​1001A406moveax,​ [ebp+var_4]
 +
 +.text:​1001A409popesi
 +
 +.text:​1001A40Aleave
 +
 +.text:​1001A40Bretn0Ch
 +
 +Листинг 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). В списке "​LoaderSymbols"​ немедленно появляется новое имя. Теперь,​ загружаем основной исполняемый файл (в данном случае oodled.exe) и устанавливаем точки останова на интересующие нас функции ("​bpx RegWiz_InitReadOnly",​ "​bpx RegWiz_InitTrial",​ "​bpx RegWiz_InitLicMgr"​),​ заставляя отладчик всплывать при их вызове.
 +
 +{{debug.tech_Image_5.png?​552}}
 +
 +Рисунок 6 загрузка экспорта из динамических библиотек
 +
 +Поскольку динамические библиотеки перемещаемы,​ адреса в дизассемблере могут не совпадать с отладчиком. Вот например,​ в oorwiz.dllIDA определяет адрес функции RegWiz_InitTrial как 10001D00h, а soft-ice как F60000. Ну и как с этим жить? А вот как: базовый адрес загрузки (Imagebase) равен 10000000h, в чем IDA честно признается в начале файла. Но загрузить по этому адресу библиотеку не получается и операционная система перемещает ее по адресу xxxx, о чем говорит команда "​MOD"​ в soft-ice:
 +
 +:mod
 +
 +hMod  Base  Module NameFile Name
 +
 +80400000 804000C8 ntoskrnl\WINNT\System32\ntoskrnl.exe
 +
 +
 +
 +00400000 00400108 oodled\Program Files\OO Software\DriveLED2\ood
 +
 +00F30000 00F300B8 oodlrwrs\Program Files\OO Software\DriveLED2\ood
 +
 +**00F60000 00F600F8 oorwiz\Program Files\OO Software\DriveLED2\oor**
 +
 +10000000 100000C0 oodledrs\Program Files\OO Software\DriveLED2\ood
 +
 +Листинг 4 просмотр базовых адресов загрузки командой MOD
 +
 +Разница базовых адресов составляет 10001000-F60000 == F0A1000,​ поэтому,​ чтобы перевести адрес из отладчика в дизассемблер к нему необходимо добавить F0A1000, а из дизассемблера в отладчик — отнять.
 +
 +===== заключение =====
 +
 +Рассмотренные приемы работают далеко не везде и не всегда. Разработчики далеко не идиоты и он взлома они все-таки защищаются. Лучше начинать с простых защит, постепенно переходя все к более сложным. Отладчик это сложный инструмент,​ который не осваивается за день. Исследование машинных кодов — настоящее искусство,​ которому учатся всю жизнь. Так что не нужно огорчаться,​ если что-то не получается. Чем хитрее защита и чем труднее взлом, тем более удовлетворение она приносит в конечном итоге! Кто-то сравнил это чувство с оргазмом. Ничего подобного! Хакерство намного круче!
 +
 +