Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Техника и философия хакерских атак

Крис Касперски

Продолжение...

СКОБКИ: 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-е таких ограничений попросту нет. Там управление передается полноценной ассемблерской программе, которая может делать все что ей заблагорассудится. Однако, 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, после чего переходит на указанную метку.

При этом 'loop 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 на выходе скрипта, шифровка окажется "прозрачной", т.е. не изменяющей значение под курсором.

Допустим, нам необходимо прочесть значения двух переменных, храняшихся в одном байте в упакованном виде. Пусть три старших бита отводятся под одну из них и пять под другую. В калькуляторе это вычислять будет утомительно и неудобно. А поскольку он не может обрабатывать двоичных чисел в строке ввода, то и вовсе невозможно. Поэтому прибегаем к довольно бесхитростному скрипту. Но как мы узнаем полученный результат? Очень просто: поскольку значения регистров сохраняются, достаточно вызвать CryptSet и взглянуть на них. Впрочем, это ненамного хлопотнее, чем ввести то же значение в калькулятор. Поэтому рассмотрим действительно полезный пример. Допустим, нам необходимо узнать хеш-сумму некоторого фрагмента (например, для того чтобы исправить 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). Это конечно, удобно, но практически этим редко пользуются. А зачем? Обычно скрипты состоят из нескольких строк и не так уж трудно вновь "набить" их вручную.

При этом автор не советует редактировать записанный файл. Цитирую выдержку из файла read_me : "Но т.к. трансляция во внутреннюю форму происходит в момент ввода строки команды с клавиатуры, не стоит пытаться править сохраненный файл, ни к чему это..." На самом деле файл состоит по крайней мере из двух частей. Из оттранслированных команд и их строкового представления. При этом никто не запрещает разобраться в логике работы транслятора и изменить сохраненные во "внутреннем представлении" команды. Разумеется, если отредактировать их "текстовый" образ, то ожидаемого эффекта это никогда не даст. Впрочем, я действительно никак не могу понять зачем редактировать записанный файл нештатными средствами.

Описание файла 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] существует и автоматический режим, который устананавливается по умолчанию и на мой взгляд очень удобен.

[StepCtrlRight] Задает число столбцов, на которые смещается текст при нажатии Ctrl-Left \ Ctrl-Right. По умолчанию равен 20. Очень удобная возможность для просмотра текстовых файлов, отформатированных более чем с 80 символами в строке и притом так, что перенос строк не представляется возможным. Например, при просмотре таблиц, диаграмм и т.д. Может принимать значения от 1 до 128. Или, другими словами, signed byte.

[DisableMouse] По идее должен прятать\не прятать мышиный курсор. Однако независимо от установленного значения курсор все равно не отображается.

[JumpTable] Задает таблицу переходов по call/jmp в дизассемблере. По умолчанию она выглядит следующим образом : "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ". При этом первый символ - это клавиша отката, т.е. возвращения назад. А.Куленцов нашел довольно оригинальное (хотя, на мой взгляд, слишком очевидное) решение представить эту строку в виде "0123456789QWERTYUIOPASDFGHJKLZXCVBNM" для удобства работы с клавиатурой. А по мне хватает и девяти цифровых символов. Заметим: если на экране появится больше ссылок, то остальные просто не будут отображены.

