Классификация способов защиты



 

При проектировании и реализации систем защиты информации (СЗИ) практически всегда возникает задача защиты ее алгоритма. Атака на алгоритм СЗИ может быть пассивной (изучение) — без изменения алгоритма СЗИ и активной — с изменением алгоритма в соответствии с целью злоумышленника. Например, при анализе СЗИ, выполняющей операции криптографической защиты, успешная пассивная атака приводит к тому, что злоумышленнику становится полностью известен алгоритм шифрования и, возможно, часть ключевых элементов, локализованных в программе. При активной атаке на СЗИ от копирования возможно отключение механизмов проверки ключевого признака.

Будем считать, что человек, преследующий цель исследования логики работы СЗИ, является злоумышленником. Для решения своей задачи он располагает средством (субъектом компьютерной системы), которое для краткости будем называть отладчиком.

Задача защиты от изучения (исследования) сводится к решению двух взаимосвязанных задач:

• выявлению отладчика;

• направлению работы защищенной программы или отладчика по "неверному пути".

Атаки злоумышленника на логику работы СЗИ сводятся к декомпозиции программного кода на множество отдельных команд (инструкций), каждая из которых (либо группа инструкций) рассматривается отдельно. Условно такие атаки можно разделить на динамические — разбор по командам, сопряженный с выполнением программы (выполнением каждой рассматриваемой команды), и статические — декомпозиция всего кода программы, возможно, не сопряженная с ее прямым исполнением, основанная на анализе логики исполнения команд и логики вызовов различных функций (дизассемблирование). Не вдаваясь в подробности обоих процессов, отметим лишь существенно важные детали.

Программное средство злоумышленника (отладчик) работает в общей для него и изучаемой программы оперативной памяти, использует те же аппаратные ресурсы (например, процессор), непустое общее подмножество внешних событий программной среды (например, прерываний) — иначе говоря, работа отладчика оставляет в программно — аппаратной среде, общей с изучаемой программой, некоторые "следы". Кроме того, отладчик управляется человеком, который, как известно, реагирует на все гораздо медленнее, чем ЭВМ. Далее, управление работой отладчика может происходить через клавиатуру, а восприятие результатов — через экран.

Вполне понятно, что изучаемая программа может "мешать" работе отладчика, имея для этого все названные выше признаки. В данном случае представляется уместной аналогия из квантовой механики, когда наблюдатель либо существенно влияет на процесс в мире микрочастиц, либо должен быть так мал, что частицы будут влиять на него. И в том, и в другом случае реальная картина эксперимента искажается.

Злоумышленник должен наблюдать за изучаемой программой как можно "незаметнее", не оставлять следов своей деятельности, и его программное средство должно быть защищено от активного воздействия со стороны изучаемой программы. С другой стороны, разработчик защиты должен так строить ее, чтобы либо обнаруживать присутствие отладчика, либо не давать работать вообще никому, кроме себя, либо мешать восприятию результатов исследования.

 

Защита от отладки и дизассемблирования

Способы защиты от исследования можно разделить на четыре класса.

1. Влияние на работу отладочного средства через общие программные или аппаратные ресурсы. В данном случае наиболее известны:

• использование аппаратных особенностей микропроцессора (особенности работы очереди выборки команд, особенности реализации команд и т.д.);

• использование общего программного ресурса (например, общего стека) с отладочным средством и разрушение данных или кода отладчика, принадлежащих общему ресурсу, либо проверка использования общего ресурса только защищаемой программой (например, определение стека в области, критичной для выполнения защищаемой программы);

• переадресация обработчиков отладочных событий (прерываний) от отладочного средства к защищаемой программе.

Выделение трех групп защитных действий в данном классе не случайно, поскольку объективно существуют общие аппаратные ресурсы (и отладчик, и защищаемая программа в случае однопроцессорного вычислителя выполняются на одном и том же процессоре), общие программные ресурсы (поскольку и отладчик, и защищаемая программа выполняются в одной и той же операционной среде), наконец, отладчик создает специфичные ресурсы, существенные для его собственной работы (например, адресует себе отладочные прерывания).

2. Влияние на работу отладочного средства путем использования особенностей его аппаратной или программной среды. Например:

• перемещение фрагментов кода или данных с помощью контроллера прямого доступа к памяти;

• влияние на процесс регенерации оперативной памяти (на некотором участке кода регенерация памяти отключается, а затем опять включается — при нормальной работе никаких изменений нет, при медленном выполнении программы отладчиком она "зависает");

• переход микропроцессора в защищенный режим.

3. Влияние на работу отладчика через органы управления или/и устройства отображения информации.

Выдаваемая отладочными средствами информация анализируется человеком. Следовательно, дополнительный способ защиты от отладки — это нарушение процесса общения оператора и отладчика, а именно искажение или блокирование вводимой с клавиатуры и выводимой на терминал информации.

4. Использование принципиальных особенностей работы управляемого человеком отладчика. В данном случае защита от исследования состоит в навязывании для анализа избыточно большого объема кода (как правило, за счет циклического исполнения некоторого его участка).

Рассмотрим данный метод подробнее. Пусть имеется некоторое полноцикловое преобразование из N состояний ti: Т = t1, t2, ..., tN (например, обычный двоичный счетчик либо рекуррента). Значение N выбирается не слишком большим. Например, для k-битового счетчика N = 2k . Участок кода, защищаемый от изучения, динамически преобразуется (шифруется) с использованием криптографически стойкого алгоритма на ключе ti, который выбирается случайно равновероятно из множества состояний Т.

Работа механизма защиты от исследования выглядит следующим образом. Программа полноциклового преобразования начинает работу с детерминированного или случайного значения. На установленном значении производится расшифрование зашифрованного участка кода. Правильность расшифрования проверяется подсчетом хеш — значения расшифрованного кода с использованием элементов, связанных с отладкой (стек, отладочные прерывания и др.). Хеш-функция должна с вероятностью 1 определять правильность расшифрования (для этого хеш — значение должно быть не менее k).

Предположим, что полноцикловое преобразование стартует с первого значения. Тогда при нормальном выполнении программы (скорость работы высокая) будет совершено i циклов алгоритма, после чего защищенный участок будет корректно исполнен. При работе отладчика, управляемого человеком, скорость выполнения программы на несколько порядков ниже, поэтому для достижения необходимого значения i будет затрачено значительное время.

Для численной оценки данного метода введем следующие значения. Предположим, что i в среднем равно N/2. Пусть w0 — время выполнения цикла алгоритма (установка текущего значения, расшифрование, проверка правильности расшифрования) в штатном режиме функционирования (без отладки);.w1 — время выполнения того же цикла в режиме отладки; z — предельное время задержки при штатной работе защищенной программы. Тогда N = z / w0. Затраты времени злоумышленника исчисляются средней величиной Тзл = Nw1/2. Для приблизительных расчетов w1/w0 » 10000.

В ряде способов защиты от отладки идентификация отладчика и направление его по ложному пути происходят одновременно, в одном и том же фрагменте кода (так, при определении стека в области кода защищаемой программы при работе отладчика, использующего тот же стек, код программы будет разрушен). В других случаях ложный путь в работе программы формируется искусственно. Часто для этого используют динамическое преобразование программы (шифрование) во время ее исполнения.

