Logo    
Деловая газета CitCity.ru CITKIT.ru - все об Open Source Форумы Все публикации Учебный центр Курилка
CitForum    CITForum на CD    Подписка на новости портала Море(!) аналитической информации! :: CITFORUM.RU
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

28.03.2017

Google
WWW CITForum.ru
С Новым годом!

2004 г.

Неизвестная уязвимость функции printf

Крис Касперски
Статья была опубликована в журнале "Открытые системы"

"Машинная программа выполняет то, что вы ей приказали делать, а не то, что бы вы хотели, чтобы она делала".
Третий закон Грида

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

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

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

#include <string.h>

void main()
{
	FILE *psw;
	char buff[32];
	char user[16];
	char pass[16];
	char _pass[16];

	printf("printf bug demo\n");
	if (!(psw=fopen("buff.psw","r"))) return;
	fgets(&_pass[0],8,psw);

	printf("Login:");fgets(&user[0],12,stdin);
	printf("Passw:");fgets(&pass[0],12,stdin);

	if (strcmp(&pass[0],&_pass[0])) 
		sprintf(&buff[0],"Invalid password: %s",&pass[0]);
	else
		sprintf(&buff[0],"Password ok\n");

	printf(&buff[0]);

}

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

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

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

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

Такую ситуацию позволяет продемонстрировать следующий пример: “main(){int a=0xa;int b=0xb;printf("%x %x\n",a);}”, в котором присутствует один "беспарный" спецификатор “%x”. Поскольку содержимое стека на момент вызова функции “printf” зависит от используемого компилятора, то поведение данного кода неопределенно. Например, результат работы программы, полученной с помощью Microsoft Visual C++ 6.0, выглядит так: “a b”

Функция вывела два числа, несмотря на то, что ей передавали всего одну переменную “a”. Каким же образом она сумела получить содержимое переменной “b”? Ответить на этот вопрос поможет дизассемблирование машинного кода программы, в результате которого удается установить содержимое стека на момент вызова функции printf (сам дизассемблерный листинг в журнальном варианте статьи опущен, полный текст содержится в книге "Техника сетевых атак", которую планируется выпустить в скором будущем):

off aXX ('%x %x') (строка спецификаторов)
var_4   ('a')     (аргумент функции printf)
var_8   ('b')     (локальная переменная)
var_4   ('a')     (локальная переменная)

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

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

При вызове “printf("%x %x\n",a)“ функция извлекает из стека на одно слово больше, чем было ей передано, и в результате происходит вторжение в область памяти, занятой локальными переменными материнской функции. Переменная “b” принимается за аргумент функции и выводится на экран. (В зависимости от используемого компилятора в заданном месте стека может оказаться все что угодно, например переменная “a”, сохраненные значения регистров общего назначения, "черная дыра" – область памяти, отведенная для выравнивания данных и т.д.).

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

В тех случаях, когда функция printf используется для вывода единственной символьной строки, строку спецификаторов обычно опускают, т.е. вместо printf (“%s”, &buff[0]) пишут “printf(&buff[0])”. На первый взгляд обе формы записи равносильны, но это не так! Самый левый аргумент всегда проверяется функцией printf на наличие спецификаторов, даже если он передан функции в единственном числе. Поэтому использовать его для вывода строки можно в том и только том случае, когда она гарантированно не содержит никаких "внеплановых" спецификаторов, в противном случае, работа приложения окажется нестабильной. Особенно опасно полагаться на отсутствие спецификаторов в данных, введенных пользователем, и недопустимо передавать их функции printf в первом слева аргументе.

Возможные последствия такого подхода позволяет продемонстрировать программа, приведенная в начале статьи: если злоумышленник введет вместо пароля один или несколько спецификаторов, на экране появится содержимое локальных переменных, в том числе и буфера, хранящего эталонный пароль. Компилятор Microsoft Visual C++ 6.0 располагает этот буфер на вершине стека и просмотреть его можно следующим образом (предполагается, что файл “buff.psw” содержит строку “K98PN*”):

printf bug demo
Login:kpnc
Passw:%x %x %x
Invalid password: 5038394b a2a4e 2f4968

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

Перевод шестнадцатеричных значений в символьное представление сопряжен с определенными неудобствами, но использование спецификатора “%s” приведет не к выводу строки в удобочитаемом виде, а к аварийному завершению приложения. Такое поведение объясняется тем, что, встретив спецификатор “%s”, функция printf ожидает увидеть указатель на строку, но не саму строку. В результате происходит обращение по адресу 0x5038384B (“K98PN” в символьном представлении), который находится вне пределов досягаемости программы, что и вызывает исключение.

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