[Linefeed] Для текстоых файлов задает символ переноса строки. Из-за того что в разных системах он разный, могут возникнуть некоторые проблеммы с его интерпретацией. Большинство просмотрщиков автоматически определяют используемый формат. Точно так же поступает и hiew (Auto). Однако если нужно, то можно перевести его и на ручной режим управления. Он понимает следующие значения - LF (0xA), CR (0xD), CRLF (0x0D0A), но, к сожалению, неправильно интерпретирует (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.xlt может отсутствовать. В этом случае поддерживается единственная кодировка по умолчанию DOS, или, в терминологии hiew-а, 'AS IS'.

BoundsCheck OverView

"Покажите мне пример совершенно гладко идущей рутины и я найду вам того, кто прикрывает ошибки."

Ф. Херберт. "Дом Глав Дюны".

BoundsChecker фирмы NuMega (далее просто BC) - это инструмент, прежде всего нацеленный на поиск ошибок в вашем собственном программном обеспечении. Однако он подходит и для исследования взаимодействия приложений с операционной системой или другими приложениями, поступившими в ваше распоряжение без исходных кодов.

Что представляет собой BC? Отладчик или дизассемблер? Ни то ни другое. Это Win32-шпион. Обычные шпионы (типа Spyxx из MS VC) перехватывают только сообщения, которыми приложение обменивается с окном. Учитывая, что архитектура Windows фактически полностью построена на сообщениях, перехват последних несет достаточно полную информацию о происходящих событиях. Полную, но увы, не исчерпывающую. Множество функций вообще не генерируют сообщений (например, выделение памяти, чтение из файла или реестра).

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

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

BC же - это десятки мегабайт сложного кода, который ненамного хитрее созданного Питтреком; он разве что покрывает больший круг задач. По крайней мере я, поработав с версией 5.0, пришел к выводу, что нет ничего лучше собственных шпионов, специализированных применительно к интересующему вас кругу задач. И все же BC не совсем то, что нужно хакеру. Очень многого в нем недостает: в частности, нет никакой системы навигации по его протоколам. Нет и никакого фильтра функций, так что вам предстоит тяжелая археологическая работа: отыскивать нужные имена среди бесконечных вызовов GetMessage\TranslateMessage\DispathMessage и им подобных. Так же обстоит дело и с сообщениями - километрами листингов, в основном не представляющих для хакера в данный момент ничего интересного. Spyxx имеет гибкую систему фильтров, которая сокращает протоколы и заметно ускоряет анализ.

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

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

Вышесказанное не означает, что я призываю отказаться от BC. Вовсе нет! Это действительно очень мощный инструмент, в настоящее время не имеющий аналогов. Но нужно четко представлять, для решения каких задач он полезен. Часто более быстрый путь - использование дизассемблера или отладчика.

Не стоит пытаться "перетянуть" одеяло и решать BC-ом те задачи, для которых он, мягко выражаясь, не совсем предназначен. Строго говоря, BC даже и не может работать в одиночку. Его назначение - показать вызовы API функций и сообщений в изучаемом приложении. Для чего может понадобиться эта информация?

Рассмотрим случай, когда программа, считывающая строку из окна редактирования, не вызывает ни GetWindowText, ни GetDlgItemText, и даже не посылает сообщения WM_GETTEXT. Чтобы понять, как текст все же попадает в буфер, надо проанализировать манипулирующий с ним код. Т.е. пройтись дизассемблером по нужному участку кода. Но тут вся проблема в том, что мы не знаем, какой код "нужный", и в поисках последнего рискуем потерять уйму времени.

В этом случае BC, показывая все вызовы API и связанных DLL, наверняка покажет и те, которыми приложение считывает текст. Это может быть посимвольное чтение клавиш или еще что-нибудь. Конечно, будет большой проблемой найти эти функции и в протоколе (т.к.он наверняка будет иметь немалый размер, сравнимый, может быть, даже с листингом дизассемблера) - при изучении последнего придется порядком попотеть.

ВС поможет также при исследовании приложений на предмет недокументируемых функций и возможностей. Или документируемых, но плохо понятных. Например, если работа Менеджера Задач вам кажется сплошной загадкой, а дизассемблировать его, естественно, не хватает времени и терпения, можно запустить API-шпиона и посмотреть, какие функции приложение вызывает.

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

Быстрый старт

"- Существуют во Вселенной вопросы, на которые нет ответов."

Ф. Херберт. "Мессия Дюны".

BC необычайно прост в управлении. NuMega специально отмечает это в прилагаемой документации. Иначе говоря, вас сильно ограничили в гибкости и возможностях контроля над приложением. Все за вас делает BC!

Воистину непостижим такой подход на фоне Soft-Ice, который содержит весьма привлекательный для профессионала интерфейс. Но почему-то применительно к BC фирма-разработчик пошла другим путем, чем явно огорчила многих своих поклонников.

Остается использовать то, что дают. Запустим BC и попробуем открыть какой-нибудь файл для анализа. Напомню, что поддерживаются только 32-разрядные Win32 файлы. Даже сегодня во время победного шествия Win32 API это ограничение все еще существенно, и существует немало 16-разрядных приложений даже среди новых разработок.

Чтобы согласовать наши действия, предлагаю вам остановить свой выбор на примере BUG1, находящемся в комплекте поставки BC. При этом последний автоматически откроет окно "Program Transcript". В нем на протяжении всего сеанса работы будут отображаться такие события, как загрузка различных DLL, а также выводиться все отладочные сообщения. Это нас будет интересовать в последнюю очередь.

Если открыть руководство, то можно прочесть рекомендацию кликнуть по кнопке "run" (эдакая соблазнительная стрелочка, направленная вниз) и запустить программу. Но не будем спешить и полагаться только на руководство. В противном случае BC будет мирно крутиться в фоне, ожидая ошибок или аварийных ситуаций. Естественно, что в изучаемом приложении таковых скорее всего не окажется и финальный рапорт будет пустым.

Это кстати, самая распространенная ошибка начинающих пользователей BC. За неудачной попыткой следует разочарование или вопрос - а где же обещанные вызовы API?

На самом деле, как уже отмечалось, это и есть нормальная работа BC, который в первую очередь предназначен для предотвращения ошибок и их локализации. Зададимся вопросом - а как это он делает? Полистав документацию, мы узнаем, что BC перехватывает практически все ключевые функции и проверяет корректность передаваемых им параметров. В противном случае он выводит в окно сообщение об ошибке.

Обратите внимание: ВС перехватывает функции, но не отмечает этот факт в протоколе, если вызов функции с его точки зрения корректен. Быть может, есть какой-то способ отображать все события вне зависимости от аварийности ситуации?

Действительно, NuMega предусмотрела такую возможность. Конечно, среднестатическому пользователю она не нужна и поэтому по умолчанию выключена. Чтобы исправить это, заглянем в установки программы (Program\Setting). Выберем закладку "Event Reporting". Появится выбор из следующих пунктов:

Collect and report program event data

Report messages

Report pointer data for API

Report Hooks

Но последние три пункта будут недоступны, пока не установлена галочка "Collect and report program event data". Выбор остальных зависит от выбранной вами цели и исследуемой программы. Для перехвата функций API нужно установить "Report pointer data for API", а также остальные - для перехвата сообщений или хуков.

Если теперь снова перейти на первую закладку "Error Detection", то будет возможность сохранить текущие настройки значениями по умолчанию. Это и в самом деле приятная возможность, особенно если планируется использовать BC в основном для анализа чужих программ, а не по прямому назначению.

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

При этом в окне отображения событий появится единственный поток приложения (непонятно почему изображенный катушкой с зелеными нитками), а ниже - встретившаяся ошибка (умышленно допущенная разработчиками для демонстрации возможностей BC), но сейчас не будем акцентировать на ней внимания.

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

И где же ожидаемый нами протокол? Почему он по-прежнему выглядит пустым? Куда подевались все функции API, ведь наши ушки явно слышали, что в протокол записывалось что-то "тяжелое"! Не будем волноваться. На самом деле все сработало успешно, просто BC по умолчанию не показывает в окне событий ничего, кроме ошибок и потоков.

Нажатием правой кнопки мыши, вызовем контекстное меню и установим галочку над пунктом "Show All Evetns". А затем "Expand All". Если все было сделано правильно, то в окне появится длинный перечень вызываемых функций.

         +----------------------------T--------------¦
         ¦  окно отображения событий  ¦ окно стека   ¦
         ¦                            ¦              ¦
         ¦                            ¦              ¦
         ¦                            ¦              ¦
         ¦                            ¦              ¦
         ¦                            ¦              ¦
         +----------------------------+--------------+
         ¦           Окно исходного текста           ¦
         ¦                                           ¦
         ¦                                           ¦
         L--------------------------------------------

Прокрутим его немного вниз, пока не встретим вызов функции CreateWindowExA. Щелкнув по нему, мы увидим в окне стека, расположенном справа, все передаваемые параметры в удобочитаемом виде. Из этой информации можно узнать много интересного. Но важно уже то, что мы знаем, какой именно функцией было создано окно.

Теперь, если потребуется перехватить момент создания окна, у нас уже не возникнет вопрос, на какую функцию ставить BreakPoint. Вряд ли нужно говорить, что приложение может создать NagScreen множеством способов и вручную перебрать их все будет очень затруднительно. BC же позволяет нам заглянуть "под капот" выполняемой программы, чтобы узнать, какие именно функции оно для этого вызывает.

Подключение нестандартных DLL

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

BC реализует далеко не лучшую схему перехвата вызовов API и DLL-функций. Это отличает его, например от продвинутых шпионов, перехватывающих на лету все функции загруженных приложением модулей. Причем последние даже не обязательно должны быть DLL-модулями. Например, IDA поддерживает плагины, которые представляют собой PE или LE файлы, экспортирующие определенные функции. А IDA в свою очередь предоставляет им собственный API.

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

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

Если бы научить BC "видеть" эту DLL, то никаких проблем бы не было и мы получили бы интересный протокол, раскрывающий все секреты защиты. К счастью, NuMega предусмотрела этот момент и снабдила пользователей инструментарием для поддержки "их собственных DLL". Понятно, что BC не может с уверенностью сказать, ваша это DLL или еще чья-то. При перехвате BC никак не изменит исследуемую DLL, а поэтому это действие не противоречит нашему законодательству.

Чтобы понять, как происходит подключение нестандартных DLL, нужно представить себе механизм перехвата экспортируемых ими функций. К сожалению, это очень емкая тема, для которой требуется отдельная книга; кроме того, она уже многократно и исчерпывающе освещалась. Поэтому ограничусь двумя словами. Для каждой перехватываемой DLL нужно построить определенную заглушку. BC подменяет вызовы оригинальной DLL на "свои". При этом он полностью контролирует управление и передаваемые параметры. Разумеется, для этого должна существовать специальная база данных, которая содержит типы и допустимые параметры. Впрочем, последнее нас интересует меньше всего, ибо нам необходимо отметить сам факт вызова какой-то функции, и только. Это облегчит нам задачу написания "заглушки".

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

Однако написание заглушки - очень трудоемкий процесс, требующий определенных навыков и знаний. Впрочем, специалисты (а именно такой специалист подразумевается под словом "хакер") не боятся этих трудностей. Была бы только документация и хотя бы краткое описание. В том-то и беда, что его нет! Веселенькое начало нам обеспечила NuMega! Как же быть? Остается использовать мастера, который сгенерирует за вас весь код автоматически, на C++.

Работу мастера описывать я не буду. Скажу только, что она проста, и этот мастер, как любой другой, потребует от вас минимальных умственных и физических усилий. Разумеется, возможности выбора окажутся очень ограниченными, но, как бы то ни было, на финальном пункте появятся три файла - *.cpp, *.h и *.mak При этом откомпилировать это MS VC можно только с ручной правкой некоторых мест, что не приносит абсолютно никакого удовольствия и тормозит весь процесс.

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

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

Пункты меню

Вся жизнь его в этот момент представилась ему веткой, дрожащей после взлета птицы, а эта птица была - возможность. Свободная воля.

Ф. Херберт. "Мессия Дюны".

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

Кому-то моя критика может показаться несправедливой. Быть может, я слишком суров по отношению к этой великолепной утилите? Кто знает... когда конкуренты спят и не предлагают ничего лучшего, то на безрыбье и рак рыба. Хотя есть еще и WinScope, написанный фирмой Periscope, но он почему-то не получил широкого распространения.

Меню "файл" типично для Windows-приложений. Пунткы Open\Close\Save As коментариев не требуют. Заострим внимание только на одном моменте: "сохранить" подразумевает сохранить текущее состояние и перехваченные вызовы в файл. К сожалению, используется не текстовой, а внутренний формат BC, а это означает, что написание собственного навигатора усложняется. Для этого потребуется проделать кропотливую работу по изучению сложной, а местами и запутанной структуры файла. Быть может, я опишу ее подробно (или хотя бы кратко) или даже предоставлю собственную DLL, работающую с файлами, созданными BC 5.0, и, возможно, более поздних версий (до сих пор не было возможности это проверить).

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

"Print" и "Print PreView" позволят распечатать или хотя бы показать на экране протокол в более удобочитаемом виде. К сожалению, для его распечатывания потребуется тонны бумаги (соответственно, литры чернил в случае струйного принтера), что вряд ли оправдано. Особенно если вспомнить про сегодняшний кризис и стоимость расходных материалов... Непосредственная печать в файл невозможна, поскольку BC представляет все данные в графическом, а не текстовом формате.

Меню "Edit" содержит традиционную команду "Find" (Ctrl-F). Вызов ее приводит к появлению стандартного диалога поиска, которое вроде бы не поддерживает ни шаблонного, ни мультистрокового поиска. Однако при близком рассмотрении справа от окна ввода обнаруживается маленькая прямоугольная кнопочка со стрелкой, обращенной вправо. Нажатие ее раскрывает подменю поиска, которое притягивает к себе с первого взгляда.

Error

Resource, memory or interface leak

API or OLE method call

API or OLE method return

Windows or Dialog Message

Hook

Comment

Thread start of switch

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

Поиск вызовов API был бы полезен, если бы была хоть какая-то возможность указывать сложную маску. Фактически их так много, что следующий вызов нетрудно найти и ручным поиском. Более того, он скорее всего, окажется в пределах окна событий, так что не потребуется даже прокрутки последнего.

Фактически единственным используемым пунктом будет 'Windows of Dialog Message' - т.к. не всегда легко найти сообщения, относящиеся к окну, (диалогу) среди множества малоинформативных вызовов функций API.

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

Приятно, что BC поддерживает поиск не только вперед, но и назад. Это весьма упрощает навигацию и значительно экономит драгоценное время разработчика.

Заметим, что окно поиска вынесено и в панель инструментов. Как и следует ожидать, оно поддерживает историю ввода; пара кнопок, расположенных рядом, задает направление поиска - вперед и назад. Но фильтр можно вызвать только через меню. Впрочем, редкое его использование не позволяет считать отсутствие его в панели инструментов поводом для критики или возмущения. Даже наоборот - панель меньше загромождается ненужными кнопками.

Меню VIEW начинается с пункта 'Event Summary'. Это своего рода и "легенда" всех условных обозначений, но в то же время - статистика вызовов функций API, оконных сообщений и всего остального в виде сводной таблицы. Эта бесполезная (но очень любопытная) информация не несет в себе ничего, что можно было бы использовать для анализа программы. Ну какой мне прок знать, что приложение вызвало 2562 функций API и приняло\передало 115 сообщений?

Следующие три пункта:

Show Error and leak only (показывать только ошибки и утечки)

Show All Events (показывать все события)

Show Error and Specific event (показывать ошибки и выбранные события)

Specific event

Нам уже должны быть хорошо знакомы по "быстрому старту". Обычно используется "Show All Events" или "Show Error and Specific event". При этом можно выбрать произвольный набор отображаемых событий. К несчастью для хакера, крайне грубый и непрактичный.

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

Установка флажка "Arguments" приводит к тому, что в круглых скобках будут указываться аргументы каждой из отображамых функций. Это в самом деле очень удобно. При этом BC распознает строки и представляет их в символьном виде. Поэтому мы имеем все шансы встретить введенный пароль и найти функции, манипулирующие им. То же верно и по отношению к другим типам переменных. Если при этом последняя представляет собой какую-то сложную структуру, то она будет отображена в развернутом виде в окне стека, расположенном справа.

По умолчанию этот флаг опущен. Настоятельно рекомендуется его взвести и больше никогда не опускать. То же самое можно сказать и о 'Sequence number' - последовательном номере функции, отображаемом слева. Это повышает эстетическое восприятие текста, а также дает понять, в каком месте протокола вы в данный момент находитесь (и помогает собрать рассыпавшиеся листы распечатки, если вы все же решитесь его распечатать).

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

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

Меню "run" содержит только один интересный пункт "Setting", который и будет подробно рассмотрен ниже. Если кликнуть по нему мышкой, то появится окно с несколькими закладками.

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

Гораздо более интересна следующая закладка - 'Events reporting', уже рассмотренная выше. Я думаю, мне уже нечего добавить, разве лишь напомнить еще раз о необходимости взвести нужные флажки: в противном случае просто ничего не будет работать.

"Program Info" позволяет задавать командную строку приложения (что уже давно не актуально для Windows приложений, но, может быть, когда-нибудь и пригодится) и рабочую директорию (по умолчанию выбирается текущая); а также указать путь к исходным текстам, которых скорее всего просто в нашем распоряжении не окажется. (а потому никакого пути и указывать не придется).

А вот 'Error Supressions'- очень полезная и актуальная функция. Помните, я говорил, что нет никакой возможности задать фильтр для произвольных и мешающих функций? Так вот: я вас обманул. Эта возможность есть, правда, в очень грубом варианте ее реализации. Можно вообще отключить перехват не интересующих нас в данный момент функций. Но это не самый лучший выход. Если в процессе изучения рапорта потребуется информация о "заблокированных" функциях, она уже никак не может быть получена, разве что полным ре-анализом, что удовольствия не приносит.

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

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

Как сломать TRIAL.COM

- Я говорю людям: смотрите! У меня есть руки! Но мне говорят: "А что такое руки?"

Ф. Херберт. "Дюна".

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

Одним из способов определить профессионализм человека - подсунуть ему crack_me и посмотреть, как он его взломает. В последнее время, кстати, хороших crack_me стало очень мало. Обычно закладывают какой-нибудь математический алгоритм, решение которого требуется найти. Или, что еще хуже, просто зашифровывают достаточно криптостойким алгоритмом - так, чтобы полный анализ был не возможен. Утомительные часы перебора (а то и дни) - кому они интересны?

Я попытался (и не без успеха) предложить нетривиальную задачу, рассчитанную на нестандартное мышление, при этом предоставив неограниченную свободу творчества. Увы, я был разочарован. Никто так и не приблизился к решению. Самое парадоксальные, что задачка была очень простой и... А, впрочем, зачем "и" - все равно никто не решил.

> Crack Me by [KPNC] ',0Dh,0Ah

> Если вы сломаете данный crack_me, то получите членство в группе [KPNC]

> Под "сломать" понимается узнать, на кого зарегистрирован demo_def: точнее,

> расшифровать его. Там содержится имя экс-президента группы. Скажу сразу:

> оно не мое, поэтому забудьте про атаку по открытому тексту. Скажу больше

> для расшифровки нужно найти ключ длиной в шесть байт. Два из них -

> 0xF0 0x83. Остается четыре. Ну что - найдете? Аль нет? Взломать будет

> непросто - эти шесть байт просто отсутствуют в ключе. (см. сам ключ)

> Есть два независимых метода взлома, так что дерзайте...

> [KPNC!!AMPER!!Usa.net]

Ниже будет дано подробное решение. Быть может, оно кого-то рассмешит. Но... действительно, задачка проста (см. trial.com). Условие, конечно, сформулировано нечетко, и проще всего надо было определить: что собственно делать? Достоверно было известно только то, что в файле demo_def содержится имя вице-президента группы (и успел же он появиться!). И его надобно найти. Рассмотрим внимательнее этот файл:

00000000: BA 01 14 00-5B 4B 50 4E-43 5D 77 77-B4 01 10 00  ¦xx [KPNC]ww+xx 
00000010: 42 02 C3 01-4C 01 04 00-9F 01 EE 00-55 01 10 00  BxxxLxxxЯxюxUxx 
00000020: 24 04 CD 01-EA 00 82 02-48 02 03 77-11 83 17 33  $x=xъxВxHxxwxГx3 
00000030: 84 02 82 02-6C 03      -           -             ДxВxlx 

Ясно, что [KPNC] - это никак не искомое имя. Тогда... посмотрим как работает расшифровщик:

00000061: BF9701           mov       di,00097 ; Приемник 
........  .....            ...       ......... 
0000002E: AD               lodsw              ; Читаем слово шифротекста<-¬ 
0000002F: 33DB             xor       bx,bx    ; BX == NULL                ¦ 
00000031: 86E3             xchg      ah,bl    ; BL == HiByte(AX)          ¦ 
00000033: F6F3             div       bl       ; AL == AH / ~AL            ¦ 
00000035: AA               stosb              ; Пишем расшифрованный байт ¦ 
00000036: E2F6             loop      00000002E;  -------- (1) ------------- 
00000038: E85C00           call      000000097; Вызываем расшифрованный ключ 
0000003B: C3               retn               ; Возврат. 

Э, да шифровка-то тривиальна. И все бы коту масленица, да разработчик упоминал о каких-то шести "слизанных" байтах, в которых и "зарыта собака". Действительно, в demo_def шесть нулевых байт! И все старшие, т.е. делители. Ясно, что x / 0 смысла не имеет и программа просто аварийно завершается. Разумеется, пропавшие байты по заверениям автора не относятся собственно к имени, да и не могли относиться, т.к. иначе было бы попросту нечестно. Хотя, в любом случае это не важно - уж слишком беспорядочно они разбросаны по тексту...

Давайте подумаем: что можно выжать из этого файла и какую тактику нам применить? Конечно же по открытому тексту! А почему нет? Мы же знаем очень много об этом коде, который выводит сообщение. Места хватит только на то, чтобы вывести его через функцию f.9\int 21, или, во всяком случае, через f.6 Хотя f.6 откинем - рассмотрим последнее слово шифротекста - 0x36C. Расшифруем его - 0x6C \ 0x3 == 0x36 == '$'. Опля! Кой-что интересное! Не так ли, господа? Пойдем дальше, точнее, вернемся назад и расшифруем еще два символа - 0х82 \ 2 == 0х41 == 'A' и 0х84 \ 2 == 0х42 == 'B'. Итак, президента зовут *BA. А дальше нам путь преграждает любопытнейшая комбинация 0x17 \0x33 == 0? Запахло нечистым... 03\77;11\83; 17\ 33 целых три символа шифротекста, равные нулю, а в сумме шесть байт! Если их сложить с теми загадочными нулями, то.. . в общем многовато получится!

82\ 02 == 0х41 'A' и 48\ 02= 0x24 = '$' как-то непонятно выглядит. Однако так или иначе коду, выводящему это безобразие, отводится все меньше и меньше места, как раз ровно столько, сколько хватит на f.9, - но в таком случае мы имеем открытый текст, т.е. здоровую дыру, в которую можно пролезть. Заметим, что вызов int 0х21 трудно замаскировать. И точно, мы видим...

00000000: BA 01 14 00-5B 4B 50 4E-43 5D 77 77-B4 01 10 00  ¦xxx[KPNC]ww+xx 
00000010: 42 02 C3 01-4C 01 04 00-9F 01 EE 00-55 01 10 00  Bx+xLxxxЯxюxUxx 
00000020: 24 04 CD 01-EA 00 82 02-48 02 03 77-11 83 17 33  $x=xъxВxHxxwxГx3 
                ^^^^^ 
00000030: 84 02 82 02-6C 03      -           -             ДxВxlx 

Хотя, конечно, автор мог использовать call на тело своей программы, где стоит int 21 (0xE8), но 0xE8 в коде не наблюдается, а 0xCD ('=') есть. А что есть еще? Есть 0x21 (offset 0x10), но почему-то стоящий далеко от 0xCD и 0xB4 есть (mov ah,9), ну и 0х9 можно найти (offset 0x20, 0x24\0x4). Есть также MOV DX, ? (0хBA) и его старший байт - операнды (0х1 - 0x77 \0x77).

Ситуация становится все более загадочной и непонятной - весь код присутствует, но странным образом перемешан. Выходит, мы столкнулись с шифром перестановки. Попробуем найти ключ. Вполне возможно, что он генерируется всего на основе 6 байт. Это звучит вполне правдоподобно. При этом нулевые байты могут быть просто не значащими и их можно отбросить. Но как найти ключ?

Пусть нам с некоторой достоверностью известен фрагмент оригинального текста, тогда можно проследить логику перемешивания байт. Допустим, 0xCD и 0x21. Их отделяют всего 0x16 байт, или, точнее, 0xEA в знаковом представлении.

CD 01-EA 00 
^^^^^^^^^^^ 

Поразительно! Такое совпадение! Выходит, ключ содержится в файле! Ну а как пара mov ah,9 (0xB4 0x9)? Их отделяют 0х10 байт. И снова

B4 01 10 00 
^^^^^^^^^^^ 

Итак, кажется, что-то прояснилось. Логика шифрования понятна. Можно хоть сейчас садиться и писать собственный дешифровщик. Ноль обозначает, что следующий расшифровываемый символ находится на n (где n - значение младшего байта) расстоянии от текущего. Любопытный прием. Криптор может "блохой" прыгать по файлу, собирая разбросанные байты.

ОК. Это мы выяснили. Теперь можно расшифровать demo_def, "выцарапать" из него имя и зашифровать снова. Но не будем торопиться. Это была только первая самая легкая стадия проверки на знание основ криптоанализа (примитивнейшая атака по открытому тексту, что может быть еще проще?) Поразительно, но никто этого так и не решил! Печально, очень печально.

Ну да ладно, вторая стадия - на сообразительность. Чтобы trial.com вывел это имя на экран, необходимо всего лишь изменить его расшифровщик. Это нетрудно сделать, если обратить внимание на следующие строки:

00000156: E81600                       call      00000016F 
00000159: 49                           dec       cx 
0000015A: B43F                         mov       ah,03F ;"?" 
0000015C: CD21                         int       021 

(см. сам файл). Т.е. можно записать ключ по _любому_ адресу в файле! И кое-что это подтверждает!

00000166: 803C90                       cmp       b,[si],090 ;"Р" 
00000169: 7403                         je        00000016E   -------- (3) 
0000016B: E8C0FF                       call      00000012E   -------- (4) 
0000016E: C3                           retn 

Части: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог