Поддержка LE/PE/NE/LX/NLM-ФОРМАТОB

"Понятие прогресса, служит защитным механиз­мом, отгораживающим нас от ужасов будущего." Ф. Херберт. "Дюна".

Вообще-то шестнадцатиричный редактор идеологически должен быть плат­форменно-независимым. Введением в него дизассемблера SEN нарушил эту традицию, привязав его к линейке 80х86 процессоров фирмы Intel. Однако в этих пределах HIEW все же оставался кросс-платформенным, одинаково хорошо работая со всеми форматами файлов всех существующих операционных систем. Точнее даже, никак не работая, поскольку первые версии не отличали структури­рованных файлов от простых бинарных.

Десяток лет назад особо поддерживать было еще нечего. В то время господ­ствовали corn- и ехе-файлы. Первые вообще являлись бинарным образом, а вторые имели крайне простую структуру, которая относилась скорее к загрузке файла в память и была прозрачна для работы с последним "вживую". Я имею в виду таблицу перемещаемых элементов.

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

 
 

Неудивительно, что вся поддержка DOS-EXE свелась к простому отображе­нию заголовка в удобочитаемом виде.

Пояснять значения полей здесь нет смысла — это гораздо лучше расписано в руководстве программиста для MS-DOS. Ознакомившись с последним, можно попытаться отредактировать поля, когда в этом возникнет необходимость. HIEW позволяет сделать это с комфортом, избавляя от некоторых рутинных вычисле­ний. Так, например, F2 автоматически вычисляет значения полей Pages in file и Bytes on last page (это бывает необходимо при манипуляции с размером файла, чаще всего "отрезании" того мусора, который так любят оставлять в конце

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

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

Клавиша F2 поможет быстро перейти в начало оверлея. Это, пожалуй, все, что можно сказать про поддержку old-dos-форматов. Предлагаемый сервис типичен для современных hex-редакторов и скопирован практически всеми конкурентами.

Диаметрально противоположно обстоит дело с поддержкой РЕ-файлов. Выше мы уже неоднократно сталкивались с этим, а сейчас рассмотрим подробнее:

 
 

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

Когда же сведений, описываемых документацией, начинает не хватать, хакеры обычно обращаются к winnt.h — настоящей сокровищнице, где все структуры хоть и бедно комментированы, но все же хоть как-то расписаны.

Неприятным моментом будет отсутствие возможности редактирования заго­ловка непосредственно из этого экрана. То ли SEN посчитал, что среднему хакеру это не нужно, то ли просто поленился (кто знает...), — но если дело до этого дойдет, то придется, вооружившись SDK и MSDN, орудовать в hex-редакторе вручную. Или писать свою собственную утилиту, поскольку такая необходимость возникает достаточно часто.

Аналогично поступил автор и с показом флагов (F2). Смотреть можно сколько угодно, а редактировать — нет. Печально.

На этом фоне довольно качественной выглядит навигация по секциям РЕ-фай-ла (F6) или, в терминологии HIEW, по таблице объектов. При этом выдается дополнительная информация о каждой секции. При этом, к сожалению, вновь

 

Characteristics BIBF   DLL flag ВВв8  
В: Relocations stripped :Yes 8: Process initialization :No
1: Executable image :Yes 1: Process termination :No
2: Line nunbers stripped :Yes 2: Thread initialization :No
3: Local symbols stripped :Yes 3: Thread termination :No
4: reserued :No    
5: reserued :No Loader flag вввВвВвО  
6: 16 bit machine :No В: Break on load :No
7: Bytes reversed lo :No 1: Debug on load :No
8: 3Z bit machine :Yes    
9: Debug stripped :No    
IB: Patch :No    
11: reserued :No    
12: System file :No    
13: File is DLL :No    
14: reserued :No    
15: Bytes reuersed hi :No    

отсутствует возможность редактирования и все флаги показаны не в бинарном, а в шестнадцатиричном виде. Последнее вынуждает выполнять все расчеты в уме. Действительно, какие атрибуты имеет секция .text? 0х60000020 можно разложить на 0х20+0х40000000+0х20000000. (Если читатель не понял, откуда взялись эти цифры, то пусть переведет 0х60000020 в двоичное представление, оно будет таким: 000001 lOOOOOOOOOOOOOOOOOOOlOOOOOb. Теперь уже нетрудно вычислить, что ОЮООООЬ == 0х20; OlOOOOOOOOOOOOOOOOOOOOOOOOOb == 0х20000000 и OlOOOOOOOOOOOOOOOOOOOOOOOOOOb == 0х40000000. Достаточно тривиальные вы­числения, которые любой хакер производит в уме даже без помощи калькулято­ра). Получается, что секция .text имеет следующие атрибуты — Code I Can be discarded I Not cachable. Было бы куда нагляднее, конечно, представить всю эту информацию сразу в удобочитаемом виде. Но, автор признается, что не любит плодить монстров, да и не так уж трудно все эти вычисления выполнить в уме, который стремительно усыхает в наш бурный век думающих машин и автомати­ческих калькуляторов.

Другой вопрос, что утомительно было бы держать в уме все значения флагов (кому приятно запоминать эту чисто справочную информацию?). К счастью, автор это предусмотрел и включил в контекстную помощь соответствующий пункт, который можно увидеть на следующем рисунке:

Кроме отображения секций, HIEW еще умеет читать IMAGE_DATA_DIREC-TORY и представлять ее в удобочитаемом виде. Это действительно наиболее важный элемент структуры РЕ-файла, необходимый для поиска таблиц экспор­та/импорта и ресурсов. Оставим временно в стороне ресурсы и обратим внима­ние на таблицу импортируемых функций. Фактически изучение любого приложе­ния начинается с ее анализа. Какие функции вызывает программа? Какие загружает DLL? Ставить ли точку останова на GetWindowTextA или GetDIgItem-TextA? На все эти вопросы можно найти ответ, просмотрев список импортируе­мых функций.

Естественно, что при изучении DLL нас в первую очередь будет интересовать, наоборот, экспорт и соответствующая ему секция. Конечно, мне могут возразить, что для этого существуют специальные программы наподобие dumpbin, которые делают всю работу за нас, генерируя удобный список, а в HIEW-e еще придется полазить по каждой секции вручную. И уж совсем, казалось бы, не к месту разговор о ресурсах, в которых с первого взгляда ни одному смертному разобрать­ся не дано. К тому же существуют великолепные визуальные редакторы ресурсов наподобие популярного Borland ResourceWorkShop.

Так-то оно так, да только на первый взгляд. "Популярные и великолепные" редакторы оказываются неспособными поддержать новые элементы Win98 (на­пример календарь) и при этом просто необратимо портят ресурс (особенно это относится к Борландовскому редактору).

Относительно же таблиц экспорта/импорта разница между "структурирован­ным" листингом и "живым" представлением "AS IS" не так уж и велика. Действительно, взгляните на рисунок. Не нужно большой сноровки, чтобы бегло пробежаться глазами по знакомым функциям MSVCRT. Впрочем, для "гурманов" Сусликов включил в пакет несколько специальных программ *dump, позволяю­щих более детально исследовать формат файла.

Однако если бы HIEW только и мог, что отображать некоторые структуры РЕ-файлов, то эта возможность скорее всего осталась бы так и не замеченной на фоне таких конкурентов, как dumpbin, делающий, кстати, это значительно лучше HIEW-a.

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

Должен сказать, что автор допустил несколько досадных упущений, которые заметны уже в первые полчаса работы (как он сам до сих пор этого не заметил?!) HIEW никак не учитывает косвенной адресации, которую так "любят" использо­вать все компиляторы, особенно оптимизирующие компиляторы от MicroSoft.

В результате имя вызываемой функции по-прежнему остается загадкой. Тут на помощь приходит недокументированная особенность, заключающаяся в том, что секция адресов во многих случаях совпадает с секцией имен. Несмотря на то что она в любом случае будет затерта загрузчиком, это дает нам возможность определить по косвенному вызову ординал и имя функции. Как это сделать, подробно рассказывают другие книги, здесь можно лишь посоветовать обратиться по RVA-адресу (если он не равен нулю). Например, в нашем случае он равен 0х02856 и по нему располагается строка 'AppendMenuA', таким образом mov ebx, [0004021 E8) следует читать как mov ebx.AppendMenuA. Если же секция адресов пуста (или там содержится мусор), то необходимо вычислить индексы элемента от ее начала и обратиться к секции имен или просто скопировать ее самостоя­тельно поверх первой. Как уже отмечалось, ее содержание некритично и лишь помогает при анализе программы в дизассемблере.

qview:

00001730: FF250C214000 jmp d,[00040210C] 000019АЕ: FF25D8214000 jmp d, [0004021D8] 00001372: 8BIDE8214000 mov ebx,[0004021E8]

HIEW:

.00401730: FF250C214000 jmp MFC42.4673 .004019AE: FF25D8214000 jmp __CxxFrameHandler ,-MSVCRT.dll .00401372: 8BIDE8214000 mov ebx,[0004021E8]

Вторым по распространенности после РЕ-файлов является LE-формат, кото­рый широко используется в VxD-файлах. HIEW позволяет осуществлять навига­цию по различным его структурам, а также обеспечивает удобное представление некоторых из них.

Заметим, что далеко не все дизассемблеры поддерживают LE-формат файлов, а те, которые все же его поддерживают, ужасно медленно работают, HIEW на этом фоне выглядит весьма прогрессивно, и предоставляемых им возможностей вполне хватит для серьезной работы с драйверами виртуальных устройств. Невозможно представить себе надежную защиту, не использующую собственный vxd, особенно когда речь идет об обмене данных, например, с электронным ключом или с ключевой дискетой (к огромному моему удивлению, до сих пор встречаются разработчики, не расставшиеся с этим пережитком прошлого).

Однако vxd полезны не только как собственно драйверы устройств. Код, размещенный в них, работает в нулевом кольце защиты и практически без ограничений. Это открывает широкое поле для фантазии разработчиков. Дейст­вительно, трудно представить себе мало-мальски серьезный защитный механизм, не выходящий за пределы третьего кольца.

Впрочем, анализ vxd-файлов ненамного сложнее любого другого, и ничего в этом таинственного и загадочного нет. Достаточно заглянуть в SDK, чтобы хотя бы в общих чертах ознакомиться с форматом файла, и уже можно начинать вгрызаться в него дизассемблерм. Hiew-ом, например.

Как видно из рисунка, LE-заголовок ненамного сложнее своего РЕ-собрата и не должен вызвать особых трудностей.

Назначение большинства полей понятно из их названия, и только несколько моментов могут потребовать уточнения в SDK. Между прочим, MicroSoft не очень-то открыто предоставляет сей формат на общественное растерзание. Опи­сания довольно скудные и отрывочные. Несколько статей по этому поводу в MSDN только возбуждают аппетит и разжигают любопытство, но никак не проясняют ситуацию.

Фактически анализ формата приходится выполнять каждому кодокопателю самостоятельно. И в этом значительную помощь могут оказать HIEW и прилага­емая к нему программ ledump. К последней мы еще вернемся, а возможности HIEW-a опишем прямо сейчас: