Описание функций встроенного языка
Скачать 2.86 Mb.
|
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”, |