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

Ваш аккаунт

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

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

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

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

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

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

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 == сумматор                       ~~6 
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: ~~7 //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 

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

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

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
57K
25 января 2010 года
Rapstar
0 / / 25.01.2010
Мне нравитсяМне не нравится
25 января 2010, 01:18:31
и что это даёт?
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог