Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Практическая криптография алгоритмы и их программирование
.pdf
Глава 7. Прикладные задачи шифрования 221
Листинг 7.7
В таком случае данные зашифрованного файла по этому же смещению могут
выглядеть так же, как и в листинге 7.8 (авторы берут на себя смелость немного
свободно обращаться с шифротекстом, однако, как будет показано, это не меняет
ситуации в целом):
Листинг 7.8
Если теперь данные из зашифрованного файла сложим по модулю два (ведь по
правилу Керкхоффа нам известен способ сложения гаммы с открытым текстом) с
данными типового договора, то получим не что иное, как несколько байтов гаммы
(см. листинг 7.9). Точно так же мы поступали с текстом «Приветствую, мой ненаглядный сосед!», рассматривая способ подделывания подобных сообщений.
Листинг 7.9
Байты из типового договора по смещению 500h:
C420CE20C320CE20C220CE20D0202020 ДОГОВОР .
Складываем с байтами шифротекста договора по тому же смещению:
F2 A9 BC 9B 37 FD 49 C0 1E 89 20 EC 3A B9 F1 2E ªé+Û7¤I+-É ü:|¸.
И получаем байты гаммы:
36 89 72 BB F4 DD 87 E0 DC A9 EE CC EA 99 D1 0E ªé+Û7¤I+-É ü:|¸.
Теперь допустим, мы каким-либо образом узнали, что сделка была оформлена
на общую сумму $15000. Следовательно, эта сумма была проставлена в документе, зашифрованный вариант которого мы имеем.

222 Глава 7. Прикладные задачи шифрования
Посмотрим на документ — поле для ввода суммы сделки находится по смещению 562h (1378) в файле. Можно предположить, и это почти наверняка окажется
так, что и в зашифрованном файле по тому же смещению находится строка
«$15000».
42
Если злоумышленник
задастся целью подделать сумму сделки, он может в
этом преуспеть, сделав всего несколько простых вычислительных действий при
помощи средств модулярной арифметики.
Итак, следуя данному немного выше примеру и сделав предположение, что
сумма равна ни больше ни меньше $15000, сложим по модулю два байты строки в
зашифрованном тексте, начиная со смещения 562h (именно там находится сумма
договора), с байтами строки «$15000» — предполагаемой нами суммой. Результат отражен в листинге 7.10.
Листинг 7.10
7E DA 16 35 8F 86 6C 52 2D 8F F2 FB 2A C7 E9 85 ~+_5ÏÆlR-Ϫ_*|ùÅ
cкладываем с байтами строки "$15000":
24 31 35 30 30 30 $15000
И получаем байты гаммы:
32 04 BA B6 5C 62 2_||\b
Получив таким простым образом уже не просто несколько байтов гаммы, а
участок гаммы, где находится интересующая нас информация, мы можем зашифровать все, что нам заблагорассудится. В нашем случае это любая сумма договора. А затем мы можем поместить результат по выбранному смещению обратно в
зашифрованный файл и выслать его действительному получателю.
Уменьшим слегка сумму контракта, сложив байты шифротекста с байтами
строки «$00000» (см. листинг 7.12):
Листинг 7.11
cкладываем байты гаммы:
32 04 BA B6 5C 62 2_||\b
с байтами строки "$00000":
24 30 30 30 30 30 $00000
и снова получаем байты шифротекста:
16 34 8A 86 6C 52 .4ÊÆlR
В результате этих действий получаем почти тот же зашифрованный текст, но
теперь в контракте стоит совершенно другая сумма (см. листинг 7.12, рамочкой
обведены изменившиеся байты).
42
Авторы ни в коем случае не хотели бы ставить себя и тем более читателя на место зло
умышленника, но — «увы и ах!» — криптоаналитику всегда приходится это делать.
-

