Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 [ 116 ] 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140

Return

Завершение

Пояснения

Норма

Считанная строка

Ошибка

long writestr (long handle,char str);

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

Если файл открыт как текстовой, то функция будет преобразовывать все символы 0xA в 0xD 0xA.

Операнд

Пояснения

Handle

Дескриптор открытого с правами на чтение файла

Записываемая строка

Return

Завершение

Пояснения

Норма

Ошибка

ВИРТУАЛЬНЫЕ МАССИВЫ

ОРГАНИЗАЦИЯ МАССИВОВ

IDA поддерживает два типа массивов, и это иногда порождает небольшую путаницу.

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

seg000:0006 db 0A0h,0ACh,0AEh,0A3h,0AEh, 20h,0ADh,0A0h

seg000:0006 db 0A0h, 20h,0ADh,0A0h,0A4h,0AEh, 20h,0AEh

И массивы как выделенные области памяти под нужды скрптовых программ. Вот их-то мы сейчас и рассмотрим. Они концептуально очень сильно отличаются от привычных для нас массивов языков Си и Паскаль.

Скорее это объект, который в Microsoft непременно бы назвали CArray, предоставляющий соответствующие API, но скрывающий реализацию всех своих методов.

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



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

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

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

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

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

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

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

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

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

long CreateArray(char name);

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

Как узнать идентификатор ранее созданного массива при перезапуске скрипта? Конечно, можно его сохранить как в самой базе, так и во внешнем файле, но удобнее получить его по имени массива, воспользовавшись следующей функцией:

long GetArrayId(char name);

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

success RenameArray(long id,char newname);

С другой стороны, если Вам не нравятся конструкции типа:

auto ID;

ID=GetArrayId("MyArray"); RenameArray(ID,"MyRenamedArray");

то можно непосредственно получить идентификатор "на лету" типа:



RenameArray(GetArrayId("MyArray"),"MyRenamedArray");

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

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

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

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

Поэтому сразу же, как необходимость в массиве отпадет, его следует удалить функцией:

void DeleteArray(long id);

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

При запуске выполним следующие действия (для этого достаточно включить эту строку в файл ida.idc):

CreateArray("SysListTempArray");

Теперь определим функцию:

static СreateTempArray(Name) {

auto a,temp;

temp=GetLastIndex(S,GetArrayId("SysListTempArray")); a=CreateArray(Name);

if (a>0) SetArrayString(GetArrayId("SysListTempArray",++temp,Name); return a;

При выходе из IDA уже нетрудно будет удалить все временные массивы из базы автоматически.

Однако, в этом на первый взгляд логичном поступке, есть одна ошибка. Давайте подумаем, а что случиться, если сеанс работы будет аварийно завершен? Правильно, наш скрипт не получит управления и временные массивы не будут удалены!

Поэтому необходимо очищать их при входе (запуске) IDA. При этом массив "SysListTempArray" будет необходимо создавать только один раз для каждой новой базы.

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

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

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



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 [ 116 ] 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140