#include <stdio.h>
#include <string.h>
#include <malloc.h>

void main()
{
	FILE *f;
	char *pass;
	char *_pass;
	pass= (char *)malloc(100);
	_pass=(char *)malloc(100);
	if (!(f=fopen("buff.psw","r"))) return;
	fgets(_pass,100,f);
	_pass[strlen(_pass)-1]=0;
	printf("Passw:");fgets(pass,100,stdin);
	pass[strlen(pass)-1]=0;
	// Код, проверяющий истинность пароля, введенного
	// пользователем, для упрощения понимания, опущен 
	printf(pass);
}

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

В приведенном примере указатель _pass оказался расположен на верхушке стека, поэтому использование спецификатора “%s” приводит к выводу на экран эталонного пароля, в чем позволяет убедиться следующий эксперимент:

Passw:%s
K98PN*

Используя спецификатор “%s”, необходимо доподлинно знать, в каком именно месте стека находится искомый указатель. В противном случае произойдет обращение к незапланированной области памяти. Большинство локальных переменных, находящихся в стеке, содержат значения, не превышающие 0x400003, поэтому попытка использовать их в качестве указателя под операционной системой Microsoft Windows NT приведет к исключению. Злоумышленник может использовать это обстоятельство для блокирования вычислительных систем или нарушения их нормальной работы.

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

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

Однако существует механизм, позволяющий прочитать содержимое практически любой ячейки памяти независимо от ее местоположения (разумеется, при условии, что приложение обладает правами на ее чтение). Если строка, введенная пользователем, помещается в стек (а именно так чаще всего и происходит), существует возможность "вручную" сформировать требуемый указатель и затем вывести строку, на которую он ссылается посредством спецификатора “%s”.

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

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

Описанную выше уязвимость можно было бы отнести к забавным курьезам, если бы она ограничивалась одной лишь функцией printf. Но функции с переменным количеством аргументом – не редкость в программистской практике, и многие из них используют ненадежные алгоритмы определения числа переданных параметров. Кроме того, существует множество "швейцарских" функций многоцелевого назначения. Например, функция “open” языка Perl в зависимости от символов, содержащихся в имени файла, может не только открывать файлы, но и запускать другие приложения, клонировать манипуляторы, выдавать содержимое директории и т.д.

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

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

Некоторые разработчики предлагают собственный вариант реализации nargs, который сводится к следующему алгоритму: из стека извлекается адрес возврата из функции и, исходя из предположения, что он указывает на команду наподобие ADD SP, xx, производится попытка определить значение ‘xx’, равное количеству байт, помещенных в стек перед вызовом функции. Недостатки такого приема следующие: он не переносим на отличные от Intel 80x86 платформы; современные компиляторы ведут себя не так, как пять-десять лет назад, и генерируют чрезвычайно запутанный код, допускающий дисбаланс стека на некотором промежутке, отчего процедура анализа количества переданных функции аргументов по сложности приближается к самому компилятору.

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

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

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

1 Здесь и далее первый аргумент функции printf называется "строкой спецификаторов", а все последующие "переменными"    назад

2 Ну чем не трюк для соревнований в "магическом программировании"?    назад

3 Базовый адрес загрузки большинства приложений равен 0x400000    назад

4 Спецификатор "%f" "съедает" восемь байт, но сам занимает два байта, таким образом, в ста байтах вводимой строки можно расположить не более пятидесяти спецификаторов "%f", которые выведут четыреста байт.    назад

5 Тем самым он откроет доступ к коду и данным 32-разрядных приложений, исполняющихся под управлением операционной системы Windows NT, поскольку большинство из них расположено в памяти по адресу выше 0x00401000    назад

Размещение рекламы — тел. +7 495 4119920, ICQ 232284597

Подписка на новости IT-портала CITForum.ru
(библиотека, CITKIT.ru, CitCity)

Новые публикации:

24 декабря

