Восстановление паролей к хэшам

SAMInside
Скачать v2.6.3.0
Купить лицензию
Архив обновлен: 11.10.2008

PasswordsPro
Скачать v2.4.4.1
Купить лицензию
Архив обновлен: 17.11.2008


23.10.2008
Вышла EGB v1.4
Обсудить (комментариев: 44)

11.10.2008
Вышла PasswordsPro v2.4.4.1
Обсудить (комментариев: 7)

28.09.2008
Вышла EGB v1.3
Обсудить (комментариев: 16)

Словари
Файлов: 72

Библиотека
Документов: 309

Генератор хэшей
Алгоритмов: 104

Новости интернета
RSS-лент: 11

Подписка на новости
Подписчиков: 795

Дополнительные сервисы

Всего запросов: 15367126
Всего посещений: 2593514
Посетителей сегодня: 1581
Форум
Сообщений: 12634
Последнее: 02.12.2008, 14:55
  База хэшей
Найдено паролей: 806076
Всего хэшей в базе: 27173283
 

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

Автор: (c)Крис Касперски

О чем эта книга

... В моем уме не оставалось места для беспокойства об успехе или
провале книги. Было лишь желание работать над ее созданием.
Ф. Херберт. "Еретики Дюны"

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

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

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

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

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

Я даже не буду пытаться научить читателей "ловить рыбу", а рискну пойти немного дальше и дать навыки самообучения. Из любой самой нестандартной ситуации и при самом скудном инструментарии всегда можно найти выход. Типовые схемы часто оказываются бессильными и бесполезными. Любые навыки слишком привязаны к конкретному окружению. В наше время больших перемен уже поздно хвататься за традиционные схемы обучения. На обучение просто нет времени. Большинству программистов приходится осваивать новые технологии "на ходу" и задолго до конца обучения они уже полностью устаревают.

Возьмем популярную платформу Windows, находящуюся в состоянии бурного развития. Разве можно сопоставить его с вялым развитием компьютерных систем только десятилетней давности? Объем электронной документации для сегодняшней платформы Win32 (MSDN) перевалил за отметку одного гигабайта и стремительно продолжает расти!

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

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

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

Цель этой книги - научить читателя самостоятельно добывать необходимые ему знания и навыки, порой не имея соответствующей литературы и информации. Современное информационное изобилие приводит к атрофированию навыка самостоятельного получения необходимых знаний. Парадоксально на первый взгляд, но недостаток литературы развивает и тренирует мозги куда лучше, чем ее избыток. Сам я осваивал ассемблер 8086 с помощью утилиты debug.com: кроме нее (и свободного времени) у меня в ту пору не было НИЧЕГО. Логика работы команд изучалась анализом воздействия последних на регистры и память. Эта было утомительное занятие, и свободное владение ассемблером (без учета ряда некритичных команд) ко мне пришло приблизительно через три месяца. Наличие инструкции сократило бы этот срок до двух-трех дней (с учетом знания ассемблера других платформ), но зато не дало бы никаких полезных навыков.

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

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

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

История хакерства

Попытка понять Муаддиба, не поняв его смертельных врагов, - это
попытка увидеть правду без знания лжи. Это попытка понять, что
такое свет, не зная, что такое тьма. Это просто невозможно.
Принцесса Ирулэн, Руководство Муаддиба

"I remember the good old days, when computers were mainframes,
analysts were magicians,and programmers punced cards..."
Philip Fites, Peter Johnston, Martin Kratz "Computer viruses crysis".

1. Рассвет. Первые лучи

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

На протяжении всей истории человечества всегда находились люди, которые выходили за рамки господствующих установок и традиций, создавая свою философию и субкультуру. По иронии судьбы, хакерство оказалось тесно сплетенным с криминалом. Так было во все века, так и будет до самого последнего вздоха человечества. Почему? Хакер стремится разобраться во всем до конца, понять все до мельчайших подробностей, выйти за область определения объекта, проанализировать и испытать его поведение во всех нештатных ситуациях. От "простого смертного" хакера прежде всего отличает исчерпывающее знание предмета. Абсолютное знание по умолчанию подразумевает абсолютную власть над системой. Очень трудно устоять перед искушением и открывающимися перспективами.

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

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

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

Я понимаю, что данная трактовка является моим субъективным мнением и может встретить возражения. И тут мы приходим к обычной лингвистической проблеме. В самом деле, любой термин может менять свое узкое "словарное" значение в ходе развития языка.

Обратимся к лучшему на сегодняшний день исследованию хакерской культуры, словарю Жаргона Э.С. Рэймонда (заметим, что моя трактовка никак не противоречит традиционной, но лишь расширяет ее):

":hacker: [originally, someone who makes furniture with an axe] n. 1. A person who enjoys exploring the details of programmable systems and how to stretch their capabilities, as opposed to most users, who prefer to learn only the minimum necessary. 2. One who programs enthusiastically (even obsessively) or who enjoys programming rather than just theorizing about programming. 3. A person capable of appreciating {hack value}. 4. A person who is good at programming quickly. 5. An expert at a particular program, or one who frequently does work using it or on it; as in `a UNIX hacker'. (Definitions 1 through 5 are correlated, and people who fit them congregate.) 6. An expert or enthusiast of any kind. One might be an astronomy hacker, for example. 7. One who enjoys the intellectual challenge of creatively overcoming or circumventing limitations. 8. [deprecated] A malicious meddler who tries to discover sensitive information by poking around. Hence `password hacker', `network hacker'. The correct term is {cracker}."

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

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

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

Документированная история американского хакерства берет начало от все того же Словаря Жаргона Рэймонда.

2. Лаборатория искусственного интеллекта в США и PDP-1

"Нет четкой грани между богами и людьми: одни переходят в других".
Ф.Херберт "Мессия Дюны".

Персонал, обслуживавший правительственные компьютеры, относился к работе серьезно и машинное время жестко протоколировалось, поэтому хакерство в то время было настолько экзотической редкостью, что не оставило заметного следа в истории. Нам остается только гадать, а существовали ли в самом деле хакеры во времена машин масштаба ЭНИАКа? Будем надеяться. Достоверно известно лишь то, что уже тогда сотрудников частенько увольняли за отклонение от технологических режимов работы аппаратуры. Было ли это следствием халатности или попытки получить от машины больше, чем предусмотрел ее создатель, уже нельзя установить.

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

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

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

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

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

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

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

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

Но и на этом фоне заметно выделялась лаборатория искусственного интеллекта MIT (Массачусетский технологический институт Massachusets Institute of Technology), в которой работали сливки компьютерной общественности. Со временем эти люди, разъедутся по другим городам и займутся другой работой, распространяя повсюду свой жаргон и стиль жизни. Но об этом расскажем несколько позже.

Вторым центром хакерства в Америке был Корнеллский университет, расположенный в штате Нью-Йорк. Лояльное отношение к студентам и предоставление "ночного машинного времени" способствовало развитию интереса к вычислительной технике и формированию хакерских традиций. Это поколение навсегда оставило след в истории "звездными войнами", открыв тем самым возможности компьютера как игровой платформы. Первые образцы ANSI-искусства были созданы именно Корнелловскими студентами. И хотя сегодня уже трудно установить, кто первым применил символьный терминал для передачи графического образа, этот человек несомненно был хакером. Способность заставить систему делать то, чего никак не ожидал ее разработчик, поистине заслуживает восхищения. В СССР же картины, созданные на принтерах типа "Ромашка", появились гораздо позже и явно были копиями западных.

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

Последнее явление вообще стало национальной чертой русского андерграунда. Отсутствие клубов и разобщенность людей не способствовали развитию собственной субкультуры.

Центрами возникновения отечественных хакеров стали не нищие ВУЗы, а производственные предприятия и НИИ. Не секрет, что в то время в журналы загрузки машинного времени часто писали "липу", а рабочее время использовали для удовлетворения собственного любопытства.

