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

  • AddStrucEx(-1,"MYSTRUC",0);

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


    Скачать 2.86 Mb.
    НазваниеОписание функций встроенного языка
    Анкорobraz_mihlenia_-_dizassembler_IDA
    Дата29.09.2022
    Размер2.86 Mb.
    Формат файлаpdf
    Имя файлаobraz_mihlenia_-_dizassembler_IDA.pdf
    ТипСправочник
    #704305
    страница25 из 39
    1   ...   21   22   23   24   25   26   27   28   ...   39
    long GetStrucSize(long id);
    Функция возвращает размер структуры в байтах, который равен сумме размера всех ее членов. Он отображается в качестве комментария в окне просмотра структур.
    Допускается существование структур без единого элемента, размер которых равен нулю.

    250 0000 _msExcInfo struc ;
    (sizeof=0x8)
    0000 0000 Id dd ?
    0004 Proc dd ?
    0008 _msExcInfo ends
    Message("0x%X \n",
    GetStrucSize(GetStrucIdByName("_msExcInfo"))
    );
    0x8 0000 struc_3 struc ; (sizeof=0)
    0000 struc_3 ends
    Message("0x%X \n",
    GetStrucSize(GetStrucIdByName("struc_3"))
    );
    0x0
    Операнд Пояснения id Идентификатор (ID) структуры
    ==return Пояснения
    !=BADADDR
    Размер структуры
    Return
    ==BADADDR
    Ошибка
    long GetMemberQty(long id);
    Функция возвращает число членов структуры. Допускается существование структур без единого элемента, число членов которых равно нулю.
    0000 _msExcept struc ;
    0000 Magic dd ?
    0004 Count dd ?
    0008 InfoPtr dd ?
    000C CountDtr dd ?
    0010 DtrPtr dd ?
    0014 _unk dd 3 dup(?)
    0020 Info _msExcInfo 0 dup(?)
    0020 _msExcept ends
    Message("0x%X \n",
    GetMemberQty(GetStrucIdByName("_msExcept"))
    );
    0x7
    Операнд
    Пояснения id Идентификатор (ID) структуры

    251
    Завершение
    Пояснения
    !=BADADDR
    Число членов структуры
    Return
    ==BADADDR
    Ошибка
    long GetStrucNextOff(long id,long offset);
    Функция возвращает смещение начала очередного элемента в структуре. Первый элемент всегда имеет нулевое смещение (что очевидно), а последний смещение численно равное размеру структуры минус единица.
    Это происходит потому, что каждую структуру замыкает «виртуальный» элемент, который не видим для всех остальных функций (в том числе и GetMemberQty). Он был введен из соображений удобства программирования, и во всех остальных случаях может не браться в расчет.
    Если неверно задан идентификатор или структура не содержит ни одного члена, то обоих случаях возвращается ошибка BADADDR
    Например:
    0000 _msExcept struc ; (sizeof=0x22)
    0000 0000 Magic dd ?
    0004 Count dd ?
    0008 InfoPtr dd ?
    000C CountDtr dd ?
    0010 DtrPtr dd ?
    0014 _unk dd 3 dup(?)
    0020 Info dw ?
    0022
    _msExcept ends auto a; a=0; for (;;)
    {
    Message("0x%X \n",a); a=GetStrucNextOff
    (GetStrucIdByName("_msExcept"),a); if (a==-1) break;
    }
    0x0 0x4 0x8 0xC
    0x10 0x14 0x20 0x22 0000 struc_9 struc ; (sizeof=0)
    0000 struc_9 ends
    Message("0x%X \n",
    GetStrucNextOff(
    GetStrucIdByName("struc_9"))
    );

    252 0xFFFFFFFFF
    Числа, отображаемые IDA слева элементов структуры, и есть искомые смещения элементов. При этом необязательно, что бы каждому смещению соответствовал именованный элемент. Поскольку для доступа к членам структуры используются не имена, а смещения элементов, то IDA поддерживает и безыменные поля, которые могут оказаться полезными в ряде случаев.
    0000 struc_3 struc ; (sizeof=0xd)
    0000 field_0 dw ?
    0002 db ? ; undefined
    0003 field_3 dd ?
    0007 field_7 db ?
    0008 db ? ; undefined
    0009 db ? ; undefined
    000A db ? ; undefined
    000B field_B db ?
    000C field_C db ?
    000D struc_3 ends
    Членом структуры могут быть, в том числе, и массивы однотипных (гомогенных) элементов.
    0000 struc_7 struc ; (sizeof=0x15)
    0000
    field_0 dd ?
    0004 field_4 db 16 dup(?)
    0014
    field_14 db ?
    0015 struc_7 ends
    В этом случае очередным смещением будет смещение следующего элемента структуры.
    Операнд
    Пояснения id Идентификатор (ID) структуры
    Завершение
    Пояснения
    !=BADADDR
    Смещение начала очередного члена структуры
    Return
    ==BADADDR
    Ошибка
    long GetStrucPrevOff(long id,long offset);
    Функция возвращает смещение начала предыдущего элемента структуры. В остальном полностью идентична GetStrucNextOff
    Смещение конца (не начала!) последнего элемента можно получить вызовом
    GetStrucPrevOff(id,-1);
    Если неверно задан идентификатор или структура не содержит ни одного члена, то обоих случаях возвращается ошибка BADADDR
    Например:
    0000 _msExcept struc ; (sizeof=0x22)

    253 0000 Magic dd ?
    0004 Count dd ?
    0008 InfoPtr dd ?
    000C CountDtr dd ?
    0010 DtrPtr dd ?
    0014 _unk dd 3 dup(?)
    0020 Info dw ?
    0022 _msExcept ends auto a; a=-1; for (;;)
    { a=GetStrucPrevOff
    (GetStrucIdByName("_msExcept"),a); if (a==-1) break;
    Message("0x%X \n",a);
    }
    0x22 0x20 0x14 0x10 0xC
    0x8 0x4 0x0 0000 struc_9 struc ; (sizeof=0)
    0000 struc_9 ends
    Message("0x%X \n",
    GetStrucPrevOff(
    GetStrucIdByName("struc_9"))
    );
    0xFFFFFFFFF
    Операнд
    Пояснения id Идентификатор (ID) структуры
    Завершение
    Пояснения
    !=BADADDR
    Смещение начала предыдущего члена структуры
    Return
    ==BADADDR
    Ошибка
    long GetFirstMember(long id);
    Функция возвращает смещение начала первого члена структуры. Это значение всегда равно нулю, за тем исключением, когда неверно задан идентификатор или структура не содержит ни одного члена. В обоих случаях возвращается ошибка BADADDR
    Например
    0000 _msExcInfo struc ; (sizeof=0x8)
    0000 Id dd ?

    254 0004 Proc dd ?
    0008 _msExcInfo ends
    Message("0x%X \n",
    GetFirstMember(
    GetStrucIdByName("_msExcept"))
    );
    0x0 0000 struc_9 struc ; (sizeof=0)
    0000 struc_9 ends
    Message("0x%X \n",
    GetFirstMember(
    GetStrucIdByName("struc_9"))
    );
    0xFFFFFFFFF
    Операнд
    Пояснения id Идентификатор (ID) структуры
    Завершение
    Пояснения
    !=BADADDR
    Смещение начала первого члена структуры
    Return
    ==BADADDR
    Ошибка
    long GetLastMember(long id);
    Функция возвращает смещение начала (не конца!) последнего члена структуры.
    Обратите внимание, что этот результат не совпадает со значением, взращаемым
    GetStrucNextOff для последнего элемента!
    Например:
    0000 _msExcept struc ; (sizeof=0x22)
    0000 0000 Magic dd ?
    0004 Count dd ?
    0008 InfoPtr dd ?
    000C CountDtr dd ?
    0010 DtrPtr dd ?
    0014 _unk dd 3 dup(?)
    0020 Info dw ?
    0022
    _msExcept ends auto a; a=0; for (;;)
    {
    Message("0x%X \n",a); a=GetStrucNextOff
    (GetStrucIdByName("_msExcept"),a); if (a==-1) break;

    255
    }
    0x0 0x4 0x8 0xC
    0x10 0x14 0x20 0x22
    Message("0x%X \n",
    GetLastMember(
    GetStrucIdByName("_msExcept”))
    );
    0x20
    Если неверно задан идентификатор или структура не содержит ни одного члена, то обоих случаях возвращается ошибка BADADDR
    Операнд
    Пояснения id Идентификатор (ID) структуры
    Завершение
    Пояснения
    !=BADADDR
    Смещение начала последнего члена структуры
    Return
    ==BADADDR
    Ошибка
    char GetMemberName(long id,long member_offset);
    Функция возвращает имя члена структуры. Для этого необходимо задать идентификатор (ID) структуры и смещение интересующего нас элемента от ее начала
    (member_offset) Подробнее об этом можно почитать в описании функции GetStrucNextOff.
    Пример использования:
    0000 MyStruc struc ; (sizeof=0x7)
    0000 field_0 db ?
    0001 field_1 dw ?
    0003 field_3 dd ?
    0007 MyStruc ends auto a; for (a=0;;)
    {
    Message("0x%X %s \n", a,
    GetMemberName(
    GetStrucIdByName("MyStruc"),a)
    ); a=GetStrucNextOff(
    GetStrucIdByName("MyStruc"),a
    );

    256
    if (a==-1) break;
    }
    0x0 field_0 0x1 field_1 0x3 field_3 0x7
    Очевидно, что код работает неправильно, и пытается возвратить на один элемент больше, чем содержит структура. Причина такого поведения заключается в том, что функция GetStrucNextOff возвращает смещение «виртуального» элемента, замыкающего структуру. И хотя IDA отображает его имя, как показано ниже, на самом деле виртуальный элемент не имеет никакого имени и не видим для всех остальных функций, кроме
    GetStrucNextOff, GetPrevNextOff
    0007
    MyStruc ends
    Поэтому необходимо использовать другую проверку, например очередное смещение, возвращенное GetStrucNextOff со смещением последнего элемента, которое можно узнать вызовом GetLastMember.
    В результате код должен выглядеть так: auto a; for (a=0;;)
    {
    Message("0x%X %s \n", a,
    GetMemberName(
    GetStrucIdByName("MyStruc"),a)
    ); a=GetStrucNextOff(GetStrucIdByName("MyStruc"),a); if (a>GetLastMember(GetStrucIdByName("MyStruc"))) break;
    }
    0x0 field_0 0x1 field_1 0x3 field_3
    Не обязательно указывать точное смещение начала элемента. Необходимо лишь, что бы указанная величина лежала в границах интересующего нас члена структуры. IDA автоматически округлит ее до смещения начала элемента.
    Этот может продемонстрировать следующий скрипт:
    0000 MyStruc struc
    0000 field_0 dw ?
    0002 field_1 dw ?
    0004 field_2 dw ?
    0006 MyStruc ends auto a; for (a=0;;)
    {

    257
    Message("0x%X %s \n", a,
    GetMemberName(
    GetStrucIdByName("MyStruc"),
    a+1
    )
    ); a=GetStrucNextOff(
    GetStrucIdByName("MyStruc"),a
    ); if (a==-1) break;
    }
    0x0 field_0 0x1 field_1 0x3 field_2
    Операнд
    Пояснения id Идентификатор (ID) структуры member_offset
    Смещение, лежащее в границах интересующего нас элемента
    Завершение
    Пояснения
    !=””
    Имя члена структуры
    Return
    ==””
    Ошибка
    char GetMemberComment(long id,long member_offset,long repeatable);
    Функция возвращает комментарий, связанный с членом структуры. IDA поддерживает два типа комментариев – ‘regular’ и ‘repeatable’. Последний отличается тем, что дублируется по месту обращения к элементу обращения структуры. Однако в случае со структурами и их членами, IDA игнорирует это требование, в чем убеждает следующий пример:
    0000 MyStruc struc ; (sizeof=0x4) ; XREF: seg000:0F72r
    0000 field_0 dw ? ;
    My Repeatable comment
    0002 field_1 dw ? ;
    0004 MyStruc ends seg000:0F72*stru_0_F72 dw 0 ; field_0
    ; DATA XREF: sub_0_F56r seg000:0F72* ; sub_0_2456+1Cw ... seg000:0F72* dw 0 ; field_1 seg000:0F56 mov es, stru_0_F72.
    field_0
    seg000:0F5A assume es:nothing seg000:0F5A xor bx, bx
    Остается только надеяться, что в будущем рано или поздно такая поддержка появится.
    Операнд
    Пояснения id Идентификатор (ID) структуры member_offset
    Смещение, лежащее в границах интересующего нас элемента

    258
    Флаг
    Пояснения
    0
    Неповторяемый комментарий
    Repeatable
    1
    Повторяемый комментарий
    Завершение
    Пояснения
    !=””
    Комментарий
    Return
    “”
    Ошибка
    long GetMemberSize(long id,long member_offset);
    Функция возвращает размер члена структуры в байтах. Для этого необходимо задать любое, принадлежащее ему смещение. Это дает возможность самостоятельно проходить список элементов, без использования GetStrucNextOff, которая отличается несколько необычным поведением (подробности можно узнать в описании этой функции)
    Например:
    0000 MyStruc struc ; (sizeof=0x19)
    0000 field_0 db ?
    0001 field_1 dw ?
    0003 field_3 dd ?
    0007 field_7 dq ?
    000F field_F dt ?
    0019 MyStruc ends auto a; for (a=0;;)
    {
    Message ("0x%X 0x%X\n", a,
    GetMemberSize(
    GetStrucIdByName("MyStruc"), a)); a=a+GetMemberSize(
    GetStrucIdByName("MyStruc"), a); if (a>GetLastMember(
    GetStrucIdByName("MyStruc"))
    ) break;
    }
    0x0 0x1 0x1 0x2 0x3 0x4 0x7 0x8 0xF 0xA
    Операнд
    Пояснения id Идентификатор (ID) структуры member_offset
    Смещение, лежащее в границах интересующего нас элемента
    Return
    Завершение
    Пояснения

    259
    !=BADADDR
    Размер члена структуры в байтах
    ==BADADDR
    Ошибка
    0000 MyStruc struc ; (sizeof=0x12)
    0000 field_0 db ?
    0001 field_1 dw ?
    0003 field_3 dd ?
    0007 field_7 dq ?
    000F field_F ChldStruc ?
    0012 MyStruc ends
    0012 0000 0000 ChldStruc struc ; (sizeof=0x3)
    0000 field_0 db ?
    0001 field_1 dw ?
    0003 ChldStruc ends auto a; for (a=0;;)
    {
    Message ("0x%X 0x%X\n", a,
    GetMemberStrId(
    GetStrucIdByName("MyStruc"), a)); a=a+GetMemberSize(
    GetStrucIdByName("MyStruc"), a); if (a>GetLastMember(
    GetStrucIdByName("MyStruc"))
    ) break;
    }
    0x0 0xFFFFFFFF
    0x1 0xFFFFFFFF
    0x3 0xFFFFFFFF
    0x7 0xFFFFFFFF
    0xF
    0xFF0000FB
    long GetMemberStrId(long id,long member_offset);
    Функция возвращает ID элемента структуры, если он является структурой или
    BADADDR в противном случае.

    260
    То есть, IDA поддерживает вложенные структуры, и дает возможность получить идентификатор, для нисходящего разбора.
    Вложение при этом может быть как угодно глубоким и вложенные структуры могут содержать ссылки друг на друга.
    Например:
    0000 struc_1 struc ; (sizeof=0x11)
    0000 field_0 dw ?
    0002 field_2 dw ?
    0004 field_4 dw ?
    0006 field_6 dw ?
    0008 field_8 struc_2 0 dup(?)
    0011 struc_1 ends
    0011 0000 ; -----------------------------------
    0000 0000 struc_2 struc ; (sizeof=0x11)
    0000 field_0 struc_1
    ?
    0011 struc_2 ends
    0011
    Можно создавать и вовсе бессмысленные комбинации, за исключением, пожалуй, структур, ссылающихся на самих себя.
    На самом деле максимальная глубина вложенности равна единице! То есть IDA всего-навсего поддерживает членов типа «структура» и умеет возвращать их ID. Все остальное ложиться на плечи программиста, пишущего скрипт.
    И, как нетрудно убедиться, что все эти вольности, допускаемые IDA при обращении со структурами приводят к огромным трудностям в написании действительно, корректно работающего скрипита.
    Так, в приведенном выше примере, при попытке вывести полный перечень членов структуры, включая вложенные, получиться бесконечный рекурсивный спуск и скрипт
    «зависнет»
    Однако, по-видимому, все же не стоит усложнять код, а просто лишь быть внимательным в отношении вложенных структур и не допускать подобных ситуаций.
    Пример использования:
    0000 struc_2 struc ; (sizeof=0x11)
    0000 field_0 struc_1 ?
    0011 struc_2 ends
    Message("%x \n",
    GetMemberStrId(
    GetStrucIdByName("struc_2"),0x0)
    ); ff0000f8
    Операнд
    Пояснения id Идентификатор (ID) структуры member_offset
    Смещение, лежащее в границах интересующего нас элемента
    Завершение
    Пояснения
    !=BADADDR
    Идентификатор структуры
    Return
    ==BADADDR
    Элемент не является структурой

    261
    long AddStrucEx(long index,char name,long is_union);
    Функция позволяет создавать новую структуру. Для этого необходимо указать ее имя (которое впоследствии может быть изменено) и тип, который в дальнейшем уже не может быть изменен.
    Поддерживаются следующие типы структур:
    Флаг is_union
    Значение
    1
    Структура типа «Объединение» UNION
    0
    Структура по умолчанию
    С точки зрения IDA оба типа абсолютно идентичны и работа с один из них ничем не отличается от другого.
    Однако, различия проявляются при ассемблировании листинга.
    При необходимости ассемблер может располагать члены структуры по удобным для него адресам, вставляя незначимые байты, например, для выравнивания (что ускоряет работу кода).
    Разумеется, что во многих случаях это недопустимо и просто развалит всю программу. Для предотвращения этого и была введена поддержка типа «объединение», которая отличается от обычной структуры лишь тем, что ассемблер всегда ее оставляет в неприкосновенности и гарантирует, что смещения членов относительно друг друга всегда останутся неизменными.
    0000 struc_3 struc
    0000 field_0 dw ?
    0002 field_2 db ?
    0003 field_3 dw ?
    0005 struc_3 ends
    0000 struc_4 union
    0000 field_0 dw ?
    0002 field_2 db ?
    0003 field_3 dw ?
    0005 struc_3 ends
    Какой тип выбрать при создании структуры должен решать сам пользователь.
    Чаще всего взаимное расположение элементов в структуре некритично, поскольку ассемблер автоматически вычисляет смещение каждого члена.
    Но если речь идет о структуре, выражающей, скажем, заголовок файла, то в этом случае любые отклонения от жестко заданных смещений приведут к неправильной работе программы, а следовательно, для работы с ними необходимо использовать тип
    «объединение»
    При этом структуры оба типа разделяют общее пространство имен. Другими словами невозможно создать структуру, совпадающую по имени с уже существующим объединением.
    В остальном же на имена наложены точно такие ограничения, как и на метки.
    Необходимо помнить, что IDA различает строчечные и заглавные буквы, поэтому имена
    ‘MyStruc’ и “MYSTRUC” для нее два разных имени и могут быть присвоены двум структурами.
    0000 MyStruc struc ; (sizeof=0x0)
    0000 MyStruc ends
    0000 0000 ; -------------------------------------
    0000

    262 0000 MYSTRUC struc ; (sizeof=0x0)
    0000 MYSTRUC ends
    Но большинство ассемблеров не различает регистра и выдаст ошибку! Поэтому необходимо не допускать таких ситуаций.
    Индекс структуры обычно устанавливают равным BADADDR – при этом IDA добавляет новую структуру в конец списка, автоматически расширяя последний.
    Например:
    0000 struc_10 struc ; (sizeof=0x0)
    0000 struc_10 ends
    0000 0000 ; --------------------------------------
    0000 0000 struc_11 struc ; (sizeof=0x0)
    0000 struc_11 ends
    AddStrucEx(-1,"MYSTRUC",0);
    0000 struc_10 struc ;
    0000 struc_10 ends
    0000 0000 ; ---------------------
    0000 0000 struc_11 struc ;
    0000 struc_11 ends
    0000 0000 ; ---------------------
    0000 0000 MYSTRUC struc ;
    0000 MYSTRUC ends
    0000
    Но имеется так же возможность задать произвольный индекс из уже
    существующих. При этом старая структура будет уничтожена! Поэтому, обычно к этому способу не прибегают.
    Например:
    0000 struc_10 struc ; (sizeof=0x0)
    0000 struc_10 ends
    0000 0000 ; --------------------------------------
    0000 0000 struc_11 struc ; (sizeof=0x0)
    0000 struc_11 ends
    AddStrucEx(0,"MY_STRUC",0);
    0000
    MY_STRUC
    struc ;
    0000
    MY_STRUC
    ends
    0000 0000 ; ---------------------
    0000 0000 struc_10 struc ;

    263 0000 struc_10 ends
    0000
    При этом невозможно создать со структуру с индексом более чем на единицу превышающим индекс последнего существующего.
    Например:
    0000 struc_10 struc ; (sizeof=0x0)
    0000 struc_10 ends
    0000 0000 ; --------------------------------------
    0000 0000 struc_11 struc ; (sizeof=0x0)
    0000 struc_11 ends
    Message(“0x%X \n”,
    1   ...   21   22   23   24   25   26   27   28   ...   39


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