HIEW
Крис Касперски
"Ничто не может возникнуть из ничего"
Ф. Херберт. "Дюна"
ПАРА СЛОВ ПО ПОВОДУ:
Сказанное ниже является только моим линым мнением и впечателением от
hiew 6.03. Местами оно идет вразрез с мнением автора hiew. После попытки
настоять на исправлении ряда моментов я пришел к выводу, что легче написать
собвственный *view с нуля, чем заниматься перепалкой с автором.
Конкретно, он наотрез отказался поддержать хотя бы интерпретируемый
язык скриптов или предоставить мне API (компилятор мог бы и я сам
написать), добавить поддержку двоичного ввода в калькулятор, поддержать
редактирование заголовков PE\LE\LX файлов.
HIEW это замечательный и необыкновенно мощный инструмент,
предназначенный для анализа и редактирования программ непосредственно в
исполняемом коде.
Десятилетиями для этой цели традиционно использовались hex-редакторы,
которые концептуально мало отличались друг от друга. Менялся интерфейс и
предоставляемый сервис - только и всего. HexWorkShop под Windows 95 и hexed
под Агат-9 (может кто помнит такую машину) имеют больше сходств, чем
различий. Евгений Сусликов, был первым кто догадался прикрутить в
шестнадцатиричный редактор дизассемблер. Это породило продукт с совершенно
новыми качествами. Вы пробовали когда нибудь загружать в IDA или SOURCER
исполняемый файл мегабайт эдак под двадцать? Десятки часов жужжания винта и
сотни метров свопа явление хорошо знакомое каждому хакеру. А сам
дизассемблер? Сколько дискет потребуется, что бы его разместить, если
предстоит работа "на выезде"?
Всех этих недостатков лишен hiew. Шустрый, компактный, проворный, в
умелых руках он способен творить чудеса, при этом ограничиваясь число
"формальными" требованиями к аппаратуре.
По прошествии нескольких лет, возможности этой утилиты заметно
возросли. Конкретно, скачивая версию 6.03 (последнюю на момент написания
данного руководства) вы приобретаете в одном флаконе:
v Шестнадцатиричный редактор файлов неограниченной длинны
v Уникальное средство поиска ассемблерских команд по маске
v Встроенный ассемблер (Pentiun Pro)
v Встроенный дизассемблер (Pentiun Pro)
v Интерпретирумая крип-система (Virtual CPU)
Иными словами готовый инструментарий на все случаи жизни. Не хватает
только интерпретируемого языка, и интеграции с отладчиками. Впрочем, два
последних пункта сейчас обсуждаются с автором и очень возможно, что
следующая версия будет поддерживать встроенный язык.
Перечисленные возможности позволяют полностью отказаться от остальных
инструментов и проводить анализ программ, не используя ничего кроме hiew.
При этом задача взломщика не намного усложнится если даже не сказать
наоборот. HIEW относятся к ИНТЕРАКТИВНЫМ дизассемблерам, и его мощь в
некотором отношении сравнима лишь с мощью IDA.
Т.е. процесс дизассемблирования тесно связан с пользователем. Последний
сам должен определить где код, а где данные, как интерпретируется та или
иная инструкция. Последнее особенно актуально с самомодифицирующимся и
шифрованным кодом. В книге "Образ мышления - HIEW" это будет показано на
конкретных примерах, а пока Вам ничего не остается, кроме как поверить мне
на слово.
Заметим, что когда IDA или Sourcer дизассемблируют весь файл целиком,
что требует длительного времени на анализ, hiew-же показывает за раз
только небольшой фрагмент размером с экран. Конечно, если требуется
получить хорошо документированный листинг программы, то это покажется
крайне неудачным вариантом, однако же в работе хакера последнее обычно и не
требуется. Любопытно, что hiew незаменим при анализе программ в в пару
килобайт (когда расточительно запускать ради них IDA), так и в пару
мегабайт (когда IDA последние дольше будет дизассемблировать, чем хакер
сносить защиту с помощью hiew).
Кроме того, HIEW позволяет с легкостью и комфортом прогуляться по
LE/PE/NE/LX/NLM файлам, в исследовании формата и перекраивании, к
примеру, таблиц импорта под свой вкус. При этом вообще hiew
является единственным шестнадцаричным редактором поддерживающим
таблицы импорта вышеуказанных файлов:
Взгляните на следующий фрагмент:
.00401145: 83EC18 sub esp,018 ;""
.00401148: 57 push edi
.00401149: 33FF xor edi,edi
.0040114B: 57 push edi
.0040114C: FF1500204000 call GetCommandLineA ;KERNEL32.dll
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.00401152: 50 push eax
.00401153: 57 push edi
.00401154: 57 push edi
.00401155: FF1504204000 call GetModuleHandleA;KERNEL32.dll
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.0040115B: 50 push eax
И сравгите его, например с qview:
00001145: 83EC18 sub esp,00000018
00001148: 57 push edi
00001149: 33FF xor edi,edi
0000114B: 57 push edi
0000114C: FF1500204000 call dword ptr [00402000]
^^^^^^^^^^^^^^^^^^^^^^^^^^
00001152: 50 push eax
00001153: 57 push edi
00001154: 57 push edi
00001155: FF1504204000 call dword ptr [00402004]
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Не правда ли потрясающие возможности для шестнадцатиричного редактора?
HIEW можно считать полноценным win32\DOS\OS/2 дизассемблером,
поддерживающим не только 32-битные инструкции, но и форматы исполняемых
файлов популярных операционных систем.
Заметим, что не так много популярных дизассемблеров поддерживают
LE-формат. Но hiew - поддерживает, оставаясь моим незаменимым помощником
при путешествиях в дебрях VxD. Использовать для этой цели IDA не всегда
удобно - часто заранее точно неизвестно в какой файл разработчик поместил
защитный механизм и требуется окинуть беглым взглядом далеко не один
драйвер виртуально устройства. IDA тратит больше времени на загрузку, чем я
на анализ. Самое обидно, что анализ-то в большинстве случаев и не
трубетеся, потому что сразу видим, что тут, например, защита и не ночевала:
.00000007: B800000000 mov eax,000000000 ;
.0000000C: B94A000000 mov ecx,00000004A ;
.00000011: C7400400000000 mov d,[eax][00004],000000000
.00000018: CD2014000A00 VxDcall VDD.Get_DISPLAYINFO
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.0000001E: 66F705020000000008 test w,[000000002],00800 ;
.00000027: 0F85790D0000 jne .000000DA6 -------- (1)
HIEW позволит сэкономить немало драгоценного времени хакера, которое
можно потратить на нечто более полезное, чем утомительное ожидание
окончания загрузки файла.
Сказанное не должно восприниматься как наезд или повод для отказа от
IDA. Отнюдь. Это уникальный в своей категории инструмент, аналогов которому
не существует и в обозримом будущем и не предвидится. Но IDA это все же
тяжелое стратегическое оружие, а общение c hiew-ом больше напоминает работу
разведчика.
Бытует мнение, что анализ программ непосредственно в hiew-е более
сложен, чем в отладчике или полноценном дизассемблере. Некоторые это
считают "высшим пилотажем". На мой взгляд это не более, чем
распространенное заблуждение. За исключением, может быть IDA, hiew
обеспечивает весь сервис, предоставляемый другими "полноценными"
дизассемблерами, при этом обладая и присущими IDA возможностями - например,
интерактивностью. Когда SOURCER может быть легко сбит с толку хитрым
приемом разработчика защиты, с hiew-ом такого не произойдет, поскольку он
работает в тесной связке с человеком. Нетрудно обмануть машину, но человек
человека перехитрить не может (ну разве что ввести во временное
заблуждение).
К сожалению автор hiew-а не позаботился о некоторых мелочах, которые
делают жизнь хакера более приятной и экономят его время. Например,
ближайший конкурент qview позволяет создавать в файлах комментарии, а hiew
- нет. Впрочем, последнее не вызывает особых проблем и надеюсь будет
реализовано в последующих версиях.
Не будем больше заниматься бессмысленным сравнением конкурирующих
утилит, а перейдем к описанию пакета поставки. В версию 6.03 входят
следующие файлы:
--------------------------------------------------------------------------
FILES.LST - Файл описания (увы,плохо совместим с DN и др. оболочками)
HIEW.EXE - Собственно сам HIEW (одновременно для DOS и OS\2)
HIEW.INI - Конфигурационный файл
HIEW.HLP - Файл помощи
HIEW.ORD - Символьная информация ординалов распространенных файлов
HIEW.VMM - VMMcall/VxDcall для LE файлов
HIEW.XLT - Файл перекодировок (Windows-1251\KOI-8R)
HIEWR.nnn - Краткое описание на русском языке
HIEWE.nnn - Краткое описание на английском языке
NEDUMP.EXE - Утилита для исследования NE-файлов (не актуальна сегодня)
LXDUMP.EXE - Утилита для исследования LX\LE-файлов
DEXEM.EXE - Утилита для работы с Dual-EXE (NE/LE/LX/PE) файлами
SEN.ASC - Публичный PGP ключ автора
--------------------------------------------------------------------------
HIEW.exe очень тяжел. Целых 284,855 байт, что отнимает много места,
например, на спасательной дискете (а он у меня всегда на ней. Мало ли с
какими вирусами воевать придется). На самом деле это DUAL-exe файл, т.е.
_два_ файла для MS-DOS и OS\2 _одновременно_. Это оригинально, но слишком
расточительно. (заметим, что такие программы могут существовать и под
windows).
Первое, что необходимо сделать - "разрезать" файл на две половинки и
взять "родной" для вашей операционной системы. Для этого предназначениа
утилита dexem.exe
Подробнее она будет рассмотрена ниже, а пока просто запустим ее
следующим образом dexem.exe /S hiew.exe При этом DUAL-exe будет расшеплен
на два файла hiew.mz (MS-DOS) и hiew.ne (OS\2) по 102 и 183 килобайта
соответственно. Отметим, что 102 много меньше 285, и учитывая, что OS\2 в
жизни многих пользователей может быть никогда и не встретится, то хорошим
решением будет удалить оригинальный hiew.exe и переменовать в последний
hiew.mz
Не зависимо от того сделали вы это или нет, попробуем запустить
hiew.exe без параметров. Кто знаком с ранними версиями hiew помнит, что при
этом программа просто не запускалась, ссылаясь на отсуствие файла в
командной строке.
В версии 6.03 поддерживает встоенную систему навигации по файлам и
каталогам, которая активируется всякий раз, когда hiew запускается без
явного указания файла в команной строке. Логично было бы предположить, что
то же произойдет при задании маски (например hiew.exe *.exe). Но автор
мыслил инчае. При этом hiew просто найдет первый попавшийся файл, а если
таковых не окажется, то с грусттью сообщит "File(s) not found" и закончит
работу. Печально, однако.
Но вернемся к навигатору.
г==================D:\KPNC\HIEW===================¬
¦ .. ¦>UP--DIR<¦Attr¦---Date---¦--Time-- ¦
¦ PROHACK ¦>SUB-DIR<¦....¦15-03-1999¦14:06:06 ¦
¦ CRACKME.EXE ¦ 182455¦.a..¦15-03-1999¦21:07:18 ¦
¦ DEXEM.EXE ¦ 11408¦.a..¦22-10-1998¦11:32:26 ¦
¦ ¦
L========================*========================-
^
маска отображ. файлов ---
1Help 2Hidden 3Name 4Exten 5Time 6Size 7Unsort 8Revers 9FilHis10Filter
Вообще навигатор очень напоминает Нортена Командера и общение с ним
проблемм вызвать не должно. На всякий случай я все же опишу назначение
клавиш управления:
Alt-F1 (Drive) : смена текущего дисковода. Замечу что hiew немного
некорректно обрабатывает список существующих устройств. Так, например, у
меня он обраружил 'B', хотя тут 'B' отродясь не было. Попытка чтения с него
привела к переадресации на 'A', что прошло не без возмущений со стороны
WINDOWS.
F2 (Hidden): отображение скрытых и системных файлов. Кнопка действует
как триггер.
F3 (Name) : сортировка по именам файлов.
F4 (Exten) : сортировки по расширениям.
F5 (Time) : сортировка по времени создания.
F6 (Size) : сортировка по размерам.
F7 (Unsort): распологать файлы в том порядке, в каком их находит
FindNextFile
F8 (Revers):обратить условние сортировки. Т.е. по умолчанию (за
исключением даты) принята сортировка по возрастанию параметра. Реверс
приводит к сортировки по убыванию. Действует как триггер.
F10 (Filter) :задать маску отображаемых файлов. К сожалению не
позволяет задавать более одной маски, что может вызвать неудобства.
Маленький баг - если удалить маску, то hiew ее не восстановит по умочанию.
Для этого необходимо будет задать явно '*.*', что лично мне например,
просто неудобно.
При этом существует возможность быстрого поиска необходимого файла.
HIEW вобрал в себя все лучшие решения от DN и NC и реализовал очень нехилые
для простого встроенного менедрежа возможности.
Нажатие любой символьной клавиши приводит к появлению консольной
строки, в которой можно ввести имя файла. (при этом курсор будет
перемещаться по списку синхронно с вводом).
Есть и чисто юниковская возможность дополнения введенного имени до
полного, при условии, что последнее однозначно определяет файл. Возможно,
что это определение покажется витиеватым, поэтому покажу на примере.
Допустим, нам нужно найти файл crackme.exe Если в текщей директории на 'c'
есть только один файл, то логично, что он может однозначно быть определен
заданием всего одной буквы. Вводим 'c' и нажимаем <tab>. Hiew, догадываясь,
что мы хотим открыть crackme.exe выводит его имя (между прочим без
расширения). А что будет если у нас есть два файла crackme1 и crackme2?
Тогда hiew сердито пискнув, напишет только 'crackme' и остановится, ожидая
уточнения - какой именно из двух файлов нам требуется открыть.
Кому-то это может показаться не удобным, тогда можно
воспользоваться '*' - непосредственным аналогом Ctrl-Enter в DN и NC -
последовательному перебору подходящих файлов.
Имеется и очень ценная недокументированная возможность задания списка в
квадратных скобках. Например, [cr,h]ack.exe найдет все crack и hack. Если
запятую опусть, то hiew будет интерпретировать стоку как [c,r,h]. Т.е.
*.[ch] он найет все файлы c,cpp,h и др. Это очень полезная и вообще
уникальная для плафвормы MS-DOS возможность, которая не сущестует ни в
одной другой аналогичной программе.
Жалко, конечно, что эти возможности большей частью остаются
невостребованными - hiew все же не файловая оболчка и чаще всего
редактируемый файл непосредстенно задается в строке, хотя бы по чистой
привычке, оставшейся от старых версий. (я вот тут думаю, если бы автор
предусмотрел еще и запуск из Файлового Навигатора, то многие, включая в
первую очередь меня, использовали бы его как оболочку, которая особенно
была бы удобной на "спасительных" дискетах).
Если hiew запушен с имененм несуществующего файла, то он предложит
создать его. Альтернативным вариантом является клавиша <Ins> в Навигаторе.
Последняя возможность просто незаменима, когда новые файлы приходится
создавать и открывать непосредственно во время работы. К примеру, может
потребоваться сдеалть некоторые заметки по ходу работы, скопировать
фрагмент в новый файл и при этом тут же открыть его и, скажем,
расшифровать. (отметим, что навигатор можно вызвать в любой момент работы
клавишей F9).
Ctrl - '\' обеспечивает быстрый переход в корневую директорию текущего
диска, а F10 в материнскую директорию (ту, из которой был запущен hiew).
При этом существует полезная возможность быстрого переключения между
четырьмя произвольно выбранными директориями. Для этого сущестуют клавищи
Ctrl-F1, Ctrl-F3, Ctrl-F5,Ctrl-F7 которые запоминают текщую директорию и
Ctrl-F2, Ctrl-F4, Ctrl-F6,Ctrl-F8 которые соответственно переходят в
записанную. При этом есть возможность сохранения текщего состояния в файл
и его последующего использования во всех сеансах. Впрочем, последнее
реализовано не самым лучшим образом. Нет никакой возможности сохранить
состояние непосредственно из навигатора, поэтому приходтся открывать файл
только для того, что бы получить доступ к клавише 'Ctrl-F10' - 'SaveSatus'.
К последней мы еще вернемся, а пока отметим, такую приятную особенность,
как ведение истории просматриваемых файлов (F9)
г=Mode Offset Name===============================================¬
¦ Hex ¦0000163C¦D:\KPNC\HIEW\HIEWR.602 ¦
¦ Text¦00000452¦D:\KPNC\HIEW\DEXEM.EXE ¦
L==================================================================-
При этом кроме собстенно имен сохранятся текущий режим и позиция
курсора (что особенно приятно). Последнее позвояет использовтаь hiew для
чтения больших текствоых файлов (электонных книг, документации). При этом
никогда не придется помнить на каком месте вы в последний раз находились
перед выходом. (Впочем, что бы быть до конца честными отметим, что эта
возможность присуща сегодня практически всем современным вьюверам - qview
by AGC, UniversalViewer и MessageViewer by KPNC да и многим другим). Так же
позволю себе отметить, что в этом UniversalViewer обогнал других. Тогда как
hiew и qview привязываются к имени файла, UV - к хеш сумме заголовка и
окресностей текущей позиции курсора. Имя файла при этом игнорируется.
Последнее вызывает меньше конфликтов, хотя немного медленее работает. Будем
надеяться, что SEN в ближайших версиях реализует нечто похожее.
Перейдем теперь к рассмотрению командной стоки. Большинтсво ею
пользуется все же гораздо чаще, чем непривычным навигатором.
В командной строке можно задавать более одно файла, но при этом будет
открыт только первый из них, а остальные доступны по Ctrl-F9, что, впрочем,
удобно, т.к. уменьшает время загрузки. Если спецификация файла не будет
полной, то hiew найдет все подходящие файлы и добавит их имена в список.
Это неудобно и нелогично. Неполная спецификация должна приводить к вызову
Навигатора (во всяком случае по моему личному мнению).
Параметр /SAV задает имя SAV-файла, который автоматически будет
загружен. По умолчанию принимается hiew.sav, но последнее может быть
изменено в hiew.ini:
; StartUp
Savefile = "hiew.sav"
sav-файл полностью сохраняет текущее состояние hiew-а, включая текщую
позицию, все закладки и т.д. Обычно чтобы воспользоваться sav - файлом,
нужно запустить hiew без параметов. Заметим, что 'hiew.exe MyFile.exe' не
приведет к должному результату. Неудобно, конечно, но приходится мирится. А
что же остается делать - хозяин (SEN) - барин.
Интересная особенность - конфигурационный файл можно так же указывать в
командной строке после ключа /INI. Это особенно удобно для "корпоративного"
использования hiew сразу несколькими людьми. Каждому - настройки на свой
вкус.
Если же требуется показать содержимое вложенный директорий, то можно
использовать ключ /S с указанием пути и маски. При этом hiew /s C:\*.* с
большой вероятностью после продолжительного шуршания диском завершит свою
работу с сообщением:
"No free memory"
Это будет зависить от количества имеющихся у вас на диске файлов. Если
же их относительно немного, то есть шанс, что hiew запустится и можно будет
выбрать любой понравившийся файл, нажав Ctrl-F9.
Долгие размышления мне так и не позволили придумать такую ситуацию, в
которой данная возможность была бы не заменимой. Ведь всегда же есть под
рукой встоенный файловый Навигатор!
После выбора файла hiew автоматически показываает его в текстовом
режиме. Не слишком удачный выбор для хакера, поэтому последние обычно
первым делом редактируют следующую строку hiew.ini
StartMode = Text ; Text | Hex | Code
Впрочем, если hiew планируется и для просмотра текстовых сообщений то
ничего трогать не надо. Жалко, однако, что нет функции "автодетект", тем
более что реализовать последнию совсем не трудно.
ОСНОВНОЙ ЭКРАН:
- TRIAL.COM R NE 0000007B a16 -------- 823 ¦ Hiew 6.03 (c)SEN
^ ^ ^^ ^ ^ ^ ^ ^
¦ ¦ ¦¦ ¦ ¦ ¦ ¦ ¦
¦ L-имя файла ¦¦ L тип ¦ ¦ ¦ L--длина файла (dec)
¦ ¦¦ ¦ ¦ ¦
¦ направление --L- состояние ¦ ¦ L- закладки
¦ ¦ ¦
L-лифт|% текущее смещение (hex) -- L-режим 16/32 разрядный
Вообще же строка статуса может меняться в зависимоти от режима, но это
не должно вызвать каких-то проблемм в понимании. Рассмотри подробнее
некоторые элементы:
Левосторонний лифт может показаться непривычным и действительно не
очень удобен. Поэтому автор предусмотрел возможность настроить последний по
вкусу пользователя, а то и вовсе отключить его. Для этого необходимо
отредактировать hiew.ini Если комментариев в файле окажется недостаточно,
то обратитесь к главе "КОНФИГУРИРОВАНИЕ HIEW" настоящего руководства.
Направление поиска (прямое или обратное) задается клавшей Alt - 7 в
любой момент или непосредственно во время вызова окна поска клавишей F2.
При этом индикатор направления будет обновлен только после завершения
поиска. Не нравится мне последнее. Не плохо бы перенасти управление с F2 на
ALt-F7 и при этом обновлять индикатор. Но не будем строги к автору - эта
возможность появилась только в версии 6.03 и, конечно, до конца еще не
отлажена.
Состояние файла может быть следующим:
(R)ead - открыт по чтению
(W)rite - открыт по записи
(U)pdate - изменен
При этом последний режим обрабатывается некорректно. В независимоти от
того был ли изменен хотя бы один байт, при каждом сбросе буферов редкатора
(F9) на диск (включая пустые!) всегда выставляется флаг изменения.
Впрочем, это не баг, а фича и маловероятно, что бы она была
исправлена в ближайших версиях.
Первый же вызов редкатора (F3) приводит к автоматическому переоткрытию
файла в режиме полного доступа (чтения и записи). Этот режим сохраняется и
после выхода из редактора. Т.е. автоматического переоткрытия "Только на
чтение" не происходит. А жаль. Индикация просто теряет смысл.
Hiew автоматически распознает следующие типы файлов DOS EXE, NE, PE,
LE,LX,NLM но при этом отображет в стороке статуса только пять последних
из них. DOS-EXE hiew стого говоря _не_ поддерживает (ну за исключением
заголовка). Да, собстенно, там и поодерживать особо нечего. Можно, конечно,
правильно настроить регистр DS, но это было бы слишком для
шестнадцатиричного редактора - все же hiew изначально ну ниака не
планировался как дизассемблер. Впрочем, если будет встроенный язык (а он
все равно будет) - эти вопросы могут решаться пользователями на месте не
дожидаясь новой версии. То же относится и к нестандартным бинарым файлам,
например, разныем BIOS-ам или дампам памяти. Зачему, что для всего этого
SEN написал замечательную утилиту StructLook, версия 4.20 котрой выложена
на ftp автора (ftp.kemsc.ru/pub/sen). Она содержит интерпретируемый
препроцессор и очень удобна при "низкоуровневой" работе с различными
фоматами файлов. Но это совсем другая история.
Режим 16/32 определяется автоматически для поддерживаемых типов
файлов. Это отличает его от qview, где режимы приходится переключать
вручную, в противном же случае код дизассемблируется неправильно, что может
приводить к печальынм результатам. В режиме 'text', где понятие 16\32
разрдного кода как таково отсутствует это поле выражает номер самой левой
отображаемой колонки, считая с нуля.
Очень неплохо продумана работа с закладками. Впрочем, удобно еще не
значит привычно. Фирма Borlan установила стаднарт де-факто: Ctrk-K-n
запомниить состояние, Atl-Q-n восстановить его. Такая точка зрения не была
поддержана SEN и он задействовал совсем другие "горячие" клавиши. Grey-'+'
запомнить текщее состояние. Этот факт мгновнно отражается в индикаторе.
Изображение '-' изменяется на порядковый номер закладки (считая с единицы?!
). При этом hiew может запомнить до восьми закладок. Большего
обычно и не трубется.
Восстановть текущую закладку (которая индикатор отмечает '') можно
нажав Gray-'-'. Выбрать любую другую закладку поможет Alt-'1-8'. При этом
последняя автоматически помечается как текущая. Если ее потребуется
удалить, то можно нажать Alt-'-'. А 'Alt-0' - удаляет сразу все закладки
без предупреждения. Так что будьте осторожны с этой комбинацией!
В режиме редактора '<Editor>' закладки к сожалению становится
недоступны по причине того, что последний ограничен всего одним окном.
Удивительно, но этот недостаток присущ лишь hiew-у, а конкуренты давно
реализовали это достойным образом. Самое интересное, что мне непонятные
какие затруднения может испытывать автор с последним... Тем более, что это
действительно жесткое ограничение, которое особенно дает о себе знать при
расшифровке даже небольших файлов. Поэтлму все больше и больше людей
сколоняются к мысли, что эту операцию лучше делать в qview, где нет таких
ограничений. Остается только надеяться, что автор под мощным натиском
общественного движения (ау! хакеры!) хотя бы через несколько версий
реализует то, что конкуренты имели от рождения.
Длина файла отображается исключительно в неродном для хакеров
десятичном исчислении. В купе с шестнадцатиричном смещением это особенно
неприятно. Неплохой идеей думается мне был бы переход полностью на
шестнадцатиричный режим в decode режиме и соответственно - десятичный в
текстовом. При этом было полезно отделять точкой каждые три знака, что
улучшает читабельность больших числел. Так что поле работы автору в
последующих версиях еще есть, а это значит, что они будут выходить,
выходить и еще раз выходить (правда при том условии, если SEN-у все это не
надоест и он не забросит свое творение в самый пыльный угол винчестера, как
это произошло с ДеГдюкером, Cup-ом, InSight-ом... да, собстенно долго можно
перечислять-то. Я как-то писал в одной своей утилите, что пожалев сейчас 1$
через некоторое время можно потерать в сотни раз больше из-за отстутсия
утилиты, которая не была написана именно по причине экономии этого самого
доллара. Увы, российские пользователи привыкли, что лучшие программисты
страны должны работать "просто так" для их собстенного удовольстия)
АССЕМБЛЕР
"Убийство острием лишено артистизма,
Но пусть тебя это не останавливает,
если плоть, раскрываясь,сама себя
предлагает".
Ф.Херберт "Дюна"
Перейдем к непосредственному описанию возможносей hiew-а. Я долго
колебался между "руководством по ключам" между "описанием возможносей".
В конце-концов выбор остался за последним. По моему глубокому убеждению
описание на уровне клавитары, не нужно тем пользователям, которые читают
это руководство. HIEW все же хакерский продукт. "А зачем хакеру хелп?" -
улыбается Сусликов. Но вот возможности, приемы работы и маленькие секреты
будут прочитаны с большим удовольствием. И может быть тогда начинающие
прекратят задавать глупые вопросы "ну вот я занаю какие байтики подправить,
а в hiew-е их никак найти не могу",
Встроенный ассемблер может быть полезен для многих вещей. Так,
например, небольшие файлы удобно набивать сразу в hiew-е, а не пользоваться
MASM\TASM-ом, которые на порядок медленнее работают. При этом последние не
понимают многих извратов, так например, когда мне потребовалоь для хитрой
защиты ассембировать смесь шестнадцати и тридцати-двух разрядного кода со
множеством команд Pentuim Pro. никто кроме hiew-а и моих собстенных ручек
не смог этого сдеалть.
Кроме того, все команды сразу показываются и в hex-кодах, а не после
редактирования\ассемблирования\линковки\дизассемблирвоания, (при работе со
стандарными средствами), что открывает свободу для экспеременирования и
страхует от ошибок. Так, например, тот же TASM частенько даже при задании
директиры USE32 почему-то вставляет в неужных местах ненужные префиксы или
(что не лучше) опускает с целью отпимизации расставленные мной. Хотите
пример? Попробуйте указать префикс DS для данных. TASM его проигнорирует (и
разве, что у виска пальцем не покрутит). А теперь предствавим, что в
самомодифицирующеся коде я пытаюсь менять префикс, которой был опущен.
Так же незаменим встоенный ассемблер, если в ломаемой программе нужно
не просто поменять 7x на EB, а дописать десяток-другой строк кода (а такое
случается достаточно часто).
К сожалению встроенный ассемблер содержит много ограниченй, о которых
будет рассказано ниже. Прежде всего самое обидное, что в этом режиме hiew
еще не поддерживает локальных смещений и все вычисления адоесов приходится
проводить вручную. К моему удивлению не все знают как последнее делается. В
самом деле все очень просто, достаточно знать формат редактирумого файла.
Покажем на примере, наверное самого распростаненного PE-формата файлов,
поддерживаемых платформой Win32 (это все же руководство по hiew, а не по
взлому). Для этого сначала рассмотрим, как происходит загрузка PE файлов.
MicroSoft неплохо оптимизировала этот процесс и PE целиком проецируются в
память, включая и DOS-секцию. При этом один селектор выделяется для кода и
данных. А это ознаечает, что перевод глобальных в локальные смещения
осуществляется триивальным добавлением адреса загрузки, который можно
узнать из заголовка PE файла. Поскольку hiew отображает последний в удобно
читаемом виде, то наша задача упращается еще больше - достаточно заглянуть
в поле Image base. В большинсте случаем там содержатся круглые значния,
например 0x400000,0x010000. Не сложно выполнить все вычисления и в уме,
однако, к чему напрягаться? Я так и не нашел в песках истории с какой
версии hiew поддерживает базирование, но это нам не помашает им с успехом
воспользоваться. Переймем в начало файла и нажмем Ctrl-F5, после чего
введем значение Image base (в моем случае 400000). Посмоим что получилось;
Дизассемблер Ассемблер
Без базирования: .0040119A: call .000401298 0000119A: call 000001298
С базированием: .0040119A: call .000401298 0040119A: call 000401298
Как мы можем с удовлетворением отметить, базирование решило проблемму и
можно даже не пинать автора исправить этот недостаток (хотя с его стороны
это все же непростительный баг).
Очень удобно, что hiew при ассемблировании не пытается оптимизировать
то что его не посят. Например, если вы укажите адресацию через DS. то перед
командной появится соответствующий префикс 0x3E. Сравите:
00000000: 3EA16606 mov ax,ds:[00666]
^^
00000004: A16606 mov ax,[00666]
Любой другой привычный нам ассемблер (tasm, masm) выдал бы идентичные
результаты, что не вызвает у меня восторга. За это и любим hiew, что он
послушно делает то, что его говорят.
Вообще ассемблирование процесс довольно творческий. Одна и та же
мнемоническая инструкция может быть ассемблирована по-разному. Такова уж
специфика архитекуры линейки 80x86 микропроцессоров от Intel. Микрокод
первых процессоров разрабатывался в то далекое время, когда экономить
приходилось каждый байт и поэтому инженеры Intel обратили внимания на такую
ситуацию когда регистр размером слово манипулирует непрсредственным
значением меньшим 0x100. При этом старщий байт равен нулю, т.е.
теоритически можеть быть ужат до одного бита, а этом самый бит можно
разместить с пустующем поле приемника (ясно, что приемником
непосредственный операнд быть ну никак не может). В результате этих
ушишрений экономится один байт. Итак, такую команду можно записать двумя
способами:
00000007: 83C266 add dx,066 ;"f"
0000000A: 81C26600 add dx,00066 ;" f"
При этом hiew всегда выбирает первый из них (т.е. пытается
оптимизировать код). Последние восторга у хакеров не вызывает, ибо часто не
соответсует ожидаемому результату.
Диметрально противоположна ситуация при генерации переходов. По
умолчанию hiew всегда генериует близкий (near) переход 0xE9. Если
необходимо задать близкий переход, то заставить hiew это сделать поможет
команда jmps (jmp short действует аналогично). Позволю себе малость
покритиковать автора и заметить что чаще всего кракеры заменяют условный
переход на безусловный. При этом jmp near откровенно портит код. Обидно,
однако.
Продолжая критику заметим, что ассемблер так же не понимает ни
ординалов ни символьных имен, что совсем - совсем не радует. Очень хотелось
бы в следующих версиях получить полноценную поддерку перечисленных выше
форматвов.
В остальном же ассемблер ведет себя корректно и безглючно. При этом
имеет встроенный калькулятор. Т.е. он прекрасно перевариает конструкции
типа mov ax,[66+11] и даже mov ax,[-77]. Последнее правда без учета режиа.
(еще один баг - в копилку!) Отрицательные числа адреса всегда дополняюся
до слова. При этом в 32-разрядном режиме забавно выглядит попытка
ассемблировать 'jmp -1'
00000003: E9F7FFFFFF jmp
^^^^^^
Заметим, что последним только извращенцем придет в голову пользоваться,
однако же в защитах это встречается! и работает следующим образом - пусть
например, есть код:
00000000: E9FAFFFFFF jmp -1
00000005: 90 nop
00000006: 90 nop
При этом jmp смещает указатель команд на единицу и получется:
00000000: FF9090909090 call d,[eax][090909090]
Что, заметим ну никак не очевидно и является довольно любопытным
приемом. Очевидно, не всем приходит в голову что jmp можеть прыгать в
границах своего операнцда. Хотя вообще ассемблирование отрицательных
переходов в hiew это один большой баг, или фича. Во всяком случае от не
работет так, как это ожидается.
Впрочем, это все мелочи и в ближайших верисях обоих продуктов будут
исправлены.
Еще одним недостатком приходящим на ум является упорное нежелание
hiew-a 'переваривать' директиру <ptr>, поэтому выражение
mov Word ptr CS: [077],66
не может быть обработано синтаксическим анализатором. Приходится его
сокращать до
mov Word CS:[077],66
Ужасно неудобно менять свои привычки, но что поделаешь - приходится.
Последнее частично скрашивается приятной возможность сокращать
byte/word/dword/pword/qword/tbyte до b/w/d/p/q/t, как показано ниже:
г= Pentium(R) Pro Assembler =====================================¬
¦ mov w,[0077],0022--------------------------------------- ¦
L================================================================-
Все числа считаются шестнадцатиричными по умолчанию, но никто не будет
против буковки 'h'. А вот с 'x' анализатор не знает что делать и
незамедлительно ругается. Последнее выглядит особенно странно на фоне
калькулятора, который такую нотацию как раз-таки понимает, но не
переваривает в свою очередь 'h'.
Чем больше я изучаю hiew, тем больше у меня складывается впечатление,
что его писали два разных человека. Впрочем, последнее все же больше шутка,
чем правда. Однако, не мешало бы попинать автора, что бы привести
анализатор в порядок, а то работать порой бывает весьма дискомфортно.
Анализатор ошибок на редкость упрощен, однако это не должно вызывать
каких-то проблемм, предполагая, что hiew все же расчинан на тех людей, чей
второй язык (после родного) - ассемблер и достаточно лишь намека что бы
понять почему "оно" не ассемблируется.
ДИЗАССЕМБЛЕР
Дизассемблер в hiew великая вещь. Фактически это основной режим работы
хакера. Не то что бы некоторые ленились дизассемблировать в уме hex-коды,
(что частенько приходится при работе со встроеным вьювером в DN скажем), но
ассемблерсикй листинг все же прывычнее глазу и кроме того имеет множество
дополнительных возможностей (таких как поиск ассемблерских команд по маске)
которые заметно ускоряют анализ программ.
К сожалению (и признаться еще большему моему удивлению) автор не
считает hiew дизассемблером и не хочет улучшать некоторые моменты чисто из
идеологических соображений. Ну что же, будем ждать поддержки языка, где все
это все возможно будет делать на лету, не обращаясь за помощью к автору. И
всякому на свой вкус. Беда в том, что раскачть автора на встроенный язык
или хотя бы задокументированный API (язык-то написать нетрудно) пока никак
не получается.
Ну что же, как говориться хозяин - барин, тем более, что hiew пока
пишется лишь для удовольствии последнего и исходя из его же этических
соображений. Вот когда автор будет получать за свою работу живую деньгу,
тогда и исполения желаний ждать можно будет, а пока остается только
надеяться или садиться и писать собственный Xview. Последнее, кстати,
многие активно делают и я не исключение. Впрочем, мой UniversalViever
находится в весьма заброшенном состоянии, но если когда-то будет закончен,
то... появится еще один конкурент на рынке hex-редакторов. К слову сказать
UV изначально расчитан на мульти-процессорную поддержку и будет очень
удобен при анализе эмуляторов вируальных процессоров.
Но это когда еще будет (и будет ли вообще), а hiew уже есть и
поддерживает инструкции вплоть по Pentium Pro. А точнее P6-kernel, которое
используется не только в том числе и в Celeron-ах.
Типчый вид дизассемблировано текста следующий:
.00401207: 50 push eax
.00401208: 52 push edx
.00401209: E8D2FEFFFF call .0004010E0 -------- (1)
.0040120E: 83C404 add esp,004 ;""
.00401211: 50 push eax
.00401212: E8A9FEFFFF call .0004010C0 -------- (2)
.00401217: 83C408 add esp,008 ;""
.0040121A: 663DF801 cmp ax,001F8 ;"°"
.0040121E: 7404 je .000401224 -------- (3)
.00401220: 6A03 push 003
.00401222: EB02 jmps .000401226 -------- (4)
.00401224: 6A04 push 004
Hiew позволяет "путешествовать" по файлу, входя в процедуры и выполняя
условные\безусловные переходы. Для этого нужно нажать цифру, которая
показана в круглых скобках слева. Посмею высказать свое (возможно
предвзятое мнение) что последнее в IDA реализовано несколько лучше. Переход
осуществляется по адресу, в которм находится курсор. Это действительно
удобнее, т.к. позволяет "гулять" и по смещением, передаваемым через стек
или регистры. Наприемр:
.004012B9: 6840314000 push 000403140 ;" @1@"
.004012BE: 6844314000 push 000403144 ;" @1D"
.004012C3: FF74240C push d,[esp][0000C]
.004012C7: E834010000 call .000401400 -------- (2)
hiew не распознал смещения 0х00403140 и 0х00403144. Конечно, можно
перейти по ним вручную (F5), но это не очень приятно. Но это, как
отмечалось, не более,чем мое личное мнение, которе может не совпадать с
мнением автора.
При этом поддерживается многоуровевый откат, который по умолчанию
находится на '0' (как это изменить рассказано в описании файла hiew.ini). К
сожалению буффер отката кольцевой, что не вызывает восторга. Т.к. что бы
вернуться в начальную позицию надо держать в голове глубину вложенности (а
это весьма проблематично). Было бы гораздо лучше если бы при исчерпании
стека hiew пищал хотя бы...
Вообще же навигация по исполняемым файлам дело привычно. В любой момент
можно прыгнуть в произвольную точку, нажав F5. При этом если перед адрес
будет интерпретирован как локальный, если перед ним находится символ '.' в
противном случае всегда осуществляется переход по глобальному смещению
внутри файла.
При этом hiew корректно обрабатывает относительные переходы. Т.е.
например можно задать +77 или -66 и курсор переместится на 77h байт вперед
или 0x66 назад относительно текущей позиции. Печально, но при этом откат
невозможен. Хотя поддержка его была бы не лишей и великолепно вписывающийся
в общий антураж программы. Ан, нет... не учел этого автор. Еще один камешек
в довод того, что всроенный язык избавил бы его от подобных приставаний.
Аналогично и с поиском перекресных сылок. Автоматический откат назад не
предусмотрен. С другой стороны последнее настолько уникальная и полезная
вешь, что рука не поднимается каким-либо образом критиковать ее.
Традиционно для поиска перекретсных ссылок использовали ida или sourcer
(который в этом до сих пор обгонят всех конкурентов). Однако, монстроватые
диассемблеры очень медлительны и не поворотоливы. Для анализа больших
файлов не хватит не только терпения хакера, но иной раз и дискового
пространства.
Поэтому выбор многих останавливался на hiew-е. Даже когда он не мог
деалть это автоматически ручной поиск занимал все же меньше времени, чем
загрузка файлов в IDA. К тому же в большинстве случаев ссылки на сегмент
данных в PE-файлах (например, поиск кода, выводящего сторку 'key not fond')
с легкостью обнаруживались "прямым" поиском локальных смещений (с учетом
обратного порядка байтов в двойном слове).
Однако, поиск относительных смещений таким образом был уже невозможен.
С другой стороны, требуемое нам смещение лежит "прямым текстом" в
дизассемблированном листинге. Остается лишь просканировать последний. Не
могу удержаться, что бы не заметить насколько логична в этом случае IDA,
которая поддерживает "медленный" поиск подстойки именно в тексте
дизассемблера. Это действиельно медеденно, но на все 100% надежно. hiew же
просто дизассемблирует код на лету с шагом в одну команду (или даже байт) и
сравнивает непосредстенный операнд с текущим смещением, при этом
косвенная адресания игнорируется и значения сегментых регистров не
отслеживаются.Поэтому хорошо работает такой поиск только на односегментых
моделях памяти. Во всех других случаях появиятся проблеммы (ссылки не будут
найдены или найдены неверно).
Последнее, впрочем, исправлению не подлежит без переработки всей
архитектуры hiew-а, и мы получим продукт мало отличающийся скоростью от
средневзятого дизассемблера. К счастью наиолее популярных сегодня формат
win32 PE данные и код хранит в одном сегменте, поэтому в отслеживании
сегментых регистров никакой нужны нет.
По умолчанию при дизассемблировании hiew анализирует текст с шагом в
одну команду, что многократно ускоряет работу, но не достатночно надежно.
Разберем следующий пример.
retn
DB 0x66
call 0x0666
Для com - файлов это достаточно типичный случай. Как вы думаете его
дизассемблиет hiew? Разумеется последний не догадается, что '0x66'
перемннная и выдаст следующий результат:
00000000: C3 retn
00000001: 66E86106 call 000000668
^^^^^^^^^
Обратите внимание, что теперь переход вычислен не правильно и весь
анализ программы летит к черту. А если переменная будет равна нулю (что
чаще всего и бывает) на экране появится следующий мусор:
00000000: C3 retn
00000001: 00E8 add al,ch
^^^^
00000003: 61 popa
00000004: 06 push es
Это происходит потому, что hiew не правильно определил границы команд,
в результате чего не смог их правильно дизассемблировать. Ни в коем случае
не стоит считать последнее "глюком" или недостатком. Это следствие самой
концепции элементарного дизассемблера. IDA справляется с этой ситуацией
ценой больших затрат времени на анализ программы. Для файлов в в сотни
килобайт последние не вызывает проблемм на современных быстродействующих
процессоров, но даже мощности Pentuim-a II и Clerion-a начинает не хватать,
когда счет идет на мегабайты или даже десятки мегабайт (между прочим,
типичный размер сегодняшенего исполняемого файла под windows).
Ситуацию может спасти разве что перекладывание части работы на
человека. В приведенном примере ясно, что код после ret вообще собственно
говоря кодом гарантированно не является. С таким же успехом это могут быть
данные. Что бы это выяснить небходимо найти ссылки на эту область памяти.
Устанавливаем курос на первый байт, переключаем (на всякий случай) шаг
сканирования на единицу (alt-F6) и нажимаем F6. Допустим, hiew нашел
следующий код:
MOV AL,[01]
(Впрочем, не факт, что версия 6.03 его найдет, но для простоты будем
считать, что hiew к моменту чтения этого опуса уже научился поддерживать и
такую адресацию) Ясно, что 0x01 это перемнная размером в байт. Помечаем это
(карандашом в блокноте, т.к. hiew все еще не поддерживает комментариев) и
переходим к ячейке 0x2. Вновь нажимаем f6 и изучаем код, манипулирующий с
этим адресом. Пусть он выглядит следующим образом:
00000000: C3 retn
00000001: 00E8 add al,ch
00000003: 61 popa
00000004: 06 push es
00000005: A00100 mov al,[00001]
00000008: E8F7FF call 000000002 -------- (1)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Что бы привести код в удобно-читаемое состояние достаточно перейти по
адресу 0x2, для чего можно нажить '1' (переход по ссылке) или даже <F5>
"02".
00000002: E86106 call 000000666
00000005: A00100 mov al,[00001]
00000008: E8F7FF call 000000002 -------- (1)
Конечно, пример является надуманным, но тем не менее технику работы с
примитивными дизассемблерами он иллюстрирует неплохо. Замечу, что
"примитивный дизассемблер" вовсе не оскорбление, а соответсвующий класс
программ, которые выполняют только декодирование инструкций,
перекладиывая все остально на плечи пользователя.
Если приведенный пример действительно является com - файлом, то скорее
всего hiew не сможет правильно найти ссылки, потому что не правильно
вычислит адреса. Это не удивительно, если вспомнить, что com файлы
загружаются в память со смещения 0x100 в текущем сегменте. Пусть
оригинальный файл выглядел так:
0x100: A10401 mov ax,[00104h] -¬
0x103: C3 retn ¦
0x104: 1234 DB 3412h <----
hiew же дизассемблирует его как:
00000000: A10401 mov ax,[00104] --¬
00000003: C3 retn ¦
00000004: 1234 adc dh,[si] ¦
........ ¦
00000104: xxxx <----
Разница в том, что ссылка во втором случае указывает "в космос", но
никак на перемннную 0x4. Исправить это можно указав hiew-у вручную
начальное смещения файла. Выше мы уже сталкивались с этим при анализе PE
файлов. В терминологии SEN-а это называется базирование и может быть задано
в любой момент анализа, (а не только до загрузки как во многих других
дизассемблеров).
Нажимаем Ctrl-F5 и вводим число 0x100. Теперь код выглядит следующим
образом:
00000100: A10401 mov ax,[00104] -----¬
00000103: C3 retn ¦
00000104: 1234 adc dh,[si] <-----
00000106: 0100 add [bx][si],ax
00000108: E8F7FF call 000000102 -------- (1)
И все ссылки при этом работают правильно. Заметим, что базирование
никак не влияет на вызовы процедур и переходы, поскольку в архитектуре
процессоров intel они относительные.
Рассмотрим более сложный пример, в котором код и данные размещены в
разных сегментах. hiew ничего не знает о последних и поэтому неверно
вычисляет все ссылки. Рассмотрим например любую программу на Паскале,
Загрузим ее в hiew и перейдем в точку входа (F8,F4 но об этом чуть позже).
000000CE: 2E9A00007100 call 00071:00000 -------- (1)
000000D4: 9A0D000F00 call 0000F:0000D -------- (2)
000000D9: 55 push bp
Поскольку после загрузки файла регистр DS указывает на сегмент PSP, то
приложение должно настроить его самостоятельно. В программах,
компилированных turbo-pascal это происходит в модуле SYSTEM (самый первый
вызов). Входим в него, нажатием '1' и изучаем следующий код:
000007A0: BA0D01 mov dx,0010D ;""
000007A3: 8EDA mov ds,dx
Что такое 0x10D? Это смещение в памяти, которе отличается от смещения в
файле только длинной заголовка. В самом деле с отличае от PE файлов,
загрузчик DOS-EXE пропускает заголовок, тем самым экономя немного памяти.
Длину заголока узнать несложно, (значение поле Paragraphs in header
умножить на 0x10). Аналогичо поступим и со значением DS. Итого 0x10D0+
0x90 == 0x1160 смещение сегмента данных в файле.
Смотрим на код ниже:
000007A0: BA0D01 mov dx,0010D ;""
000007A3: 8EDA mov ds,dx
000007A5: 8C063800 mov [00038],es
Что бы узнать на какую ячейку ссылается [0x038] нам надо к последней
добавить 0x1160. Не правда ли утомительно? Было бы гораздо лучше, если бы
hiew выполнял такой пересчет автоматически. Попробуем для этой цели
использовать базирование. Установим курос на адрес 0x1160 и нажмем
Alt-F5. Теперь нам добиться, что бы текущее смещение равнялось бы нулю.
Очевидно для этого необходимо задать базирование, равное по модулю, но
противоположное по знаку. Т.е. '-0x1160'. Однако, hiew поддерживает и
относительные смещения, отмеченные префиксом '*'. Это действительно удобно
и избавляет от лишних математических вычислений. При этом Ctrl-F5,Ctrl-F5
действует аналогично '*0'.
Мы добильсь, что смещения с сегменте данных начинаются с нуля, но...
одно маленькое, но грустное "но" - взгляните на сегмент кода:
FFFFEF6F: 2E9A00007100 call 00071:00000 -------- (2)
FFFFEF75: 9A0D000F00 call 0000F:0000D -------- (3)
FFFFEF7A: 55 push bp
FFFFEF7B: 89E5 mov bp,sp
FFFFEF7D: 31C0 xor ax,ax
Печально, не правда ли? Впрочем, это не так актуально, поскольку в
кодовом сегменте большинство смещенний относительные и будут нормально
функционировать независимо от базирования.
Так-то оно так, но Турбо-Паскаль имеет странную привычку распологать
некоторые данные в кодовом сегменте - взгляните:
FFFFEF31: 10 82 A2 A5-A4 A8 E2 A5-20 AF A0 70-AE AB EC 3A Введите паpоль:
FFFFEF41: 20 04 59 75-4B 69 12 8F-A0 70 AE AB-EC 20 AD A5 YuKiПаpоль не
И вот обращение к этой строке:
FFFFEF88: BF6602 mov di,00266 ;"f"
FFFFEF8B: 1E push ds
FFFFEF8C: 57 push di
FFFFEF8D: BF0000 mov di,00000 ;" "
^^^^^^^^^^^^^^^^^^
FFFFEF90: 0E push cs
FFFFEF91: 57 push di
FFFFEF92: 31C0 xor ax,ax
FFFFEF94: 50 push ax
FFFFEF95: 9A70067100 call 00071:00670 --------(5)
Ну кто бы мог подумать, что в кодовом сегменте эта строка располагается
с нулевым смещением! Однако, это действительно так, в чем можно
убедиться: F5,90\Ctrl-F5,Ctrl-F5:
00000000: 10 82 A2 A5-A4 A8 E2 A5-20 AF A0 70-AE AB EC 3A Введите паpоль:
00000010: 20 04 59 75-4B 69 12 8F-A0 70 AE AB-EC 20 AD A5 YuKiПаpоль не
Но теперь "уползли" все смещения в сегменте данных. И теперь необходимо
при первом же обращении к последнему вернуть все на место. Как-то
неаккуратно получается. К тому же маловероятно, что бы это было как-то
исправлено в последующих версиях. Автор hiew-а изначально рассчитывал на
поддержку только одного сегмента. Теперь же, когда DOS файлы уходят в
прошлое, это ограничение выгядит уже не таким существенным.
ПОИСК
К полной луне призывы...
Шаи-Хулуд поднялся, чтобы ее увидеть;
Красная ночь, сумеречное небо,
Кровавая смерть - ты погиб.
Возносим молитвы луне: она круглая...
Счастье всегда будет с нами,
Потому, что мы нашли то, что искали,
В стране с твердой землей.
Ф. Херберт. "Дюна".
HIEW обладает развитым средством поиска, аналогов которому не
существует. Можно искать как целые команды, так и любые вхождения. В
качестве маски используется символ '?' означающим любую последовательность
символов, включая пустую. Иначе говоря, является полным аналагом
dos-символа '*'.
Это позволяет искать любые комады и их сочитания в ассемблерском
тексте. Мощность и возможности этого механизма не имееют аналогов ни среди
отчествыенных, ни среди зарубежных утилит. Даже IDA не предстваляет такого
сервиса.
SEN в очередной раз продемонстировал свои способности и оставил всех
конкурентов далеко позади. Заметим, что эта возможно впервые появилась еще
в версии 4.0, когда подражатели находились еще в зачаточном состоянии.
Как известно, наипервейшая задача хакера локализовать защитный механизм
в сотнях килобайт исполняемого кода. Это не так-то просто как может
показаться на первый взгляд (при условии, что полный анализ программы
просто нереален ввиду огромных трудозатрат на дизассемблирование и
изучение).
Поэтому взломщики используют разнообразные хитрости, которые как бы не
были различны, но сводятся только к одному - поиску
уникальной последовательности команд, которая предположительно присутсвет в
защитном механизме. Например, типичной будет конструкция
if !IsValidUser() abort();
или
if IsValidUser()
{
; // нормальное выполение программы
}
else
abort();
Достаточно много вариантов, не правда ли? Вручную их перебирать было крайне
утомительно. Используем поиск по шаблону. Для этого в режиме дизассемблера
два раза нажмем F7 и введем следующу последовательность:
г=[Forward /Full ]===================================================¬
¦ ASCII: -------------------- ¦
¦ ¦
¦ Hex: ------------------------------------------------------------¦
г= Pentium(R) Pro Assembler =====================================¬
¦ call ?;or ax,ax;j?-------------------------------------------- ¦
L================================================================-
hiew найдет приблизительно следующий код:
.0001140C: 9A3E172114 call 001:0173E -------- (4)
.00011411: 0BC0 or ax,ax
.00011413: 7405 je .00001141A -------- (5)
Разумеется, возможно, что call 001:0173E на самом деле не имеет
никакого отношения к защите (вероятнее даже, что так скорее всего и будет),
но тем не менее ожидается, что в программе не так уж много вышеприведенных
комбинаций, и в любом случе это сужает поиск.
Оданко, для файла мегабайт десять длинной такое заявление может
вызвать лишь легкую улыбку. Возможно, hiew найдет несколько сотен
подходящих вариантов и чем их все анализировать легче просто заплатить пару
долларов и приобрести легальную версию. Но не будем спешить (хотя все же
хакерство ну никак не повод работать на ворованном программном обеспечении)
Все что нам нужно собрать доступную информацию о защите и правильно задать
команду поиска. Допустим, что мы знаем, что в случае неудачи защита
выводит сообщение с известным смещением, предположим, что 0x406666. Тогда
быть может нам поможет следующая комбинация:
г=[Forward /Full ]===================================================¬
¦ ASCII: -------------------- ¦
¦ ¦
¦ Hex: ------------------------------------------------------------¦
г= Pentium(R) Pro Assembler =====================================¬
¦ call ?;or eax,eax;j?;;? 66664000------------------------------ ¦
L================================================================-
При этом ';;' интерпретируется как любое множество произвольных команд,
включая пустое. При этом шансы, что найденный фрагмент окажется именно тем
защитным механизмом, который мы ищем, очень хорошие. Если же нет, то не
отчаивайтесь, а попробуйте еще один раз.
Очень прияно, что hiew продолжает поиск не с текущей позиции курсора, а
с места последнего найденного вхождения. Это дает нам некоторую мобильность
в перемещании по файлу.
FindNext сбрасывается при перемещении курсора в начало файла по
Ctrl-Home, (или в конец по Ctrl-End). Так же разумеется FindFirst (F7) и
совершенно не понятно откуда взявщегося Goto (F5). Последние иногда
вынуждает на неприятные "путешествия" по файлу "в ручную" (кирпич на Page
Down).
При этом искать можно как во всем файле (по умолчанию), так и в
выделенном блоке. Последнее я не предстваляю для каких целей может быть
нужно. Впрочем, тут я все же утрирую. Конечно, это полезная возможность,
позволяющая работать с фрагментом файла, например, с защитной прцедурой.
К сожалению, в строке поиска нельзя задавать логические конструкции
типа 'AND'. 'OR' и другие. Между тем эта возможность очень полезна и в
последнее время поддержиаается многими популярными системами.
МАНИПУЛЯЦИИ С БЛОКАМИ
"Соединение невежества и знания,
соединение дикости и культуры
не начинается ли оно с того
чувства достоинства, с которым
мы относимся к своей смерти?"
Ф. Херберт "Дюна"
Выше мы затронули возможность hiew-а работать с выделенным фрагментом
текста (блоками). Рассмотрим теперь это подробнее. Для того что бы выделить
фрагмент необходимо однократно нажать Gray-'*'. Теперь перемещения по файлу
клавишами управления курсором будут приводить к выделению фрагмента и
заливке его по умолчанию бардовым цветом. Повторное нажатие Gary-'*'
прекращает выделение и активирут клавиши управления блоком.
Это Запись\Чтение блока в файл, а так же заливка его некоторым
значением. Рассмотрим окно записи:
г===================== Write block to file ======================¬
¦ Block: 000001FF-000002EF length:000000F1/241 ¦
¦ File: ------------------------------------------------------ ¦
¦ Offset: ........ ( Hexadecimal ) ¦
¦ Table: As Is г====== Select table =======¬ ¦
L=================¦ As Is ¦==================-
¦ Windows-1251 ¦
¦ Koi-8 ¦
L===========================-
Приятной особенностью является возможность записи в файл с произвольным
смещением. Это дейстительно, насущная потребность любого кодокопателя.
Скажем, вы решили заменить шрифты в файле или для какой-то цели дописать в
его конец маленькую программу (по типу ну скажем вируса). При этом возможно
выбрать любую кодировку. Да, я не оговорился, "любую" и это следует
понимать буквально плодь по кодировки племен индейцев Северной Америки.
Ниже описывается струткура файла hiew.hlt, который позволяет это делать.
Замечательно, что все смещения и длина блока выражены шестнадцатиричными
цифрами. Это по-просту удобно и практично для работы, поскольку
средневзятому хакеру десятичная система нарвится куда меньше.
То же самое наблюдается и в окне чтения блока. Взгляните:
г===================== Read block from file =====================¬
¦ Block: 000001FF-000002EF length:000000F1/241 ¦
¦ File: ------------------------------------------------------ ¦
¦ Offset: ........ ( Hexadecimal ) ¦
¦ Table: As Is ¦
L================================================================-
Загрузка блока процесс обратный записи. И не в пример полезный. За мою
сознательную жизнь я эту возможность как-то ни разу и не использовал. Не то
что бы мой опыт был каким-либо показателем, но я действительно не могу
придумать ситуацию, в которой эта возможность была бы незаменима, поэтому
не будем на ней останавливатся, а перейдем сразу к "заливке":
г====================================================================¬
¦ ASCII: -------------------- ¦
¦ ¦
¦ Hex: ------------------------------------------------------------¦
L====================================================================-
Это окно вызывется по Alt-F3 и следующим образом. Никаких проблемм
управление им вызвать не должно. Заметим только, что все операции с
блоком являются необратимыми и лучше семь раз подумать, чем нажать на
кнопку. Резервной копии ведь за вас никто не сделает.
ПОДДЕРЖКА LE/PE/NE/LX/NLM ФОРМАТОВ
Понятие прогресса служит защитным
механизмом, отгораживающим нас от
ужасов будущего.
Ф.Херберт "Дюна"
Вообще-то шестнадцатиричный редактор идеологически должен быть
платворменно-независимым. Введением в него дизассемблера SEN нарушил эту
традицию, привязав последний к линейке 80x86 процессоров фирмы Intel.
Однако, в этих пределах hiew все же оставался кросс-платформенным,
одинаково хорошо работая со всеми форматами файлов всех сущесвтвующих
операционных систем. Точнее даже, не хорошо работая, а никак не работая,
поскольку первые версии не отличали структурированных файлов от простых
бинарных.
Десяток лет назад особо поддерживать было еще нечего. В то время
господствовали com и exe файлы. Певые вообще являлись бинарным образом, а
вторые имели крайне простую структуру, которая относилась скорее к загрузке
файла в память и была прозрачна для работы с последним "вживую". Я имею
ввиду таблицу перемещаемых элементов.
С другой стороны, сегментами кода и данных управляло само приложение
непосредственно. Файл все еще оставался простым образом памяти. Это видно
хотя бы потому что половина полей заголовка выражается в секторах диска.
(когда-то это упрощало загрузку. но сегодя может вызвать разве что легкую
улыбку).
Неудивительно, что вся поддерка DOS-EXE свелась к простому отображению
заголовка в удобно читаемом виде.
г========[ MZ-header ]=========¬
¦ Signature 4D5A ¦
¦ Bytes on last page 01C0 ¦
¦ Pages in file 0009 ¦
¦ Relocations 001D ¦
¦ Paragraphs in header 0009 ¦
¦ Minimum memory 0436 ¦
¦ Maximum memory A436 ¦
¦ SS:SP 0149:4000 ¦
¦ Checksum 0000 ¦
¦ CS:IP 0000:003F ¦
¦ Relocation table adress 001C ¦
¦ Overlay number 0000 ¦
¦ Overlay length 00000B1F ¦
¦ NewExe offset 00000000 ¦
¦ >Entry point 000000CF ¦
L==============================-
Пояснять значения полей здесь нет смысла - это гораздо лучше расписано
в руководстве программиста для MS-DOS. Ознакомившись с последним можно
попытаться отредактировать поля, когда в этом возникнет такая
необходимость. hiew позволяет сделать это с комфортом, избавляя от
некоторых рутиных вычислений. Так, например F2 автоматически вычисляет
значения полей Pages in file и Bytes on last page (это бывает необходимо
при манипуляции с размером файла, чаще всего "отрезании" того мусора,
который так любят оставлять в конце некоторые распаковщики). При этом hiew
никак не учитывае значения поля Overlay length, что может привести к
некоторым проблеммам и является досадным багом, который автор до сих пор
ухитрился не исправить (вероятнее всего потому, что никто из пользователей
hiew этого и не заметил. А если кто и заметил, так не имел Интернета, что
бы ему об этом сообщить).
Другим приятным сервисом является возможность быстрого перехода в точку
входа (F5) и в начало кодового сегмента (F4). Заметим на всякий случай, что
это не взаимо-заменяемые понятия и редкие exe-файлы начинают выполнение с
нуля.
Клавиша F2 поможет быстро перейти в начало оверелия. И вот, пожалуй,
все что можно сказать про поддержку old-dos форматов. Предлагаемый набор
сервиса типечен для современных hex-редакторов и скопирован практически
всеми конкурентами.
Диметрально противоположно обстоит дело с поддержкой PE - файлов. Выше
мы уже неоднократно сталкивались с этим, а сейчас рассмотрим подробнее:
г===========================[ PE-header ]============================¬
¦ Count of sections 4 ¦ Machine(014C) intel386 ¦
¦ Symbol table 00000000[00000000] ¦ TimeStamp 36CC1C56 ¦
¦ Size of optional header 00E0 ¦ Magic optional header 010B ¦
¦ Linker version 6.00 ¦ OS version 4.00 ¦
¦ Image version 0.00 ¦ Subsystem version 4.00 ¦
¦ Entrypoint RVA 00001390 ¦ Size of code 00001000 ¦
¦ Size of init data 00003000 ¦ Size of uninit data 00000000 ¦
¦ Size of image 00005000 ¦ Size of headers 00001000 ¦
¦ Base of code 00001000 ¦ Base of data 00002000 ¦
¦ Image base 00400000 ¦ Subsystem(0003) Windows char ¦
¦ Section alignment 00001000 ¦ File alignment 00001000 ¦
¦ Stack 00100000/00001000 ¦ Heap 00100000/00001000 ¦
¦ Checksum 00000000 ¦ Number of directories 16 ¦
L====================================================================-
Заметим, насколько усложнился заголовок. Самое интересное, что он не
особенно хорошо документирован фиромой MicroSoft (а оно и понятно, это все
же внутренняя структура операционной системы и чем меньше приложения о ней
будт знать тем лучше).
Когда же сведений, описываемых документацией начинает нехватать, хакеры
обычно образаются к winnt.h - настоящей сокровищнице, где все структуры
хоть и бедно комментированы, но все же хоть как-то расписаны.
Неприяным моментом будет отсутствие возможности редактирования
заголовка непосредственно из этого экрана. То ли SEN посчитал, что среднему
хакеру это не нужно, то ли просто поленился (кто знает...) но если дело до
этого дойдет, то придется вооружившись SDK и MSDN орудовать в hex-редакторе
вручную. Или писать свою собствнную утилиут, поскольку такая необходимость
возникает достаточно часто.
Аналогично поступл автор и с показом флагов (f2). Смотреть можно
сколько угодно, а редактировать нет. Печально.
г===================================================================¬
¦ Characteristics 010F ¦ DLL flag 0000 ¦
¦ 0: Relocations stripped :Yes ¦ 0: Process initialization :No ¦
¦ 1: Executable image :Yes ¦ 1: Process termination :No ¦
¦ 2: Line numbers stripped :Yes ¦ 2: Thread initialization :No ¦
¦ 3: Local symbols stripped :Yes ¦ 3: Thread termination :No ¦
¦ 4: reserved :No ¦ ¦
¦ 5: reserved :No ¦ Loader flag 00000000 ¦
¦ 6: 16 bit machine :No ¦ 0: Break on load :No ¦
¦ 7: Bytes reversed lo :No ¦ 1: Debug on load :No ¦
¦ 8: 32 bit machine :Yes ¦ ¦
¦ 9: Debug stripped :No ¦ ¦
¦ 10: Patch :No ¦ ¦
¦ 11: reserved :No ¦ ¦
¦ 12: System file :No ¦ ¦
¦ 13: File is DLL :No ¦ ¦
¦ 14: reserved :No ¦ ¦
¦ 15: Bytes reversed hi :No ¦ ¦
L===================================================================-
На фоне это довольно качественно реализована навигация по секциям
PE-файла (F6) или в терминологии hiew таблице объектов. При этом выдается
дополнительная информация о каждой секции. При этом вновь к сожалению
отстутсвет возможность редактирования и все флаги показаны не в бинарном, а
в шестнадцатирицном виде. Последнее вынуждать выполять все расчеты в уме.
Действительно, какие атрибуты имеет секция .text? 0х60000020 можно
разложить на 0x20+0x40000000+0x20000000, (если читатель не понял откуда
взялись эти цифры, то пусть переведет 0x60000020 в двоичное предстваление,
оно будет равно 00000110000000000000000000100000b. Теперь уже нетрудно
вычислить, что 0100000b == 0x20; 010000000000000000000000000b == 0x20000000
и 0100000000000000000000000000b == 0х40000000. Достаточно тривиальные
вычислени, которые любой хакер считает в уме даже без помощи калькулятора).
Получется, что секция .text имеет следующие атрибуты - Code | Can be
discarded | Not cachable. Было бы куда нагляднее, конечно, представить всю
эту информацию сразу в удобно-читаемом виде. Но, автор признается, что не
любит плодить монстров, да и не настолько трудно все эти вычисления
выполнить в уме, а то последий стремительно усыхает в наш бурный век
думающих маших и автоматических калькуляторов.
Другой вопрос, что утомительно было бы держать в уме все значения
флагов (кому приятно запоминать эту чисто справочную информацию?). К
счастью автор предусмотрел последнее и включил в контекструю помощь
соответсвующий пункт, который можно увидитеть на рисунке, приведенном ниже:
г===========================[ PE-header ]============================¬
¦ ¦
¦ г=Number Name VirtSize RVA PhysSize Offset Flag===¬ ¦
¦ ¦ 1 .text 000004FA 00001000 00001000 00001000 60000020 ¦ ¦
¦ ¦ 2 .rdata 0000051A 00002000 00001000 00002000 40000040 ¦ ¦
¦ ¦ 3 .data 00000168 00003000 00001000 00003000 C0000040 ¦ ¦
¦ ¦ 4 .rsrc 000000F0 00004000 00001000 00004000 40000040 ¦ ¦
¦ ¦ г========================[PE Object flags]=========================¬
L ¦ ¦ -------------------- Flag for object ------------------------- ¦
L= C¦ 0x00000004 Used for 16-bit offset code. ¦
¦ 0x00000020 Code. ¦
¦ 0x00000040 Initialized data. ¦
Кроме отображения секций hiew еще умеет читать IMAGE_DATA_DIRECTORY и
представлять ее в удобно-читабельном виде. Это действительно, наиболее
важный элемент структуры PE-файла и необходимый для поиска таблиц
экспорта\импорта и ресурсорв. Оставиим временно в стороне последние и
обратим внимание на таблицу импортируемых функций. Фактически изучение
любого приложения начинается с ее анализа. Какие функции вызывает
программа? Какие загружает DLL? Ставить ли точку останова на GetWindowTextA
или GetDlgItemTextA? На все эти вопросы можно найти ответ, просмотрев
список импортируемых функций.
Логично, что при изучении DLL нас наоборот в первую очередь будет
интересовать экспорт и соответствующая ему секция. Конечно, мне могут
возразить, что для этого существуют специальные программы наподобии
dumpbin, которые делают всю работу за нас, генерируя удобно-читаемый
список, а в hiew-е по кажой секции еще придется полазить вручную. И уж
совсем казалось бы не к месту разговор о ресурсах, в которых с первого
взгяда ни одному смерному разобраться не дано. К тому же сущестуют
великолепные визуальные редакторы ресурсов наподобии популярного Borland
ReourceWorkShop.
Так-то оно так, да только на первый взгляд. "Популярные и
великоленые" редакторы оказываются неспособными поддерждать новые элемннты
Win98 (например, календарь) и просто при этом необратимо портят ресурс
(особенно это относится к Борландлвскому редактору, и в меньшей степени и к
другим).
Относительно же таблиц экспорта\импорта разница между
"структурированным" листингом и "живом" предствалении AS IS не так уж и
велика. Действительно, взгляните на рисунок. Не нужно большой сноровки, что
бы бегло пробежаться глазами по знакомым функциям MSVCRT. Впрочем, для
"гурманов" Сусликов включил в пакет несколько специальных программ *dump,
позволяющим более детально исследовать формат файла.
г= Name RVA Size =¬
¦ Export 00000000 00000000 ¦
¦ Import 000020E0 00000064 ¦
¦ Resource 00004000 00000010 ¦
¦ Exception 00000000 00000000 ¦
¦ Security 00000000 00000000 ¦
¦ Fixups 00000000 00000000 ¦
¦ Debug 00000000 00000000 ¦
¦ Description 00000000 00000000 ¦
¦ GlobalPtr 00000000 00000000 ¦
¦ TLS 00000000 00000000 ¦
¦ Load config 00000000 00000000 ¦
.004029F0: 00 00 00¦ (reserved) 00000000 00000000 ¦49 00 MFC42.DLL I
.00402A00: 5F 5F 43¦ (reserved) 00002000 000000A4 ¦6C 65 __CxxFrameHandle
.00402A10: 72 00 B2¦ (reserved) 00000000 00000000 ¦5F 5F r -sprintf U __
.00402A20: 64 6C 6C¦ (reserved) 00000000 00000000 ¦6E 65 dllonexit Ж_one
.00402A30: 78 69 74¦ (reserved) 00000000 00000000 ¦00 00 xit MSVCRT.dll
.00402A40: D3 00 5FL================================-74 46 L _exit H _XcptF
Однако, если бы hiew только бы и мог, что отображать некоторые
структуры PE файлов, то эта бы возмножность скорее всего осталась бы так и
не замечанной на фоне таких конкурентов, как dumpbin, делающим, кстати, это
значительно лучше hiew-а.
На самом же деле уникальность последненго заключается в другом - в
возможности просмативать непосредственно имена вызываемых функций (или
ордналы, если в DLL отсутствует символьная информаци) в окне дизассемблера.
(К сожалению, встронный ассемблер все еще не поддерживает этой
возможности).
Что бы понять насколько это удобно нужно поработать с hiew-ом хотя бы
пару часов. Сравните qview и hiew. Не правда-ли второй значительно
информативнее и просто практичнее в работе. Смысл же команд первого
совершенно не понятен и загадочен. Даже если перейти по косвенному адресу,
все равно там мы ничего не увидим, ибо содержимое этой секции не определено
до загрузки файла.
Должен заметить, что автор допустил несколько досадных упущений,
которые заметны уже в первые пол-часа работы (как это он до сих это не
зметил?!). HIEW никак не учитывает косвенной адресации, которая так "любят"
использовать все компиляторы, и особенно оптимизирующие компиляторы от
MicroSoft.
В результате по-прежнему имя вызываемом функции остается загадкой. Тут
на помощь приходит недокументированная особенность, заключающася в том, что
секция адресов во многих случаях совпадает с секцией имен. Не смотря на то,
что она в любом случае будет затерта загрузчиком, это дает нам возможность
определить по косвенному вызову ординал и имя функции. Как это сдедать
подробно рассказывают другие книги, здесь я лишь посоветую обратится по RVA
адресу, (если он не равен нулю). Например в нашем случае он равен 0х02B56 и
по которому распологается строка 'AppendMenuA', таким образом mov ebx,
[0004021E8] следует читать как mov ebx,AppendMenuA. Если же секция адресов
пуста (или там содержится мусор), то необходимо вычислить индеск элемента
от ее начала и обратится к секции имен или просто скопировать ее
самостоятельно поверх первой. Как уже отмечалось ее содежание некритично и
лишь помогает при анализе программы в дизассемблере.
Qview:
00001730: FF250C214000 jmp d,[00040210C]
000019AE: FF25D8214000 jmp d,[0004021D8]
00001372: 8B1DE8214000 mov ebx,[0004021E8]
Hiew:
.00401730: FF250C214000 jmp MFC42.4673
.004019AE: FF25D8214000 jmp __CxxFrameHandler ;MSVCRT.dll
.00401372: 8B1DE8214000 mov ebx,[0004021E8]
^^^^^^^^^^^
Вторым по распростаненности после ЗК-файлов, является LE формат, который
широко используется в VxD файлах. HIEW позволяет осуществлять навигацию по
различным его структурам, а так же обеспечивает удобно-читабельное
представление некоторых из них.
Заметим, что далеко не все дизассемблеры поддерживают LE-формат файлов,
а те которые его все же поддержиают ужасно медленно работают. Поэтому hiew
на этом фоне выглядит весьма прогрессивно и предоставляемых им возможностей
вполне хватит для серьезной работы с драйверами виртуальных устройств.
Невозможно представить себе надежную защиту, не использующую собственный
vxd, особенно когда речь идет об обмене данных с электронным ключем
например, или ключевой дискетой (к огромному моему удивлению до сих пор
встечаются разработчики, не расставшиеся с этим пережитком прошлого).
Однако, vxd подезны не только как собственно драйвера устройств. Код,
размещенный в них, работает в нулевом кольце защиты и практически без
ограничений. Это открывает широкие границы фантазии разработчикам.
Действительно, трудно представить себе мало-мальски серьезный защитный
механизм, не выходящий за пределы третьего кольца.
Впрочем, анализ vxd файлов не намного сложнее любого другого и ничего в
этом таинственного и загадочного нет. Достаточно заглянуть в SDK, что бы
хотя бы в общих чертах ознакомится с форматом файла и уже можно начинать в
последний вгрызаться дизассемблерм. Hiew-ом, например.
Как видно из рисунка, LE-заголовок ненамного сложнее своего PE собрата
и не должен вызвать особых трудностей. Назначение большинства полей понятно
из них названия и только несколько моментов могут потребовать уточнения в
SDK. Между прочим, MicroSoft не очень-то открыто предоставляет сей формат
на общественное растярзание. Описания довольно скудные и отрывочные.
Несколько статей по этому поводу в MSDN только возбуждают аппетит и
разжигают любопытство, но никак не проясняют ситуацию.
Фактически анализ формата приходится выполнять каждому кодокопателю
самостоятельно. И в этом значительную помощь могут оказать hiew и
прилагаемая к нему программ ledumd. Ну к последней мы еще вернемся, а
возможности hiew-а опишем прямо сейчас:
г============================[ LE-header ]=============================¬
¦ Object table count 2 ¦ Page count 4 ¦
¦ Starting EIP 00000000:00000000 ¦ Page size 00001000 ¦
¦ Starting ESP 00000000:00000000 ¦ Bytes in last page 00000490 ¦
¦ Fixup section size 000002D8 ¦ Loader section size 00000053 ¦
¦ Object table 000000C4/00000144 ¦ Object page 000000F4/00000174 ¦
¦ Object iterat 00000000/00000000 ¦ Resident name 00000104/00000184 ¦
¦ Resource 00000000/00000000 ¦ Number of resource 0 ¦
¦ Directives 00000000/00000000 ¦ Number of directive 0 ¦
¦ Fixup page 00000117/00000197 ¦ Fixup records 0000012B/000001AB ¦
¦ Import module 000003EF/0000046F ¦ Number of module 0 ¦
¦ Import proc 000003EF/0000046F ¦ Entry table 0000010D/0000018D ¦
¦ Data pages offset 00000600 ¦ Number preload pages 3 ¦
¦ Non-resident name 00003A90 ¦ Bytes in non-resident 51 ¦
¦ Instance in preload 00000000 ¦ Instance in demand 00000000 ¦
¦ Auto data 00000000 ¦ Heap/Stack 00000000/00000000 ¦
¦ Debug info 00000000/00000000 ¦ Debug length 00000000 ¦
L======================================================================-
Заглянув в помощь, можно просто поразитья возможностям навиганции.
Можно переходить к LE заголовку, точке входа, таблцие объектов и импорта,
DDB секции, таблице страниц и ресурсов, кроме того резидентных и не
резидентных имен, да всего и не перечислишь!
Немного печально, конечно, что Hiew показывает все вышеперечисленное
"AS IS" и не делает никаких попыток улучшить читабельность. Можно,
конечно, воспользоваться для этой цели соответствующими утилитами, но в
однозадачной MS-DOS крайне неудобно. Легче уж смириться с тем, что есть и
разбирать все структуры вруную, надеясь, что все же автор когда-нибудь
пойдет на встречу своим клиентам и реализует недостающий сервис (а вот
пойдут ли клиенты навстречу автору и не принуст ли они в жертву хотя бы
один доллар об этом история умалчивает).
Между тем, hiew все же отображает по крайней мере флаги заголовка, а это
уже не мало. Во всяком случае уже не придется копаться в битовых полях, что
ускорит работу.
Так же hiew правильно дизассемблирует все вызовы VMM, что между прочим
является не такой уж и тривиальной задачей. Qview, например это делает
совершенно неправильно, чем и вводит пользователя в заблуждение.
Сравните как дизассемблировали hiew и qview один и тот же фргамент. Увы,
но этот пример не в пользу qview-а, который я все же люблю не смотря ни на
что, но должен признать, что он безнадежно проигрывает hiew-у в этом
сравнении и вряд-ли в ближайшее время ситуация изменится в лучшую сторону.
Hiew:
.000002E3: CD208D000100 VMMcall Save_Client_State
.000002E9: 5F pop edi
Qview:
000046E3: CD20 int 20
000046E5: 8D00 lea eax,dword ptr [eax]
000046E7: 0100 add dword ptr [eax],eax
000046E9: 5F pop edi
К сожалению, SEN допустил досадную ошибку (ну с каким программистом
этого не случается!) и его творение спотыкается при попытке ассемблирования
VMM-вызова. Взгляните на экран, показанный ниже - он наглядно иллюстирует
мои слова. hiew "съедает" аргумент и отказывается анализировать любой
введунный вручную. Как символьный, так и цифровой.
г= Pentium(R) Pro Assembler =====================================¬
¦ VMMcall------------------------------------------------------- ¦
L================================================================-
Печально, конечно, но тут речь идет не более, чем о программой ошибке,
которая вероятно, будет устанена в ближайших версиях. А пока этого не
случилось ассемблировать придется "вручную". А для этого придется
познакомится с форматом вызова VMM.
Заглянем в MSDN, там по этому поводу содержится много полезных статей и
информации. Но для начала обратим внимание на базовую функцию VMMCall:
VMMCall Service, Parameters
Она ассемлируется следующим образом:
INT 0x20
DW Parameters
DW Service
Рассмотрим это на примере показанном ниже. Все настолько просто, что
никаких проблемм вызвать не должно. Если вы чего-то не понимаете, то
обратитесь к MSDN. Там множество примеров, подробно комментирующих
вышесказанное.
.00002665: CD2066661234 VxDcall 3412.6666
^^^^"""" """" ^^^^
Заслуга автора hiew в том, что последний представляет это в
удобно-читаемом виде. Откуда же он берет символьную информацию? Ведь ее
явным образом не содержится в файле! Верно, не содержится, поэтому-то автор
и создал файл hiew.vxd приблизительно следующего содержания:
[048B.VCACHE]
^^^^
Get_Version
Register
GetSize
Формат его очевиден и не требует особых комментариев, достаточно
взглянуть на расположенную ниже строку:
.00002665: CD2000008B04 VxDcall VCACHE.Get_Version
^^^^
Разумеется, этот файл можно как угодно перекраивать под свой вкус и
потребности. В частности, вносить поддержку новых vxd, используемых, скажем
защитой, или написанных вами.
При этом vxd с ординалом сервиса 0x01 иначе еще называется (в
терминологии архитектуры win32 - VMM "Virtual-Memory Manager"). На самом же
деле это все тот же vxd и вызов его происходит аналогично:
.00012161: CD2001000100 VMMcall Get_Cur_VM_Handle
^^^^
.00002665: CD2000008B04 VxDcall VCACHE.Get_Version
^^^^
Доказательством этого служит следующая стока из hiew.vmm "[0001.VMM]".
Вообще-то с названием файла, автор похоже допустил еще одну досадную
ошибку, немного сбивающую с толку. Все же это не 'hiew.vmm', а 'hiew.vxd'.
Надеюсь, что в последующих версиях это будет исправлено.
Мы еще не упомянули о таком понятии, как VxDjmp. На самом деле
вызывается он аналогично, за маленьким исключением - страрший бит параметра
в этот случае равен единице, а не нулю. Вот, взгляните сами:
.00005040: CD201C801700 VxDjmp SHELL.Update_User_Activity
^
.00005048: CD2048810100 VMMjmp RegOpenKey
^
hiew правильно интерпретирует значение этого бита, в противном случае
бы он неверно дизасемблировал бы вызов и не смог бы определить функцию. Это
еще раз подчеркивает, что автор проделал большую работу и мелкие ошибки в
благодарность ему можно и простить. Любопытно, что вместо этого их склонны
упорно не замечать, иначе трудно было бы объяснить почему они продержадись
вплодь до 6.03 версии. Пассивный нынче народ стал, однако...
На этом описание поддержки LE-формата я заканчиваю. Если кому-то оно
покажется неполным, пожалуйста, обратитесь к соответствующей документации.
После некоторых размышлений я решил не описывать остальные форматы, что бы
не повторяться. Не думаю, что бы там было что-то особо интересное.
КАЛЬКУЛЯТОР
"Врагу, которым восхищаешься,
легче вселить в тебя ужас".
Ф.Херберт "Дюна"
Необходимость встроенного калькулятора сегодня сомнений ни у кого не
вызывает. Хакеру настролько часто приходится возится с разными системами
исчесления, битовыми масками, относительными переходами, что он всего этого
голова пойдет кругом, если потребуется проводить вычисления в уме.
Впервые полноценный калькулятор насколько мне помниться появился в
qview-е, намного опередив конкуретов. В свое время это даже послужило
причиной отказа от hiew-а, у которого тай калькулятор появился относительно
недавно и, к сожалению, сильно проигрывающий qview-скому.
Признаться мне непонятна позиция автора в этом вопросе. Почему бы ему
если не опередить, то хотя бы просто догнать конкурентов? Тем более, что
основное различие как-раз и состоит в отстутствии поддержки битовой системы
исчисления. Т.е. как раз того, ради чего калькулятор в большинстве случаев
и нужен. Битовые операции в основом приходится выполнять при разборе
различных флагов и атрибутов.
К счастью во всем остальном калькулятор hiew-а ни в чем не уступает
своим собратьям и поддерживает все типовые логические и математические
операции котрые подробно будут описаны ниже:
г================ Calculator ================¬
¦ (0xFF ^ 0x80 | 128) > 0------------------- ¦
¦ Signed: 1 ¦
¦ Unsigned: 1 . . ¦
¦ Binary: 00000000000000000000000000000001 ¦
¦ Hex: 00000001 " " ¦
L============================================-
СКОБКИ: hiew поддерживает круглые скобки. Если их не ставить, то
операции будут выполняться в порядке старшинства операций. Однако, на это
я не рекомендую полагаться, а все же не полениться и ставить побольше
скобок. Никому они еще никогда не поешали.
'-' Вычитание, а так же отрицательное число. При этом двойное слово
дополняется до нуля. К сожалению выбрать другую размененность операндов
никак не получится. По крайней мере в текущих версиях.
'+' Сложение, а так же положительное число. Забавно, что hiew
переваривает такие конструкции как '+-+-++' и подобные им. При этом '-'
измняет значение всех знаков, стоящих правее в цепочке на противоположное.
Математически это верно, но ценность этого сомнительна.
г================ Calculator ================¬
¦ +1++2+-+-3----4--------------------------- ¦
¦ Signed: 10 ¦
'*' Умножение. Поддерживает знаковые числа. Конструкции типа '**' не
воспринимаются синтаксическим анализатором. (Возведение в степень, увы -
отсутствует).
'/' Целочисленное деление.
'%' Взятие остатка. ВНИМАНИЕ! HIEW Содержит большой и очень-очень
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
неприятый баг - операция 'X % 0' приводит к аварийному завершению и выходу
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
в DOS без сохранения проделанной работы.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'^' Битовая операция XOR (т.е. ИЛИ-исключающие-И)
'&' Битовая операция AND (т.е. И)
'|' Битовая операция OR (т.е. ИЛИ)
'!' Логичейское (не битовое) отрицание. !0 == 1 !X == 0, где X!=0
Вообще непонятно с чего бы автор ввел _логическое_ а не битовое отрацание.
На радкость бесполезная операция,и к тому же отсутствует логическая NOT,
что мне категорически не нравится.
'>>' циклический сдвиг вправо. Имеет самый нисший приоритет, поэтому
0xFF>>1+1 == 0x3F == 0xFF>>2. Не забывайте расставлять скобки. (Заметим,
что A >> -x == 0, что являеся еще одним багом, идущим вразрез с
математикой).
'<<' Циклический сдвиг влево.
'>' Логическое "больше". A > B == 1 если A > B и A > B == 0, если это
условние ложно. Например (1>2)+3 == 3: (10>0)+1==2; но 1>2+3==0 обратите
внимание на последний баг. Он может служить источником трудно уловимых
ошибок, а вообще, если честно эта операция
'<' Логическое "меньше".
Все числа по умолчанию десятичные. Шестнадцатиричные записываются как
0xABCD. При этом никакой другой записи или формы исчесления hiew упорно не
желает понимать, в том числе и общепринятой 0ABCDh. Вызывает некоторые
неудобства, но надеюсь будет исправлено в следующих версиях.
Окно калькулятора можно перемещать стрелочками вверх и вниз. Довольно
полезная возможность, когда последний закрывает собой экран с необходимой в
данный момент информацией. При этот вправо-влево он упрямо перемещаться не
хочет. Не то что бы неудобно, но неприятно.
КРИПТ-СИСТЕМА
"Не считай человека мертвым, пока
не увидишь его тело.И даже тогда
ты можешь ошибиться".
Ф. Херберт. "Дюна"
Уникальность hiew-а прежде всего в том, что SEN впевые в мире реализовл
в нем удобную интерпретируемую крипт-систему. До этого такого по-просту не
было. Если требовалось расшифровать файл или его фрагмент, то необходимо
было писать собственную программу на ассемблере или любом другом языке
высокого уровня.
С появлением hiew все изменилось. Стало возможным расшифровывать
программы "на лету" не отрываясь от анализа. При этом процесс расшифровки
полностью контролировался и сразу же отображался на экране.
Практическое применение крипто-системы мы рассмортим после знакомста с
системой команд.
Внешне экран встроенного редактора скриптов показан ниже. Конечно, это
не полноэкранный привычный нам редактор, а подсточечник (наподобии того,
который был в ZX-SPECTRUM-48), но пользоваться им достаточно удобно. К тому
же типичный скрпт занимает всего несколько строк, ради котрый интегрировать
в hiew полноэкранный редактор было бы расточительством.
000A0: 65 77 20 г=[Byte/Forward ]==============¬ 29 ew release V
000B0: 53 45 4E ¦ 1>mov bx,77 ¦ AX=0000 ¦ 39 SEN, Kemerovo
000C0: 39 31 2D ¦ 2 rol al,1 ¦ BX=0000 ¦ 00 91-1999.
000D0: 00 00 00 ¦ 3 xor al,bl ¦ CX=0000 ¦ 00
000E0: 00 00 00 ¦ 4 rol al,7 ¦ DX=0000 ¦ 00
000F0: 00 00 00 ¦ 5 ¦ SI=0000 ¦ 00
00100: 00 00 00 ¦ 6 ¦ DI=0000 ¦ 00
г= Pentium(R) Pro Assembler =====================================¬
¦ loop 2-------------------------------------------------------- ¦
L================================================================-
00160: 00 00 00 ¦ 12 ¦ ¦ 00
00170: 00 00 00 ¦ 13 ¦ ¦ 00
00180: 00 00 00 ¦ 14 ¦ ¦ 00
00190: 00 00 00 ¦ 15 ¦ ¦ 00
001A0: 00 00 00 ¦ 16 ¦ ¦ 00
001B0: 00 00 00 ¦ 17 ¦ ¦ 00
001C0: 00 00 00 L==============================- 00
001D0: 00 00 00 00
Хотя в заголовке стрки ввода гордо красуется 'Pentium Pro Assembler'
hiew понимает только ограниченный набор команд, котрый даже не покрывает
8086. Было бы неплохо если бы автор изменил заголовок и не вводил
пользователей в заблуждение.
Очень большим ограничение является отстутствие операндов в памяти. Из
этого следует, что сколь-ниубудь серьезный скрипт написать не удастся.
Все, что доступно хакеру это 32 байта памяти в виде регистров EAX,EBX,ECX,
EDX,EBP,ESI,EDI,ESP. Да, в последнем случае я не оговорился - в
криптосистеме hiew регистр esp - "общего" назначения и ничто не помешает
использовать его для своих нужд.
При этом скорее забавно, чем грустно смотрится отсутствие условных
переходов. Pentium Pro Assembler? Ну-ну... С другой стороны
программирование с таких "жестких" рамках само по себе предстваляет
увлекательнейшую головоломку и действительно иногда напоминает "высший
пилотаж". 32 байта паяти - примерно столько было было в первых
программируемых микрокалькуляторах. Но даже там были устовые переходы и
прямая адресация памяти. Впрочем, черт, с ними, с условными переходами их
бы было можно реализовать исходя из принципа эквивалентности с помощью
всего двух команд NOR и OR. Но в hiew-е вообще нет переходов! Нет
регистра-указателя команд!
Печально все это, при том, что в qview-е таких ограничений по-просту
нет. Там управление передается полноценной ассемблерской программе, которая
может делать все что ей заблагорассудиться. Однако, это проигрывает в
интерактивности. За все, конечно, приходиться платить. Мне по душе все же
интерактивноть, поэтому я выбираю hiew. Тем более, что для ряда случаев его
все же хватает.
Итак поддерживаются следующие команды:
Набор регистров:
AL,AH,AX,EAX,BL,BH,BX,EBX.CL,CH,CX,ECX,DL,DH,DX,EDX,SI,ESI,DI,EDI,BP,EBP,
SP,ESP
Команды пересылки:
MOV регистр, регистр
MOV регистр, непосредственный операнд
Арифмитические команды:
AND, NOT, NEG, OR, XOR, SUB, ADD, ROL, ROR. MUL, DIV.
SHL и SHR не поддерживаются.
Передача параметров:
На входе AX
На выхде AX
Как видим, набор инструкций воистину "спартанский". Однако, для
большинства задач его все же хватет. Заметим, что чаще всего большинство
разработчиков использует операцию XOR, поэтому в hiew-е она выделена в
отдельный обработчик.
Самое интересное, что последний работает не только с
байтами\словами\двойными словами, но и со стоками любой длины (точнее до 20
символов). Для задания xor-маски нужно нажать Ctrl-F8, но так же это окно
вызывается и при нажатии F8, если маска еще пуста.
г========================== Enter XOR mask ==========================¬
¦ ASCII: -------------------- ¦
¦ ¦
¦ Hex: ------------------------------------------------------------¦
L====================================================================-
Очень часто в программировании используется шифр Вернама, сводящийся к
ксорении кода некой стокой, допустим 'KPNC++'. (Подробнее о нем можно
почитать в главе, посвященной криптографии). Предыдущие версии hiew не
имели такой возможности и не поддерживали строки. Разве, что из четырех
байт (двойного слова).
К сожалению, остальные команды до сих пор не могут работать со строками,
и это сильно удручает. Но вернемся, собстенно к интерпретатору скриптов.
Рассмотрим простейший пример. Для вызова редактора нажмем Ctrl-F7 и введем
следующую последовательность команд:
г=[Byte/Forward ]==============¬
¦ 1>xor ax,1234 ¦ AX=0000 ¦
¦ 2 loop 1 ¦ BX=0000 ¦
Ожидаеется, что она должна расшифровывать текст по xor word,0х1234.
Однако, это не произойдет. hiew автоматически не может определить размера
операндов и поэтому по умолчанию работает только с байтами (См строку
статуса в заголовке). При этом он старший байт регистра AX действительно
будет корректен, но вот инкремент все же будет равен единице, а не двойке,
как следовало бы ожидать по логике вещей.
Что бы измениь шаг, необходимо нажать F2, при этом в строке статуса
'Byte' смениться на 'Word'. Так же можно изменить и направление (т.е.
поменять инкремент на декремент, для чего служит клавиша F3, но в нашем
примере мы этого делать не будем).
Команда 'loop' на самом деле никакой не 'loop', а самый 'jmp', причем
наприваленный только назад. Если вы попытаетесь сделать прижок "вниз", то
произойдет приблизительно следующие:
г=[Byte/Forward ]==============¬
¦ 1 xor ax,1234 ¦ AX=1263 ¦
¦ 2> ¦ BX=0000 ¦
¦ 3 xor bl,al ¦ CX=0000 ¦
г= Pentium(R) Pro Assembler =====¬
¦ loop 3-------г==================·Hiew·==================¬
L===============¦ Jump out of range ¦
L==========================================-
Ну никак не хочет hiew понимать таких конструкций. Впрочем, так и
должно быть. Команда 'loop' последняя в скрипте и все ее назначение -
зациклить программу. При нажатии на F7 (Crypt) hiew шифрует слово\байт и
встретив 'loop' останавлиается, ожидая следующего нажатия F7, после чего
переходит на указанную метку.
При этот 'looo 1' можно опустить. Обычно так и поступают. Но иногда
необходимо выполнить только один раз некий иницилизационный код, как
например, показано ниже. При этом строка '1' выполяется один только раз, а
все остальное время hiew крутиться в циле 2-4.
г=[Byte/Forward ]==============¬
¦ 1>mov bl,66 ¦ AX=0000 ¦
¦ 2 xor al,bl ¦ BX=0000 ¦
¦ 3 sub bl,7 ¦ CX=0000 ¦
¦ 4 loop 2 ¦ DX=0000 ¦
Заметим, что приведенный алгоритм очень популярен среди
вирусописателей и разработчиков защит, поэтому применять его вам придется
довольно часто. При этом может возникуть проблемма как сбросить текущее
значение регистров и начать выполнения скрипта сначала. Дейститвельно,
предположим Вы успешно расшифровали один фрагмент и взялись было за другой,
как чувствует, что он начинает расшифровыаться некорректно. Разумеется, так
и должно быть. Ведь в регистрах остался мусор от предудушего выполения и
скрпт пытается продолжить расшифровку, ничего не зная, что нужно начать
сначала.
Это приходится делать пользователю вручную, нажимая Ctrl-F7
(Crypt-Set), F5 (ClearReg). При этом всплывает еще один баг автора -
"теневой" регистр указателя коман будет так же сброшен, но "визуальный"
указатель '>' останется неизменым вводя пользователя в некоторое
заблуждение в поисках еще одной клавиши сброса последнего. Но ее нет,
достаточно однократного нажатия F5, а на знак '>' просто попытайтесь не
обращать внимания.
Использование Crypt в качесвте калькулятора довольно любопытный
прием, облегчающий хакерам жизнь и страхующий от многих ошибок. Так или
инчае, но большая часть вычислений так или инчае связана с анализируемым
фйалом. При этом утомительно переносить необходиые значения в калькулятор
(не ошибившись при этот в проядке следования старших и младших байт), когда
просто можно указать hiew-у последние курсором. Ведь крипт принимает
входные данные и если сохранить то же самое значение регистра AX на выходе
скритпта, шифровка окажется "прозрачной", т.е. не изменяющий значение под
курсором.
Допустим, нам необходимо прочесть значения двух переменных хранияшихся
в одном байте у упакованном виде. Пусть три старших байта отводится под
одну из них и пять под другую. В калькуляторе это вычислять будет
утомительно и неудобно. Кроме того поскольку последний не может
обрабатывать двоичных числел в строке ввода, то и вовсе невозможно. Поэтому
прибегем к довольно безхитростному скрипту. Но как мы узнаем полученный
результат? Очень просто, поскольку значения регистров сохрнаяются,
достаточно вызвать SetCrypt и взгялнуть на них. Впрочем, это не намного
менее хлопотно, чем ввести то же значение в калькулятор. Поэтому рассмотрим
действительно полезный пример. Допустим, нам необходимо узнать хеш-сумму
некотрого фргмента (например для того что бы исправить CRC после правки
пары байт в коде). Возьмем к примеру простейший алгоритм суммирования байт
(который очень распростанен).
г=[Byte/Forward ]==============¬
¦ 1>add bx,ax ¦ AX=0000 ¦
"Прогоняем" расшифровщик по выбранному фргаменту, теперь вызываем
редактор и смотрим на значение регистра BX:
г=[Byte/Forward ]==============¬
¦ 1>add bx,ax ¦ AX=0121 ¦
¦ 2 ¦ BX=7534 ¦
Это и будет искомая хеш-сумма нашего фрагмента. Удобно, не правда-ли? К
сожалению, удобно-то оно удобно но не всегда. Большие фрагменты так
обрабатывать крайне утомительно. Необходимо будет "вручную" интерактивно
прогнать курсор по всему блоку, каждый раз прокручивая страницу и
возращаясь на предудушее место. Любая ошибка будет фатальной и сделать
откат (т.е. вычесть значение из BX) не предстваляется в текущих версиях
возмодным. Как это будет не печально, но придется все начинать сначала.
Для такаих целей лучше все же подходит qview. HIEW-ом же удобно
вскрывать несложные криптосистемы и пары сотен байт, зашифрованных по
сравгительно простому алгоритму.
Однако, не смотря на вышесказанное встроенный интерпретатор hiew-а
многими горяче любим и интенсивно используется. Быть может потому, что он
был первым, а может потому что сделан с любовью. Так или инчае он нужен. И
очень большое недовольство вызвало отсутствие крипта в 6.0 версии. К
счастью, автор быстро одумался и тут же вернул его на место.
Жалко, конечно, что за всю историю существования hiew-а крипт
претерпрел наименьшие изменения. Появилась разве что возможность записи
скрптов во внешний файл (F10). Это конечно, удобно, но практически этим
редко пользуются. А зачем? Обычно скрипты состоят из нескольких строк и нет
так уж и трудно их вновь "набить" вручную.
При этом записанный файл автор не советует редактировать. Цитирую
выдержку из файла реад_ми "Но т.к. трансляция во внутреннюю форму
происходит в момент ввода строки команды с клавиатуры не стоит пытаться
править сохраненный файл, ни к чему это..." На самом деле файл состот по
крайне мере из двух частей. Из отранслированных команд и их строкового
предстваления. При этом никто не запрещает разобраться в логике работы
транслятора и изменить сохраненные во "внутреннем предствалении" команды.
Разумеется, если отредактировать их "текстовой" образ, то ожидаемого
эффекта это никогда не даст. Впрочем, зачем редактировать записанный файл
не штатными средствами этого я действительно никак не могу понять.
ОПИСАНИЕ ФАЙЛА HIEW.INI
- Осторожность - важное качество
для человека, который будет вождем.
Ф. Херберт. "Дюна".
HIEW часть настроек хранит в ini файле, который немного напоминает
одноименные windows-файлы. Их легко редактировать вручную и структура
достаточно проста и не нуждается в описании. Однако, все же я решился
подробно рассказать о последнем. Кто знает, какие вопросы могут возникнуть
у читателя.
Первая строка неприменно должна быть [HiewIni 5.03] независимо от
текущией версии. Непонятно, почему так? Если для совместимости
"сврху-вниз", то почему бы просто не искать строку 'HiewIni'? Тем более,
что ini от разных версий меж собой не совместимы, т.к. автор частенько
удалял один ключи и добавлял другие.
Пустые строки и строки, начитающиеся с ';' игнорируются. Последнее как
нетрудно догадаться предназначено для комментариев.
hiew.ini не является обязательным файлом. При его отстутствии будут
браться параметры по умолчанию, которые совпадают с содержащимися в
"дистрибьтивном" варианте.
; стартовый режим
[StartMode] может принимать следующие значения Text, Hex, Code.
Выбранное значение будет автоматически установлено при открытии файла.
Рекомендую установить 'Hex', а впрочем, воля Ваша.
[Beep] включить\выключить (on\off) звуковой сигнал при ошибочных и
нештатных ситуациях. По умолчанию вколючен и я не вижу смысла изменять это
значение.
[Bar] Лифт или другими словами индикатор прогресса. По умолчанию
расположен слева (Left), несмотря на то, что пользователь приучен
интерфейсом Windows видеть эту полоску справа (Right). Впрочем, в текстовом
режиме попытки изобразить что-либо похожее всегда неудачны и поэтому на мой
взгляд полее подходящим является числовое предстваление в прцентах
(Percent). которое к тому же высвобожает одну колонку, что особенно
актуально для простотра текстовых документов, отформатированных по 80
символов в стоке.
[Wrap] Перенос длинных строк. Может принимать значения 'on' или 'off',
но намного более удобен автоматический (Auto) режим, устанавливаемый кстати
сказать по умолчанию. При этом для двоичных файлов всегда выполняется
перенос строк, а для текствоых нет.
[Tab] Поддержка табуляции. Если установлено значение 'On', то hiew
корректно обрабатывает символы табуляции, встретившиеся в просматриваемом
тексе. Если же установть 'Off', то все символы табуляции будут
проигнорированы. Аналогично вышеупомянутому [warp] существует и
автоматический режим, который устананавливается по умолчанию и на мой
взгляд очень удобен.
[StepCtrlRigh] задает число столбцов, на которые смещается текст при
нажатии Ctrl-Left \ Ctrl-Right. По умолчанию равен 20. Очень удобная
возможность для просмотра текстовых файлов, отформатированных более, чем с
80 символами в строке и причем так, что перенос строк не предстваляется
возможным. Например, при просмотре таблиц, диаграмм и т.д. Может принимать
значения от 1 до 128. Или другими словами signed byte.
[DisableMouse] по идее должен прятать\не прятать мышиный курсор. Однако
не зависимо от установленного значения курсор все равно не отображается.
[JumpTable] задает таблицу переходов по call/jmp в дизассемблере. По
умолчанию она выглядит следующим образом :
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ". При этом перый символ - это клавиша
отката, т.е. возвращения назад. А.Куленцов нашел довольно оригинальное
(хотя на мой взгляд слишком очевидое) решение предстваить эту строку в виде
"0123456789QWERTYUIOPASDFGHJKLZXCVBNM" для удобства работы с клавиатурой. А
по мне так хватает и девяти цифровых символов. Заметим, если на экране
появится больше ссылок, то остальные просто не будут отображены.
[Linefeed] для текстоых файлов задеет символ переноса строки. Из-за того
что в разных системах он разный могу возникнуть некоторые проблемм с его
интерпретацией. Большиннство просмоторщиков автоматически определяют
используемый формат. Точно так же поступает и hiew (Auto). Однако, если
нужно, то можно перевести его и на ручной режим управления. Он понимает
следующие значения - LF (0xA), CR (0xD), CRLF (0xD0xA), но к сожалению не
првильно интерпретирут (0xA 0xD) и (0xA 0xA). Впрочем, последнее
достаточно редко встречается, что бы вызвать какие-то проблеммы. Отметим,
что эта возможность впервые появилась только в версии 5.10
[AutoCodeSize] автоматически определяет разрядность кода (16\32) в LX
файлах. (префикс 'a' в строке статуса говорит, что активирован
автоматический режим определения). Не вижу никакой причины выключать эту
возможность, хотя последнее автором за каким-то загадочным случаям все же
предусмотрено.
[KbdFlush] управляет очисткой клавиатурного буффера перед вводом. По
умолачнию включено. В противном бы случае в окнах ввода информации
частенько бы появлялся мусор предудущих нажатий клавиш. Поэтому я никак не
могу предсвавить себе ситуации в которой это было бы полезно. Словом
отключать эту возможность можно разве что ради эксперемента.
; Маска для показа смещения при поиске с шаблоном и поиске ссылок
RunningOffsetMask = 0xFF ; 0 - 0xFFFFFFFF v5.53
[XlatTableIndex] задает индекс таблицы перекодировки в файле hiew.xlt
выбираемый по умолчанию. При этом '0' трактуется как остуствие таблицы
перекодировки, или в терминологии hiew-а 'AS IS'.
[FlistSort] задает критерий сортировки файлов в Навигаторе по
умолчанию.
[FlistSortReverse] инвертировать критерий сортировки. Т.е. по умолчанию
он задается по возрастанию параметра сортировки. Если это кажется
неудобным, то процесс можно и обратить.
[FlistShowHidden] показывать или нет скрытые файлы в Навигаторе. По
умолчанию такие файлы не отображаются. Странно, однако. Рекомендую
установить этот параметр в 'On'.
[NextFileSaveState] сохранять текущее состояние при переключении между
файлами. По умолчанию выключено, что мне категорически не нравиться.
Рекомендую активировать сей механизм - это сбережет Вам немало времени и
нервов.
[SaveFileAtExit] записывать состояние файла по выходу. По умолчанию
выключено (?!) что мне абсолютно непонятно. Это-то на фоне того, что выход
происходит без всякого предупреждения пользователя и на Esc и F10 и без
того понавегено немало других функций, так что ложные нажатия происходят
довольно часто. Неприменно необходимо включить этот механизм.
[ScanStep] шаг по умолчанию при поиске ссылко (F6 Reference) или команд
(F7,F7). По умолчанию имеет значение 'Command' но по мне лучше проиграть в
скорости, чем надежности и (как было сказано выше) я предпочитаю
устанавливать шаг поиска в байт ('Byte').
[Savefile] задает имя и путь к файлу сохранения состояния. По
умолачнию hiew создает файл 'hiew.sav' в текущей директории, но это можно
изменить. Это бывает полезно, например, когда на текущий диск записать
нельзя (ключевая дискета, защищенная от записи, CD-ROM)...
ЦВЕТА
Наконец-то hiew стал поддерживать цветовую раскладку! Теперь каждый
может настроить ее под свой вкус. Я, допустим, большой поклонник "зеленым
по черному" и все используемые программы настраиваю именно так.
Подробно описывать кодировку цветом цвета нет, она тривиальна. К тому
же это гораздо удобнее делать специальной утилитой, (например, похожей на
qview) чем делать это вручную.
Структура этой секции hiew.ini ясна из привиденного фрагмента:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ColorMain = 0x1B ; основной цвет
ColorCurrent = 0x71 ; текущий байт
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
HIEW.XLT
Этот файл служит для перекодировки символов. Может содержать до 15
кодировок, но в распространяемом автором варианте содержит только две -
Win1251 и KOI8R. Имеет довольно витеватую струкутру и для его
создания\просмотра\редактирования не помешает написать хорошую утилиту.
Автор в сопутствующей документации описывает структуру как:
------------------------------------------------------------------------
typedef struct{
BYTE sign[ 9 ], // "HiewXlat",0
unused[ 5 ],
versionMajor, // 0x05
versionMinor; // 0x40
}XLAT_HEADER;
typedef struct{
BYTE title[ 16 ], // заголовок
tableOut[ 256 ], // для вывода
tableIn[ 256 ], // для ввода
tableUpper[ 256 ]; // для игнорирования регистров в поиске
}XLAT;
------------------------------------------------------------------------
Не думаю, что это вызовет какие-нибудь вопросы. Структура полностью
понятна и удобна в обращении. Заметим, что ввод\вывод разделены, что
приятно. Аналогично и с переводом регистра. Разумеется hiew не может знать
как расположены символы в произвольной кодировке, поэтому регистр автоматом
не переводит.
Жалко только, что в комплекте с hiew-ом не идет утилиты для работы с
этим файлом. Ну откомпилировать его можно, положим препрцессором, но вот
декомилировать... для декомпиляции потребуется написать специальную
программу. Допустим, если вы решитесь добавить поддержку ISO, то
потреубется сначала декомпилировать существующий файл, внести исправления и
посторить опять.
Заметим, что hiew.hlt может отсутствовать. В этот случае поддерживается
единственная кодировка по умолчанию DOS или в терминологии hiew-а 'AS IS'.