Security-Enhanced Linux — линукс с улучшенной безопасностью

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

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 18.09.2016
Размер файла 61,5 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

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

3. Технологическая часть

3.1 Выбор дистрибутива

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

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

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

Вот эти три дистрибутива: Debian, Read Hat, Slackware.

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

Группа Read Hat включает в: Red Hat, Fedora Core, KSI, Black Cat, ASP Linux, AltLinux, Mandrake, BestLinux, TurboLinux и др.

Родителем всей этой группы является дистрибутив Red Hat. На сегодня это один из самых популярных дистрибутивов. Компания Red Hat представляет несколько вариантов поставки, но все они платные. Поэтому выбор пал на дистрибутив Fedora Core - настольную версию Red Hat, отправленной в свободное плавание.

Т.к. поддержка SELinux была включена в дистрибутивы Fedora Core только с версии 2, а последняя 5-ая версия считается еще не устоявшейся, то был выбран дистрибутив Fedora Core 4.

3.2 Создание демона

Демон - это консольное приложение, т.к. он работает в неинтерактивном режиме и графическая оболочка ему не нужна.

Создание демона можно логически разделить на три части:

Создание процесса с помощью fork();

Отрыв от управляющего терминала;

Обработка сигналов или событий (совершение так называемой полезной работы)

Системный вызов fork создает новый процесс. Возвращает идентификатор дочернего процесса или 0 в случае успеха и -1 в случае ошибки (код ошибки - в переменной errno).

На языке Си создание нового процесса будет выглядеть так:

int pid = fork();

if( pid = = -1 ) // fork failed

{perror(“Невозможно создать процесс!”);

exit( 1 );}

else

