<< Предыдущая

стр. 36
(из 39 стр.)

ОГЛАВЛЕНИЕ

Следующая >>

тернете можно найти и готовые программы, предназначенные для протоко-
лирования обращений к библиотечным функциям, например APIS32 от
Виталия Евсеенко и APISpy32 разработки Ярива Каплана (Yariv Kaplan).
Глава 22


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


22.1. Область применения
Поскольку хороших универсальных решений не бывает, ограничим класс
программных продуктов, для которых будет проводиться реконструкция
протокола. Исследуемая программа должна удовлетворять следующим тре-
бованиям:
• та часть программы, в которой реализован криптографический протокол,
скомпилирована в машинный код, т. е. выполняться напрямую процес-
сором, а не виртуальной машиной. Это позволит использовать эвристи-
ки, которые плохо работают (или не работают вообще), если применяют-
ся к псевдокоду. Но данное ограничение нельзя назвать очень строгим,
т. к. криптографические примитивы, полностью реализованные на базе
виртуальной машины, выполняются очень медленно и неприменимы для
большинства практических задач;
О программа выполняется под одной из версий 32-битовой операционной
системы Windows на процессоре х86. Это также не очень сильно сужает
область возможного применения, ведь большинство персональных ком-
пьютеров сейчас имеют именно такую конфигурацию. К тому же почти
все эвристики могут быть адаптированы к другим операционным систе-
мам и аппаратным платформам;
252 Часть V. Заметки об исследовании средств защиты


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


22.2. Идентификация
криптографической библиотеки
Так как самостоятельная реализация криптографических примитивов — до-
вольно сложная задача, можно предположить, что разработчики предпочли
использовать одну из существующих криптографических библиотек. Если
удастся определить, какая именно библиотека была использована при раз-
работке программы, это даст довольно много информации.
В объектных файлах, поставляемых в составе библиотеки, как правило, при-
сутствуют символические имена (названия функций и переменных), несу-
щие смысловую нагрузку. И если исследователю удастся установить одно-
значное соответствие между фрагментами кода программы и кодом
библиотеки, по именам можно будет догадаться, что делает та или иная
часть программы.
Кроме того, библиотеки обычно поставляются вместе с подробной докумен-
тацией, используя которую, исследователь сможет точно узнать, что делает
та или иная функция.
А если библиотека распространяется в исходных текстах, то сразу же стано-
вятся доступны все детали реализации того или иного алгоритма.
Так как же узнать, что за библиотека использовалась? В этом могут помочь
несколько идей.
Глава 22. Реконструкция криптографических протоколов 253

Во-первых, лицензия на использование библиотеки может требовать, чтобы
называние библиотеки упоминалось в самой программе или в сопроводи-
тельной документации, и тогда определить библиотеку не составит труда.
Во-вторых, лицензия может ограничивать область применения библиотеки,
например только для некоммерческих приложений или только на террито-
рии США. Пользуясь этим, можно исключить из рассмотрения все библио-
теки, которые не должны были применяться для создания конкретной про-
граммы из-за лицензионных ограничений. Хотя бывают и исключительные
случаи, когда разработчики кому-то предоставляют специальную лицензию,
отличающуюся от опубликованной в открытых источниках.
В-третьих, разные библиотеки имеют разный набор доступных алгоритмов.
Таким образом, если в документации на программу сказано, что для защиты
используется такой-то алгоритм и этот алгоритм реализован только в биб-
лиотеках одного разработчика (как было долгое время с RSA из-за патент-
ных ограничений), останется совсем немного вариантов.
И, в-четвертых, почти в любой библиотеке есть присущие только ей тексто-
вые или двоичные строки, по которым эта библиотека может быть иденти-
фицирована. Так, например, при использовании библиотеки BSAFE в теле
программы может присутствовать строка "bsafe" или "bcert". Библиотека
SSLeay содержит строку "part of SSLeay", а библиотека RSAEURO — "Copy-
right (с) J.SA.Kapp".


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

22.3.1. Идентификация функций по шаблонам
Наличие доступа к библиотеке, применявшейся в программе, позволяет вы-
полнить автоматический поиск функций по шаблонам. Этот процесс состо-
ит из двух этапов.
254 Часть V. Заметки об исследовании средств защиты