Но вернемся в подвалы лаборатории MIT. Трудно сказать почему именно здесь сложились благоприятные условия и хакеры росли как на дрожжах. Еще труднее сказать, что заставляло многих людей проводить ночи напролет, отказывая себе во всем, возле грохочущих телетайпов, клацающих реле и перемигивающихся огоньков. Психологи пока не ответили на вопрос, почему одни открывают в компьютере свою Вселенную, а другие не в состоянии увидеть в нем ничего, кроме груды металла, кремния и пластика?

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

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

По непроверенным данным, первый PDP-1 был создан именно в MIT. Если это верно, то не приходится удивляться, что именно тут сформировалась особая субкультура людей, которые были настоящими волшебниками больших машин. Язык определяет стиль мышления, поэтому мышление программиста постепенно преображается под воздействием используемой архитектуры в образ мышления ее создателя. Это настолько очевидно, что никто из психологов в этом не сомневается.

Немного утрируя можно сказать, что возникновением хакерства - такого, каким мы его знали в 60-х годах, - мы целиком и полностью обязаны человеку-легенде Кену Оулсену (Ken Olsen), основателю компании DEC и ведущему разработчику аппаратного обеспечения. Без сомнения, он был хакером и его образ мышления невольно копировали все пользователи его детища в течение двух десятков лет. Действительно, нужны чертовски нетривиальные мозги, чтобы создать компьютер, который стоил всего 120.000 $, тогда как майнфреймы IBM обходились в миллионы. Конечно, майнфреймы IBM заведомо превосходили PDP, но последняя имела неповторимую архитектуру, сохранившую привлекательность и до сих пор. Даже в наше время суперпроцессоров Pentium PRO немало людей с упоением программируют на ассемблере PDP, используя эмулятор или даже сохранившееся аппаратное обеспечение.

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

Именно в PDP нашли свой рай компьютерные гуру. Ее успех способствовал росту поставок DEC, расширению фирмы, а вместе с ним - возникновению полноводного хакерского течения в лабораториях крупнейших университетов.

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

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

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

Но ростки, пущенные PDP-1, живы и по сей день.

3. Сеть

Ива сгибается под ветром, пока не разрастется и
не встанет стеной на его пути. В этом ее предназначение.
Ф. Херберт. "Дюна".

До конца шестидесятых годов хакеров можно было сопоставить с античными Мастерами. Хак ассоциировался с высшим профессионализмом и вытекающей из него культурой поведения. Тесная связь культурного и интеллектуального уровней давно отмечалась психологами. Из этого правила, конечно, бывают исключения, но они редки и не меняют общей картины. А картина до конца шестидесятых годов была следующая - в условиях полной замкнутости и отсутствия какой-либо связи между компьютерными центрами страны каждый программист должен был получить необходимые ему знания САМ. Это был долгий и тернистый путь. Информатика тогда лишь зарождалась и даже эффективные алгоритмы и приемы еще не были канонизированы и широко известны. Как бы ни был очевиден древовидный поиск или линейная сортировка, но до них нужно было додуматься самому и - увы, далеко не один раз. Как следствие, все алгоритмы десятки раз открывались заново, прежде чем информация о них успевала дойти до адресатов "естественным" путем - через книги и университеты.

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

В лексиконе тогдашних хакеров еще не появилось оскорбительное слово "ламер". Не то чтобы среди них не было таковых, но программисты в то время намного лояльнее относились к непрофессионалам. Да и как бы можно было расценить такие оскорбления в тесных коллективах?

Сегодня, на фоне развитых сетевых коммуникаций, когда собеседники едва ли имеют шанс встретиться лицом к лицу в реальной жизни, ситуация кардинально изменилась. Электронное общение принесло вместе с неоспоримыми благами немало проблем, с которыми вынуждены сталкиваться сегодняшние хакеры. Первый камень этого здания был заложен в 1969 году. Тогда по инициативе Управления перспективных исследований Министерства Обороны США - Defense Advanced Research Projects Agency - создается первая вычислительная сеть, получившая название Advanced Research Projects Agency NETwork - ARPAnet.

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

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

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

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

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

Прежняя монолитность компьютерного сообщества рухнула. Теперь далеко не каждый человек, сидевший за терминалом, был программистом. Все чаще и чаще он оказывался, выражаясь сегодняшней терминологией, юзером. Успех ARPAnet и совершенствование компьютерных технологий вели к тому, что ЭВМ превращалась в предмет массового спроса и потребления.

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

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

Ярким примером могут служить первые прототипы будущих вирусов программы-кролики. Не причиняя разрушений, они, тем не менее, были сконструированы так, что, многократно копируя себя, захватывали большую часть ресурсов системы, отнимая процессорное время у других процессоров. История их создания доподлинно неизвестна. Возможно, они явились следствием программной ошибки, которая приводила к зацикливанию и наделяла программу репродуктивными свойствами. Первоначально кролики (rabbits) встречались только на локальных машинах, но с появлением Сети быстро "научились" размножаться по последней. В конце шестидесятых годов была обнаружена саморазмножающаяся по сети APRAnet программа, известная сегодня как CREEPER (вьюнок), которая будто бы была написана Бобом Томасом (Bob Thomas). Вьюнок проявлял себя текстовым сообщением

"I'M THE CREEPER ... CATCH ME IF YOU CAN" ("Я КРИПЕР ... ПОЙМАЙ МЕНЯ, ЕСЛИ СМОЖЕШЬ")

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

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

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

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

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

4. Си и UNIX

Легкие мои вдыхают ветер времени. Дующий над мертвыми песками...
Ф.Херберт "Дюна".

В 1969 г. усилиями двух талантливых программистов была создана система, сформировавшая не одно поколение хакеров и заложившая основы современных операционных систем. Я говорю о UNIX, разработанной К.Томпсоном и Д.Ричи, ведущими инженерами Bell Laboratories - подразделения American Telephone & Telegraph (AT&T). UNIX была первой системой, написанной на компилируемом языке. Так и хочется закончить - языке высокого уровня. Но уникальность Си и заключалась как раз в том, что он не походил на существующие в то время гипнотические и алгоритмические языки. Си сочетая в себе возможности низкоуровневого доступа, "отвязанные" от конкретной реализации, больше походил на крос-платформенный ассемблер. Такая идеология языка позволила создавать эффективные компиляторы и получить быстродействующий и компактный код.

Си завоевал сердца многих хакеров своей лаконичностью, краткостью, красотой и гибкостью выражения инженерной мысли.

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

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

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

Система не только вобрала в себя лучшие по тем временам многопользовательские решения, но была невероятно устойчива в работе и неплохо защищена. Разграничение затрагивало не только пользовательские, но и системные ресурсы. Именно UNIX послужила тем барьером, который приостановил попытки вбрасывания Кроликов в сеть. На несколько лет компьютерный мир вновь обрел устойчивость.

Успех системы позволил AT&T значительно усилить свои позиции на рынке. UNIX, в противоположность системе Windows 90-х годов, не только был удачной платформой, но и дружелюбной к профессионалу средой, развивающей абстрактное мышление, способствующей умственному и, в конечном счете, культурному развитию.

5. Конец хакеров шестидесятых

"Я не должна бояться. Страх убивает разум. Страх - малая смерть,
которая приносит полное уничтожение. Я смотрю в лицо моему страху..."
Ф. Херберт "Дюна".

Шагнем на пару лет вперед. Это были годы непрерывного совершенствования технологий программирования и аппаратного обеспечения. Росла вычислительная мощь ЭВМ, емкость периферийных накопителей и быстродействие центрального процессора. Собственно говоря, в то время все упиралось скорее в деньги, чем в технологии. Если клиент хотел решать с помощью компьютера серьезные задачи, то получение необходимой машинной мощности зависело только от его кошелька. Производители компьютеров заметно обгоняли в те годы потребности клиентов.