{if( pid <> 0 ) exit( 0 ); // parent process exits}

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

Т.к. по завершению fork оба процесса (потомок и предок) получают от него возвращаемое значение, а нам интересен потомок, то строкой «if( pid <> 0 ) then exit( 0 );» мы завершаем процесс предок (процесс-потомок получает от fork значение 0, родительский процесс - идентификатор процесса-потомка), в то время как дочерний процесс продолжает выполняться.

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

Новая сессия создается вызовом функции setsid:

pid = setsid();

if( pid = = -1 ) // setsid failed

{perror(“Невозможно создать новую сессию”);

exit( 1 );}

Теперь процесс выполняется в режиме демона.

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

В связи с этим было решено написать свой обработчик сигналов.

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

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

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

В данной работе демон обрабатывает только сигналы SIGUSR1, SIGUSR2, SIGTERM, SIGINT, SIGQUIT. Остальные сигналы игнорируются, ну кроме сигнала SIGKILL (данный сигнал не может блокироваться и приводит к безусловному завершению процесса на уровне операционной системы).

Сигналы SIGUSR1 и SIGUSR2 не имеют стандартного назначения. Ими можно пользоваться в различных ситуациях.

При получении сигнала SIGUSR1 демон выводит на терминал информацию о программе, при получении SIGUSR2 - системную информацию(PID, PPID, UID, GID).

Все полученные сигналы протоколируется в файл с указанием времени получения сигнала.

3.3 Политика для созданного демона

По умолчанию, в целевой политике все процессы, для которых не определены собственные политики, запускаются в домене unconfined_t, в котором SELinux разрешает все.

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

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

Для начала нужно создать саму сущность hevil. Прошу заметить, что в настоящий момент мы находимся от имени пользователя root системы UNIX, но в SELinux это будет сущность (пользователь) hevil.

В конец файла /ets/selinux/targeted/policy/src/users.te нужно добавить следующее объявление:

user hevil roles { user_r hevil_r };

Данная строчка означает, что будет создан пользователь hevil с ролями user_r и hevil_r.

Чтобы можно было запустить демона под данной сущностью нужно прописать роль hevil_r в /ets/selinux/targeted/policy/src/domains/misc/hevil.te:

full_user_role(hevil); # Создание обычной пользовательской роли (назначение

# соответствующих прав)

in_user_role(hevil_daemon_t); # Объявление перехода контекста роли user_r в домен

# hevil_daemon_t

Добавим правило перехода между ролями в /ets/selinux/targeted/policy/src/rbac:

allow user_r hevil_r;

allow hevil_r user_r;

Теперь можно будет свободно переходить из роли user_r в hevil_r.

Определим макрос перехода контекста, для этого нужно отредактировать файл

/ets/selinux/targeted/policy/src/ /macros/user_macros.te, добавив следующие строки:

undefine(`in_user_role')

define(`in_user_role', `

role user_r types $1;

role staff_r types $1;

role hevil_r types $1;')

Устанавливаем с командной строки контекст для домашнего каталога /home/hevil:

find /home/hevil -print0|xargs -0 chcon --h hevil:object_r:hevil_home_t

chcon -h hevil:object_r:hevil_home_dir_t /home/hevil

Типы hevil_home_dir_t и hevil_home_t автоматически создались при создании сущности.

Для корректной работы политики необходимо создать еще тип директории с демоном, тип файла с демоном и исполняемого файла. Это достигается редактированием файла /ets/selinux/targeted/policy/src//types/hevil_types.te:

# Создание соответствующих типов

type hevil_daemon_t, domain;

type hevil_daemon_dir_t, dir_type;

type myapp_exec_t, file_type, sysadmfile, exec_type;

# Правило перехода от типа hevil_daemon_t

# к hevil_daemon_exec_t

type_transition hevil_daemon_t hevil_daemon_exec_t:{ file }

Далее установим контекст для этой директории и файла. Эти действия аналогичны, как и для домашнего каталога.

find /root/daemon -print0|xargs -0 chcon --h hevil:object_r:hevil_home_t

chcon -h hevil:object_r:hevil_home_dir_t /root/daemon

Устанавливаем правило доступа hevil_r к hevil_daemon_t и hevil_daemon_dir_t.

hevil_t - это пользовательский домен роли hevil_r (создается автоматически).

hevil_daemon_exec_t - тип исполняемого файла.

# Разрешение записи в директорию с демоном

rw_dir_create_file(hevil_t, hevil_daemon_dir_t)

# Разрешение запуска демона

can_exec(hevil_t, hevil_daemon_exec_t)

Создаем домен, в котором выполняется демон. В файл /ets/selinux/targeted/policy/src/domains/program/hevil.te вписываем строчку:

daemon_domain(daemon_t);

Данный макрос создаст стандартный домен для демона.

В этот же файл добавим еще правило для демона:

role system_r types daemon_t; #разрешен доступ суперпользователя

role hevil types daemon_t; #разрешен доступ для hevil

in_iser_role(daemon_t) #объявление перехода контекста hevil в #daemon_t

# Автоматически при запуске демона осуществляется переход

# в домен демона

domain_auto_trans(hevil_t, hevil_daemon_exec_t, daemon_t)

# Разрешаем init переходить в daemon_t при загрузке

domain_auto_trans(initrc_t, daemon_exec_t, daemon_t)

#hevil_t может перейти в daemon_t во время запуска демона

domain_auto_trans(hevil_t, daemon_exec_t, daemon_t)

#доступ к терминалу

allow daemon_t admin_tty_type:chr_file rw_file_perms;

#разрешение на запись в файл

allow daemon_t { ttyfile ptyfile }:chr_file rw_file_perms;

#разрешение писать в файл домашнего каталога

rw_dir_create_file(daemon_t, hevil_home_dir_t)

Теперь остается самый ответственный этап: компилирование и загрузка политики в память. make load

3.4 Демонстрация работы демона

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

Регистрируемся в системе под root.

Запускаем демона командой ./hevil (в каталоге с программой).

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

С помощью команды kill [номер сигнала] [PID процесса] посылаем различные сигналы демону. Просмотрев журнал можно убедиться, что все записано в лог, т.е. демон работоспособен.

Теперь с помощью команды make load загружаем новую политику в память.

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

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

Заключение

В данной работе была освещен Security-Enhanced Linux -- линукс с улучшенной безопасностью.

Достоинства данной технологии очевидны, т.к. он базируется на принципе наименьших прав, т.е. запущенному процессу дается именно столько прав, сколько ему требуется. Более того, SELinux существует параллельно с классической системой безопасности Linux, независим от нее. SELinux обрабатывает только те запросы, которые разрешены классической системой безопасности и не может разрешить то, что запрещено последней. На примере демона, запущенного от имени root (т.е. с нулевым уровнем привилегий) было продемонстрирована «сила» Security-Enhanced Linux.

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

В настоящее время ведутся активные работы как по переводу документации SELinux на русский язык, так и попыток создания ПО.

Несомненно, нужно отметить, что LUG (Linux User Group) нашего университета тоже присоединилось к этому движению. Несколько студентов решили объединить свои силы для помощи мировому сообществу.

Список литературы

1. Эви Немеет, Гарт Снайдер, Скотт Сибасс, Трент Р.Хейн «UNIX. Руководство системного администратора для профессионалов», 3-е издание

2. Марк Дж. Рочкинд «Программирование для UNIX. Наиболее полное руководство в подлиннике», 2-е издание

3. Алексей Стахнов «Linux. Наиболее полное руководство в подлиннике», 2-е издание

Приложения

Приложение 1

Установка основных пакетов SELinux для Fedora.

Пакеты RPM с новой реализацией SE Linux могут быть получены с узла ftp://people.redhat.com/dwalsh/SELinux

Эти пакеты поддерживаются Дэном Уолшем (Dan Walsh).

Для установки SE Linux на тестовой машине с дистрибутивом Fedora нужно сделать следующее:

Отредактировать файл yum.conf, чтобы он содержал такие строки:

[main]

cachedir=/var/cache/yum

debuglevel=2

logfile=/var/log/yum.log

pkgpolicy=newest

distroverpkg=fedora-release

tolerant=1

exactarch=1

[development]

name=Fedora Core $releasever - Development Tree

#baseurl=http://download.fedora.redhat.com/pub/fedora/linux/core/development/i386

baseurl=http://mirror.dulug.duke.edu/pub/fedora/linux/core/development/i386

[SELinux]

name=SELinux repository

baseurl=ftp://people.redhat.com/dwalsh/SELinux/Fedora

Установить соответствующие пакеты.

yum install policy checkpolicy policycoreutils policy-sources pam passwd vixie-cron

После этого, выполнить такие команды:

cd /etc/security/selinux/src/policy

make load

make relabel

Перезагрузить машину.

Приложение 2

Работа с RPM-пакетами.

Основные команды:

rpm -i <имя_пакета> - установка пакета

rpm -q -p <имя_пакета> -i - краткая информация о пакете: размер, автор и т.д.

rpm -q -p <имя_пакета> -il | less - просмотр информации постранично (параметр l означает, что нужно выводить содержимое данного пакета)

rpm -q -f <имя_файла> -i - определение к какому пакету относится данный файл.

rpm -U <имя_пакета> - обновление пакета (данная команда не только установит пакет, но также удалит все предыдущие версии)

rpm -e <имя_пакета> - удаление пакета

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

Типичный пример использования RPM таков: предположим, нам нужно установить на машину некую игру, хранящуюся в файле tetris.rpm

Установка программы

rpm -i tetris.rpm

Через месяц вышла новая версия, tetris_1.rpm. Обновление программы:

rpm -U tetris_1.rpm

Ещё через месяц игра надоела. Удаляем её с машины:

rpm -e tetris.rpm

Управлять пакетами можно также с помощью программ Midnight Commander (mc), purp и ряда других, имеющихся практически в любом Linux-дистрибутиве.

Приложение 3

Исходный код демона.

#include <unistd.h>

#include <stdio.h>

#include <syslog.h>

#include <signal.h>

#include <time.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <fcntl.h>

#include <grp.h>

#include <errno.h>

int errno;

#define PATH "hevil.l"

inline void do_packet_loop();

void fsignal(int sig);

void open_mesg();

/*Здесь идет собственно тело демона, в моем случае программа

приостанавливает свою работу до получения какого-то сигнала*/

inline void do_packet_loop()

{while(1)pause();}

// Собственный обработчик сигналов

void fsignal(int sig)

{// Открытие файла лога

FILE* fp;

if( (fp = fopen(PATH, "a")) == NULL )

{open_mesg();

_exit(0);}

// Определяем текущее время

time_t timv = time(NULL);

struct tm *local_tm = localtime(&timv);

switch(sig)

{case SIGUSR1:

fprintf(fp, "[СИГНАЛ] Получен сигнал № %d в %s", sig, asctime(local_tm));

printf("\n .:Информация о демоне:.\n Данный демон перехватывает и обрабатывает некоторые сигналы, \n протоколирует в лог все происходящие с ним события. \n GID и UID присваивается в зависимости от пользователя, запустившего данный демон.\n\n Автор: Тармолов А.В. \t Группа: ИУ7-63\n\n");

break;

case SIGUSR2:

fprintf(fp, "[СИГНАЛ] Получен сигнал № %d в %s", sig, asctime(local_tm));

printf("\n .:Системная информация о демоне:.\n PID = %d \n PPID = %d \n GID =A%d \n UID = %d\n\n", getpid(), getppid(), getgid(), getuid());

break;

case SIGTERM:

case SIGINT:

case SIGQUIT:

fprintf(fp, "[СИГНАЛ] Демоном получен сигнал завершения № %d в %s", sig, asctime(local_tm));

fclose(fp);

_exit(0);

break;

default:

fprintf(fp, "Сигнал %d не обработан(пропущен)\n",sig);

break;}

fclose(fp);}

int main(int argc,char** argv)

{chdir("/"); // Переходим на рут, чтоб не блокировать файловые системы

if(fork()) _exit(0); // Форкаемся.

FILE* fp;

if( (fp = fopen(PATH, "w")) == NULL )

{open_mesg();

_exit(0);}

// Определяем текущее время

time_t timv = time(NULL);

struct tm *local_tm = localtime(&timv);

fprintf(fp, "[СИГНАЛ] Демоном стартовал в %s", asctime(local_tm));

fclose(fp);

setsid(); // Отрываемся от управляющего терминала и переходим в фоновый режим

int j;

for(j=1; j<32; j++) /*настраиваем обработчиком всех сигналов функцию fsignal*/ signal(j,fsignal);

printf("PID = %d\n\n", getpid()); // В принципе это для отладки

do_packet_loop(); // "Демонизируем" программу. В бесконечном цикле будет ожидать сигнала.}

void open_mesg()

{perror("[daemon] Ошибка открытия файла лога!");

printf("[daemon] Демон аварийно завершает свою работу!");}

Размещено на Allbest.ru

...

Подобные документы

  • Установка с помощью технологии SELinux ограничения для демона, запущенного суперпользователем. Понятие и структура процессов в системе UNIX. Вариант редактирования исходных кодов политик, компилирования, просмотра логов и внесение изменений в код.

    курсовая работа [109,3 K], добавлен 24.06.2009

  • Анализ технических возможностей операционной системы Mandriva Linux - дистрибутива GNU/Linux, разрабатываемого французской компанией Mandriva, выпускающей свободные, коммерческие и корпоративные версии своего дистрибутива. Этапы установки оболочки Linux.

    презентация [26,2 M], добавлен 23.05.2010

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

    лабораторная работа [847,5 K], добавлен 16.06.2011

  • Операционная система Linux как ПК-версия операционной системы Unix. Характеристика KOrganizer — простого в использовании менеджера персональной информации. Основные разработки в ALT Linux Master. Особенности разработки в Альт Линукс Школьный Мастер.

    курсовая работа [1,3 M], добавлен 06.06.2011

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

    презентация [486,5 K], добавлен 09.10.2013

  • Компоновка и конфигурирование Linux сервера. Общая информация об ALT Linux Server 5, его подвиды и основные функциональные возможности. Установка дистрибутива ALT Linux 5.0 "Ковчег" и Apache2+php+MySQL. Пример настройки работы сайта на web-сервере.

    курсовая работа [6,0 M], добавлен 24.10.2012

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

    курсовая работа [551,0 K], добавлен 02.04.2014

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

    дипломная работа [1,1 M], добавлен 18.07.2013

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

    презентация [1,4 M], добавлен 24.01.2014

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

    лекция [112,2 K], добавлен 29.07.2012

  • Linux - ядро операционной системы с монолитной архитектурой. Прародители операционной системы Linux, ее стабильные и экспериментальные версии. Процесс внедрения Linux и свободного программного обеспечения в школах и государственных учреждениях России.

    реферат [18,2 K], добавлен 19.01.2013

  • Рассмотрение различных дистрибутивов операционной системы. Изучение протоколов обмена данными и форматов физического хранения данных. Разработка дистрибутива на основе операционной системы Linux для функционирования в составе сетевого хранилища StarNAS.

    курсовая работа [1,6 M], добавлен 05.11.2015

  • Анализ серверных операционных систем на базе ядра Linux. Подходы к построению маршрутизации и оценка полученных результатов. Установка операционной системы CentOS 6.6 и закономерности ее настройки. Принципы и основные этапы тестирования созданного шлюза.

    курсовая работа [2,9 M], добавлен 19.11.2015

  • Основные моменты истории операционных систем, связывающих аппаратное обеспечение и прикладные программы. Характеристика операционной системы Microsoft Windows Seven, анализ операционной системы Linux. Преимущества и недостатки каждой операционной системы.

    курсовая работа [63,0 K], добавлен 07.05.2011

  • История развития и версии Linux. Ключевые черты, преимущества и сравнительные характеристики операционной системы. Программные характеристики, основные причины успеха и бурного развития Linux. Главные проблемы распространения операционной системы.

    курсовая работа [64,4 K], добавлен 13.12.2011

  • Пример окна входа в систему Linux (графический режим). Простейшие команды Linux. Основные задачи при управлении пользователями. Сведения, которые нужно указать для вновь создаваемого пользователя. Содержимое файла/etc/shadow (в котором содержатся пароли).

    лекция [603,7 K], добавлен 20.12.2013

  • Использование дистрибутива GNU/Linux Mandriva, который по праву считается одним из наиболее легких для освоения начинающими пользователями, для взаимодействия с командным интерпретатором GNU/Linux. Информация о формате и основных ключах команды cal.

    лабораторная работа [2,4 M], добавлен 28.12.2012

  • Основные понятия операционных систем. Современное оборудование компьютера. Преимущества и недостатки операционной системы Linux. Функциональные возможности операционной системы Knoppix. Сравнительная характеристика операционных систем Linux и Knoppix.

    реферат [1,5 M], добавлен 17.12.2014

  • Знакомство с этапами разработки трёх приложений для системы семейства Linux с использованием языка программирования С++. Анализ особенностей операционной системы Ubuntu 12.10. Характеристика способов тестирования команд с помощью стандартных средств.

    контрольная работа [732,1 K], добавлен 06.08.2013

  • Механизмы шифрования данных в ОС LINUX MINT. Реализация FDE в интерфейсе инсталлятора. Одно из главных достоинств утилиты CryptKeeper. Создание учётной записи через терминал. Графический интерфейс прав доступа. Резервное копирование данных программы.

    курсовая работа [2,9 M], добавлен 11.12.2014

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.