Главная страница
Навигация по странице:

  • Навигатор по функциям

  • SegCreate(long startea,long endea,long base,long use32,long align,long comb)

  • Рисунок 17 “0x020” Создание сегмента по выделенной области

  • Рисунок 20 Изменение границ сегментов

  • Описание функций встроенного языка


    Скачать 2.86 Mb.
    НазваниеОписание функций встроенного языка
    Анкорobraz_mihlenia_-_dizassembler_IDA
    Дата29.09.2022
    Размер2.86 Mb.
    Формат файлаpdf
    Имя файлаobraz_mihlenia_-_dizassembler_IDA.pdf
    ТипСправочник
    #704305
    страница7 из 39
    1   2   3   4   5   6   7   8   9   10   ...   39

    Замечание: размер сегмента ограничен разрядностью линейных адресов его
    начала и конца и составляет 4 гигабайта, но выбор адреса начала сегмента,
    первый байт которого имеет нулевое смещение, ограничен разрядностью
    базового адреса, и равен BASE
    max
    * 0x10 = 0xFFFF * 0x10 = 0xFFFF0, т.е. немногим
    менее одного мегабайта.
    Выход состоит в использовании селекторов, ссылающихся на 32-разрядные адреса, что позволяет адресовать с их помощью до 4 гигабайт.
    К селектору можно обратится по его индексу в таблице селекторов. Индексы представляют собой 16-разрядные целые значения, увеличивающиеся с каждым очередным элементом на единицу.
    Элементы таблицы – 32-разрядные базовые адреса сегмента, измеряемые в параграфах.
    Таблица селекторов представляет собой разряженный массив, допуская создание элементов с несмежными индексами. Например, 0x5,0x07,0x16,0x88…
    Если при создании сегмента в качестве базового адреса указать индекс созданного ранее селектора, его значение будет автоматически использовано для базирования данного сегмента. Аналогично, если создать селектор, совпадающий с базовым адресом некоторого сегмента, для его базирования станет использоваться значение селектора, а не базовый адрес.
    С каждым сегментом связан ряд атрибутов – имя сегмента, кратность выравнивания, разрядность и объединение. Никакой из атрибутов, включая имя, уникальной характеристикой сегмента не является и вполне допустимо существование двух и более сегментов с одинаковыми именами (однако, ассемблеры не смогут откомпилировать исходный тест, содержащий несколько одноименных сегментов).
    Замечание: создание двух сегментов с одинаковыми базовыми адресами допускается, но пользоваться этой возможностью категорически не рекомендуется.
    Над каждым сегментом можно выполнять следующие операции – создание и удаление сегментов, получение и изменение основных характеристик сегментов
    (линейного адреса начала, линейного адреса конца, базового адреса), получение и изменение атрибутов сегмента (имя, кратность выравнивания, разрядность и т.д.).

    49
    Подробнее об этом рассказано в главе «Функции, работающие с сегментами и селекторами».
    Навигатор по функциям
    Для изучения организации сегментов и селекторов рекомендуется загрузить полученный в главе «Виртуальная память» файл “tutor.idb” в дизассемблер, при этом экран
    IDA должен выглядеть так:
    0:00010000 db 48h ; H
    0:00010001 db 65h ; e
    0:00010002 db 6Ch ; l
    0:00010003 db 6Ch ; l
    0:00010004 db 6Fh ; o
    0:00010005 db 2Ch ; ,
    0:00010006 db 20h ;
    0:00010007 db 49h ; I
    0:00010008 db 44h ; D
    0:00010009 db 41h ; A
    0:0001000A db 20h ;
    0:0001000B db 50h ; P
    0:0001000C db 72h ; r
    0:0001000D db 6Fh ; o
    0:0001000E db 21h ; !
    0:0001000F db 20h ;
    0:00010010 db 0Dh ;
    Для создания нового сегмента можно воспользоваться вызовом функции
    SegCreate(long startea,long endea,long base,long use32,long align,long comb), последовательно передав ей адрес начала сегмента, адрес конца сегмента, базовый адрес сегмента, разрядность сегмента, кратность выравнивания и атрибуты (о трех последних аргументах подробно рассказано в описании функции SegCreate, сейчас их можно принять равными нулю), например, так: «SegCreate(0x10000, 0x10012, 0x1000, 0, 0, 0);» seg000:0000 ; Segment type: Regular seg000:0000 seg000 segment at 1000h private '' use16 seg000:0000 assume cs:seg000 seg000:0000 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing seg000:0000 db 48h ; H seg000:0001 db 65h ; e seg000:0002 db 6Ch ; l seg000:0003 db 6Ch ; l seg000:0004 db 6Fh ; o seg000:0005 db 2Ch ; , seg000:0006 db 20h ; seg000:0007 db 49h ; I seg000:0008 db 44h ; D seg000:0009 db 41h ; A seg000:000A db 20h ; seg000:000B db 50h ; P seg000:000C db 72h ; r seg000:000D db 6Fh ; o seg000:000E db 21h ; ! seg000:000F db 20h ; seg000:0010 db 0Dh ; seg000:0011 db 0Ah ; seg000:0011 seg000 ends

    50
    Создав новый сегмент, IDA автоматически присвоила ему имя “seg000”, где “000” порядковый номер (считая от нуля) созданного сегмента. Последующие сегменты будут названы “seg001”, “seg002” и т.д.
    Функция “long SegByName(char segname)” позволяет узнать линейный адрес базового адреса сегмента
    4
    по его имени. Ее вызов может выглядеть, например, так:
    Message(“>%X\n”, SegByName(“seg000”));
    > 10000
    Переименовать сегмент можно с помощью функции “success SegRename(long ea,
    char name)” принимающей в качестве первого аргумента любой линейный адрес, принадлежащий указанному сегменту, а вторым – его новое имя. Например:
    SegRename(SegByName("seg000"),"MySeg");
    MySeg:0000 ; Segment type: Regular
    MySeg:0000 MySeg segment at 1000h private '' use16
    MySeg:0000 assume cs:MySeg
    MySeg:0000 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
    MySeg:0000 db 48h ; H
    MySeg:0001 db 65h ; e
    MySeg:0002 db 6Ch ; l
    MySeg:0003 db 6Ch ; l
    MySeg:0004 db 6Fh ; o
    MySeg:0005 db 2Ch ; ,
    MySeg:0006 db 20h ;
    MySeg:0007 db 49h ; I
    MySeg:0008 db 44h ; D
    MySeg:0009 db 41h ; A
    MySeg:000A db 20h ;
    MySeg:000B db 50h ; P
    MySeg:000C db 72h ; r
    MySeg:000D db 6Fh ; o
    MySeg:000E db 21h ; !
    MySeg:000F db 20h ;
    MySeg:0010 db 0Dh ;
    MySeg:0011 db 0Ah ;
    MySeg:0011 MySeg ends
    Для удаления сегментов предусмотрена функция “success SegDelete (long ea,
    long disable)” Если флаг “disable” равен нулю, будет удален лишь сам сегмент, а содержимое принадлежащих ему ячеек сохранится, в противном случае вместе с сегментом будет удалены и все принадлежащие ему адреса виртуальной памяти.
    Сравните:
    SegDelete(0x10000,
    0);
    SegDelete(0x10000,
    0);
    0:00010000 db 48h ; H
    ╔═[■]══════════════════════════ IDA view-A ══
    0:00010001 db 65h ; e

    0:00010002 db 6Ch ; l

    0:00010003 db 6Ch ; l

    0:00010004 db 6Fh ; o
    ↑ Пустой экран дизассемблера
    0:00010005 db 2Ch ; ,
    0:00010006 db 20h ;
    0:00010007 db 49h ; I
    0:00010008 db 44h ; D
    0:00010009 db 41h ; A
    0:0001000A db 20h ;
    0:0001000B db 50h ; P
    0:0001000C db 72h ; r
    0:0001000D db 6Fh ; o
    4
    Т.е. функция возвращает базовый адрес, тут же умножая его на 0x10 для перевода в линейный.

    51 0:0001000E db 21h ; !
    0:0001000F db 20h ;
    0:00010010 db 0Dh ;
    0:00010011 db 0Ah ;
    Описанные выше операции можно выполнять и интерактивно – с помощью горячих клавиш и системы меню. Для последующих экспериментов потребуется перезагрузить исследуемый файл “tutor.bin”, восстановив его с прилагаемого к книге диска, поскольку удаление виртуальной памяти необратимо.
    Для интерактивного создания сегмента достаточно в меню “View” выбрать пункт
    “Segments” и дождавшись появления списка существующих сегментов (в данном случае – пустого), нажать клавишу и надлежащим образом заполнить соответствующие поля появившегося диалога. Если предварительно выделить некоторую область курсорными клавишами, удерживая , IDA автоматически подставит линейные адреса ее начала и конца в поля адреса начала и адреса конца сегмента соответственно (см. рисунок 17)
    Рисунок 17 “0x020” Создание сегмента по выделенной области
    Если поле «Segment Name» оставить пустым, IDA присвоит имя сегменту самостоятельно.
    По умолчанию базовый адрес равен наибольшему возможному значению, т.е.
    BASE
    def
    =
    Startea
    0x10 , при этом offset def
    = Startea AND 0xF, где offset def
    -- смещение первого байта в сегменте. Очевидно, что offset def
    ≤ 0xF.
    Например, если дозагрузить бинарный файл (

    File\Load file\Additional binary file), скажем, Crypt.com, по виртуальному адресу 0x20100 и, выделив его, попытаться создать сегмент, IDA по умолчанию выберет базовый адрес, равный 0x2010, в результате чего смещение первого байта в сегменте будет равно 0x0, а не 0x100! Следует очень внимательно относится к значением, предлагаемым по умолчанию – они не всегда соответствуют требуемым.
    В действительности, базовый адрес должен быть равен 0x2000, тогда после создания сегмента экран дизассемблера будет выглядеть так:
    ╔═[■]════════════════════════════════ Program Segmentation ═══════════════════════════════3═[↑]═╗
    ║ Name Start End Align Base Type Cls 32es ss ds fs gs ▲
    ║ seg000 00000000 00000012 byte 1000 pub N FFFF FFFF FFFF FFFF FFFF 00010000 00010012 ▒
    ║ seg001 00000100 0000013C byte 2000 pub N FFFF FFFF FFFF FFFF FFFF 00020100 0002013C ■
    ║ ▼
    ╚2/2 ═════════════════◄■▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒►─┘
    Рисунок 18
    Для изменения свойств сегмента достаточно подвести к нему курсор и нажать клавишу . Появится диалоговое окно следующего вида:
    ╔═[■]════════ Change segment attributes ═════════════╗
    ║ ║
    ║ ║
    ║ Segment name seg001 ▐↓▌ ║
    ║ Segment class ▐↓▌ ║
    ║ Start address 0x20100 ▐↓▌ ║
    ║ End address 0x2013C ▐↓▌ ║
    ║ ║
    ║ (•) 16-bit segment Combination ▄ (public)║
    ║ ( ) 32-bit segment ▀▀▀▀▀▀▀▀▀▀▀▀▀ ║

    52
    ║ Alignment ▄ (byte) ║
    ║ [X] Move adjacent segments ▀▀▀▀▀▀▀▀▀▀▀ ║
    ║ [ ] Disable addresses ║
    ║ ║
    ║ ║
    ║ OK ▄ Cancel ▄ F1 - Help ▄ ║
    ║ ▀▀▀▀ ▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀ ║
    ╚════════════════════════════════════════════════════╝
    Рисунок 19
    Интерактивно можно изменять все характеристики и атрибуты сегмента за исключением его базового адреса. На модификацию адресов начала и конца сегмента наложены некоторые ограничения:
    (
    )
    BASE * 0x10

    Startea > Endea, т.е. адрес начала должен быть больше либо равен базовому адресу, умноженному на шестнадцать, а адрес конца сегмента должен быть по крайней мере на единицу превышать адрес начала.
    При изменении границ одного из смежных сегментов, IDA автоматически расширит или сузит другой сегмент, если флаг “Move adjacent segments” установлен. Графически это можно изобразить так:
    │xxxxx│
    │xxxxx│
    │xxxxx│
    ├─────┤Å seg000 ├─────┤Å seg000 ├─────┤Å seg000






    │ ↑ │
    ├─────┤Å seg001 ├
    ┤Å «ничейная память»
    │ │ │




    ├──╧──┤Å seg001 ├

    ├─────┤Å seg001












    ├─────┤
    ├─────┤
    ├─────┤
    │xxxxx│
    │xxxxx│
    │xxxxx│ а) б) с)
    Рисунок 20 Изменение границ сегментов
    ??? #Художнику – перерисовать, сохраняя наклон штриховки. Крайняя левая картинка должна изображать как границу сегментов тянут вверх – можно нарисовать привязанную нитку и поднимающую ее руку.
    На рисунке (10.a) показано уменьшение нижней границы сегмента seg000, к концу которого вплотную примыкает сегмент seg001. Если флажок “Move adjacent segment” взведен, IDA автоматически изменит адрес начала сегмента “seg001” как показано на рисунке 10.b; напротив сброс этого флажка приведет к тому, что между сегментами образуется дыра «ничейной памяти», изображенная на рисунке 10.c
    Установка флажка “Disable addresses” автоматически уничтожит «дыру», удалив принадлежащие ей адреса памяти, вместе с их содержимым. Внимание! Эта операция
    необратима и вернуть утерянные данные обратно уже не удаться!
    Для закрепления всего вышесказанного рекомендуется провести несколько простых экспериментов. Для начала попробуйте расшить границы сегмента “seg000” до адреса 0x20120 (или любого другого, принадлежащего сегменту “seg001”). Одним лишь изменением атрибутов сегмента “seg000” это сделать не удаться – IDA сообщит об ошибке
    “set_segm_end(10000) -> 20120: areas overlap” и, независимо от состояния флага “Move adjacent segment”, прервет выполнение операции.
    Причина в том, что автоматическое изменение границ работает с смежными и только с смежными сегментами, а “seg000” и “seg001” таковыми, очевидно, не являются,

    53
    поскольку адрес конца сегмента “seg000” равен 0x10012, а адрес начала “seg001” –
    0x20100.
    Выполнить поставленную задачу можно, по меньшей мере, двумя путями: первое – предварительно увеличить адрес начала сегмента “seg001” и повторить операцию; второе
    - увеличить адрес конца сегмента “seg000” до максимально возможного значения (т.е.
    0x20100), добившись слияния сегментов, что даст возможность расширить “seg000” до требуемого адреса установкой флага “Move adjacent segment”.
    Последовательности нажатий клавиш для первого способа: переместить курсор в пределы сегмента “seg001” и нажать , в поившемся диалоговом окне изменить значение поля “Start address” на 0x20120; затем переместится в границы сегмента
    “seg000”, нажать и изменить значение поля “End Address” на 0x20120”. Задача выполнена.
    Последовательности нажатий клавиш для второго способа: переместить курсор в пределы сегмента “seg000” и нажать , в появившемся диалоговом окне изменить значение поля “End address” на 0x20100, затем повторено вызвав тот же диалог, распахнуть сегмент до требуемо адреса, изменив значение поля “End address” на 0x20120.
    Задача выполнена.
    Программно изменить атрибуты сегмента можно вызовами функций SegCreate,
    SegBounds, SegRename, SegClass, SegAlign, SegComb, SegAddrng
    Функция success SegBounds (long ea,long startea,long endea,long disable) принимает в качестве первого аргумента любой адрес, принадлежащий сегменту, startea, endea – новые адреса начала и конца сегмента соответственно, ненулевое значение флага disable удаляет виртуальную память освободившуюся при уменьшении сегмента (при расширение сегмента его значение игнорируется).
    Следует помнить, что startea
    ≥ BEGIN_ADDRES * 0x10, т.е. верхнее расширение сегмента жестко ограничено его базовым адресом.
    Например, для восстановления сегмента “seg000” до его прежних размеров можно воспользоваться следующим кодом: “SegBounds(0x10000,0x10000,0x10012,1);”
    Если базовый адрес создаваемого сегмента больше или равен 0x10000, IDA автоматически создает селектор для его адресации.
    Например, результат выполнения “SegCreate(0x100000,0x100100,0x10000,0,0,0);” приведет к следующему:
    ╔═[■]═════════════════════════════════ Program Segmentation ═══════════════════════════════3═[↑]═╗
    ║ Name Start End Align Base Type Cls 32es ss ds fs gs ▲
    ║ seg000 00000000 00000012 byte 1000 pub CODE N FFFF FFFF FFFF FFFF FFFF 00010000 00010012 ▒
    ║ seg001 00000100 0000013C byte 2000 pub N FFFF FFFF FFFF FFFF FFFF 00020100 0002013C ■
    ║ seg002 00000000 00000100 at 0001 pub N FFFF FFFF FFFF FFFF FFFF 00100000 00100100 ▼
    ╚3/3 ══════════════════◄■▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒►─┘
    Базовый адрес сегмента “seg002” равен 0x1, но не смотря на это, смещение первого байта в сегменте равно 0x0, а не 0x1000000 – 0x1 * 0x10 = 0xFFFFF0. Причина в том, что 0x1 – это селектор, а не сегмент. Чтобы убедиться в этом достаточно просмотреть список селекторов, вызвать который можно нажатием “,”:
    ╔═[■]═══════════ Selectors ══════════3═[↑]═╗
    ║ Sel Value ▲
    ║ 0001 00010000 ▓
    ║ ▓
    ║ ▼
    ╚1/1 ════════════════════════════─┘
    В отличие от базового адреса, значение селектора легко изменить, для чего достаточно выделить его курсором и нажать . Появится диалоговое окно следующего содержания:
    ╔═[■]Define a selector ════╗

    54
    ║ ║
    ║ Selector 0x1 ▐↓▌ ║
    ║ Value 0x10000 ▐↓▌║
    ║ ║
    ║ OK ▄ Cancel ▄ ║
    ║ ▀▀▀▀ ▀▀▀▀▀▀▀▀ ║
    ╚══════════════════════════╝
    Значение селектора может совпадать с базовым адресом любого из существующих сегментов, на него не действует ограничение startea
    ≥ BASE_ADDRES * 0x10, но если присвоить селектору значение численно равное его индексу, он будет немедленно удален.
    Присвоение селектору базового адреса, превышающего адрес начала сегмента, приводит к появлению байт с отрицательными смещениями, которые автоматически дополняются до нуля, т.е. offset = NEG
    (
    )
    |
    |
    startea - SEL_VALUE .
    Например, после увеличения значения селектора 0x1 на один параграф экран дизассемблера будет выглядеть так: seg002:FFFFFFF0 seg002 segment at 10001h private '' use16 seg002:FFFFFFF0 assume cs:seg002 seg002:FFFFFFF0 ;org 0FFFFFFF0h seg002:FFFFFFF0 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing seg002:FFFFFFF0 db ? ; unexplored seg002:FFFFFFF1 db ? ; unexplored seg002:FFFFFFF2 db ? ; unexplored seg002:FFFFFFF3 db ? ; unexplored seg002:FFFFFFF4 db ? ; unexplored seg002:FFFFFFF5 db ? ; unexplored seg002:FFFFFFF6 db ? ; unexplored seg002:FFFFFFF7 db ? ; unexplored seg002:FFFFFFF8 db ? ; unexplored seg002:FFFFFFF9 db ? ; unexplored seg002:FFFFFFFA db ? ; unexplored seg002:FFFFFFFB db ? ; unexplored seg002:FFFFFFFC db ? ; unexplored seg002:FFFFFFFD db ? ; unexplored seg002:FFFFFFFE db ? ; unexplored seg002:FFFFFFFF db ? ; unexplored seg002:0000 db ? ; unexplored seg002:0001 db ? ; unexplored seg002:0002 db ? ; unexplored seg002:0003 db ? ; unexplored seg002:0004 db ? ; unexplored seg002:0005 db ? ; unexplored seg002:0006 db ? ; unexplored seg002:0007 db ? ; unexplored
    Исправить ситуацию можно соответствующим увеличением адреса начала сегмента.
    После вызова «SegBounds(0x100000,0x100010,0x100100,1);» экран дизассемблера должен выглядеть так:
    ╔═[■]═════════════════════════════════ Program Segmentation ════════════════════════════════4═[↑]═╗
    ║ Name Start End Align Base Type Cls 32es ss ds fs gs ▲
    ║ seg000 00000000 00000012 byte 1000 pub CODE N FFFF FFFF FFFF FFFF FFFF 00010000 00010012 ▒
    ║ seg001 00000100 0000013C byte 2000 pub N FFFF FFFF FFFF FFFF FFFF 00020100 0002013C ■
    ║ seg002 00000000 000000F0 at 0001 pub N FFFF FFFF FFFF FFFF FFFF 00100010 00100100 ▼
    ╚3/3 ═══════════════════◄■▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒►─┘
    Смещение первого байта в сегменте “seg002” равно нулю, чего и требовалось достичь.
    Программно создать новый селектор или изменить значение уже существующего селектора можно с помощью функции “void SetSelector (long sel,long value)”, где sel – индекс селектора, а value – его значение, измеряемое в параграфах.

    55
    Например, вызов “SetSelector(0x1,0x10000);” изменит значение селектора 0x1 и смещение первого байта в сегменте “seg002” будет равно нулю, а вызов
    “SetSelector(0x4,0x500000);” создаст новый селектор с индексом 0x4 (индексы селекторов не обязательно должны следовать друг за другом).
    ┌───────────────────────────────────── Program Segmentation ────────────────────────────────4─────┐
    │ Name Start End Align Base Type Cls 32es ss ds fs gs │
    │ seg000 00000000 00000012 byte 1000 pub CODE N FFFF FFFF FFFF FFFF FFFF 00010000 00010012 │
    │ seg001 00000100 0000013C byte 2000 pub N FFFF FFFF FFFF FFFF FFFF 00020100 0002013C │
    │ seg002 00000010 00000100 at 0001 pri N FFFF FFFF FFFF FFFF FFFF 00100010 00100100 │
    └3/3 ────────────────────────────────────────────────────────────────────────────────────┘
    ╔═[■]══════════ Selectors ═════════5═[↑]═╗
    ║ Sel Value ▲
    ║ 0001 00010000 ▒
    ║ 0004 00500000 ■
    ║ ▼
    ╚2/2 ══════════════════════════─┘
    Удалить селектор можно вызовом функции “
    1   2   3   4   5   6   7   8   9   10   ...   39


    написать администратору сайта