CITKIT.ru:

  • Новогодние поздравления
  • Сергей Кузнецов. Цикл Операционные системы: Ностальгия по будущему:

  • Алексей Федорчук. OpenSolaris 2008.11 Release

  • Сергей Голубев:

  • Евгений Чайкин aka StraNNik (Блогометки):

    17 декабря

  • С.Д.Кузнецов. Базы данных. Вводный курс

    10 декабря

    CITKIT.ru:

  • OpenSolaris 2008.11 Release

  • Альтернативные ОС: две грустные истории (С.Кузнецов)
  • Nokia N810 — доведение до ума
  • CitCity:

  • Платформа 2009: заоблачные перспективы Microsoft

    4 декабря

  • Лекция С.Д.Кузнецова Понятие модели данных. Обзор разновидностей моделей данных

    CITKIT.ru:

  • OpenSolaris 2008.11 Release. Первые впечатления

  • Linux vs FreeBSD: продолжим "Священные войны"?

  • Nokia N810 as is

  • Индульгенция для FOSS

  • Друзья СПО'2008

    26 ноября

  • Нечеткое сравнение коллекций: семантический и алгоритмический аспекты

    CitCity:

    CITKIT.ru:

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • 19 ноября

  • Проблемы экономики производства крупных программных продуктов

  • Язык модификации данных формата XML функциональными методами

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Заметки к книге:

  • FreeBSD: монтирование сменных устройств и механизм HAL
  • Текстовый редактор ee

    12 ноября

  • Правило пяти минут двадцать лет спустя, и как флэш-память изменяет правила (Гоц Грейф, перевод: Сергей Кузнецов)

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:
  • OSS в России: взгляд правоведа (В.Житомирский)

  • Новая статья из цикла С.Голубева "Железный марш":

    29 октября

  • О некоторых задачах обратной инженерии

  • Веб-сервисы и Ruby

  • Тестирование web-приложений с помощью Ruby

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

  • PuppyRus Linux - беседа с разработчиком (С.Голубев)

  • Сергей Кузнецов. Заметка не про Linux

    22 октября

  • Обзор методов описания встраиваемой аппаратуры и построения инструментария кросс-разработки

    CITKIT.ru:

  • Сергей Кузнецов. Почему я равнодушен к Linux

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • Что надо иметь
    3. Базовые познания

    CitCity:

  • Управление IT-инфраструктурой на основе продуктов Microsoft

    15 октября

  • Методы бикластеризации для анализа интернет-данных

    CitCity:

  • Разъемы на ноутбуках: что они дают и зачем их так много?
  • AMD Puma и Intel Centrino 2: кто лучше?

    CITKIT.ru:

  • Новый цикл статей С.Голубева
    Железный марш:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    8 октября

  • Автоматизация тестирования web-приложений, основанных на скриптовых языках
  • Опыт применения технологии Azov для тестирования библиотеки Qt3

    Обзоры журнала Computer:

  • SOA с гарантией качества
  • Пикоджоуль ватт бережет
  • ICT и всемирное развитие

    CitCity:

  • Пиррова победа корпорации Microsoft

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Статья из архива:

  • Я живу в FreeBSD (Вадим Колонцов)

    Новые Блогометки:

  • Перекройка шаблона Blogger или N шагов к настоящему
  • Blogger. Comment style
  • Screenie или глянцевый снимок экрана

    2 октября

    CITKIT.ru:

  • Сага о FreeBSD (А. Федорчук)

    Zenwalk: пакет недели

  • Банинг — интеллектуальное развлечение (С.Голубев)

    CitCity:

    25 сентября

  • Клермонтский отчет об исследованиях в области баз данных

    CITKIT.ru:

  • Пользователям просьба не беспокоиться... (В.Попов)

  • Снова про ZFS: диск хорошо, а два лучше
  • Командная оболочка tcsh (А.Федорчук)

    Zenwalk: пакет недели

    17 сентября

  • T2C: технология автоматизированной разработки тестов базовой функциональности программных интерфейсов
  • Технология Azov автоматизации массового создания тестов работоспособности

    CITKIT.ru:

  • FreeBSD: ZFS vs UFS, и обе-две — против всех (А.Федорчук)

    Zenwalk: пакет недели

  • Дачнет — практика без теории (С.Голубев)

    10 сентября

  • За чем следить и чем управлять при работе приложений с Oracle
  • Планировщик заданий в Oracle
    (В.Пржиялковский)

    CITKIT.ru:

  • Microsoft: ответный "боян" (С.Голубев)

  • Причуды симбиоза, или снова "сделай сам" (В.Попов)

  • Файловые системы современного Linux'а: последнее тестирование
  • Zsh. Введение и обзор возможностей
    (А.Федорчук)

    Описания пакетов Zenwalk: Zsh, Thunar, Thunar-bulk-rename, Xfce4-places-plugin, Xfce4-fsguard-plugin

    Блогометки:

  • Google Chrome
  • Лончер для ASUS Eee PC 701

    3 сентября

    CITKIT.ru:

  • Заметки о ядре (А.Федорчук):

    Добавлены описания пакетов Zenwalk: Galculator, Screenshot, Gnumeric, Pidgin

    В дискуссинном клубе:

  • И еще о Википедии и Google Knol

  • Лекция для начинающего линуксоида (С.Голубев)

    26 августа

  • Транзакционная память (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Открыт новый проект Zenwalk: пакет недели

  • Статья Текстовые процессоры и их быстродействие: конец еще одной легенды?

    21 августа

    CITKIT.ru:

  • Почему школам следует использовать только свободные программы (Ричард Столлман)
  • Беседа Сергея Голубева с учителем В.В.Михайловым

  • Википедия или Гуглезнание? Приглашение к обсуждению (Алексей Федорчук)
  • Народная энциклопедия от Google (StraNNik)

  • Обзор Mandriva 2009.0 Beta 1 Thornicrofti
  • Новичок в Линукс: Оптимизируем Mandriva 2008.1

  • Книга Zenwalk. Приобщение к Linux:

    13 августа

    CitCity:

  • Мирный Atom на службе человеку. Обзор платы Intel D945GCLF с интегрированным процессором
  • Обзор процессоров Intel Atom 230 на ядре Diamondville

  • iPhone - год спустя. Скоро и в России?

    CITKIT.ru:

  • Интермедия 3.4. GRUB: установка и настройка (из книги Zenwalk. Приобщение к Linux)

    6 августа

  • СУБД с хранением данных по столбцами и по строкам: насколько они отличаются в действительности? (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Интермедия 2.2. Что неплохо знать для начала (из книги Zenwalk. Приобщение к Linux)

  • И снова про шрифты в Иксах (А.Федорчук)

  • 20 самых быстрых и простых оконных менеджеров для Linux

  • Дело о трех миллиардах (С.Голубев)

    30 июля

  • OLTP в Зазеркалье (Пересказ: С. Кузнецов)

    CitCity:

  • Будущее BI в облаках?
  • Тиражные приложения и заказная разработка. Преимущества для заказчика
  • Дискуссия со сторонниками заказной разработки

    CITKIT.ru:

  • Новые главы книги Zenwalk. Приобщение к Linux:
  • Глава 8. Пакеты: средства установки, системы управления, системы построения
  • Глава 9. Zenwalk: репозитории, пакеты, методы установки

    23 июля

    CITKIT.ru:

  • Все против всех. 64 vs 32, Intel vs AMD, tmpfs vs ext3
  • Две головы от Intel

  • Zenwalk: обзор штатных приложений (глава из книги "Zenwalk. Приобщение к Linux")

  • Нормально, Григорий...

    16 июля

    Обзоры журнала Computer:

  • Перспективы и проблемы программной инженерии в XXI веке
  • Большие хлопоты с большими объемами данных
  • Перспективы наноэлектроники

    CITKIT.ru:

  • Интермедия о лицензиях (А.Федорчук. "Zenwalk. Приобщение к Linux")

  • Есть ли будущее у KDE?

  • Linux в школе: альтернативный вариант в задачах

  • Шифр (приключения агента Никодима)

    10 июля

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия вступительная. Linux или GNU/Linux? Как вас теперь называть?
  • Глава 5. Среда Xfce
  • Глава 6. Xfce: приложения и плагины

  • ZUR (Zenwalk User Repository) FAQ

    2 июля

  • Персистентность данных в объектно-ориентированных приложениях (С. Кузнецов)

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия 1.2. Дорога к Zenwalk'у. Период бури и натиска
  • Интермедия 3.3. Немного о Linux'е и "железе"
  • Глава 4. Настройка: инструментами и руками
  • Интермедия 4.1. Zenpanel и конфиги: поиски корреляции

  • Интервью с Жан-Филиппом Гийоменом, создателем дистрибутива Zenwalk

  • Linux в школе: первые итоги (С. Голубев)

    25 июня

    CITKIT.ru:

  • Zenwalk. Приобщение к Linux (А. Федорчук)

  • Логика и риторика (С.Голубев)

  • Технология Tru64 AdvFS

  • Ханс Райзер предлагает отвести полицейских к телу Нины

    18 июня

  • Проекты по управлению данными в Google (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • ОС и поддержка "железа": мифы и реальность (А. Федорчук)

  • Linux в школе: другие дистрибутивы

  • Пинок (С. Голубев)

    4 июня

  • Ландшафт области управления данными: аналитический обзор (С. Кузнецов)

    CITKIT.ru:

  • Linux в школе: слово заинтересованным лицам

  • SlackBuild: пакеты своими руками

  • Linux от компании Novell. Установка и обзор openSUSE Linux

    Все публикации >>>




  • IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

    Информация для рекламодателей PR-акции, размещение рекламы — тел. +7 495 4119920, ICQ 232284597 Пресс-релизы — pr@citcity.ru
    Послать комментарий
    Информация для авторов
    Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
    Copyright © 1997-2000 CIT, © 2001-2007 CIT Forum
    Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...