Глава 7. Прикладные задачи шифрования 223
Листинг 7.12
Таким образом, для выбранного специалистами фирмы «Рога и Копыта» способа шифрования (то есть однократного шифрования равновероятной гаммой) существуют вполне приемлемые условия, при которых может быть использован по
крайней мере один способ подделки сообщений. А это уже весьма ощутимый результат, который может оказаться «последней ошибкой».
Аналогичным и еще более простым с точки зрения криптоанализа примером
является шифрование методом однократного гаммирования электронных почтовых сообщений.
Сообщения электронной почты в сети Интернет передаются (как и многие
другие данные простых сетевых протоколов прикладного уровня) в текстовом
виде, приемлемом для анализа невооруженным взглядом. В листинге 7.13 представлен пример почтового сообщения в том виде, в котором оно путешествует в
сети от компьютера к компьютеру. А листинг 7.14 содержит то же самое сообщение, но так, как его видит рядовой пользователь.
Листинг 7.13
From POPmail Tue Nov 17 18:45:15 1998
(with Netcom Interactive pop3d (v1.21.1 1998/05/07) Wed Nov 18 02:39:15 1998)
X-From_: seg@crow.sec.gov Tue Nov 17 20:36:28 1998
Received: from crow.sec.gov (crow.sec.gov [204.192.28.11]) by
multi33.netcomi.com (8.8.5/8.7.4) with ESMTP id UAA32707 for <fc@all.net>;
Tue, 17 Nov 1998 20:36:28 -0600
Received: (from seg@localhost) by crow.sec.gov id VAA01882 for fc@all.net;
Tue, 17 Nov 1998 21:37:15 -0500
From: Joe Segreti <seg@crow.sec.gov>
Message-Id: <199811180237.VAA01882@crow.sec.gov>
Subject: Ответ на пpедложение
To: fc@all.net
Date: Tue, 17 Nov 1998 21:37:14 -0500 (EST)
X-Mailer: ELM [version 2.4 PL25 PGP7]
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
Добpого вpемени суток!
Уважаемые коллеги, пpедлагаем вам следующую фоpму сотpудничества.
...

224 Глава 7. Прикладные задачи шифрования
Листинг 7.14
Date: Tue, 17 Nov 1998 21:37:14 -0500 (EST)
From: Joe Segreti <seg@crow.sec.gov>
To: fc@all.net
Subject: Ответ на пpедложение
Добpого вpемени суток!
Уважаемые коллеги, пpедлагаем вам следующую фоpму сотpудничества.
...
И в том и в другом случае в сообщении остается много служебных слов, которые используются почтовым программным обеспечением для доставки сообщения
адресату. Например, ключевое слово Date: и следующая за ним дата отсылки письма является обязательным атрибутом любого письма. И точно так же, как подвергся анализу текстовый файл формата MSWord, мы можем подвергнуть пристальному изучению это электронное сообщение, подставив, к примеру, другую дату
43
отсылки письма или изменив приветствие и подпись
.
Собственно говоря, все приведенные примеры и недостатки и есть ответ на
вопрос, почему почти никто не пользуется методом однократного гаммирования — все зависит от того, как именно это делается и какими ресурсами обладает
пользователь шифросистемы.
Криптографическая защита исходных текстов
Время реакции на весьма динамично развивающуюся среду веб-технологий
определяет эффективность работы любого Интернет-сайта. Современные технологии создания веб-контента в режиме реального времени дали профессиональному веб-мастеру мощнейшие инструменты для управления потоками информации в
Интернет. В условиях постоянного роста производительности использование языков сценариев или, как их еще называют, scripting languages или scripts стало одним из опорных решений фундаментального подхода организации инфраструктуры Интернет-сайтов. Мощные, легко осваиваемые специализированные языки
программирования, ориентированные на разработчиков веб-сайтов, получили широчайшее распространение. Языки сценариев изначально были ориентированы на
быстрое и эффективное решение иных задач, нежели языки программирования
системного уровня, поскольку они создавались как логически связующие компоненты к уже готовым программным решениям. Преимущества такого подхода перед традиционным статическим наполнением веб-порталов видны невооруженным взглядом. Это и гибкость построения гипертекстовых переходов, и возможность создания отчетов по записям в базах данных в реальном времени, и
генерация комплексных веб-документов из существующих элементарных компонентов.
43
Чтобы узнать приветствие и подпись другого человека, иногда бывает достаточно просто
написать ему письмо так, как будто бы вы ошиблись адресом. Ответ от него с сообщением об
этом будет наверняка содержать всю необходимую информацию.

