Анимация
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

Для задания значений элементов используется пара функций:

success SetArrayLong (long id,long idx,long value);

success SetArrayString(long id,long idx,char str);

Причем обе функции могут принимать как символьный, так и числовой тип значения.

SetArrayString(id,idx,0x21) занесет в ячейку знак ! и соответственно SetArrayLong (id,idx,!*) - 0x2A21.

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

Примечательно, что не нужно предварительно каким-либо образом задавать размер массива. Просто указываете требуемый индекс вот и все.

Всего доступно 0x100000000 индексов (32 бита), что позволяет расширять массивы, не только "вперед", но и "назад".

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

Чтение элементов массива выполняется несколько неожиданным способом. Вместо двух функций GetArrayLong и GetArrayString используется одна:

char or long GetArrayElement(long tag,long id,long idx);

Уточнение типа, требуемого элемента выполняется через тег. Если он равен A, то функция возвратит числовое значение, и строковое в противном случае.

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

Можно так же использовать и определения AR LONG и AR STR, однако, на мой взгляд, их несколько утомительнее писать. С другой стороны, использовать непосредственные значения более рискованно в плане возможной несовместимости с последующими версиями.

idx - это индекс элемента массива. Традиционно в большинстве языков программирования (например, Си) нет никаких средств навигации по индексам и даже невозможно узнать, сколько элементов содержит массив и какие из них инициализированные, а какие нет.

Всех этих проблем нет в IDA.. Индекс первого элемента поможет узнать функция:

long GetFirstIndex(long tag,long id);

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

Соответственно, индекс последнего элемента поможет найти функция:

long GetLastIndex(long tag,long id);

Следующий или предыдущий индекс в цепочке можно найти с помощью функций:

long GetNextIndex(long tag,long id,long idx);

long GetPrevIndex(long tag,long id,long idx);



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

Ну и, наконец, удалить любой элемент массива можно с помощью функции:

success DelArrayElement(long tag,long id,long idx);

Теперь можно попробовать реализовать наш проект "Записная книжка". Начнем с создания массива. С первого взгляда стоило бы реализовать такую конструкцию:

if (GetArrayId("Notepad")==-1) CreateArray("Notepad");

однако, можно ограничиться вызовом CreateArray("Notepad"), т.к. если массив уже существует, то функция вернет ошибку вот и все. И если обращаться к массиву по имени, то совершенно необязательно сохранять его ID.

Реализуем функцию "NotepadAdd" для внесения новых записей:

static NotepadAdd(s0) {

SetArrayString(GetArrayId("Notepad"), GetLastIndex(GetArrayId("Notepad"))+1,

s0);

И естественно просмотр онных:

static NotepadPrint()

auto a; a=0;

Message("Блокнот: \n");

while((a=GetNextIndex(S,GetArrayId("Notepad"),a))>0) Message("%s \n",GetArrayElement(S,GetArrayId("Notepad"),a));

Чуть позже мы добавим к "Блокноту" соответствующий интерфейс, а пока будем пользоваться его функциями с консоли. Нажмем <Shift-F2> и введем

NotepadAdd("Это только тест");

и нажмем <Ctrl-Enter>. Затем вызовем консоль еще раз и введем еще одну строку

NotepadAdd("Пусик хочет кушать");

Попробуем посмотреть содержимое блокнота командой

NotepadPrint();

Блокнот:

Это только тест

Пусик хочет кушать

А теперь реализуем наш "универсальный расшифровщик" на массивах и сравним с предбудущими результатами.



auto a,temp; CreateArray("MyArray");

for (a=SegStart(0x10000);a<SegEnd(0x10000);a++) SetArrayLong(GetArrayId("MyArray"), Byte(a),GetArrayElement(A,GetArrayId("MyArray"), Byte(a))+1);

a=GetFirstIndex(A,GetArrayId("MyArray"));

temp=0;

while(1)

(GetArrayElement(A,GetArrayId("MyArray"),a)>GetArrayElement(A,GetArrayId("MyArra y"),a)) temp=a;

a=GetNextIndex(A,GetArrayId("MyArray"),a);

процедура дешифровки

DeleteArray(GetArrayId("MyArray"));

Как видно, массивы имеют определенные преимущества перед использованием виртуальной памяти сегментов для своих нужд.

Поскольку созданный массив заполнен едва ли не на треть, то переход по элементам списка функцией GetNextIndex() заметно быстрее перебора всего массива в цикле, как это было в предбудущем примере.

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

Большой неожиданностью явилась поддержка IDA Perl-подобных ассоциативных массивов. Кардинальное отличие их обычных заключается в возможности индексирования элементов строковыми значениями.

Например:

a["Москва"] = "Москва-Столица"; a["Кремль"] = "Старинное здание в Москве";

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

При этом внутренне представление индексов таких массивов очень компактно и быстродествющие.

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

Впрочем, с какой-то стороны это и оправдано. Ассоциативные массивы реализованы "поверх" существующих, и отличаются только тем, что используют строковые, а не числовые индексы.

К ним применимы функции CreateArray, GetArrayID, RenameArray и остальные. Различие лишь в том, что все функции ассоциативных массивов не имеют тегов. Это означает, что один и тот же индекс не может одновременно ссылаться на строковое и числовое значение. Поэтому следующий пример вернет 0x1234, т.к. последнее присвоение затирает предыдущее.

SetHashString(GetArrayId("MyArray"),"1st","Это строка"); SetHashLong (GetArrayId("MyArray"),"1st",0x1234); Message("%x \n",GetHashLong(GetArrayId("MyArray"),"1st"));



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