И необходимость в высокопрофессиональных программистах и тщательно оптимизированном коде мало-помалу начала отпадать. Ярким подтверждением тому была UNIX, полностью написанная на компилируемом языке. Могли ли программисты представить такое расточительство хотя бы пару лет назад? Си стал первым кирпичом в фундаменте быстрых средств проектирования, на котором сегодня построены такие чисто визуальные системы как Visual Basic и Delphi.

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

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

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

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

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

Коммерция и жажда наживы поглощала все. Главным критерием становилась скорость написания продукта, какого бы он ни был качества. Любые недостатки и ошибки программного обеспечения не обнаруживаются сразу и всегда есть время их устранить... потом, когда клиент, поверивший рекламе, вложит деньги в ваш товар и приобретет его. Кто первым выбрасывает на рынок продукт, тот и захватывает его. Таков закон. Собственно под "сопровождением ПО" почти любая фирма понимала его доработку и доведение из сырого состояния в некоторое подобие законченного продукта.

Быть может, я сгущаю краски? Каждый имеет право на свою точку зрения и видение ситуации. Нужно быть большим оптимистом, чтобы увидеть хоть что-то хорошее в этой конкурентной борьбе и спекуляции старыми идеями и технологиями, которая просто вышвырнула многих специалистов на обочину дороги. "Крутой поворот", как любит выражаться Билл Гейтс, на этот раз и вправду оказался настолько крутым и непредвиденным, что никто не успел к нему как следует подготовиться.

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

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

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

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

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

Хакеры шестидесятых вырождались. Не было больше "больших" машин и открытого духа свободного общения. С каждым днем все больше и больше находок и неординарных решений окутывались мраком коммерческой тайны и тщательно охранялись фирмой от окружающих.

Красивые решения уже никому не были нужны и никого не интересовали. Возможность компьютеров того времени была уже достаточна, чтобы "небрежно" написанный код удовлетворял заказчика по всем параметрам (скорости, объему). "Железо" дешевело куда быстрее программного обеспечения. Легче было купить вчетверо более мощный компьютер для небрежно написанной дешевой программы, чем приобретать для дешевой машины оптимизированный до последнего байта код, стоимость которого в этом случае была бы просто астрономической. Так, к примеру, средняя стоимость UNIX в семидесятых годах составляла шесть - семь тысяч долларов и была доступна далеко не всем желающим.

6. RSX-11M

Подсмотреть будущее - значит украсть мистический огонь от священного костра.
Ф. Херберт "Дюна".

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

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

Однако, "свято место пусто не бывает" и "природа не терпит пустоты". А вот в отношении операционных систем для PDP-11 появился заметный вакуум. UNIX требовала на несколько порядков больше мощности и попросту не могла работать на компьютерах такого класса. 32 килобайт памяти было недостаточно, чтобы разместить такого монстра.

И в 71 году компания DEC решилась создать собственную операционную систему RSX-11M. Необходимо было поддержать многозадачность, планировщик, иерархическую файловую систему, виртуальную память. На все это отводилось только 16 килобайт оперативной памяти, так как другие 16 килобайт было решено отдать приложениям.

Разумеется, выбор пал на ассемблер. В то время, кстати, он претерпел первое серьезное изменение. Появились директивы условного ассемблирования. Это позволило легко модифицировать исходный текст - вносить одни фрагменты, удалять другие; и при этом всегда была возможность вернуться назад, если последнее изменение внезапно приводило систему к краху.

Благодаря этой новой технологии лучшие специалисты DEC смогли в бешеном темпе завершить свою работу за 18 месяцев. При этом операционная система получилась, в конечном счете, очень простой и сильно уступающей набирающей популярность UNIX. Но своего потребителя все же нашла. Им стали многие средние предприятия, которые могли себе позволить купить несколько ЭВМ - по одному для каждого отдела. И их вполне устраивала мощность простого 16-разрядного процессора PDP.

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

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

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

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

7. INTEL

"Солнце не просит о милосердии".
Ф. Херберт "Дюна".

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

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

Такой чип впервые появился в 1972 году и вышел под кодовым обозначением 8008. Это была первая и очень простая модель микропроцессора, которая могла служить калькулятором, и не более того. Тем не менее юный Билл Гейтс все же ухитрился создать на ее основе устройство для анализа городского трафика. Разумеется, назвать это устройство компьютером было нельзя даже с большой натяжкой.

Но время не стояло на месте, а инженеры Intel не сидели сложа руки. Через три года, весной 1974, журнал Electronics опубликовал сообщение о новом чипе Intel 8080. Это действительно был шедевр, который каждый мог приобрести всего за 200 долларов. Конечно, этому микропроцессору было далеко до "больших машин" как по скорости, так и по архитектуре, системе команд, но для "персонального" использования он вполне годился.

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

Однако это и был первый минимально функциональный ПК. Микропроцессор, немного оперативной памяти и сопрягающих микросхем - вот и все, что было нужно для работы этой груды железа. Единственным устройством вывода служили 16 индикаторов на передней панели, а устройством ввода - 16 переключателей. Собственно говоря, это была машина для радиолюбителей и электронщиков. Последние вообще могли просиживать ночи напролет, заставляя индикаторы перемигиваться самым причудливым образом. 4 килобайта памяти тогда казались более чем достаточными для таких целей. А вот отсутствие удобных средств ввода/вывода сильно обескураживало.

Поэтому практически каждый, купивший Альтаир, пытался в той или иной степени его модернизировать. Не будем забывать, что в то время он стоил 1000$ и позволить себе купить его могли только фанатично преданные электронике (или компьютерам) люди. Теперь они получали ЭВМ в свое личное распоряжение и могли экспериментировать с ней как им вздумается.

Почти все из них были "молодым" поколением, до этого нигде не работавшим, а, может быть, и не видевшим "серьезных" машин. Поэтому их не смущало, что система команд и архитектура микропроцессора фирмы Intel значительно уступала даже первым моделям PDP и требовала совсем иного мышления и подхода.

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

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

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

8. Хаос

Хаос существовал в виде сырья, из которого творится порядок.
Ф. Херберт "Дом Глав Дюны".

Перенесемся на десяток лет назад. Многие до сих пор помнят это время. Десятки моделей машин от разных производителей, совершенно не совместимые друг с другом даже на уровне переноса текстовых файлов данных. Это стало настоящим бедствием для программистов восьмидесятых годов. Обмен программным обеспечением был невозможен. Портабельных компиляторов не существовало. Более того, диалекты одного и того же языка реализовывались на каждой машине по-своему.

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

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

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

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

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

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

При этом качество его оставляло желать лучшего. Может быть, среди читателей найдутся такие, которые до сих пор помнят некоторый шедевр отечественного компьютеростроения "Агат-9" и его на редкость корявую программную оснастку. Агат-DOS 3.3 не выдерживала никакой конкуренции даже с существующей в то время CP\M.

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

Это же можно сказать и о прикладных программах. Практически все они были созданы самостоятельно. Конечно, это был глупый и пустой труд, но зато приобретенные навыки оказались бесценными. Полученные знания позволяли писать качественные, компактные, удобные в работе программы. Однако...

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

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

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

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

9. Бытовой компьютер восьмидесятых

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

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

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

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

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

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

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

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

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

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

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

Это, однако, особая тема.

10. Рождение современных хакеров, или снова INTEL

...он был протозойским творением, рождение и смерть которого по сути одновременны.
Ф. Херберт "Дети Дюны".

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

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

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

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

Однако эффект был совершенно непредсказуемым - вместо того чтобы поддерживать новую перспективную модель, десятки фирм начали клонировать ее и продавать гораздо дешевле, чем оригинальный производитель. Парадоксально, но это только играло на руку компании. Убыток от "пиратства", конечно, был велик, но он способствовал популярности этой модели.