На первом этапе для каждой библиотечной функции, имеющей имя, созда-
ется шаблон. Для этого анализируются первые несколько байт функции
и запоминаются значения тех байт, которые не будут изменяться редактором
связей во время сборки программы. Изменяемые байты (как правило, это
ссылки на данные и другие функции) в скомпилированной программе могут
принимать любое значение, и в шаблоне они помечаются специачьным
образом.
После того как созданы шаблоны для всех функций, можно приступать не-
посредственно к идентификации. Для этого необходимо попытаться "при-
ложить" шаблон каждой библиотечной функции к началу каждой функции
в исследуемой программе. При совпадении всех неизменяемых байт шабло-
на функция считается опознанной. Однако необходимо учитывать, что
несколько библиотечных функций могут иметь одинаковые шаблоны, как
и один шаблон может соответствовать нескольким функциям в программе.
В дизассемблере IDA и сопутствующем ему инструментарии разработчика
(Software Development Kit, SDK) реализованы средства, значительно облег-
чающие идентификацию функций. Для построения и удобного хранения
шаблонов библиотек используется набор утилит FLAIR (Fast Library Acquisi-
tion for Identification and Recognition, быстрая обработка библиотек для
идентификации и распознавания). Для распознавания функций применяет-
ся технология быстрой идентификации FLIRT (Fast Library Identification and
Recognition Technology).
В FLAIR и FLIRT применено несколько интересных решений, позволяю-
щих компактно хранить шаблоны и очень быстро оценивать соответствие
им функций. При этом процент нераспознанных функций и, что более важ-
но, процент неверно распознанных функций получаются очень низкими.
Предположительно, FLAIR и FLIRT основаны на работах Кристины Цифу-
ентес (Cristina Cifuentes) и Майкла Ван Еммерика (Michael Van Emmerik).


22.3.2. Константы в алгоритмах
Если не удалось установить, какая библиотека использовалась при компи-
ляции исследуемой программы, или нет возможности получить доступ
к этой библиотеке, можно попытаться идентифицировать криптографиче-
ские функции другим способом — по используемым константам.
Так, например, при инициализации многих хэш-функций (таких как MD4,
MD5, SHA-1, RIPEMD-160) используются константы 0x67452301,
0xEFCDAB89, 0x98BADCFE и 0x10325476. В SHA-1 и RIPEMD-I60 исполь-
зуется также значение 0xC3D2ElF0.
Глава 22. Реконструкция криптографических протоколов 255

В функции трансформации, используемой при вычислении SHA-1, приме-
няются константы 0х5А827999, 0x6ED9EBAl, 0x8FlBBCDC и 0xCA62ClD6.
3O
Эти константы являются представлением целой части чисел 2 xSqrt(2),
3O 30 30
2 xSqrt(3), 2 xSqrt(5) и 2 xSqrt(10), где Sqrt(jt) — функция извлечения
квадратного корня из х.
В функции трансформации RIPEMD-160 последняя константа вместо
3O
0хСАб2СШ6 имеет значение 0xA953FD4E, что соответствует 2 xSqrt(7).
Функция трансформации MD5 использует 64 константы, вычисляемые как
32
2 xAbs(Sin(/)), где i — номер раунда, от 1 до 64. Sin(jt) вычисляет синус ар-
гумента, заданного в радианах, a Abs(x) возвращает абсолютное значение х
(без знака). Так, например, константы для первых четырех раундов равны
0xD76AA478, 0xE8C7B756, 0x242070DB и OxClBDCEEE соответственно.
При вычислении хэш-функции MD2 используется таблица перестановок
(S-Box) размером 256 байт, начинающаяся с последовательности 0x29, 0х2Е,
0x43, 0хС9, 0хА2, 0xD8, 0x7C, 0x01.
При шифровании по алгоритму RC5 используются две константы Р и Q,
значения которых основаны на двоичном представлении чисел е и п. Для
версии RC5, работающей с 64-битовыми словами, эти константы имеют
значения 0xB7E151628AED2A6B и 0x9E3779B97F4A7C15.
В спецификации некоторых алгоритмов, например RC4, нет вообще ни од-
ной константы, позволяющей выполнять поиск (числа 256 и OxFF, исполь-
зуемые при загрузке ключа и при шифровании, применяются настолько
часто, что будут найдены и в сотнях посторонних функций). Однако если
в программе используется оптимизированная версия RC4, подходящая кон-
станта может быть найдена. Дело в том, что процедура загрузки ключа на-
чинается с того, что 256-байтовый массив заполняется последовательно чис-
лами от 0 до 255. Существует весьма эффективный способ выполнения
данного цикла:
lea edi,data
mov eax,03020100h
mov edx,04040404h
mov ecx,64
setNext:
stosd
add eax,edx
loop setNext
Как видно, использование оптимизации привело к появлению сразу двух кон-
стант, позволяющих выполнить идентификацию: 0x03020100 и 0x04040404.
256 Часть V. Заметки об исследовании средств защиты