Способ динамического преобразования заключается в следующем: первоначально в оперативную память загружается фрагмент кода, содержание части команд которого не соответствует тем командам, которые данный фрагмент в действительности выполняет; затем этот фрагмент по некоторому закону преобразуется, превращаясь в исполняемые команды, которые затем и выполняются.

Преобразование кода программы во время ее выполнения может преследовать три основные цели:

• противодействие файловому дизассемблированию программы;

• противодействие работе отладчика;

• противодействие считыванию кода программы в файл из оперативной памяти.

Перечислим основные способы организации преобразования кода программы.

1. Замещение фрагмента кода функцией от находящейся на данном месте команде и некоторых данных.

2. Определение стека в области кода и перемещение фрагментов кода с использованием стековых команд.

3. Преобразование кода в зависимости от содержания предыдущего фрагмента кода или некоторых условий, полученных при работе предыдущего фрагмента.

4. Преобразование кода в зависимости от внешней к программе информации.

5. Преобразование кода, совмещенное с действиями, характерными для работы отладочных средств.

Поясним кратко приведенные способы. Первый способ заключается в том, что по некоторому адресу в коде программы располагается, например, побайтовая разность между реальными командами программы и некоторой хаотической информацией, которая располагается в области данных. Непосредственно перед выполнением данного участка программы происходит суммирование хаотической информации с содержанием области кода и в ней образуются реальные команды.

Второй способ состоит в перемещении фрагментов кода программы в определенное место или наложении их на уже выполненные команды при помощи стековых операций.

Третий способ служит для защиты от модификации кода программы и определения точек останова в программе. Он состоит в том, что преобразование следующего фрагмента кода происходит на основе функции, существенно зависящей от каждого байта или слова предыдущего фрагмента или нескольких фрагментов кода программы. Такую функцию называют обычно контрольной суммой участка кода программы. Особенностью данного способа является то, что процесс преобразования должен существенно зависеть от посчитанной контрольной суммы (хеш-функции) и не должен содержать в явном виде операций сравнения.

Четвертый способ заключается в преобразовании кода программы на основе некоторой внешней информации, например считанной с ключевой дискеты некопируемой метки, машинно-зависимой информации или ключа пользователя. Это позволит исключить анализ программы, не имеющей ключевого носителя или размещенной на другом компьютере, где машинно-зависимая информация иная.

Пятый способ состоит в том, что вместо адресов отладочных прерываний помещается ссылка на процедуру преобразования кода программы. При этом либо блокируется работа отладчика, либо неверно преобразуется в исполняемые команды код программы.

Часто с отладочными прерываниями бывают совмещены сложные алгоритмы преобразования кода программы, которые при выполнении каждой команды производят преобразование последующей команды в исполняемую и предыдущей в хаотический код. Такой метод получил название "бегущая строка". Как правило, это прерывание int 1h (ONE STEP). Для успешного применения данного метода обязательно выполнение следующих условий:

- невозможность переопределения функции, замещающей отладочное прерывание и выполняющей преобразование кода программы, на неиспользуемое прерывание;

- отсутствие операций сравнения для определения факта работы под отладчиком.

Выполнить первое условие возможно, просчитывая контрольные суммы (хеш-функции) пройденного участка кода либо вводя в функциях, замещающих отладочные прерывания, зависимость от положения их в таблице прерываний.

Если нельзя избежать операции сравнения (например, чтобы нелегальная копия программы не "зависала"), то желательно сравнивать не контрольные числовые значения, а некоторые необратимые или сложнообратимые функции от них.

Важной задачей является защита от трассировки программы по заданному событию (своего рода выборочное исследование). В качестве защиты от трассировки по заданному событию (прерыванию) можно выделить ряд основных способов.

1. Пассивная защита — запрещение работы при переопределении обработчиков событий относительно заранее известного адреса.

2. Активная защита первого типа — замыкание цепочек обработки событий минуя программы трассировки.

3. Активная защита второго типа — программирование функций, исполняемых обработчиками событий, другими способами, не связанными с вызовом "штатных" обработчиков или обработчиков событий, которые в текущий момент не трассируются.

Например, для защиты от трассировки по дисковым прерываниям для DOS при чтении некопируемой метки с дискеты или винчестера можно использовать следующие приемы:

- работа с ключевой меткой путем прямого программирования контроллера гибкого диска (активная защита второго типа);

- определение одного из неиспользуемых прерываний для работы с диском (активная защита первого типа);

- прямой вызов соответствующих функций в ПЗУ (BIOS) после восстановления различными способами их физического адреса (активная защита первого типа);

- определение факта переопределения адреса прерывания на другую программу и невыполнение в этом случае дисковых операций (пассивная защита).

При операциях с жестким диском, как правило, используется прерывание int 13h. Для предотвращения трассировки программы по заданному прерыванию (в данном случае прерыванию int 13h) можно также использовать указанные выше способы, а именно:

- переопределение исходного прерывания в BIOS на неиспользуемый вектор прерывания;

- прямой вызов функций BIOS.

Прерывание int 1h относится к аппаратным прерываниям, вызываемым особым состоянием процессора. Данное состояние достигается установкой специального флага трассировки в регистре флагов. При этом после завершения выполнения каждой инструкции процессора автоматически вызывается прерывание int 1h (режим покомандного управления). Для того чтобы включение трассировки не воздействовало на саму программу — обработчик первого прерывания (в режиме обычной работы она состоит из одной команды iret), при вызове прерывания флаг трассировки автоматически сбрасывается. Поскольку при вызове прерывания регистр флагов автоматически сохраняется в стеке, а при окончании работы обработчик его автоматически восстанавливает, то после обработки прерывания управление возвращается к следующей трассируемой команде вновь с установленным флагом трассировки. Функционально это аналогично тому, что после каждой команды прикладной программы находится команда вызова первого прерывания. Выполнив покомандно цепочку int 13h и проанализировав исполняемые инструкции, можно легко определить точки входа в BIOS.

Часто недооценивается опасность трассировки по событиям операционной среды. В основном таким образом могут быть выделены следующие действия программ:

- определение факта замены обработчиков событий на собственные функции (в частности, для защиты от отладчиков);

- файловые операции, связанные со считываниями различных счетчиков или паролей, вычисление контрольных сумм и хеш-функций файлов;

- файловые операции, связанные со считыванием заголовков и другой существенно важной информации в исполняемых файлах или загружаемых библиотеках.

Кроме того, в защищаемых программах, полученных при помощи распространенных компиляторов, в самом начале идет последовательность предопределенных событий операционной среды (для программ DOS — прерываний 21h). Этот факт позволяет в очень многих случаях при остановке на одном из этих прерываний считать код программы из оперативной памяти в незащищенном виде, поскольку к этому моменту антиотладочные средства обычно завершают свою работу.

 

Основы использования IDA

 

Запуск IDA

Начнем с описания опций, которые предоставляет IDA при запуске, а затем объясним, что именно происходит, когда вы открываете бинарный файл для анализа. Наконец, мы сделаем краткий обзор пользовательского интерфейса.

Для единообразия примеры будут представлены с GUI Windows, за исключением случаев, когда разговор идет о специфической версии IDA (например, в примере отладки под Linux).

Обратите внимание: При установке в Windows IDA создает ключ реестра HKEY_CURRENT_USER\Software\Hex-Rays\IDAC:\launching_ida.html - CHP-4-FNOTE-1. Многие опции, которые можно изменять из самого IDA (не редактируя файлы конфигурации) хранятся в этом ключе. На других платформах IDA хранит подобные значения в бинарном файле данных ($HOME/.idapro/ida.cfd), который непросто редактировать. 

При запуске IDA встретит вас загрузочным экраном, отображающим информацию о лицензии. После него отображается диалог, предлагающий три способа попасть в рабочее окружение:

New запускает помощника, который будет направлять вас при выборе файла для анализа. Вначале пользователь должен определить тип файла, который он хочет открыть. После того, как указан тип файла, для выбора файла используется стандартный диалог "Открыть файл". Наконец, отображается один или более дополнительных диалогов, которые позволяют вам указать специфические опции для анализа перед тем, как файл будет загружен, проанализирован и отображён.

Трудность в работе с помощником New File кроется в том, что пользователь должен точно знать тип файла, который необходимо открыть. Если тип файла неизестен, лучше использовать другой метод загрузки в IDA. Кнопка New соответствует команде File ► New. 

Go прерывает процесс загрузки и открывает IDA с пустой рабочей областью. Команда File ► New запускает помощник New File Wizard. Команда File ► Open запускает диалог "открыть файл" без запуска помощника.