За короткое время было продано несколько тысяч полностью совместимых между собой машин. Разработчики ПО не могли мечтать о лучшем и активно переходили на новую платформу. Это вызывало популярность и среди пользователей.

Сейчас фирма IBM утратила лидирующее положение в производстве компьютеров, да и архитектура современных машин уже мало напоминает древний XT/AT, но единственное, что осталось неизменным, - это сердце компьютера: микропроцессор фирмы Intel. Если бы выбор IBM пал на другой микропроцессор, облик современных компьютеров мог быть другим.

Сегодня идут ожесточенные дискуссии о том, что лучше: PowerPC или Intel, причем основная часть спорящих крайне агрессивно настроена против последнего. Сразу видно, что практически все спорящие являются простыми пользователями, или, по крайне мере, прикладными программистами. Дело в том, что ни один хакер на трезвую голову никогда не будет выражать свою симпатию к RISC процессорам. Их ограниченный набор команд и адресаций загоняет ассемблерщиков в тиски и не позволяет проявить никакой индивидуальности. Да, для компиляторов подобный подход весьма практичен и упрощает их написание. Но человек не компилятор: он всегда хочет иметь свободу выбора и выражения собственных идей и решений.

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

Парадокс, но большая часть "хакеров" до сих пор ограничивается реальным режимом и не в состоянии хотя бы в общих чертах освоить защищенный. При этом за Intel'ом уже закреплен ярлык "нехакерского" микропроцессора. Но это всего лишь распространенное заблуждение! То же можно сказать и о Билле Гейтсе, которого сегодня склоняют на все лады, забыв, что именно он настоял на том, чтобы фирма IBM использовала не 8-разрядный процессор (как она первоначально планировала), а именно передовой 16-разрядный. Не окажись Билла - кто знает, может быть, IBM выпустила бы очередной "спектрум", который бы бесследно исчез и не было бы ничего, что окружает нас сейчас.

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

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

Современных хакеров, какие они есть, сформировал главным образом именно Билл Гейтс. Когда вы работаете с его продуктами, они вольно или невольно накладывают на вас отпечаток своего создателя. Впрочем, Билл лично не участвовал в разработке ни Dos, ни Windows, поэтому его присутствие ощущалось только косвенно. Между прочим, лишь редкие системные программисты под Windows ругают последнюю или ее создателя. И если ваш собеседник настроен против Microsoft, то он скорее всего не имеет никакого отношения к хакерам.

Настоящий хакер работает не на чем хочет, а на чем дают. Хакер должен любить свою операционную систему или сменить ее. Иначе это не хакер. Однако сегодня смена Windows на UNIX для рабочих станций все же малооправданный поступок, что бы об этом ни говорили. Впрочем, это только мое личное мнение.

11. Психологический анализ. Что движет хакером?

"Инструменты управления государством всегда должны быть остро
отточены и готовы к употреблению. Власть держится на страхе".
Ф. Херберт "Мессия Дюны".

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

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

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

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

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

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

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

Со временем появились защищенные операционные системы типа Windows NT, но они не получили ожидаемой популярности именно по причинам плохой совместимости с уже существующим программным обеспечением. Большинство до сих пор работает на ничем не защищенной Windows 95/Windows 98. Впрочем, надо признать, что последняя все же обрела, хоть и с большим запозданием, защитные механизмы, предотвращающие некоторые деструктивные действия. К сожалению, это достигается ценой ухудшенной совместимости. Многие программы могут не работать или работать неправильно. В этом мире за все нужно платить.

Но оставим дискуссию о проблеме незащищенности "народной" операционной системы Windows 9x. Словами горю не поможешь: если вам требуется безопасность, переходите хотя бы на Windows NT. Это не решит всех проблем, но по крайней мере позволит спать спокойно.

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

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

К счастью, подавляющее большинство таких людей обладает весьма смутными знаниями. Они не представляли бы никакой угрозы, если бы пользователи не были так беспечны в отношении собственной безопасности. По разным оценкам, ущерб от вандалов составляет 5-10 процентов от общего числа случаев потери информации (при этом более 50% инцидентов происходит из-за ошибок или неверных действий пользователя).

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

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

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

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

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

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

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

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

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

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

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

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

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

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

То же можно сказать и о взломе программ. И в том и в другом случае многих сознательно или подсознательно привлекает власть. Вряд ли последнее утверждение нуждается в пояснении.

Введение в криптосистемы

Введение

"Стать хакером очень просто. Достаточно выучить и понять
математические дисциплины (математический анализ,
теорию функций комплексного переменного, алгебру, геометрию,
теорию вероятностей, математическую статистику, математическую
логику и дискретную математику...)".
Борис Леонтьев "Хакеры & Internet".

Существуют два основных подхода, применяемых в системах защиты информации. Первый построен на затруднении прямого или косвенного анализа алгоритма с помощью оригинальных приемов программирования (использование недокументированных функций, специальных антиотладочных приемов). Такой подход широко применяется в условно-бесплатных программах, однако он крайне неэффективен. Для него характерно плохое соотношение накладных расходов на создание/вскрытие защиты; кроме того, он не обеспечивает даже минимальной безопасности. Большинство подобных программ ломаются в течение нескольких минут, самое большее - нескольких дней.

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

Кроме того, обычно такие оценки исходят из предположения, что злоумышленник будет просто перебирать последовательно все пароли один за другим. Наивно, не так ли? Лобовая атака на современных вычислительных мощностях персональных компьютеров сегодня попросту невозможна. Сколь-нибудь удовлетворительные результаты могут быть получены только при объединении десятков тысяч компьютеров.

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

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

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

Несмотря на то что первая часть является неизбежным теоретическим введением, все ее положения будут рассмотрены на примерах конкретных реализаций. Для этого необходимо выбрать платформу. Приучая читателя к детальному ("низкоуровнему") мышлению, я выбираю ассемблер. Реже буду использовать IDA Си и MS VC. Поклонники Паскаля и Делфи должны делать свой выбор самостоятельно. Во всяком случае, без знания ассемблера изучение и защита программ в большинстве случаев невозможна. Эта книга не научит вас основам ассемблера и рассчитана на уже подготовленного читателя.

С другой стороны никакой математической подготовки книга не требует. Однако, я надеюсь, что в процессе чтения читатель будет обращаться к соответствующим источникам для получения более детальной картины подаваемого материала.

Настоящий хакер никогда не откажет себе в удовольствии копаться не только в недрах кода, но и в литературе (бумажной или электронной). Соблазн использовать готовые схемы и решения "AS IS" достоин только коммерческих кракеров (поставивших взлом на поток и зарабатывающих деньги на эксплуатации чужих идей и инструментов). Я не хочу вдаваться в этическую полемику и задаваться извечным вопросом "что такое хорошо и что такое плохо?" Так или иначе это есть. Для использования любой законченной технологии не требуется понимать ее функционирование. Воплощенная в конкретный программный код, она становится в руках вандалов разрушающим программным оружием. Выход из ситуации "методом Страуса" невозможен. Сегодня вычислительная техника уже не контролируется, и такая программа будет создана и распространена - если не одним, так другим человеком. Распространение технологий и инструментов для взломов и атак является не актом вандализма, а напротив, указанием на уязвимость существующих систем и побуждает к исправлению последних.

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

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

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

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

Хеши. Односторонние функции

"Ночь - это туннель,- подумала она. - Это дыра
в завтра, если только оно наступит, это завтра".
Ф.Херберт. "Дюна"

Вся современная криптография основана на использовании методов хеширования. Метод хеширования позволяет хранить элементы множества А в линейном массиве Х. Математически это можно записать:

h: А --> {0,x-1}