Глава 7. Прикладные задачи шифрования 225
Точно так же, как и несколько лет назад в малых интегрированных сетях, в
программировании контента публичных серверов существует два подхода.
А именно создание интерпретируемых сценариев и компиляция байт-кода. Первый подход не выходит за рамки CGI-программирования, согласно которому для
разработки гипертекстовой страницы нужен только обычный текстовый редактор,
а сам гипертекстовый документ должен легко читаться человеком. Второй подход
повышает эффективность исполнения программы, а также защищенность кода от
доступа и несанкционированных изменений.
Реализации интерпретаторов таких языков сценариев, как Perl и Phyton, в целях повышения эффективности перед исполнением сценария проводят предварительную перекомпиляцию в специальный мобильный байт-код. Для обозначения
байт-кода существует даже собственное название — пи-код (p-code). Такое название байт-коду было дано одним из создателей «псевдомашины» (p-system) — операционной системы для микроконтроллеров (и, например, машин CP/M), которая разрабатывалась в 1977 году и работала как эмулирующий интерпретатор
языка UCSD Pascal. Автор UCSD Паскаля — Урс Арманн (Urs Armann) вместе с
профессором Кеннетом Боулсом (Kenneth Bowles) и дали название коду, в который компилировались исходные тексты.
Такой код, будучи сформирован в результате трансляции исходного текста
сценария, записывается в память или файл и лишь потом обрабатывается интерпретатором. Для языка Python файлы с байт-кодом (они имеют специальное расширение *.pyc) в дальнейшем можно спокойно переносить с платформы на платформу и исполнять с равными правами как, к примеру, на Sun, так и на Intel
PC/win32 — мобильность пи-кода это позволяет.
В конце 90-х годов прошлого столетия CGI-программирование — а это автоматизация, гостевые книги, форумы, опросы, списки рассылки, интерфейсы к базам данных и многое другое — стало наиболее популярным и эффективным способом организации интерактивного взаимодействия с пользователями. Как и в
любой другой области программирования, стали возникать свои вопросы и проблемы.
Одними из самых интересных и неоднозначных вопросов были и остаются вопросы о защите программных кодов и исходных текстов от несанкционированной
модификации и копирования. Актуальность стоящих проблем защиты программного обеспечения очевидна хотя бы потому, что все сценарные языки, такие, как
Perl, Phyton, JavaScript и всевозможные производные с постфиксом *script (то
есть VBScript, PerlScript и т. д.), являются интерпретируемыми, и ни о каких бинарных кодах и скрытом исходном тексте не может идти и речи.
В этом случае исследованию алгоритма работы сценария и использованию
его без разрешения авторов не создано никаких препятствий. Программисты, создающие средства веб-автоматизации, пытаются решить эту проблему всевозможными способами, прибегая порой к изощренным методикам сокрытия исходных
текстов и защиты их от модификации. Собственно говоря, защита от модификации хороша также и как защита, что называется, «от дурака», что немаловажно
при продаже программного обеспечения не в комплексе, а как отдельной единицы, когда приобретающий программное обеспечение пользователь получает пол
-

