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

  • GetStucQty() ); 3 ==return Пояснения !=0 Число структур, созданных вызовами AddStrucEx Return ==0 Нет ни одной структуры long GetFirstStrucIdx(void);

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


    Скачать 2.86 Mb.
    НазваниеОписание функций встроенного языка
    Анкорobraz_mihlenia_-_dizassembler_IDA
    Дата29.09.2022
    Размер2.86 Mb.
    Формат файлаpdf
    Имя файлаobraz_mihlenia_-_dizassembler_IDA.pdf
    ТипСправочник
    #704305
    страница24 из 39
    1   ...   20   21   22   23   24   25   26   27   ...   39

    поименный доступ к объектам.
    Символьные имена в самом деле гораздо удобнее малоосмысленных 32 битных числовых значений. Однако, поддерживать два набора функций, для имен и для идентификаторов по меньшей мере неразумно.
    Поэтому в IDA была введена всего лишь одна функция, которая позволяла по имени структуры установить ее идентификатор (GetStrucIdByName). И обратная ей,
    GetStrucName, которая по идентификатору возвращала имя.
    Это позволило писать понятый код наподобие следующего:
    DelStruc(
    GetStrucIdByName("struc_10")
    );
    Небольшое замедление выполнения с лихвой окупалось его удобочитаемостью, и поэтому он стал очень популярным (именно так построены все примеры скриптов, приведенные ниже)
    Однако, одно лишь это не решало всех проблем. Все равно имя структуры требовалось как-то передавать скрипту, что было не всегда осуществимо.
    Поэтому был необходим механизм, обеспечивающий доступ ко всем существующим структурам. Теоретически это можно осуществить с помощью идентификаторов. Так, если проскандировать все числа от нуля до 0xFFFFFFFE, то можно обнаружить все структуры, которые присутствуют в базе и получить к ним доступ.
    Но как же это будет медленно! Однако, не стоит быстро отказываться от умный идей. Ведь можно загнать все структуры в один список, проиндексированный числами от

    238
    нуля до номера последней созданной структуры, – тогда все операции с ним не потребуют никаких накладных расходов.
    И в самом деле, IDA поддерживает именно такой список. Так, например, что бы узнать идентификаторы всех существующих структур достаточно выполнить следующий бесхитростный код: auto a; a=0; while(1)
    {
    Message(“0x%X 0x%X \n”, a,
    GetStrucId(a)
    ); a=GetNextStrucIdx(a); if (a==-1) break;
    }
    Ключевой его фигурой является функция GetStrucid, которая возвращает идентификатор по индексу структуры.
    Однако, индексы не жестко связаны с идентификаторами и использовать их для доступа к структурам можно только сразу же после получения. А точнее только на протяжении того времени, в течении которого гарантировано ни одна структура не была добавлена или удалена.
    Фактически индексы были введены, что бы было можно быстро получить список структур. И ни для чего большего их использовать не рекомендуется – разве что на свой страх и риск.
    При этом будьте внимательны, иначе можно совершить ошибку наподобие следующей: auto a; for(a=0;aDelStruc(GetStrucId(a));
    С первого взгляда в этих двух строчках нет никакой ошибки и скрипт будет работать как часы, но попробуйте его запустить и произойдет нечто невразумительное.
    В чем же дело? Вся причина в том, что индексы обновляются при каждом удалении структуры. То есть, удалив структуру с индексом ноль, мы не может переходить к индексу один, так как индексы были реорганизованы, и теперь нулевому индексу соответствует другая структура, а список был сокращен на единицу.
    Правильный код, как бы это ни парадоксально на первый взгляд должен выглядеть так: auto a; for(a=0;aDelStruc(GetStrucId(
    0
    ));
    Поэтому, если вы не хотите искать подобных приключений, не используйте индексы ни для чего другого, кроме как просмотра существующих структур.
    Теперь рассмотри, как осуществляется доступ к элементам структуры. Но для начала рассмотрим все характеристики члена структуры. Как известно руководств к языкам высокого уровня – это имя, тип и смещение относительно начала структуры.
    Однако, в отличие от языков высокого уровня ассемблер MASM использует глобальное пространство имен, а это означает, что имя каждого члена структуры уникально и не может быть дважды повторено в системе.

    239
    Это огромный недостаток, который сводит на нет все преимущества структур. Так, например, если структура MCB (смотри выше) имеет члена с именем size, то невозможно дать тоже имя никакому члену другой структуры.
    Впрочем, в TASM-е это ограничение устранено. Но, к сожалению, IDA не поддерживает такого режима работы. Поэтому имя члена могло бы служить идеальным средством доступа к нему, однако, в IDA использован другой подход, который при ближайшем рассмотрении оказывается не только более удобным, но и универсальным.
    Доступ к элементам структуры осуществляется по их смещением, а точнее заданием любого, принадлежащего им смещения.
    Это позволяет рассматривать структуру, как непрерывный «лоскут» адресного пространства, с «объектами» - членами. Именно так, например, организован доступ к локальным переменным функций.
    С точки зрения IDA каждый член структуры характеризуется не только его типом
    (грубо говоря, размером ячейки), но и может иметь связанные объекты, такие как имя или комментарий.
    Более того, член структуры может являться не только ячейкой памяти, но и вложенной структурой!
    Методы
    Функция
    Описание
    Long GetStrucQty(void)
    Возвращает количество структур, созданных вызовом AddStrucEx
    Long GetFirstStrucIdx(void);
    Возвращает индекс первой структуры в списке long GetLastStrucIdx(void);
    Возвращает индекс последней структуры в списке long GetNextStrucIdx(long index);
    Возвращает следующий индекс в списке структур long GetPrevStrucIdx(long index)
    Возвращает предыдущий индекс в списке структур long GetStrucId(long index)
    Возвращает ID структуры по индексу. long GetStrucIdByName(char name);
    Возвращает идентификатор структуры по ее имени char GetStrucName(long id)
    Возвращает имя структуры по ее идентификатору char GetStrucComment(long id,long repeatable);
    Возвращает комментарии к структуре long GetStrucSize(long id)
    Возвращает размер структуры в байтах, который равен сумме размера всех ее членов long GetMemberQty(long id);
    Возвращает число членов структуры long GetStrucNextOff(long id,long
    Возвращает смещение начала очередного

    240
    offset); элемента в структуре long GetStrucPrevOff(long id,long offset)
    Возвращает смещение начала предыдущего элемента структуры long GetFirstMember(long id);
    Возвращает смещение начала первого члена структуры long GetLastMember(long id);
    Возвращает смещение начала (не конца!) последнего члена структуры char GetMemberName(long id,long member_offset);
    Возвращает имя члена структуры char GetMemberComment(long id,long member_offset,long repeatable);
    Возвращает комментарий, связанный с членом структуры long GetMemberSize(long id,long member_offset);
    Возвращает размер члена структуры в байтах long AddStrucEx(long index,char name,long is_union)
    Создает новую структуру long IsUnion(long id);
    Возвращает единицу если тип структуры – объединение success DelStruc(long id); удаляет существующую структуру по ее идентификатору long SetStrucIdx(long id,long index);
    Изменяет индекс структуры long SetStrucName(long id,char name)
    Изменяет имя структуры long SetStrucComment(long id,char comment,long repeatable)
    Задает комментарий к структуре long DelStrucMember(long id,long member_offset);
    Удаляет члена структуры long SetMemberName(long id,long member_offset,char name)
    Изменяет имя члена структуры long SetMemberType(long id,long member_offset,long flag,long typeid,long nitems
    Изменяет тип члена структуры long SetMemberComment(long id,long member_offset,char comment,long repeatable)
    Задает комментарий члена структуры

    241
    long GetStrucQty(void);
    Функция возвращает количество структур, созданных вызовом AddStrucEx. Все они отображаются IDA в списке структур, который доступен из меню

    View \ Structures.
    Структуры, обеспечивающие доступ к элементам стековых фреймов в это число не входят.
    Если не создано ни одной структуры, то функция возвращает ноль.
    Пример использования:
    0000 struc_1 struc
    0000 field_0 db ?
    0001 field_1 db ?
    0002 struc_1 ends
    0002 0000 ; -------------------
    0000 0000 struc_2 struc
    0000 field_0 dw ?
    0002 struc_2 ends
    0002 0000 ; -------------------
    0000 0000 struc_3 struc
    0000 field_0 db ?
    0001 struc_3 ends
    Message(“0x%X \n”,
    GetStucQty()
    );
    3
    ==return
    Пояснения
    !=0
    Число структур, созданных вызовами AddStrucEx
    Return
    ==0
    Нет ни одной структуры
    long GetFirstStrucIdx(void);
    Функция возвращает индекс первой структуры в списке. Если существует хотя бы одна структура, то функция всегда взращает ноль.
    Например:
    0000 struc_1 struc
    0000 field_0 db ?
    0001 field_1 db ?
    0002 struc_1 ends
    0002 0000 ; -------------------
    0000 0000 struc_2 struc
    0000 field_0 dw ?
    0002 struc_2 ends

    242 0002 0000 ; -------------------
    0000 0000 struc_3 struc
    0000 field_0 db ?
    0001 struc_3 ends
    Message(“0x%X \n”,
    GetFirstStrucIdx()
    );
    0x0
    Список автоматически перестраивается при операциях удаления или добавления структур, поэтому индексы не остаются постоянными. Использовать их для доступа к структуре не рекомендуется.
    Например, если удалить struc_1, а потом повторить вызов GetFirstStrucIdx, то она вновь вернет ноль, однако, теперь это индекс struc_2, а не srtuc_1.
    0000 struc_2 struc
    0000 field_0 dw ?
    0002 struc_2 ends
    0002 0000 ; -------------------
    0000 0000 struc_3 struc
    0000 field_0 db ?
    0001 struc_3 ends
    Message(“0x%X \n”,
    GetFirstStrucIdx()
    );
    0x0
    ==return
    Пояснения
    ==0
    Индекс первой структуры в списке (всегда ноль)
    Return
    ==BADADDR
    Нет ни одной структуры
    long GetLastStrucIdx(void);
    Функция возвращает индекс последней структуры в списке. Он всегда равен
    GetStrucQty() – 1. В том случае если не определено не одной структуры, то функция возвратит ошибку BADADDR.
    0000 struc_1 struc
    0000 field_0 db ?
    0001 field_1 db ?
    0002 struc_1 ends
    0002 0000 ; -------------------
    0000 0000 struc_2 struc
    0000 field_0 dw ?

    243 0002 struc_2 ends
    0002 0000 ; -------------------
    0000 0000 struc_3 struc
    0000 field_0 db ?
    0001 struc_3 ends
    Message(“0x%X \n”,
    GetLastStrucIdx()
    );
    0x2
    ==return Пояснения
    !=BADADDR
    Индекс последней структуры в списке
    Return
    ==BADADDR
    Нет ни одной структуры
    long GetNextStrucIdx(long index);
    Функция возвращает следующий индекс в списке структур. Индекс выражается целым числом от нуля до GetStrucQty() – 1. Индексы следуют последовательно вплотную друг за другом без «пустот» Поэтому псевдокод этой функции очень прост.
    CODE:1001D3E0 push ebx
    CODE:1001D3E1 mov ebx, eax
    CODE:1001D3E3 inc ebx
    CODE:1001D3E4 call @get_struc_qty$qqrv
    CODE:1001D3E9 cmp ebx, eax
    CODE:1001D3EB jb short loc_0_1001D3F2
    CODE:1001D3ED or eax, 0FFFFFFFFh
    CODE:1001D3F0 pop ebx
    CODE:1001D3F1 retn
    Или то же на языке Си: long GetNextStructIdx(long index)
    { if (GetStrucQty()}
    По этой причине два следующих скрипта абсолютно идентичны:
    0000 struc_1 struc
    0000 field_0 db ?
    0001 field_1 db ?
    0002 field_2 db ?
    0003 struc_1 ends
    0003 0000 ; -------------------
    0000 0000 struc_2 struc

    244 0000 field_0 dw ?
    0002 struc_2 ends
    0002 0000 ; -------------------
    0000 0000 struc_3 struc
    0000 field_0 dd ?
    0004 struc_3 ends
    0004 auto a; for(a=0;aMessage(“0x%X 0x%X \n”, a,GetStrucId(a)
    );
    0x0 0xFF0000F0 0x1 0xFF0000FE
    0x2 0xFF000100
    auto a; a=0; while(1)
    {
    Message(“0x%X 0x%X \n”, a,GetStrucId(a)
    ); a=GetNextStrucIdx(a); if (a==-1) break;
    }
    0x0 0xFF0000F0 0x1 0xFF0000FE
    0x2 0xFF000100
    Какой из этих двух способов использовать дело вкуса каждого. Однако, читабельность первого примера значительно лучше, а вероятность допустить ошибку – меньше.
    Операнд Пояснения index Индекс структуры в списке (от нуля до GetStrucQty()-1)
    ==return Пояснения
    !=BADADDR
    Индекс следующей структуры в списке
    Return
    ==BADADDR
    Ошибка
    long GetPrevStrucIdx(long index);
    Функция возвращает предыдущий индекс в списке структур. Индекс выражается целым числом от нуля до GetStrucQty() – 1. Индексы следуют последовательно вплотную друг за другом без «пустот» Поэтому псевдокод этой функции очень прост. long GetPrevStrucIdx(long index)
    {

    245
    if (index<-1) return; return –index;
    }
    По этой причине два следующих скрипта абсолютно идентичны:
    0000 struc_1 struc
    0000 field_0 db ?
    0001 field_1 db ?
    0002 field_2 db ?
    0003 struc_1 ends
    0003 0000 ; -------------------
    0000 0000 struc_2 struc
    0000 field_0 dw ?
    0002 struc_2 ends
    0002 0000 ; -------------------
    0000 0000 struc_3 struc
    0000 field_0 dd ?
    0004 struc_3 ends
    0004 auto a; for(a=GetStrucQty();a>0;--a)
    Message(“0x%X 0x%X \n”, a,GetStrucId(a)
    );
    0x2 0xFF000100 0x1 0xFF0000FE
    0x0 0xFF0000F0 auto a; a=GetStrucQty()-1; while(1)
    {
    Message(“0x%X 0x%X \n”, a,GetStrucId(a)
    ); a=GetPrevStrucIdx(a); if (a==-1) break;
    }
    0x2 0xFF000100 0x1 0xFF0000FE
    0x0 0xFF0000F0
    Какой из этих двух способов использовать дело вкуса каждого. Однако, читабельность первого примера значительно лучше, а вероятность допустить ошибку – меньше.
    Операнд Пояснения

    246
    index Индекс структуры в списке (от нуля до GetStrucQty()-1)
    ==return Пояснения
    !=BADADDR
    Индекс предыдущей структуры в списке
    Return
    ==BADADDR
    Ошибка
    long GetStrucId(long index);
    Функция возвращает ID структуры по индексу. Как уже отмечалось выше, индекс не может точно идентифицировать связанную с ним структуру, поскольку при любых операциях связанных с дополнением или удалением структур, список перестраивается, и тот же индекс уже может указывать совсем на другую структуру.
    В отличие от этого, идентификатор (ID) структуры представляет собой уникальное
    32-битное значение, всегда указывающие на одну и ту же структуру. Более того, даже если структура, связанная с конкретным идентификатором, была удалена, гарантируется, что тот же идентификатор не будет выдан ни одной созданной после этого структуре. Это гарантирует непротиворечивость ситуации и позволяет совместно использовать один и тот же идентификатор различным скриптам.
    Пример использования:
    0000 struc_1 struc
    0000 field_0 db ?
    0001 field_1 db ?
    0002 field_2 db ?
    0003 struc_1 ends
    0003 0000 ; -------------------
    0000 0000 struc_2 struc
    0000 field_0 dw ?
    0002 struc_2 ends
    0002 0000 ; -------------------
    0000 0000 struc_3 struc
    0000 field_0 dd ?
    0004 struc_3 ends
    0004 auto a; for(a=0;aMessage(“0x%X 0x%X \n”, a,GetStrucId(a)
    );
    0x0 0xFF0000F0 0x1 0xFF0000FE
    0x2 0xFF000100
    Идентификатор, как и дескриптор, с точки зрения пользователя являются абстрактным «магическим» числом, интерпретировать которое допускается только операционной системе (в качестве которой выступает в данном случае IDA).

    247
    Операнд Пояснения index Индекс структуры в списке (от нуля до GetStrucQty()-1)
    ==return Пояснения
    !=BADADDR
    Идентификатор (ID) структуры
    Return
    ==BADADDR
    Ошибка
    long GetStrucIdx(long id);
    Функция позволяет получить индекс структуры в списке по ее идентификатору (ID).
    Обычно такой операции не требуется, поскольку практически все функции принимают на входе именно идентификатор, а не индекс.
    Операнд Пояснения id Идентификатор структуры
    ==return Пояснения
    !=BADADDR
    Индекс
    Return
    ==BADADDR
    Ошибка
    long GetStrucIdByName(char name);
    Функция возвращает идентификатор структуры по ее имени. Имя структуры уникально (двух и более структур с одним и тем же именем существовать не может), поэтому неоднозначности не возникает.
    Пример использования: auto a,b; a=AddStrucEx(-1,"MyNewStruc1",0); b=GetStrucIdByName("MyNewStruc1");
    Message("0x%X 0x%X \n",a,b);
    0000 MyNewStruc struc ; (sizeof=0)
    0000 MyNewStruc ends
    0xFF00020A 0xFF00020A
    Обратите внимание, что функция чувствительна к регистру, (большинство ассемблеров его игнорируют). Поэтому имена “MyStruc” и “mystruc” не считаются идентичными, что и доказывает следующий пример: auto a,b; a=AddStrucEx(-1,"MyNewStruc",0); b=GetStrucIdByName("mynewstruc");
    Message("0x%X 0x%X \n",a,b);
    0000 MyNewStruc struc ; (sizeof=0)
    0000 MyNewStruc ends
    0xFF00020A 0xFFFFFFFF

    248
    Операнд Пояснения name Имя структуры
    ==return Пояснения
    !=BADADDR
    Идентификатор
    Return
    ==BADADDR
    Ошибка
    char GetStrucName(long id);
    Функция возвращает имя структуры по ее идентификатору. Очень часто используется совместно с GetStrucId.
    Например:
    0000 MyGoodStuc struc ; (sizeof=0x2)
    0000 field_0 dw ?
    0002 MyGoodStuc ends
    0002 0000 ; ----------------------------------
    0000 0000 MyStruc struc ; (sizeof=0x5)
    0000 field_0 dw ?
    0002 field_2 dw ?
    0004 field_4 db ?
    0005 MyStruc ends
    0005 0000 ; ----------------------------------
    0000 0000 My struc ; (sizeof=0)
    0000 My ends
    0000 0000 ; ----------------------------------
    0000 0000 MyNewStruc struc ; (sizeof=0)
    0000 MyNewStruc ends
    0000 auto a; for (a=0;aMessage("%s \n",
    GetStrucName(GetStrucId(a))
    );
    MyGoodStuc
    MyStruc
    My1
    MyNewStruc
    Операнд Пояснения id Идентификатор (ID) структуры
    ==return Пояснения
    !=””
    Имя структуры
    Return
    ==””
    Ошибка

    249
    char GetStrucComment(long id,long repeatable);
    Функция возвращает комментарии к структуре. В текущих версиях, включая IDA 4.0, комментарии к структурам поддерживаются лишь частично. Так, например, отсутствует возможность интерактивного комментирования функций (приходится пользоваться вызовом SetStuctComment), повторяемые комментарии поддерживаются лишь частично, что подтверждается следующим примером:
    SetStrucComment(
    GetStrucIdByName("_msExcInfo"),
    " MyComment",1);
    0000 ;
    MyComment
    0000 _msExcInfo struc ; (sizeof=0x8) ; XREF: .rdata:
    004077E6 0000 ; .rdata:00407780r ...
    0000 Id dd ? ; sss
    0004 Proc dd ? ; offset (FFFFFFFF)
    0008 _msExcInfo ends
    .rdata:
    004077E6 dd 1879048192 ; Id
    .rdata:004077E6 dd 0 ; Pro
    Message(“%s \n”,
    GetStrucComment(
    GetStrucIdByName("_msExcInfo"),
    1);
    MyComment
    Обратите внимание, что IDA не отобразила повторяемый комментарий в строке rdata:004077E6, хотя это и следовало бы.
    Операнд
    Пояснения id Идентификатор (ID) структуры
    Флаг
    Пояснения
    0
    Неповторяемый комментарий
    Repeatable
    1
    Повторяемый комментарий
    Завершение
    Пояснения
    !=””
    Комментарий
    Return
    “”
    Ошибка
    1   ...   20   21   22   23   24   25   26   27   ...   39


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