Это читается: функция h отображает каждый элемент А в индекс множества Х. Поскольку число элементов А, как правило, намного больше Х, то функция h наверняка неинъективна. Однако, возможно существование такого интервала на области определения функции, в границах которого она становится инъективной. Это означает, что только для одного элемента А существует индекс x1. Функция будет инъективной и в том случае, если ни один элемент А не отображается на интервал {x1,x2} при условии, что последний не равен нулю. В любом другом случае на каждый индекс множества Х отображается более одного элемента А. Это так называемая коллизия хеш-функции. Реверс хеш-функции заключается в поиске всех отображаемых на данный индекс элементов. Для любого конечного множества А это разрешимая задача, которая имеет наиболее простое решение на инъективных интервалах хеш-множества.

Давайте остановимся на инъективных интервалах. Невозможно практическое использование хеш-преобразований без понимания их значения. В качестве примера рассмотрим следующую задачу: пусть нам требуется эффективный алгоритм сравнения строк, допустим, для синтаксического анализатора. Простое посимвольное сравнение потребует значительной памяти для хранения образов строк. Представим все возможное множество строк в данной разрядной сетке массивом S, тогда мы можем хеш-преобразованием привести его к множеству b {0,0xFF}. Разумеется, b много меньше S и требует для хранения значительно меньше памяти.

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

Для начала нужно построить хеш-таблицу значений для всех элементов множества S. Воспользуемся для этого программой file://CD:/SRC/hash00.exe - "хеш-калькулятор". Рассмотрим ее ключевой фрагмент:

BYTE GetHash(CString s0)
{
     BYTE hash = 0;
     for (int a = 0; a < s0.GetLength(); a++)
         hash = hash + s0[a];    // Вычисляем хеш-сумму
     return hash;
}

Мы посимвольно складываем элементы множества символов s0, получая в результате некоторый элемент из множества calc {0,0xFF}. Как нетрудно видеть, на каждый элемент множества calc отображается не более чем один элемент S. Таким образом, в заданных рамках функция calc=calc+s0[a] инъективна. Следовательно, для заданного индекса единственным образом определяется элемент S. Этим доказывается корректность работы хеш-анализатора.