Когда известно, какие константы присутствуют в том или ином алгоритме,
остается найти эти константы в теле исследуемой программы. Поиск можно
выполнять вручную или воспользоваться готовым инструментом, таким как
СС (Crypto Checker), созданный человеком с псевдонимом Aleph, или
KANAL (Krypto ANALyzer), разработанный группой uNPACKiNG gODS.
Crypto Checker 1.1 beta 7 умеет распознавать алгоритмы Blowfish, CAST-128,
CAST-256, HAVAL, MARS, MD4, MD5, RC5, RC6, Rijndael, RIPEMD-128,
RIPEMD-160, SHA-1, SHA-256, Tiger, Twofish, WAKE, а также некоторые
генераторы псевдослучайных чисел, функции вычисления CRC16 и CRC32
и более 3000 простых чисел.

22.3.3. Принцип локальности
Если удалось найти хотя бы одну из использованных криптографических
функций, обычно не очень сложно найти и все остальные. В этом очень
помогает несколько эвристик.
Согласно первой эвристике все функции, относящиеся к одной библиотеке,
редактор связей обычно располагает рядом. То есть, опознав один из крип-
тографических примитивов, имеет смысл внимательно изучить функции,
расположенные в непосредственной близости от него. С большой вероятно-
стью это будут фрагменты других криптографических примитивов.
Вторая эвристика использует тот факт, что очень часто отдельные стадии
алгоритма выполняются непосредственно друг за другом. То есть, например,
при вычислении значения хэша используются три функции. Первая функ-
ция (init) устанавливает начальное значение контекста. Вторая функция
(update) обрабатывает очередную порцию данных, от которых вычисляется
значение хэша и обновляется состояние контекста. Третья функция (Final)
завершает процедуру вычисления и возвращает итоговое значение. И в ре-
альной программе вызов функции m i t обычно находится в непосредствен-
ной близости от первого вызова функции update, а последний вызов
update — прямо перед вызовом Final. Следовательно, найдя любую из этих
функций, очень просто найти все остальные. На рис. 22.1 приведен пример
процедуры, вычисляющей хэш-значение по алгоритму MD5. Функции
MD5_Init И MD5_Update ЛеГКО ОПОЗНатЬ ПО КОНСТЭНТам, a MD5_Final МОЖНО
найти исходя из того, что она вызывается сразу после MD5_update.
Третья эвристика очень помогает, если криптографический примитив реа-
лизован как класс в объектно-ориентированном языке. При компиляции
класса создается таблица виртуальных функций (Virtual Function Table,
VTable), содержащая адреса всех функций, являющихся методами данного
класса. Следовательно, определив расположение одного из методов, можно
найти ссылку на него из таблицы виртуальных функций, а значит, отыскать
Глава 22. Реконструкция криптографических протоколов 257


и все остальные методы класса. На рис. 22.2 проиллюстрированы структуры
данных класса, предназначенного для вычисления значения хэш-функции.
Конкретный экземпляр класса вычисляет хэш-функцию MD5.

BY"ГЕ "calcMD5 (BYTE buf[16], Код MD5_lnit
BY!ГЕ «data, int ten) {
М D5_CTX ctx; 0x67452301
М D5_lnit (&ctx);
М D5_Update (&ctx, data, ten); 0x10325476
М D5_Final (buf, &ctx);
re urn buf; /


}
/


Код MD5_Update

<< Предыдущая

стр. 36
(из 39 стр.)

ОГЛАВЛЕНИЕ

Следующая >>