226 Глава 7. Прикладные задачи шифрования
ный доступ не только к конфигурационным файлам, но и к пакету самих сценариев. И при отсутствии у него должной квалификации внесенные в сценарий изменения могут существенно повлиять на отказоустойчивость и работоспособность
всего комплекса. Кроме того, как показывает практика обеспечения информационной безопасности в открытых системах, программное обеспечение веб-серверов
зачастую столь несовершенно, что при достаточной сноровке злоумышленник
вполне способен получить исходный текст сценариев веб-сервера (классическим
примером может послужить инцидент с веб-сервером WebTrends, который позволял получить исходный текст сценариев, просто добавив пробел к его имени в
строке запроса. Òàê, запрос ïî адресу «http://somewhere.in.the.inter-
net.com/cgi-bin/script.pl» запускал script.pl на исполнение, а запрос к
«http://somewhere.in.the.internet.com/cgi-bin/script.pl%20» выдавал исход-
ный текст сценария любому неавторизованному пользователю.
На сегодняшний день существует несколько способов защитить исходные
тексты программных модулей для интерпретаторов от модификации и даже совсем скрыть их от глаз пользователя. Рассмотрим их на примере одного из самых
популярных в сети Интернет (то есть по всему миру) языка сценариев Perl.
Одним из вариантов сокрытия исходных текстов является возможность «компилирования» исходных текстов в исполняемый бинарный код (формат PE-exe
для win32 платформ и ELF для Linux/BSD). Для этого исходный текст может
быть скрыт внутри исполнимого файла (например, сжат с помощью алгоритма
криптографического сжатия). Сам исполнимый файл в этом случае представляет
собой пригодный для исполнения файл, содержащий полную реализацию функций интерпретатора программного языка, на котором написан исходный текст защищаемого скрипта. После начала исполнения исполнимый файл разархивирует
исходный текст скрипта и исполняет его с помощью встроенного интерпретатора.
В случае с Perl для этого используется технология «Perl Embedded in C», разработанная Ларри Уоллом, инструментарий для которой распространяется вместе с интерпретаторами языка сценариев Perl бесплатно.
В начале апреля 2002 года среди писем, распространяемых в популярной рассылке BugTraq, посвященной информационной безопасности и, в частности, выявлению фактов уязвимости программного обеспечения, можно было встретить
письма о безопасности предлагаемого разработчиками IndigoStar Software распространения исходных текстов сценариев в виде бинарных файлов. Данное программное обеспечение (утилита Perl2Exe, распространяемая в виде shareware software, то есть за деньги) реализует описанную выше функциональность.
Несмотря на то что авторы утилиты Perl2Exe не предоставляют ее исходных
текстов, оказалось возможным, исследовав ее программный код, найти инженерный пароль и способ зашифрования исходных текстов. Более того, это оказалось
возможно делать в совершенно автоматическом режиме, без участия человека-оператора. Говорить о криптографической стойкости примененного метода
бессмысленно, поскольку ключ к шифру находится в исполнимом файле рядом с
самим шифром.
Таким образом, чтобы извлечь исходный текст из бинарного файла, достаточно запустить на исполнение специальную утилиту, совершающую обратное пре
-

Глава 7. Прикладные задачи шифрования 227
образование Exe2Perl. Автором одной из таких утилит, с легкостью позволяющей
«доставать» исходные тексты, является Четан Ганатра (Chetan Ganatra, ganatras@infotech.icici.com).
Следующим способом сокрытия исходных текстов и их защиты от несанкционированной модификации можно указать встроенные средства языка Perl. Это так
называемые фильтры исходных текстов или source filters.
Необходимость создания механизма подобных фильтров была продиктована
именно соображениями защиты исходных текстов сценариев. Защищенный сценарий может выглядеть следующим образом:
#!/bin/perl
use DecipherModule;
@*x$]'0uN&k^Zx02jZ^X{.?s!(f;9Q/^A^@~~8H]|,%@^P:q-=
jkhsdk$*#@&((#$Y%@ #EDUF(HFU#@H(@#(F(@#CDLnclser#@
sd0U3R0FR32 239RUW0EFR&y^3843#q*%&^#$##@ ERFSDHFF=
#&^*&$e(*#qyr(#@yrHFhwp4y$@#83yhFwhEhfishfjlq247@$
...
Фильтры исходных текстов в частном случае позволяют зашифровать и/или
заархивировать часть основного тела сценария так, что сначала будет загружен
специальный модуль, который будет расшифровывать остальную часть сценария
построчно.
Конечно, преимущества такого подхода, возможно, не очевидны на первый
взгляд. Для этого необходимо чуть более детально разобраться в достаточно универсальном механизме фильтров исходных текстов. На первый взгляд этот весьма
специфичный инструмент несет в себе возможности и разработки нескольких последних лет в смежных областях программирования и защиты программного
обеспечения. Многие технологии защиты программного обеспечения от несанкционированного копирования и использования могут быть с легкостью перенесены на «почву» фильтров исходных текстов и использованы для веб-сценариев.
И здесь точно так же, как и на платформах с win32, существуют те же проблемы
и методы обхода защитных барьеров.
Самым уязвимым в смысле защиты от исследования сценария является модуль расшифрования основного тела исходного текста. Он может быть написан на
самом языке Perl, но тогда достаточно будет исследовать его, что является в общем-то тривиальной задачей, поскольку он не может быть зашифрован. Кроме
этого, если алгоритм зашифрования достаточно сложен, расшифровка всего исходного текста может занять долгое время, что неизбежно скажется на эффективности функционирования веб-узла, а это нежелательно ни при каких обстоятельствах. Очевидно, что в этом случае применять шифрование может быть не очень
удачным решением. Однако в качестве расшифровывающего модуля можно использовать своего рода плагин (plugin), то есть специальную подключаемую библиотеку, написанную на любом другом языке и откомпилированную как разделяемый
модуль (shared library).
Используя специальный набор функций Perl API, данный модуль расшифрует
исходный текст гораздо быстрее, чем если бы он сам был написан на языке Perl.
Кроме того, такой подход позволяет на полную мощность использовать средства