По умолчанию IDA применяет фильтр known extensions. Убедитесь, что в фильтре установлено нужное вам значение или он вообще отключен (необходимо выбрать "All Files". Когда вы открываете файл этим способом, IDA пытается автоматически определить тип загружаемого файла. 

Previous позволяет открыть ранее используемые файлы. Список этих файлов наполняется значениями из записи History ключа реестра IDA. 

Загрузка файла в IDA. Если вы решите открыть файл, используя команду File ► Open. IDA генерирует список потенциальных типов файлов и отображает этот список вверху диалога. Список показывает, какие загрузчики IDA лучше всего подходят для работы с выбранным файлом. Этот список создается в результате запуска каждого файлового загрузчика в директории loaders. Если не знаете, какой загрузчик выбрать, неплохим решением будет остановиться на выбранном по умолчанию варианте.

Иногда Binary File будет единственной записью, доступной в списке загрузчиков. В таком случае подразумевается, что ни один из загрузчиков не распознал выбранный файл. 

Выпадающее меню Processor Type позволяет вам указать, какой процессорный модуль (из директории procs IDA) надо использовать при дизассемблировании. 

Поля Loading Segment и Loading Offset активны, только если выбраны выходной формат Binary File и процессор семейства x86. Так как двоичный загрузчик не может извлечь из файла какую-либо информацию о размещении памяти, значения сегмента и смещения используются для получения начального адреса загруженного содержимого. Если вы забудете указать начальный адрес во время загрузки, его в любое время можно изменить с помощью команды Edit ► Segments ► Rebase Program command.

Кнопки Kernel Options предоставляют доступ к конфигурации специфических опций дизассемблирования, которые IDA будет использовать для улучшения процесса рекурсивного погружения. 

Кнопки Processor Options предоставляют доступ к опциям конфигурации выбранного процессорного модуля. 

Оставшиеся опции используются для тонкой настройки процесса загрузки файов, каждая опциям подробно описана в файле помощи IDA. 

Файлы баз данных IDA. Когда вы будете довольны опциями загрузки, то нажмите ОК, чтобы закрыть диалог (или Finish). После этого IDA загрузит выбранный исполняемый файл в память и проанализирует необходимые части этого файла. В результате будет создан файл базы данных IDA, компоненты которого хранятся в четырех файлах. Их имена совпадают с именем выбранного исполняемого файла, а разрешения становятся .id0, .id1, .nam, и .til. В файле .id0 находится содержимое базы данных В-дерева, тогда как файл .id1 содержит флаги, описывающие каждый байт программы. Файл .nam содержит индексную информацию, относящуюся к именованным областям программы, которые отображаются в окне имён IDA. Наконец, файл .til используется для хранения информации о локальных определениях типов, специфических для конкретной базы данных. Формат каждого из этих файлов является проприетарным форматом IDA, и их непросто редактировать без помощи инструментария IDA.

Для удобства эти четыре файла архивируются (опционально – со сжатием) в единственный IDB-файл каждый раз, когда вы закрываете текущий проект. Когда говорят о базе данных IDA, обычно имеют в виду IDB-файл. Если база данных закрыта корректно, вы не увидите файлов с расширениями .id0, .id1, .nam, or .til в ваших рабочих директориях. 

Создание базы данных IDA. После того, как вы укажете файл для анализа и выставите нужные опции, IDA начнет создание базы данных. Загрузчик IDA определяет структуру виртуальной памяти на основе информации, содержащейся в заголовке файла, и соответствующим образом конфигурирует базу данных.

После загрузчика работать начинает движок дизассемблирования IDA. Он передает выбранному процессорному модулю по одному адресу. Задача процессорного модуля – определить тип команды, расположенной по этому адресу, длину команды и место, с которого программа продолжит работу после выполнения инструкции. Когда IDA отыщет все команды в файле, он делает второй проход по списку адресов команд и просит процессорный модуль сгенерировать ассемблерную версию каждой команды.

После дизассемблирования IDA автоматически проводит дополнительный анализ двоичного файла, чтобы извлечь дополнительную информацию, полезную для аналитика. Информация типов, перечисленных ниже, может быть найдена и интегрирована в базу данных после начального анализа:

− Идентификация компилятора может помочь понять соглашения вызова функций, использованных в двоичном файле, а также определить, с какими библиотеками может быть связан файл. 

− Идентификация аргументов функций и локальных переменных. Для каждой идентифицированной функции IDA проводит детальный анализ поведения регистра указателя стека чтобы определить доступ к переменным внутри стека и понять структуру стекового кадра. 

− Информация типов данных. Используя знания о распространенных библиотечных функциях и требуемых ими параметрах, IDA добавляет в базу данных комментарии, указывающие, в каких местах параметр передается этим функциям. 

Закрытие баз данных IDA. Если это первое сохранение новой базы данных, имя базы будет соответствовать имени входного файла, а расширение будет заменено на .idb (например, example.exe получит базу данных example.idb). Если у входного файла нет расширения, .idb все равно добавляется к имени (например, httpd становится httpd.idb). Доступные опции сохранения и их описания приведены ниже:

− Don't pack database. Эта опция просто сбрасывает изменения четырех компонентов базы данных и закрывает рабочее окружение, не создавая IDB-файл. 

− Pack database (Store). Выбор этой опции архивирует четыре компонента базы данных в единый IDB-файл. Предыдущий IDB будет перезаписан без подтверждения. 

− Pack database (Deflate). Эта опция аналогична предыдущей, за исключением того, что компоненты базы данных будут сжаты внутри IDB-архива.

− Collect garbage. Чтобы создать IDB-файл минимального размера, выберете эту опцию вместе с Deflate. Эту опцию обычно использует только в случае, если места на диске недостаточно.

− DON'T SAVE the database. Эта опция – единственный способ не сохранять изменения, сделанные в базе данных с момента последнего сохранения и наиболее близкий аналог отмены, доступный в IDA.

Повторное открытие баз данных. Нужно выбрать базу данных одним из методов открытия файлов IDA. Базы данных открываются гораздо быстрее во второй раз потому что никакого анализа выполнять не надо.

Любые сбои могут повредить открытую базу данных.

В таком случае у IDA нет возможности закрыть активную базу данных, и потому временные файлы базы данных не удаляются. IDB-файл соответствует последнему стабильному состоянию базы данных, а временные файлы содержат изменения, которые могли быть сделаны с момента последнего сохранения. Вариант «Choosing Continue with Unpacked Base» вовсе не гарантирует, что вы восстановите свою работу. 

Другая ситуация, если базу данных вообще никогда не сохраняли, и от нее остались только временные файлы, с которыми велась работа на момент сбоя. В этом случае IDA предложит использовать опцию исправления сразу, как только вы откроете исполняемый файл.

 

Рабочая область IDA

Здесь присутствуют следующие области:

Область панели инструментов содержит инструменты, соответствующие наиболее часто используемым операциями IDA. Панели инструментов добавляются и удаляются из рабочей области с помощью команды View ► Toolbars command. 

Цветная горизонтальная панель - это навигатор обзора, или просто полоска навигации. Навигационная полоска отображает линейный вид адресного пространства загруженного файла. Маленький индикатор текущей позиции (по умолчанию желтый) на навигационной полоске указывает на адресный диапазон, который отображается в данный момент в главном окне. Щелчок по навигационной полоске отображает соответствующую часть двоичного файла в окне дизассемблирования. 

Окна данных содержат информацию, извлеченную из двоичного файла и отображающуюся в виде различных представлений базы данных. Большая часть вашего анализа скорее всего будет заключаться в работе с этими окнами. Дополнительные окна видов данных доступны через меню View ► Open Subviews, также это меню используется для восстановления нечаянно закрытых окон данных.

Окно дизассемблирования служит основным средством вывода данных. У него есть два режима вывода: граф (по умолчанию) и листинг. В режиме графа IDA отображает схематический граф одной функции. Обзор графов поможет понять процесс выполнения функции. Когда окно IDA-View активно, пробел переключает режимы между графом и листингом. Если вы хотите сделать режим листинга режимом по умолчанию, вы должны снять галочку с опции Use Graph View by Default на вкладке Graph в меню Options ► General.

Обзор графа, доступный только когда активен режим графа, предоставляет общий вид базовой структуры графа. Пунктирный прямоугольник показывает текущую область, видимую в окне. 

Окно сообщений предоставляет всю информацию, генерируемую IDA.

Поведение рабочей области при начальном анализе. Во время начального автоанализа нового файла в главном окне Вы можете увидеть такие процессы, как:

− Сообщения о прогрессе появляются в окне сообщений.

− Для окна дизассемблирования генерируется вывод дизассемблирования.

− Наполняется окно строк, после чего в конце фазы анализа происходит последнее сканирование.

− Окно имён наполняется и периодически обновляется в процессе анализа.

− Навигационная полоска изменяется, так как распознаются новые области кода и данных, затем блоки кода распознаются как функции и, наконец, с использованием техник сопоставления шаблонов IDA функции распознаются как конкретный библиотечный код.

− Индикатор текущей позиции перемещается по навигационной полоске, показывая область, анализируемую в данный момент.

Дваособеннополезныхсообщенияэто You may start to explore the input file right now и The initial autoanalysis has been finished. Первое сообщение информирует вас о том, что IDA достаточно проанализировал файл для того, чтобы уже можно было изучать его с помощью различных окон данных. Если вы попытаетесь изменить базу данных до завершения этапа анализа, аналитический движок может вернуться и модифицировать ваши собственные изменения, или вы можете помешать ему выполнить анализ. Второе оповещает, что никаких автоматических изменений больше не будет. Теперь можно вносить в базу данных любые изменения.

Советы и хитрости рабочего окружения IDA. IDA предлагает огромный объем информации, и окно может стать сильно загромождено. Вот некоторые советы, которые помогут вам наиболее эффективно использовать рабочее окружение:

Чем больше экранного пространства вы выделите для IDA, тем приятней будет работать. Этим фактом вполне можно оправдать покупку гигантского монитора (или двух)!

Не забудьте, что команду View ► Open Subviews можно использовать для восстановления нечаянно закрытых окон данных.

Команда Windows ► Reset Desktop позволяет быстро вернуть рабочее окружение к виду по умолчанию.

Используйте команду Windows ► Save Desktop, чтобы сохранить текущий вид рабочего окружения. The Windows ► Load Desktop позволит вернуть сохраненный вид рабочего окружения.

Единственное окно, для которого можно менять шрифт, это окно дизассемблирования (и в режиме графов, и в режиме листинга). Шрифт задается командой Options ► Font.

 

Окна данных IDA

 

Перед тем, как мы займемся основными окнами IDA, полезно обсудить несколько базовых понятий, касающихся пользовательского интерфейса IDA: 

− В IDA нет отмены. Если с вашей базой данных произойдет что-то неожиданное, вам самостоятельно придется восстанавливать все до прежнего состояния.

− Практически все действия имеют собственный пункт меню, горячую клавишу и кнопку на панели инструментов. Помните, что как панель инструментов IDA, так и горячие клавиши можно сконфигурировать под свои нужды.

− IDA предоставляет мощное контекстно-зависимое меню по правому щелчку мыши. Хотя это меню и не отображает полный список доступных действий, оно напоминает о наиболее часто используемых командах, которые могут вам понадобиться.

 

Основные окна IDA

В конфигурации по умолчанию во время начального этапа загрузки и анализа IDA создает восемь (в версии 5.2) окон. Каждое из этих окон доступно через одну из вкладок, которые отображаются сразу под навигационной полоской. Три непосредственно видимых окна это окно обзора, окно имен и окно сообщений. Все эти окна можно открыть через меню View ► Open Subviews. 

Когда активно окно дизассемблирования, ESC работает аналогично кнопке «Назад». Любое другое окно ESC просто закрывает. 

 

Окно дизассемблирования

Для окна дизассемблирования доступно два формата: текстовый листинг и графы, добавленные в версии 5.0. Режим графа всегда включается по умолчанию. Вы можете изменить его поведения с помощью вкладки Graph диалога Options ► General. Когда окно дизассемблирования активно, вы можете переключаться между графом и листингом в любое время по нажатию пробела.

 

Просмотр графа

Просмотр графа немного напоминает блок-схему программы тем, что функция разбита на базовые блоки, что позволяет визуализировать переход функции от одного блока к другому. 

IDA использует стрелки разных цветов, чтобы различать течения различных типов между блоками функции. Базовые блоки, которые прерываются переходом по условию, генерируют два возможных течения в зависимости от проверяемого условия: край «Да» (есть переход по этой ветке) по умолчанию зеленый, край «Нет» - красный. Блоки без ветвления, имеющие всего один вариант продолжения, используют нормальный край (по умолчанию синий) для указания на следующий блок.

В режиме графа IDA отображает одну функцию за раз. Зажав CTRL и прокручивая колесико мыши, можно приближать и отдалять граф. То же самое можно выполнить, зажав CTRL и нажимая клавиши + и – на дополнительной клавиатуре. В случаях больших или сложных функции может пригодиться окно Общего вида графа. Оно всегда отображает структуру графа целиком, а пунктирная рамка показывает область, которая отображена в окне дизассемблирования. 

Существует несколько способов изменить вид дисплея графов для своих нужд.

Panning. IDA прячет менее необходимую информацию о каждой ассемблерной строчке (например, информацию о виртуальном адресе) чтобы блок занимал меньше места на экране. Вы можете включить отображение дополнительной информации с каждой строчкой кода, выбирая нужные пункты в disassembly line parts, доступном во кладке Disassembly через меню Options ► General. Например, чтобы добавить виртуальные адреса к каждой строчке, мы включаем line prefixes.

Перемещение блоков. Отдельные блоки внутри графа можно перемещать на новые места, нажимая на панель с названием блока и перетаскивая в нужное место. Вы можете вручную перенаправить края, перетаскивая вершины в новые места. Новую вершину можно сделать, дважды кликнув по желаемому месту на крае, зажав клавишу SHIFT. Если вам понадобится вернуться к расположению графа по умолчанию, вы можете щелкнуть по графу правой кнопкой и выбрать Layout Graph.

Группировка и сворачивание блоков. Блоки можно группировать, по одному или вместе с другими блоками, и сворачивать, чтобы освобождать место на экране. Свернуть блок можно, нажав правой кнопкой по его панели с названием и выбрав Group Nodes.

Создание дополнительных окон дизассемблирования. Если вы захотите видеть графы двух разных функций одновременно, вам надо всего лишь открыть новое окно дизассемблирования, используя Views ► Open Subviews ► Disassembly. Первое окно дизассемблирования называется IDA View-A, последующие - IDA View-B, IDA View-C и так далее. Каждое окно дизассемблирование независимо от других.

 

Режим текста

Текстовое окно дизассемблирования – традиционный режим просмотра сгенерированного IDA кода. Текстовый дисплей показывает полный листинг программы (а не единственную функцию, как в режиме графов) и только он предоставляет средства для просмотра области данных двоичного файла. Вся информация, доступная в режиме графа, в том или ином виде доступна и в текстовом режиме.

Ассемблерный код представленный линейно, виртуальные адреса по умолчанию включены и обычно отображаются в формате [название раздела]:[виртуальный адрес], например, text:0040110C0.

Окно стрелок используется для отображения нелинейных переходов внутри функции. Обычные стрелки соответствуют безусловным переходам, а пунктирные – переходам по условию. Когда переход передает управление более раннему адресу программы, используется жирная линия. Обратное течение в программе указывает на наличие цикла. 

Объявления отражают оценку стекового кадра, сделанную IDA. IDA определяет структуру стекового кадра функции, выполняя детальный анализ поведения указателя стека и всех указателей стековых кадров, использованных в функции.

Комментарии (точка с запятой начинает комментарий) - это перекрёстные ссылки. 

Для примеров в книге мы чаще всего будем использовать текстовый режим. 

 

Окно имён

Окно имён предоставляет общий список всех глобальных имен в двоичном файле. Имя – не более чем символическое описание, данное виртуальному адресу программы. IDA получает список имен с помощью символьной таблицы и анализа подписи во время начальной загрузки файла. Имена можно отсортировать по алфавиту или в порядке виртуальных адресов (по возрастанию и по убыванию). Двойной щелчок по любой записи окна имён отобразит в окне дизассемблирования выбранное имя.

Отображаемые имена кодируются цветом и буквами. Система кодирования описана ниже:

• F Обычная функция. Эти функции IDA не распознает как библиотечные.

• L Библиотечная функция. IDA распознает библиотечные функции с помощью алгоритма сопоставления подписей.

• I Импортированное имя, чаще всего имя функции из общей библиотеки.

• C Именованный код. Это именованные места программы, которые IDA не относит ни к каким функциям.

• D Данные. Именованные секции даты обычно представляют собой глобальные переменные.

• A Строковые данные ASCII. Это секция данных, содержащая четыре или более последовательных символа ASCII, завершаемых нулевым байтом.

В процессе дизассемблирования IDA генерирует имена для всех мест, на которые есть прямые ссылки как на код (цель ветвления или вызова) или как на данные (чтение, запись или взятие адреса). Если место именовано в символьной таблице имен, IDA заимствует имя из таблицы. Если для данного места записи в таблице нет, IDA генерирует имя по умолчанию, которое будет использоваться при дизассемблировании. Когда IDA решает назвать место, виртуальный адрес места совмещается с префиксом, указывающим на тип места. Ниже перечислены наиболее часто встречаемые префиксы, используемые при автоматической генерации:

− sub_xxxxxx - Подпрограмма по адресу xxxxxx

− loc_xxxxxx - Инструкция, расположенная по адресу xxxxxx

− byte_xxxxxx - 8-битовые данные по адресу xxxxxx

− word_xxxxxx - 16-битовые данные по адресу xxxxxx

− dword_xxxxxx - 32-битовые данные по адресу xxxxxx

− unk_xxxxxx

Данные неизвестного размера по адресу xxxxxx.

 

Окно сообщений

Окно сообщений служит для IDA выходной консолью, там надо искать информацию о задачах, выполняемых IDA. Когда открывается новый двоичный файл, генерируются сообщения, сообщающие об этапе анализа, который на данный момент выполняет IDA, а также о действиях, выполняемых IDA для создания новой базы данных. 

 

Окно строк

Окно строк – это встроенный в IDA эквивалент утилиты strings с некоторыми дополнениями. Начиная с версии 5.2, окно строк не открывается само, но доступно с помощью View ► Open Subviews ► Strings.

Окно строк отображает список строк, извлеченных из двоичного файла, а также адреса, где они находятся. При использовании перекрестных ссылок, окно строк позволяет быстро обнаружить интересующую вас строку и отследить ее к месту ссылки на нее программой. Сканирование на предмет содержания строк выполняется в соответствии с настройками окна строк, вы можете получить к ним доступ, нажав правой кнопкой в пределах окна строк и выбрав Setup. Окно Setup Strings используется для указания типов строк, которые будет искать IDA. По умолчанию IDA ищет написанные в стиле Си, прерываемые нулём, 7-битовые ASCII-строки, состоящие по меньшей мере из пяти символов.

Для поиска строки другого типа, вы должны перенастроить сканирование и выбрать соответствующий тип строк. Каждый раз, когда вы закрываете окно Setup Strings, нажимая ОК, IDA повторно сканирует базу данных в соответствии с новыми настройками. Две опции заслуживают отдельного упоминания:

− Отображать только определенные строки. Эта опция заставляет окно строк отображать только именованные строковые данные, которые были автоматически созданы IDA или вручную – пользователем. С этой IDA не будет автоматически сканировать файл на предмет строк.

− Игнорировать определения команд/данных. Эта опция заставляет IDA искать строки в командах и существующих данных. Использование этой опции позволяет IDA, во-первых, видеть строки, встроенные в программную часть двоичного файла и по ошибке сконвертированные в команды и, во-вторых, распознавать строки внутри данных, отформатированные как что-то другое. 

IDA показывает не все строки внутри двоичного файла, если настройка не сконфигурирована соответствующим образом. 

 

Дополнительные окна IDA

Также IDA открывает несколько окон, свернутых в вашем рабочем окружении. Вкладки для быстрого доступа этих окон находятся под навигационной лентой. Эти окна предлагают альтернативные или специализированные представления базы данных. 

Окно шестнадцатеричного просмотра. Окно шестнадцатеричного просмотра отображает стандартный шестнадцатеричный дамп содержимого программы и списков, по 16 байт на строку. ASCII-эквиваленты отображаются сбоку. Одновременно может быть открыто несколько окон шестнадцатеричного просмотра. Первое окно называется Hex View-A, второе - Hex View-B, следующее Hex View-C и так далее. По умолчанию первое окно синхронизируется с первым окном дизассемблирования. Когда окно дизассемблирования синхронизировано с окном шестнадцатеричным просмотра, прокрутка одного из окон заставляет другое прокручиваться до того же места (того же виртуального адреса). Если что-то выделено в окне дизассемблирования, соответствующие байты подсвечиваются в окне шестнадцатеричного просмотра. Отключение опции синхронизации позволяет прокручивать окна независимо друг от друга.

В некоторых случаях шестнадцатеричное окно не показывает ничего, кроме вопросительных знаков. Таким способом IDA сообщает вам, что он не знает, какие значения могут находиться в данной области виртуального адресного пространства. 

Окно экспортов. Окно экспортов перечисляет входные точки файла. Они включают в себя входную точку исполнения программы, как указано в заголовочном разделе, а также все функции и переменные, которые файл экспортирует для использования другими файлами. Экспортированные записи отображают имя, виртуальный адрес и, если это возможно, порядковый номер. Для исполняемых файлов окно экспортов всегда содержит по меньшей мере одну запись: входную точку исполнения программы. IDA называет эту точку start. Далее приведена типичная запись окна экспортов: 

LoadLibraryA 7C801D77 578

Двойной щелчок по записи в окне экспортов перемещает окно дизассемблирования к адресу, связанному с данной записью. Функции окна экспортов доступны через утилиты командной строки, такие как objdump (-T), readelf (-s) и dumpbin (/EXPORTS).

Окно импортов. Окно импортов перечисляет все функции, импортируемые анализируемым двоичным файлом. Окно импортов нужно, только в случае если двоичный файл использует общие библиотеки. Каждая запись в окне импортов включает в себя имя импортируемой функции или данных и имя библиотеки, их содержащей. Так как код импортируемой функции находится в общей библиотеке, адресный список для каждой записи относится к виртуальным адресам связанной с ним записи в таблице импорта. Пример записи таблицы импорта показан ниже:

0040E108 GetModuleHandleA KERNEL32

Двойной щелчок по этой записи заставит окно дизассемблирования переместиться к адресу 0040E108.

Функции окна импортов также доступны через утилиты командной строки, такие как objdump (-T), readelf(-s), и dumpbin (/IMPORTS).

Окно функций. Окно функций перечисляет все функции, распознанные IDA в базе данных. Запись окна функций может выглядеть так:

malloc .text 00BDC260 00000180 R . . . B . .

Эта строка указывает на то, что функция malloc находится в разделе .text по виртуальному адресу 00BDC260, размером 384 байт (180 в шестнадцатеричной), возвращается к вызову (R) и использует регистр EBP (B) для ссылки на свои локальные переменные. Флаги, используемые для описания функции (такие как R и B в примере выше), расшифровываются во встроенной помощи IDA.

Как и с другими окнами, двойной щелчок по записи в окне функций заставляет окно дизассемблирования перейти к местоположению выбранной функции.

Окно структур. Окно структур используется для отображения распознанных IDA сложных структур данных, таких, как structs и unions в Си. На этапе анализа IDA сопоставляет используемую в программе память с библиотекой подписей.

Двойной щелчок по имени структуры данных заставляет IDA расширить структуру, что позволяет вам увидеть ее детальную схему, включая имена и размеры отдельных полей.

Две основные функции окна структур - отображение стандартных структур данных и предоставление средств для создания собственных структур данных для использования в качестве шаблонов размещения памяти, если вы узнаете, что программа использует собственные структуры данных.

Окно перечислений. Если IDA обнаруживает использование стандартного перечисляемого типа данных, этот тип данных будет указан в окне перечислений. Окно перечислений позволяет определять собственные перечисляемые типы, которые вы сможете использовать с дизассемблируемыми двоичными файлами.

 

Вспомогательные экраны IDA

Каждое из этих окон доступно через меню View ► Open Subviews, они предоставляют информацию, которая нужна не всегда, поэтому изначально они отсутствуют на экране.

Окно сегментов. Окно сегментов отображает общий список сегментов, присутствующих в двоичном файле. Обратите внимание, что в терминах IDA сегментами обычно называют секции, на которое разбит двоичный файл. Информация, отображаемая в данном окне, включает в себя имя сегмента, начальный и конечный адреса и флаги разрешений. Начальный и конечный адреса представляют диапазон виртуального адресного пространства, который будет назначен данной части программы при выполнении. Ниже приведен пример содержимого окна сегментов:

Name Start End R W X D L Align Base Type Class AD es ss ds fs gs

UPX0 00401000 00407000 R W X . L para 0001 public CODE 32 0000 0000 0001 FFFFFFFF F

FFFFFFF

UPX1 00407000 00408000 R W X . L para 0002 public CODE 32 0000 0000 0001 FFFFFFFF F

FFFFFFF

UPX2 00408000 0040803C R W . . L para 0003 public DATA 32 0000 0000 0001 FFFFFFFF F

FFFFFFF

.idata 0040803C 00408050 R W . . L para 0003 public XTRN 32 0000 0000 0001 FFFFFFFF F

FFFFFFF

UPX2 00408050 00409000 R W . . L para 0003 public DATA 32 0000 0000 0001 FFFFFFFF F

FFFFFFF

 

В данном случае мы можем подозревать, что с данным двоичным файлом что-то не так, поскольку он использует нестандартные имена сегментов, и два его сегмента кода доступны для записи, что позволяет реализовать самомодифицирующий код. То, что IDA знает размер сегмента, не означает, что нам известно и его содержимое. По ряду причин сегменты часто занимают меньше места на диске, чем в памяти. В таких случаях IDA отображает значения для тех частей сегмента, которые IDA смог взять из файла на диске. Для остальных сегментов отображаются вопросительные знаки.

Двойной щелчок по любой записи в окне перемещает окно дизассемблирования к началу выбранного сегмента. Щелчок правой кнопкой мыши по записи выводит контекстное меню, которое позволяет добавлять новые сегменты, а также изменять и удалять существующие.

Функции окна сегментов, доступные из командной строки, включают в себя objdump (-h), readelf (-S), и dumpbin (/HEADERS).

Окно сигнатур. Сигнатуры используются для идентификации распространенных последовательностей запуска, сгенерированных компилятором, чтобы определить, каким компилятором был собран данный двоичный файл. Кроме того, сигнатуры используются для категоризации функций в качестве известных библиотечных функций, вставленных компилятором, или в качестве функций, добавленных в двоичный файл в результате статической линковки.

Окно сигнатур используется для перечисления распознанных IDA сигнатур. Примериз Windows PE показанниже:

File State #func Library name

vc32rtf Applied 501 Microsoft VisualC 2-8/net runtime

Данный пример показывает, что IDA сопоставил с файлом сигнатуры vc32rtf (из <IDADIR>/sigs) и, сделав это, смог распознать 501 библиотечных функций.

Применение дополнительных сигнатур может быть весьма полезным. IDA может не распознать компилятор и не сможет выбрать нужные сигнатуры для сопоставления. В этом случае вам придется заставить IDA применить одну или более сигнатур самостоятельно. Вы можете создавать собственные сигнатуры для библиотек, для которых у IDA сигнатур нет. Чтобы применить новые сигнатуры, нажмите клавишу INSERT или щелкните правой кнопкой по окну сигнатур, и вам будет предложено применить новую сигнатуру из списка всех сигнатур, известных вашему IDA.

Окно библиотеки типов. Окно библиотек типов похоже на окно сигнатур. Библиотеки типов отражают знания IDA о стандартных типах данных и прототипах функций, используемых наиболее популярными компиляторами. Обрабатывая заголовочные файлы, IDA понимает, какие типы данных можно ожидать от библиотечных функций и делает соответствующие комментарии к коду. Также из заголовочных файлов IDA узнает о размере и положении сложных структур данных. Вся эта информация собрана в TIL-файлах (<IDADIR>/til) и. Чтобы загрузить нужный набор TIL-файлов, IDA должен вначале определить, какие библиотеки используются в программе. Вы можете заставить IDA загрузить дополнительные библиотеки типов, нажав INSERT или щелкнув правой кнопкой в окне библиотеки типов и выбрав Load Type Library.

Окно вызовов функций. Граф, отображающий отношения между вызывающими и вызываемыми функциями, называют граф вызова функций или дерево вызова функций . Иногда нам будет нужно увидеть не весь граф целой программы, а только ближайших соседей конкретной функции. Будем называть Y соседом X, если Y непосредственно вызывает X или X вызывает Y.

Когда вы открываете окно вызовов функций, IDA определяет соседей выбранной функции и генерирует окно.

Двойной щелчок по любой строчке окна вызовов функций перемещает окно дизассемблирования к выбранной функции (вызывающей или вызванной). Перекрестные ссылки IDA (xrefs) – это механизмы, которые лежат в основе генерации окна вызовов функций.

Окно проблем. С помощью окна проблем IDA информирует вас обо всех трудностях, которые возникли у него в процессе дизассемблирования двоичного файла и о том, какие решения были приняты для их преодоления. Ниже приведен пример набора проблем:

Address Type Instruction

.text:0040104C BOUNDS call eax

.text:004010B0 BOUNDS call eax

.text:00401108 BOUNDS call eax

.text:00401350 BOUNDS call dword ptr [eax]

.text:004012A0 DECISION push ebp

.text:004012D0 DECISION push ebp

.text:00401560 DECISION jmp ds:__set_app_type

.text:004015F8 DECISION dd 0FFFFFFFFh

.text:004015FC DECISION dd 0

 

Каждая проблема характеризуется, во-первых, адресом, в котором она возникла, во-вторых, типом проблемы и, в-третьих, командой в месте возникновения проблемы. В этом примере мы видим проблемы BOUNDS и DECISION. Проблема BOUNDS возникает, когда место назначения вызова или перехода невозможно установить или находится внутри виртуального диапазона адресов программы. Проблема DECISION обычно представляет адрес, по которому IDA решил дизассемблировать байты как команду, а не как данные, несмотря на то, что на этот адрес не было ссылок при просмотре команд алгоритмом рекурсивного спуска.

Полный список типов проблем и их возможных решений доступен во встроенной помощи IDA.

 

Навигация в дизассемблере

 

Стековые кадры

Перемещение между окнами – один из важнейших навыков, необходимых для работы в IDA. Как мы увидим, основа базы данных IDA позволяет реализовать исключительные навигационные возможности.

Стековые кадры. При работе с IDA Pro от пользователя ожидается знание особенностей низкоуровневых языков программирования, касающихся тонкостей генерирования машинного кода и использования памяти высокоуровневой программой.

Одно из таких низкоуровневых понятий – стековый кадр. Стековые кадры - это блоки памяти, выделенной в стеке программы и предназначенные для конкретной функции. Программисты, как правило, группируют исполняемые выражения в единицы, называемые функциями (также их называют процедуры, подпрограммы и методы).

Соглашения вызова. Дальнейшие примеры относятся к архитектуре х86 и поведению типичных х86-компиляторов. Вызывающая функция должна хранить параметры именно в том виде, в котором их ожидает принять вызываемая,. Для установки формата, в котором функции будут принимать свои аргументы, существуют соглашения вызова.

Соглашение вызова определяет, куда вызывающая функция должна поместить требуемые параметры. Соглашения вызова могут потребовать поместить параметр в определенные регистры, стек программы или сразу и туда, и туда. При передаче параметров в программный стек также важно определить, кто должен будет удалить их, когда функция закончит свою работу. Некоторые соглашения вызова устанавливают, что вызывающий отвечает за удаление параметров, другие делают ответственной вызываемую функцию. Следование соглашением вызова необходимо для сохранения целостности указателя программного стека.

Размещение локальных переменных. В отличие от соглашений вызова, определяющих способ передачи параметров в функцию, никаких соглашений, определяющих расположение локальных переменных функции, не существует. Имея лишь исходный код обычно невозможно определить, куда будут помещены переменные, потому что ни вызывающая, ни вызываемая функции не определяют это единолично.

Окна стека IDA. Во время начального анализа IDA внимательно следит за указателем стека, помечая каждую команду push и pop, а также многие другие арифметические операции, которые могут изменить указатель стека, например, сложение и вычитание констант. Основная цель анализа – выяснить точный размер зоны локальных переменных, выделенных в стековом кадре функции. Также IDA выясняет, используется ли отдельный указатель кадра (например, распознавая последовательность push ebp/mov ebp, esp) и распознает все ссылки на переменные внутри стекового кадра. Например, если бы IDA пометил следующую инструкцию в теле demo_stackframe

mov eax, [ebp+8]

он понял бы, что первый аргумент функции (а в данном случае) загружается в регистр EAX.

В результате внимательного анализа структуры стекового кадра IDA может различать ссылки на память, которые обращаются к аргументам функции (они находятся ниже сохраненного адреса возврата) и ссылки, обращающиеся к локальным переменным (они находятся выше сохраненного адреса возврата). IDA определяет, к каким места внутри стекового кадра есть прямые обращения.

Понимание поведения функции часто сводится к пониманию типов данных, с которыми она оперирует. При чтении листинга дизассемблирования первым ключом к пониманию типа данных функции будет структура стекового кадра функции. IDA предлагает два окна, отображающих стековый кадр любой функции: общий вид и детальный вид. Чтобы понять оба этих окна, мы рассмотрим следующую версию demo_stackframe, скомпилированную gcc:

void demo_stackframe(int a, int b, int c) {

int x = c;

char buffer[64];

int y = b;

int z = 10;

buffer[0] = 'A';

bar(z, y);

}

В этом примере мы дали начальные значения переменным y и z, чтобы компилятор не жаловался на неинициализированные переменные, используемые в вызове bar. Кроме того, символ сохранен в первый элемент массива buffer, и мы решили не инициализировать локальную переменную x. Соответствующий результат дизассемблирования IDA показан ниже:

.text:00401090 ; ========= S U B R O U T I N E ===========================

.text:00401090

.text:00401090 ; Attributes: bp-based frame

.text:00401090

.text:00401090 demo_stackframe proc near ; CODE XREF: sub_4010C1+41p

.text:00401090

.text:00401090 var_78 = dword ptr -78h

.text:00401090 var_74 = dword ptr -74h

.text:00401090 var_60 = dword ptr -60h

.text:00401090 var_5C = dword ptr -5Ch

.text:00401090 var_58 = byte ptr -58h

.text:00401090 var_C = dword ptr -0Ch

.text:00401090 arg_4 = dword ptr 0Ch

.text:00401090 arg_8 = dword ptr 10h

.text:00401090

.text:00401090 push ebp

.text:00401091 mov ebp, esp

.text:00401093 sub esp, 78h

.text:00401096 mov eax, [ebp+arg_8]

.text:00401099 mov [ebp+var_C], eax

.text:0040109C mov eax, [ebp+arg_4]

.text:0040109F mov [ebp+var_5C], eax

.text:004010A2 mov [ebp+var_60], 0Ah

.text:004010A9 mov [ebp+var_58], 41h

.text:004010AD mov eax, [ebp+var_5C]

.text:004010B0 mov [esp+78h+var_74], eax

.text:004010B4 mov eax, [ebp+var_60]

.text:004010B7 mov [esp+78h+var_78], eax

.text:004010BA call bar

.text:004010BF leave

.text:004010C0 retn

.text:004010C0 demo_stackframe endp

 

В этом листинге многое следует пояснить. IDA считает, что эта функция использует регистр ЕВР как указатель кадра на основе анализа пролога функции. В 00401093 мы узнаем, что gcc выделил 120 байтов (78h равно 120) места под локальные переменные в стековом кадре. В него входят 8 байт для передачи двух параметров функции bar , но это все равно гораздо больше 76 байтов, которые мы ранее собирались запросить. Начиная с 00401090 IDA предоставляет общий вид стека, перечисляющий каждую переменную, к которой напрямую обращались внутри стека, а также размер переменных и их смещение относительно указателя кадра.

IDA назначает переменным имена на основе их местоположения относительно сохраненного адреса возврата. Локальные переменные находятся над сохраненным адресом возврата, а параметры – под ним. Имена локальных переменных создаются путем сложения префикса var_ с шестнадцатеричным суффиксом, показывающим дистанцию в байтах, на которую переменная отстоит от сохраненного указателя кадра. Локальная переменная var_C в этом случае занимает 4 байта (dword) и находится на 12 байтов выше сохраненного указателя кадра ([ebp-0Ch]). Параметры функции называются с помощью префикса arg_ вместе с шестнадцатеричным суффиксом, показывающим дистанцию до самого верхнего параметра. Таким образом, верхний 4-байтовый параметр будет называться arg_0, а последующие - arg_4, arg_8, arg_C и т.д. В данном примере arg_0 не показан, потому что функция не использует параметр a. Так как IDA не может найти ссылки на память [ebp+8] (местоположение первого параметра), arg_0 не приводится в окне просмотра стека. Быстрый просмотр общего вида стека показывает, что есть много мест в стеке, которые IDA не смогла назвать, потому что в коде программы на них нет прямых ссылок.

Обратите внимание: IDA автоматически генерирует имена только для тех переменных стека, на которые есть непосредственные ссылки внутри функции.

Важное отличие между листингом дизассемблирования IDA и анализом стекового кадра, который мы выполнили ранее, заключается в том, что нигде в ассемблерном листинге мы не видим ссылок на память вроде [ebp-12]. Вместо этого IDA заменил все постоянные смещения на символические имена, соответствующие символам в окне стека и их относительным смещениям относительно указателя стекового кадра. Это позволяет IDA генерировать код более высокого уровня – просто гораздо удобней работать с символическими именами, а не с цифровыми константами. Окно общего вида стека показывает, какие имена, сгенерированные IDA, соответствуют каким смещениям. Например, там, где в коде появляется ссылка на память [ebp+arg_8], можно использовать [ebp+10h] или [ebp+16].

 

Поиск в базе данных

Если вы внимательно осмотрите содержимое меню Search, вы обнаружите длинный список опций, большинство из которых приведут вас к следующему пункту какой-нибудь категории. Search ► Next Code перемещает курсор к следующему месту, содержащему команду. Вы также можете ознакомиться с опциями, доступными в меню Jump.

Текстовый поиск. Текстовый поиск IDA позволяет искать подстроку в листинге дизассемблирования. Текстовый поиск можно вызвать с помощью меню Search ► Text (горячая клавиша: ALT-T). Некоторое количество говорящих сами за себя функций позволяют тонкую настройку поиска.

Опция Find all occurences отображает результат поиска в новом окне, обеспечивая легкую навигацию к любому совпадению с критериями поиска. Предыдущий поиск может быть повторен для нахождения следующего совпадения по горячей клавише CTRL-T или из меню Search ► Next Text.

Двоичный поиск. Если вы хотите найти определенную двоичную информацию, например, последовательность байтов, текстовый поиск не подходит. Вместо этого используйте двоичный поиск IDA. Текстовый поиск ищет в окне дизассемблирования, бинарный поиск может проводиться только в часть шестнадцатеричного окна. Можно искать как в шестнадцатеричном дампе, так и в ASCII-дампе, в зависимости от того, как вы укажете строку для поиска. Бинарный поиск вызывается из меню Search ► Sequence of Bytes либо горячей клавишей ALT-B. Чтобы искать последовательность шестнадцатеричных байтов, поисковая строка должна быть представлена в виде разделенных пробелом двузначных двоичных значений, например, CA FE BA BE. К идентичному результату приведет поиск ca fe ba be, несмотря на включение опции «учитывать регистр».

Чтобы искать фрагмент ASCII-дампа в шестнадцатеричном окне, нужно заключить поисковой запрос в кавычки. Опция Unicode strings используется для поиска вашей строки в юникоде.

Опция Case-sensitive может вас запутать. С поиском строк все понятно: поиск "hello" найдет "HELLO", если Case-sensitive отключен. Всё становится немного интересней, если вы делаете шестнадцатеричный поиск с выключенным Case-sensitive. Если вы будете искать E9 41 C3, вы будете удивлены, что найдется E9 61 C3. Строки считаются совпадающими, потому что 0x41 соответствует символу «A», а 0x61 – символу «a». Так что не смотря на то, что вы указали шестнадцатеричный поиск, 0x41 считается равным 0x61, если не включена опция «Учитывать регистр».

Поиск последующих совпадений двоичных данных выполняется с помощью CTRL-B или Search ► Next Sequence of Bytes.

 


Дата добавления: 2018-06-27; просмотров: 1101; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!