Ниже приведен фрагмент реально работающего эмулятора виртуального процессора GetMe01 (file://CD:\CrackMe\GetMe01.asm).

        LEA     SI,     Buffer   ; Буфер исполнительных команд
start_r:                         ; ----------------------------------------
        CALL    GetHashe         ; Вычисление хеш-суммы очередной команды |
        CALL    CallIt           ; Вызов обработчика  для  данной команды |
        MOV     SI,DI            ; Позиционирование     указателя команд  |
        CALL    Seek             ; ^                                      |
        JMP     short start_r    ; ДД[uncond]------------------------------

GetHashe        PROC    NEAR
        PUSH    SI               ; Сохраняем виртуальный указатель команд
        XOR     AX,AX            ; AH == сумматор
gh_Repeat:                       ; ----------------------------------------
        LODSB                    ; Берем очередной элемент множества s0   |
        ADD     AH,AL            ; Добавляем в сумматор                   |
        XOR     AL,':'           ; Проверка на конец команды              |
        JNZ     gh_Repeat        ; ДД([SI]<>':')---------------------------
        POP     DI               ; si-->di; return SI
        RETN                     ; --\
ENDP

Seek            PROC    NEAR
s_repeat:                        ; ----------------------------------------
        LODSB                    ; Взять следующий символ                 |
        OR      AL,AL            ; Проверить на равенство нулю            |
        JNZ     s_repeat         ; ДД([SI]<>NULL)--------------------------
        RETN                     ; --\
ENDP

CallIt  Proc NEAR
        PUSH    SI               ; Сохранить SI
        LEA     SI,TableOfRange  ; Таблица указателей на обработчики
        XCHG    AX,BX            ; BH == AL
ci_rep:                          ; ----------------------------------------
        LODSB                    ; Читаем очередную хеш-сумму             |
        OR      AL,AL            ; Конец таблицы?                         |
        JZ      _err             ; --достигнут конец таблицы-->           |
        CMP     AL,BH            ; Хеш найден?                            |
        LODSW                    ; Читаем очередное смещение обработчика  |
        JNZ     ci_rep           ; ДД(!Hash)-------------------------------
        XCHG    AX,BX            ; BX == AX == смещение обработчика
        POP     SI               ; Восстановить SI
        CALL    BX               ; Вызвать обработчик данной команды
        RET                      ; --\

_err:                            ; Исключительная ситуация. Неверная команда
        MOV     AH,9             ; Печать строки MS-DOS
        LEA     DX,errr          ; Смещение печатаемой строки
        INT     21h              ;
        MOV     AH,4Ch           ; Завершение работы
        INT     21h              ; --\

errr     DB      'Неизвестная команда',0Dh,0Ah,'$'
ENDP

; //////////////////////////////////////////////////////////////////////////
; //     ТАБЛИЦА ПОДДЕРЖИВАЕМЫХ КОМАНД И СООТВЕТСТВУЮЩИХ ИМ ОБРАБОТЧИКОВ
; //------------------------------------------------------------------------
TableOfRange:
        DB      0EFh             ; Хеш-сумма команды
        DW      Offset Proc1     ; Обработчик данной команды
        DB      0E3h
        DW      offset Proc2
        DB      79h
        DW      offset Proc3
        DB      0E6h
        DW      offset Proc4
        DB      01h
        DW      offset Proc5
        DB      0D1h
        DW      offset Proc7
        DB      054h
        DW      offset Proc8
        DB      0ADh
        DW      offset Proc9
        DB      0                ; Конец таблицы

Buffer:                          ; Буфер исполнительных команд

Данный пример хранит восьмибитную хеш-сумму каждой команды. Следовательно, независимо от длины используемых команд для хранения потребуется всего N байт памяти (где N - число команд), что существенно меньше объема, необходимого для полного хранения тех же самых команд. Теоретически, восьмибитная хеш-сумма может вместить до 0xFF+1 команд. Однако, практически предложенная реализация при добавлении некоторого числа команд окажется неработоспособной. Это случится, когда двум разным командам будет соответствовать одна и та же хеш-сумма. В таком случае математики говорят о коллизии хеш-функции. Следовательно, на выбранном интервале хеш-функция становится неинъективной и для рассматриваемой задачи непригодной.

Казалось бы - если множество S намного больше X, то любая хеш-функция на полной области определения S окажется неинъективной. На самом деле, число элементов S практически всегда много меньше его мощности. Например, множество слов русского языка представляется множеством последовательностей от одного до десяти и более символов, но общее число существующих слов заведомо меньше 0xFFFFFFFF. Поэтому, возможно существование 32-битной инъективной хеш-функции для синтаксического анализатора русского языка.

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

Наиболее часто используется и хорошо изучен мультипликационный метод отображения. Математически его можно выразить как h(S[x])=C*S[x] mod N, где N - это число элементов хеш-множества или, другими словами, его мощность. С - любая константа из интервала [0,N). При C=1 эта формула приобретает вид h(S[x])=S[x] mod N и является самостоятельным хеш-преобразованием, называемым методом остатка. Данный алгоритм также широко используется и для генерации псевдослучайных чисел. И неудивительно, ведь генераторы случайных чисел являются ни чем иным, как хеш-преобразованием!

К числу наиболее популярных принадлежит также необычайно мощная функция CRC 32 (crc16): cyclic redundancy check (код циклического контроля). Эта функция в первую очередь призвана подтверждать неискаженность выбранной числовой последовательности. Это еще одна область применения хеш-преобразований. В самом деле - здесь осуществляется все то же хеш-сравнение. Конечно, существует определенная вероятность таких искажений, которые не отразятся на хеш-сумме, но она достаточно невелика при условии хорошего рассеяния и чувствительности к незначительным изменениям выбранного хеш-преобразования.

CRC 32 - это многократно проверенная, быстродействующая и качественная хеш-функция, дающая превосходный результат. Для большинства последовательностей она будет инъективна. Так, например, многие текстовые редакторы реализуют синтаксическую "подсветку" именно на основе CRC32, не вызывая при этом коллизий.

Рассмотрим алгоритм этой функции. Целую беззнаковую 32-х битовую переменную инициализируем значением 0FFFFFFFFh. Далее умножаем на 2 аргумент функции и значение CRC. Если старшие биты окажутся не равны, тогда CRC = CRC XOR 0xEDB88320. И так до последнего бита аргумента. Если аргумент - строковая (или какая-либо другая) последовательность, то операции проводятся над двойными словами. В каноническом варианте в конце цикла требуют инвертировать все биты CRC, но это важно только для совместимости результатов, полученных разными функциями, и никак не сказывается на качестве. "Магическое число" 0xEDB88320 есть стандартный полином, менять который не следует, т.к. это ухудшит качество функции.

Может возникнуть такая ситуация, когда требуемое число элементов хеш-множества будет заметно меньше, чем 2^32. Чтобы избежать лишних расходов, умножают результат сам на себя и берут N старших бит так, чтобы 2^N было по возможности близко к требуемому значению. Смысл этой операции в том, чтобы получить битовую последовательность, чувствительную ко всем битам значения CRC.

Рассмотрим теперь применение хеш-преобразований в криптографии. Одной из задач последней является проверка достоверности пароля. Для этого используют особые хеш-функции. Почему поступают так, мы поймем, рассмотрев принцип действия криптосистем. Пусть имеется некоторая криптографическая функция F, расшифровывающая паролем p последовательность Ai в последовательность Aj.

p
F(Ai) ------> Aj

Разумеется, только для одного-единственного p мы получим исходную последовательность Aj, а для всех остальных p - "мусор". Каким способом можно удостовериться в том, что полученная Aj и есть искомая последовательность (при условии, что самой последовательности в наличии не имеется)? Можно сохранить фрагмент исходной последовательности и затем сверить его с полученным результатом. Однако это делает возможной атаку по открытому тексту на шифр и, кроме того, очень ненадежно, т.к. совпадение одного фрагмента не обязательно обеспечивает совпадение всей последовательности.

Вот тут-то на помощь и приходит хеш-преобразование. Мы можем вычислить CRC32 для исходного текста. Сравнивая его с CRC32 Aj, мы можем проверить правильность расшифровки. Поскольку количество Aj наверняка больше 2^32, то хеш-функция окажется неинъективной и хеш-значение не даст никакого представления об исходной последовательности.

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

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

Функция f: X -> Y называется односторонней, если f(x) может быть легко вычислена для любого элемента X, тогда для всех элементов Y вычисление такого аргумента x, для которого f(x) = y, не разрешимо полиноминально. Ясно, что CRC32 не является односторонней функцией и, невзирая на распространенное мнение, подлежит реверсированию. Поскольку, для каждого значения х CRC32 существует бесконечное множество верных аргументов А, таких что F:CRC32(A) = x, то получение множества подходящих аргументов А' ничем не помогает нахождению в нем искомого элемента. Именно этим и вызвано широкое (и, между прочим, неоправданное) применение CRC32 в криптографии. Односторонность этой функции держится всего лишь на ее неинъективности. Однако, как было показано выше, возможно существование такого интервала I, на котором выбранная хеш-функция является инъективной. Практически во всех популярных криптосистемах не делается никаких попыток проверки принадлежности хешируемых данных к этому интервалу. Более того, для любого конечного перечисленного множества Z возможен как прямой (предвычисленный), так и обратный реверс хеш-функции. CRC32 успешно обращается полиномиально. И, как следствие, часто становится уязвимым местом криптозащит.

Рассмотрим табличное реверсирование. Для этого вычислим CRC32 каждого элемента перечисленного множества Z и сравним ее с исходной. Среди полученных элементов находится по крайней мере один действительный пароль. Множество Z в нашем случае - это множество возможных паролей. Нетрудно вычислить, что даже для восьмисимвольных паролей потребуется по крайней мере 4^8 (или 2^16) байт памяти для хеш-сумм и еще больше для хранения образа паролей. Кроме того, потребуется очень большое число итераций.

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

b == !Hibit(xor (crc32,0xEDB88320)) | Hibit(crc32)

Предположим, что каждый бит аргумента может являться как нулем, так и единицей. Проверим оба результата на принадлежность к множеству Z и отбросим ненужные. Если оба значения принадлежат Z, то запоминаем оба и дальше вычисляем оставшиеся биты для обоих из них - и так до тех пор, пока не будет отброшен последний элемент, как не принадлежащий к множеству Z. Иначе говоря, мы строим бинарное дерево. Очень легко подсчитать необходимое число итераций для нахождения всех возможных паролей. Кроме того, для этой ситуации применимы все эффективные алгоритмы, работающие с двоичными деревьями. Сбалансированное двоичное дерево позволит эффективно реверсировать crc32 даже в случае большого рассеяния элементов Z. Т.е. мы можем быстро проверить, не является ли этот хеш контрольной суммой какого-нибудь словарного слова. Обратное преобразование осуществит эту проверку намного быстрее, чем прямой перебор множества словарных слов. Подробнее операции с двоичными деревьями изложены в книге Майкла Ласло "Вычислительная геометрия и компьютерная графика на C++" (Москва БИНОМ, 1997) и во многих других изданиях. Очень рекомендую ознакомиться с конспектами лекций Манфрейда Броя "ИНФОРМАТИКА" (Диалог-Мифи, 1998).

А мы не будем на этом больше задерживаться и рассмотрим алгоритмы генерации любой заданной последовательности ключей. Атака перебором - это один из вариантов вскрытия односторонних хеш-функций. Все криптосистемы строятся с учетом того, что полный перебор ключей займет заведомо чрезмерный промежуток времени. Ситуации с выбором короткого пароля мы безжалостно отбросим. Не то, чтобы они были достаточно редки, но уповать на это очень рискованно: отнюдь не гарантировано, что данные попытки увенчаются успехом. Однако в ряде случаев возможен ограниченный перебор ключей. Так, например, в архиваторе rar ранних версий любой пароль преобразовывался в 80-битовую хеш-последовательность. Перебором 2^80 вариантов можно было вскрыть любой, сколь угодно длинный пароль. С другой стороны, для паролей, состоящих менее чем из восьми символов, необходимо было перебрать гораздо меньшее число вариантов. Таким образом, нам нужно построить последовательность всех возможных вариантов для перебора. Она будет очень велика, но вполне разрешима за приемлемое время.

Чтобы научиться строить эффективные алгоритмы, необходимо хотя бы вкратце ознакомиться с теорией формальных языков. Алфавитом является конечное перечисленное множество A. Множество всех конечных последовательностей элементов А называется формальным языком. Языки оперируют словами. Для заданного множества A последовательность элементов x1..xn, принадлежащих A, образует слово длины n, которое записывается как <x1..xn>. Множество всех слов равняется AxAx...xA, что принято записывать как A*. Для каждого слова формального языка существует отображение length:A' --> N, где N - длина слова.

Таким образом, нашей задачей будет перечисление множества слов формального языка. Множества слов разных языков можно объединить в одно общее множество. Эту операцию приходится выполнять очень часто при атаках на криптоалгоритмы. В нашем примере мы должны объединить множество паролей и множество ключей и распределить так, чтобы по возможности слова оказались отсортированы по вероятности совпадения с истинным паролем (ключом). Это заметно усложняет алгоритм, но чрезвычайно повышает его эффективность. Часто криптостойкость системы оказывается недостаточной, чтобы противостоять такой хитрой атаке.

Для начала рассмотрим простейший алгоритм генерации паролей, построенный на последовательном множестве. Полный исходный текст находится на file://CD:/SRC/parole.asm, а ниже приводится только ключевой фрагмент. Предложенный алгоритм исключительно прост и быстр; при этом он достаточно гибок и может быть применен для произвольных перечисленных множеств.

        MOV     AH, 9h                  ; Телетайпный вывод
        LEA     SI, Password            ; Начальный пароль
        MOV     DX, SI                  ; для f.9/Int 21h
NextPassword:                           ; Генерация следующего пароля
        XOR     BX, BX                  ; С нулевого разряда
CheckOver:                              ; Проверка на переполнение
        INC     Byte Ptr DS:[SI+BX]     ; Увеличиваем первый слева символ
        CMP     Byte Ptr DS:[SI+BX],'z' ; Выход за допустимые границы?
        JB      WritePassword           ; ДД{Нет переноса}------------------
        MOV     Byte Ptr [SI+BX], ' '   ; Сбрасываем текущий разряд
        INC     BX                      ; Перенос на следующий разряд
        JMP     Short CheckOver         ; ----------------------------------
WritePassword:                          ; > Вывод пароля на экран
        INT     21h                     ; ^
        JMP     SHORT   NextPassword    ;
Password        DB 8 Dup(' ')           ; <- - начальный пароль
                DB 13, 10, '$'          ; <- - конец строки

Тот же алгоритм изящно выражается одной строкой на языке Cи (file://CD:/SRC/PAROLE/Parole.cpp):

while ((pasword[index++]++)>'z') pasword[index-1]=' ';

Математический смысл сводится к последовательному перебору всех элементов множества [' ','z'] путем добавления единицы с учетом переноса. Т.е. эту функцию иначе можно назвать INC x, где x - число практически неограниченной разрядности.

Данный алгоритм относится к числу простейших, но для практического применения не годится. Нам необходимо перебирать пароли из произвольного множества символов. Данный пример работает на единственном интервале [x1, xn] линейного множества C.

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

f
C ---> Z

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

Рассмотрим следующий аспект. Как правило, пароли состоят не из равновероятных символов. Хорошая перебирающая программа должна это учитывать. Может ли это обеспечить предложенный алгоритм? Рассмотрим такую функцию отображения f, которая отображает более одного индекса C на один и тот же элемент Z, задавая тем самым вероятность его появления в генерируемом пароле. Отметим, однако, что при этом возрастут накладные расходы. Пусть два элемента c1 и с2 отображаются на один и тот же элемент z1. Тогда мы получим дважды один и тот же пароль z1. Обычно этим можно пренебречь, т.к. доля дублирующихся паролей несущественна. Но когда она достигнет нескольких процентов от общего числа, то разумно запоминать все встретившиеся пароли и игнорировать повторные. Двоичное дерево обеспечивает приемлемую скорость поиска.

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

В качестве примера приведем усовершенствованный алгоритм с отображением, выполняемым функцией xlat (file://CD:/SRC/Parole01.asm).

Repeat:
       MOV     AL, Byte Ptr DS:[SI+BP] ; Взять элемент psw
       XLAT                            ; Отобразить его на мнж. alf
       MOV     [DI+BP], AL             ; Записать результат

       INC     Byte ptr [SI+BP]        ; Следующий
       CALL    WritePassword           ; Вывести пароль
       CMP     [SI+BP],CL              ; Проверка на переполнение
       JB      Repeat

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

Теперь можно атаковать любую одностороннюю функцию, перебирая все допустимые аргументы и занося их в таблицу, после заполнения которой можно найти все аргументы А, для которых справедливо f:a = key, где key - известный результат функции. Если выбранная функция инъективна и существует не более одного аргумента для заданного кey, то в построении таблицы нет никакой необходимости. Первый совпадающий аргумент и будет искомым.

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

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

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

Как ни парадоксально, но использование хороших хеш-функций уменьшает число возможных паролей, облегчая работу взломщика. Использование плохих - дает информацию об исходном пароле, по которой его можно частично восстановить. Поэтому никакие хеш-функции нельзя использовать для "свертки" с пароля. Например, RAR не проверяет пароль на валидность, а сверяет CRC расшифрованных данных. Это не дает никакой информации об исходном пароле, но работает медленно. С другой стороны, у всех быстрых алгоритмов шифрования (хвалебные сообщения о которых периодически появляются в разных источниках) есть существенный недостаток - быстрый перебор увеличивает шансы лобовой атаки.

Рассмотрим еще одну область применения хеш-функций. Пусть у нас есть некоторый пароль p, который "зашит" в электронном ключе или введен пользователем. Сравнивать пароль типа if(UserPassword!=MyPassword) abort(); нельзя т.к. это очень просто ломается. Можно расшифровать паролем некоторый фрагмент кода или использовать его как константу. Если для шифрования выбрана криптостойкая схема, пароль можно найти только перебором всех возможных вариантов. Контроль правильности ввода можно обеспечить с помощью контрольных сумм. Эта схема очень надежна, но в большинстве приложений реализована с ошибками. Как уже догадался читатель, контрольная сумма снимается с пароля, а не с расшифрованных данных. Но это далеко не самая глупая ошибка! В целях безопасности электронный ключ не должен сообщать пароль в "прямом" виде. С него снимается хеш-сумма, которая и передается для расшифровки. Таким образом, мы имеем два значения разных хеш функций. Первое - для контроля правильности пароля, второе - для расшифровки. Мы получаем систему двух уравнений, решением которого будет пересечение двух множеств реверсированных хеш-преобразований. Это сокращает множество перебираемых паролей вплоть до единственного. Такой подход применим в случае идеальных хеш-функций. Другим решением будет попытка вычислить вторую контрольную сумму из первой.

Распространенной ошибкой является и использование "длинных" crc, сравнимых с длиной пароля. Читатель может сам подсчитать сколько возможных восьмисимвольных паролей имеют одно и то же значение 32-битной контрольной суммы. Однако использование более коротких хеш-сумм увеличивает вероятность того, что неверный пароль будет воспринят как правильный.

Популярная система Novell NetWare 3.x-4.x использовала уязвимый алгоритм. Суть его сводилась к тому, что с пароля снималась хеш-сумма, с которой затем сравнивался вводимый пароль. Эта функция была обратима. Таким образом можно получить МНОЖЕСТВО паролей, которые все воспринимались системой как верные.

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

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

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

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

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

ReHashe(unsigned char hashe)
{
   for (unsigned char a = 'A'; a < 'a'; a++)
   {
       if (!hashe -= a) return;
       ReHashe(hashe);
   }
}

Данный пример не рекомендуется запускать. Легко доказать, что для любого hashe существует бесконечное множество таких ключей, что f(key) == hashe. Реально разрядность паролей ограничена емкостью стека. При исчерпании последнего возникнет исключительная ситуация и выполнение программы будет аварийно завершено.

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

Кроме этого, нужно ввести ограничение на глубину рекурсии, определяемую максимально допустимой длиной ожидаемого пароля.

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

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

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

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

Попробуем количественно выразить ожидаемое число паролей для другой популярной функции hashe(A)= a1 xor a2 xor a3...xor an. Для начала докажем, что для любого a, равного x1 xor x2, существуют только две пары x1 и x2, при условии что X [0,1]. Как известно из булевской алгебры, операция xor может быть представлена следующей логической матрицей.

       xor |  0   1
       ----|------------
        0  |  0   1
           |
        1  |  1   0

Мы видим, что для каждого значения функции существуют ровно две пары x1, x2, что и требовалось доказать. Поэтому ожидаемое число паролей будет 2^n, где n - разрядность хеш-суммы. Разрядность пароля при этом не выше разрядности хеш-суммы. Т.е. мы провели простое побитовое обращение функции xor. Для восьмибитной хеш-суммы это число равно 0x100. Т.е. значение хеша нам абсолютно ничего не дает, т.к. x1 и x2 могут быть любыми! Однако, x1x2 это 2^16 вариантов, т.е. знание хеш суммы все же позволяет сократить число перебираемых паролей в 0x100 раз. Неплохо; но даже этот результат можно улучшить. Множество допустимых символов пароля, как правило, много меньше 0x100. Пусть ожидаемый пароль состоит только из символов 'A'..'Z'. Тогда для него существует не более 2^5 возможных пар x1 и x2!

Последним мы рассмотрим реверс мультипликационного алгоритма. Пусть A = CX mod N, тогда X = k*N/C+A, где k !=0. Но в пределах [0,N) мультипликационная функция инъективна! Для доказательства этого вспомним, что любое число можно представить как x*n+y единственным образом.

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

Все приведенные хеш-функции не являются односторонними и значительно уменьшают число возможных паролей. Совсем иначе дело обстоит с односторонними функциями, использующимися в криптостойких системах. Казалось бы, если обращение их дело безнадежное, то на этом можно ставить точку и даже не пытаться заниматься заведомо неразрешимой проблемой. Отчасти это верно. Действительно, необратимость большинства функций сомнений не вызывает, но другие, отличные от обращения, пути часто остаются неучтенными и не закрытыми, лишний раз подтверждая слабость большинства реализаций. Часто односторонние функции вычисляются очень быстро. Таким образом, выгоднее сначала последовательно перебрать все возможные пароли, дающие заданный хеш, а затем атаковать шифр заданным множеством паролей. Все "сильные" криптостойкие алгоритмы, как правило, очень медленны. Именно это и препятствует атаке. Так, например. на P-120 скорость перебора UNIX - MD5 не превышает 200 паролей\сек. Тогда как многие хеш-функции до 300.000 и выше! Однонаправленность сама по себе не спасает функцию. Да, реверс невозможен, но прямая атака (т.е. последовательный перебор всех аргументов до совпадения со значением функции) эффективнее прямой атаки на шифр. Впрочем, не стоит обольщаться. Весьма вероятно, что несмотря на грубые ошибки реализации криптосистемы, взлом будет лежать за допустимой гранью. Скажем, мы найдем пароль не за биллион, а за десять лет. Так, вероятно, и рассуждают конструкторы защит. А ведь в эти рассуждения вкралась ошибка! На чем держится криптосистема? На малой скорости перебора паролей и большом количестве подходящих под хеш ключей. При условии использования бессмысленного пароля хакеру осталось бы только развести руками. Однако пользователи склонны выбирать осмысленные пароли. Если такой встретится в множестве подходящих под хеш паролей, то в дальнейшей атаке на систему, возможно, уже не будет нужды! Время, затраченное на атаку, в таком случае определяется только скоростью выполнения хеш-преобразования! Предложенный механизм очень близок к словарной атаке и основан на "слабых" паролях. Поиск "осмысленного" пароля представляет выборку всех паролей, включающих в себя, по крайней мере, трехсимвольный фрагмент словарного слова и отсортированных по убыванию длины подстроки.

Существует, по крайней мере, еще одно уязвимое место, введенное в некоторые криптосистемы под давлением правительства. Это так называемые "мастер-пароли". Предполагается, что они должны быть известны исключительно спецслужбам и не могут быть найдены иначе как методом перебора. Удивительно, но встречаются словарные мастер-пароли. Так, например, AWARD_SW. Забавно: когда даже пользователи начинают осознавать слабость словарных паролей и администраторы используют нечто вроде t%7Nh6i!!AMPER!!SrF, самое мощное оружие (ведь оно дает доступ ко ВСЕМ паролям) так уязвимо для атаки. Однако криптографы предпочитают использовать вместо мастер-паролей односторонние функции с секретом. Это означает, что в действительности эти функции совсем не односторонние и существует простое обратное решение. Но вот только найти его не более просто, чем атаковать пароль.

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

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

Простейшие системы шифрования

" - Высказана мысль или нет, она существует и имеет свою власть,-
сказал Туек. - Ты можешь обнаружить однажды, что грань между
жизньюи смертью у Свободных слишком тонка."
Ф. Херберт. "Дюна".

Данная глава является кратким обзором проблемы для неподготовленного читателя. Остальные могут ее смело пропустить.

Неоправданно популярный способ:

if (!IsValidUser())
{
    Message("Invalid user! Aborting...");
    Abort;
}

транслируется компилятором приблизительно в следующий код:

       CALL IsValidUser
       OR   AX,AX
       JZ   continue
       ^^^^^^^^^^^^^
       PUSH offset str_invalid_user
       CALL Message
       CALL Abort
continue:               ; нормальное продолжение исполнения программы
       ...........

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

IsValidUser();
if (!true)
{
    Message("Invalid user! Aborting...");
    Abort;
}

Т.е. ветка {...} никогда не получит управления! На самом деле все не так просто, поскольку в исполняемом файле нужно еще найти эту инструкцию перехода. К тому же разработчики защиты это всячески пытаются затруднить. Запутывают алгоритм, используют самомодифицирующийся код, применяют недокументированные вызовы операционной системы... Однако такие препятствия хакера не смущают. Технологии противодействия заметно обгоняют эволюцию систем защиты. А с появлением дизассемблера IDA, отладчика Soft-Ice и распаковщика cup386 копание в чужом коде не только превратилось в удовольствие, но и стало доступно широкому кругу лиц. Десять лет назад всего выше перечисленного богатства еще не было, процессор работал только в реальном режиме, и не было никакой возможности уберечь отладчик от разрушающего воздействия со стороны изучаемой программы. Хакеры "старого поколения" работали в основном карандашом, листком бумаги и головой. Зачастую код приходилось дизассемблировать в уме, а недокументированные вызовы изучали, погружаясь в недра операционной системы. Это не только требовало высокого профессионализма, но и огромного количества свободного времени, которое было нечем занять.

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

Отсюда и возникло твердое убеждение: как бы разработчик ни защищал свой продукт, все равно сломают. На самом же деле существуют алгоритмы, делающие взлом по меньшей мере неэффективным. Основанные на криптографии, они обеспечивают не только надежную, но и математически обоснованную степень защиты.

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

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

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

Большинство защит сегодня используют шифровку своего кода в целях затруднения анализа и модификации кода. Ключ, используемый в расшифровщике, хранится непосредственно в последней, поэтому теоретическая криптостойкость подобной системы равна нулю. Впрочем, это неважно, т.к. преследуются совсем другие цели. Кроме IDA, ни один известный мне дизассемблер не может работать с шифрованным кодом. Отладчик не сможет функционировать, если декодер использует необходимые ему ресурсы. Наконец, непосредственная модификация кода становиться невозможна. При этом сам алгоритм шифра и его криптостойкость не играют никакой роли! Действительно, если пароль, используемый декодером, известен, то использовать криптостойкие алгоритмы бессмысленно!

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

a xor b xor a = b.

Для этого просто перечислим все возможные значения a и b в следующей табличке:

         a\b |         0           |            1
        -----|---------------------|---------------------
          0  | 0 xor 0 xor 0 == 0  |  0 xor 1 xor 0 == 1
             |                     |
          1  | 1 xor 0 xor 1 == 0  |  1 xor 1 xor 1 == 1

Заметим, что xor - битовая операция. Аргументы a и b могут иметь только два значения: 0 и 1. Однако никто не запрещает проводить ту же операцию для последовательности битов. Команда процессора XOR word, const на самом деле представляет собой не word xor const, а последовательность операций над каждой парой битов двух переменных.

Теперь обратим внимание, что a xor 0 == a; a xor 1 == !a. Т.е. значащими в маске шифрования являются только единичные биты. Поэтому рекомендуется выбирать такую маску, в которой единичные и нулевые биты равномерно перемешаны. К примеру, 00001111b (0xF) будет плохой маской, т.к. оставляет неизменными четыре старшие бита в каждом символе шифротекста, что позволяет (как будет показано ниже) успешно атаковать шифр. Маска 01010011 полностью уничтожает вероятностное распределение исходных символов в шифротексте, поэтому считается хорошей.

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