Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ida.final.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
6 Mб
Скачать

Char GetFuncOffset(long ea);

Преобразует линейный адрес к строковому представлению в следующем формате: ИмяФункции+СмещениеОтносительноНачалаФункции. Смещение представлено в шестнадцатеричном виде без префиксов и постфиксов.

Например:

.text:004010FF __amsg_exit proc near

.text:004010FF

.text:004010FF

.text:004010FF arg_0 = dword ptr 4

.text:004010FF

.text:004010FF cmp dword_0_408758, 2

.text:00401106 jz short loc_0_40110D

.text:00401108 call __FF_MSGBANNER

.text:0040110D

.text:0040110D loc_0_40110D:

.text:0040110D push [esp+arg_0]

.text:00401111 call __NMSG_WRITE

.text:00401116 push 0FFh

.text:0040111B call off_0_408050

.text:00401121 pop ecx

.text:00401121 __amsg_exit endp

.text:00401121

.text:00401122 pop ecx

.text:00401123 retn

Message(“%s \n”,

GetFuncOffset(0x401108)

);

__amsg_exit+9

Операнд

Пояснения

ea

Линейный адрес, принадлежащий хотя бы одной функции

Return

Завершение

Пояснения

!=””

Смещение относительно начла функции (строка)

“”

Ошибка

Если смещение относительно функции равно нулю, то вызов GetFuncOffset возвратит только одно имя.

Long FindFuncEnd(long ea);

Описание этой функции, приведенное в контекстной помощи, немного запутанное и с первого взгляда назначение этой функции не ясно.

Но на самом деле она очень находит широкое применение в автономных скриптах. Основное ее назначение – определение линейного адреса при создании функции.

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

Например:

seg000:22C0 start:

seg000:22C0 call sub_0_22DD

seg000:22C3 call sub_0_2325

seg000:22C6 call sub_0_235B

seg000:22C9 call sub_0_2374

seg000:22CC call sub_0_23B6

seg000:22CF call sub_0_23F8

seg000:22D2 jnz loc_0_22DA

seg000:22D4 nop

seg000:22D5 nop

seg000:22D6 nop

seg000:22D7 call sub_0_2412

seg000:22DA

seg000:22DA loc_0_22DA: ;

seg000:22DA call halt

seg000:22DD

seg000:22DD ; _______________ S U B R O U T I N E ___

seg000:22DD

seg000:22DD

seg000:22DD sub_0_22DD proc near ;

seg000:22DD call sub_0_28CC

Функция start не завершается командой возврата ret. Вместо этого она перывает выполнение программы, процедурой Halt.

Если пытаться создать функцию, определяя линейный адрес ее конца поиском ret, то полученный адрес будет принадлежать функции sub_0_22DD!

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

Вторая проблема заключается в отождествлении инструкции возврата. Это может быть все что угодно. И RETN, и RETF…

Таким образом, определение конца функции «вручную» оказывается слишком утомительно. И тогда стоит прибегнуть к вызову FindFincEnd.

Что она делает? Она возвращает линейный адрес на единицу больший линейного адреса конца функции, которая может быть успешно создана.

Таким образом, задача создания определения адреса конца функции для ее создания упрощается, тем более, что FindFuncEnd ищет не первую встретившуюся ей инструкцию возврата, а последнюю в цепочке перекрестных ссылок на следующую команду (подробнее об этом рассказано в главе «Перекрестные ссылки»).

Отсюда следует тот замечательный факт, что она поддерживает функций со множественными возвратами (а таким, как правило большинство).

Например:

seg000:0100 start:

seg000:0100 mov ax, 3D01h

seg000:0103 mov dx, 10Fh

seg000:0106 int 21h

seg000:0106

seg000:0106

seg000:0106

seg000:0108 jb loc_0_10B

seg000:010A retn

seg000:010B ; -------------------------------------

seg000:010B

seg000:010B loc_0_10B:

seg000:010B mov ax, 0FFFFh

seg000:010E retn

seg000:010E ; -------------------------------------

seg000:010F aMyfile db 'MyFile',0

Message("0x%X \n",

FindFuncEnd(0x10103)

);

0x1010F

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

Однако, если быть уж совсем «буквоедом», то можно заметить, что строка aMyFIle вероятнее всего принадлежала функции, но IDA автоматически не смогла это распознать. Поэтому иногда результат работы функции все же приходится корректировать.

Очень важный факт – линейный адрес должен указывать на начало команды, иначе вызов провалиться.

Например:

Message("0x%X \n",

FindFuncEnd(0x10102)

);

0xFFFFFFFF

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

Если же функция уже существует, то вызов FindFuncEnd так же возврат адрес ее конца:

seg000:0100 start proc near

seg000:0100 mov ax, 3D01h

seg000:0103 mov dx, 10Fh

seg000:0106 int 21h

seg000:0106

seg000:0106

seg000:0106

seg000:0108 jb loc_0_10B

seg000:010A retn

seg000:010B ; ------------------------------------

seg000:010B

seg000:010B loc_0_10B:

seg000:010B mov ax, 0FFFFh

seg000:010E retn

seg000:010E ; ------------------------------------

seg000:010F aMyfile db 'MyFile',0

seg000:010F start endp

Message("0x%X \n",

FindFuncEnd(0x10103)

);

0x10116

То, что последний отображаемый адрес равен 0x10F это небольшой баг IDA. На самом деле это адрес начала стоки, но не ее конца. Как нетрудно вычислить, адрес конца строки равен 0x115, следовательно функция FindFuncEnd работает правильно.

В описании этой функции в idc.idc утверждается, что требуется передать линейный адрес начала функции, но это не так. С таким же успехом функция принимает любой, принадлежащий ей адрес, если он приходится на начало инструкции.

Операнд

Пояснения

ea

Линейный адрес, конца функции

Return

Завершение

Пояснения

!=BADADDR

ID структуры обеспечивающий доступ к локальным переменным и аргументам

BADADDR

Ошибка

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]