228 Глава 7. Прикладные задачи шифрования
усложнения анализа программного кода, включая такие известные приемы, как
применение самомодифицирующегося кода, шифрование/расшифрование «на
лету», во время исполнения процедур модуля.
Чтобы не давать голословных утверждений, попробуем реализовать подобное
программное обеспечение. В качестве алгоритма шифрования мы можем использовать один из уже реализованных в предыдущих главах алгоритмов. Попробуем
остановиться на алгоритме RC4. Для его использования нам понадобится простая
программа, которая будет зашифровывать любые наши данные с помощью RC4 и
заданного нами ключа (см. листинг 7.15).
Листинг 7.15
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>
#include "hexdump.h"
#include "rc4.h"
#define RC4_KEYSIZE 32
void prepare_pass(uchar *pass) {
srandom(time(NULL));
memset(pass, 0, sizeof(pass));
for(inti=0;i<RC4_KEYSIZE; i++) pass[i] = random()+i*i;
for(inti=0;i<sizeof(pass); i++) pass[i] ^= pass[sizeof(pass) - i];
}
void main(int argc, char *argv[]) {
FILE *f, *f_ec;
RC4_KEY key;
char buf[1024];
uchar pass[RC4_KEYSIZE];
int read;
printf("Scripher RC4-Encoder\n[c] Roman A. Hady, Specvuzautomatika\n\n");
if (argc == 1 || argc > 2) {
printf("Usage: encoder file_to_encode\n\n");
exit(1);
}
prepare_pass(pass);
strcpy(buf, argv[1]);
strcat(buf, ".pass");
f = fopen(buf, "wb");
if (!f) {
printf("Can't open %s for write\n", buf);
exit(2);
}
fwrite(pass, sizeof(pass), 1, f);
fclose(f);
setup_rc4_key(&key, pass, sizeof(pass));

Глава 7. Прикладные задачи шифрования 229
f = fopen(argv[1], "rb");
if (!f) {
printf("Can't open %s for read\n", argv[1]);
exit(2);
}
strcpy(buf, argv[1]);
strcat(buf, ".coded");
f_ec = fopen(buf, "wb");
if (!f) {
printf("Can't open %s for read\n", buf);
exit(2);
}
do {
read = fread(buf, 1, sizeof(buf), f);
if (read <= 0) break;
hexdump((uchar *) buf, read, 16, NULL);
encode_rc4((uchar *) buf, read, &key);
hexdump((uchar *) buf, read, 16, NULL);
fwrite(buf, 1, read, f_ec);
} while (1);
fclose(f);
fclose(f_ec);
printf("\nOK. Job done.\n");
}
Программа из листинга 7.15 работает с несколькими файлами: на вход ей подается имя файла, который необходимо зашифровать. При этом программе понадобится файл с таким же именем, но с дополнительным расширением *.pass, который будет содержать сгенерированный программой случайным образом пароль
шифрования. Именно этим паролем и будет зашифрован исходный файл данных.
Файл данных в нашем случае будет не чем иным, как исходным текстом скрипта,
который нужно защитить от модификации и просмотра пользователем.
Для работы с этим зашифрованным файлом нам понадобится специальный
механизм обработки зашифрованных данных и их интерпретации с помощью интерпретатора языка Perl.
Все это мы можем осуществить с помощью механизма Perl source filters. Для
этого мы должны создать специальный программный модуль в системе интерпретатора языка Perl, который взял бы на себя функции обработки зашифрованного
текста. Авторы дали название данной системе Scripher как производное от script
è cipher.
Более того, нам необходимо написать этот модуль не на Perl'е, а на другом —
компилируемом в бинарный код языке (например, Си), который предоставит дополнительный уровень защиты, и каким-то образом реализовать его сопряжение с
системой интерпретатора.
На самом деле это не очень сложно. Для этого понадобится интерфейсный
модуль scripher.pm, написанный на Perl (см. листинг 7.16) и модуль обработки
данных, написанный на Си, но оформленный в специальном формате XS.

230 Глава 7. Прикладные задачи шифрования
Листинг 7.16
package scripher;
require DynaLoader;
@ISA = qw(DynaLoader);
$VERSION = "0.0.1";
bootstrap scripher $VERSION;
1;
__END__
А сам модуль, оформленный по форме XS, выглядит следующим образом (см.
листинг 7.17). На самом деле это обычный файл исходного текста на языке Си, но
содержащий дополнительную информацию для динамической линковки и связи с
интерпретатором Perl.
Листинг 7.16
/*
* Filename : scripher.xs
*
* Author : A.V. Agranovsky & R.A. Hady
* Date : 25.04.2001
* Version : 1.0.1
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifdef __cplusplus
}
#endif
, размер ключа для RC4
#define RC4_KEYSIZE 32
#define HEADER_SIZE (4+4+4+RC4_KEYSIZE)
, SEGMENT_SIZE must be greater than HEADER_SIZE
#define SEGMENT_SIZE (((HEADER_SIZE + 16) / 16) * 16)
, check for correct ID and cipher version stamp
#define RIGHT_ID 0xDEADFACE
#define RC4_CIPHER 0xC4C4C401
#define uchar unsigned char
#define decode_rc4 encode_rc4
, заголовок - первые несколько байтов зашифрованных данных
typedef struct SCR_HEAD_t {
long ID;
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
