Розробка програми генеруючої паролі користувачів

[ виправити ] текст може містити помилки, будь ласка перевіряйте перш ніж використовувати.

скачати

Федеральне агентство з освіти
Пензенський державний університет
Кафедра «Інформаційна безпека систем і технологій»
Пояснювальна записка до курсової роботи
по темі:
«Розробка програми, яка генерує паролі користувачів»
Дисципліна: Теоретичні основи
комп'ютерної безпеки
Група:.
Виконав:
Проект прийнятий з оцінкою:
Керівник проекту:.
Пенза, 2006р.

Реферат
Пояснювальна записка містить 32 с., 2 рис., 4 джерела, 4 дод.
MICROSOFT VISUAL С + +, ПРОГРАМА, парольної системи, кількісна оцінка стійкості пароля.
Об'єктом дослідження є парольні системи.
Метою роботи є розробка програми, яка генерує паролі користувачів з урахуванням кількісної оцінки стійкості пароля.
У процесі роботи була проведена кількісна оцінка стійкості паролів користувачів і відповідно до отриманої оцінкою була розроблена програма, що генерує паролі користувачів.
У результаті роботи була розроблена програма, що генерує паролі користувачів (її текст наведено у додатку).

Зміст
Реферат
Завдання
Введення
1. Кількісна оцінка стійкості пароля
2. Інтерфейс
2.1 Поняття інтерфейсу і його призначення
2.2. Вибір інтерфейсу
3. Розробка алгоритму програми
4. Створення програми на базі розробленого алгоритму
5. Експериментальна перевірка кількісних оцінок стійкості пароля
6. Керівництво користувача
Висновок
Список використаних джерел
ДОДАТОК А. Алгоритм програми
ДОДАТОК Б. Текст програми
ДОДАТОК В. Random. Cpp
ДОДАТОК Г. PassGenDlg. Cpp

Введення
Проблему комп'ютерної безпеки надуманою не назвеш. Практика показує: чим більш цінна інформація довіряється комп'ютерів, тим більше перебуває охочих порушити її нормальне функціонування заради матеріальної вигоди або просто з цікавості. Йде постійна віртуальна війна, в ході якої організованості системних адміністраторів протистоїть винахідливість комп'ютерних зломщиків.
Основним захисним кордоном проти зловмисних атак є система парольного захисту, яка є у всіх сучасних програмних продуктах. Відповідно до встановленої практики, перед початком сеансу роботи з операційною системою користувач зобов'язаний зареєструватися, повідомивши їй своє ім'я та пароль. Ім'я потрібно для ідентифікації користувача, а пароль служить підтвердженням правильності виробленої ідентифікації. Інформація, введена користувачем в діалоговому режимі, порівнюється з тією, що є у розпорядженні операційної системи. Якщо перевірка дає позитивний результат, то користувачеві стають доступні всі ресурси операційної системи, пов'язані з його ім'ям.
Несанкціонований доступ (Н.С.Д.) до інформації - доступ до інформації, що порушує встановлене правило розмежування доступу і здійснюваний з використанням позаштатних коштів, наданих автоматизованою системою.
Виділяють 2 типи методів захисту від Н.С.Д.:
1) організаційні заходи - визначаються документально.
2) Технічні заходи - група методів, які реалізуються програмними, апаратними та програмно - апаратними засобами.
Існують 3 групи методів аутентифікації, які засновані на володінні деякого властивості або об'єкта
1) володіння певним об'єктом;
2) засноване на знанні інформації відомої користувачеві і перевіряє стороні;
3) засноване на тому, що у кожного користувача є унікальні біометричні характеристики.
Загальні підходи до побудови парольних систем.
Способи:
1. з використанням інформації, що зберігається копії пароля;
2. деякий перевірочне значення;
3. парольна система без безпосередньої передачі інформації, про пароль перевіряє стороні;
4. використання пароля для отримання криптографічного ключа.
Ідентифікатор користувача - деяка унікальна інформація, що дозволяє розрізняти індивідуальних користувачів парольної системи. Часто ідентифікатор користувача називають іменем користувача. Пароль - деяка секретна інформація, яка відома тільки користувачеві і парольного системі, яка пред'являється для проходження процедури ідентифікації.
Обліковий запис користувача - сукупність його ідентифікатора і пароля. База даних користувачів парольної системи містить облікові записи користувачів парольної системи. Під парольного системою розуміється програмно-апаратний комплекс, який реалізує ідентифікацію і аутентифікації користувачів автоматизованої системи на основі одноразових і багаторазових паролів.
Загрози для парольної системи.
1. розголошення параметрів облікового запису
а) підбір пароля;
б) візуальне спостереження;
в) перехоплення пароля в мережі.
2. втручання у функціонування парольної системи
а) використання програмних закладок;
б) виведення з ладу парольної системи;
в) використання помилок і недоробок у парольного системі.
Вибір паролів
Вимоги до вибору паролів:
вимоги до вибору пароля
досягнутий результат
обмеження мінімальної довжини
1 ускладнюється підбір методом прямого перебору
2 ускладнюється підглядання
Використання різних груп символів
ускладнюється підбір методом прямого перебору
перевірка і відбраковування по словнику
утруднення підбору пароля за словником
встановлення терміну дії пароля
ускладнюється підбір методом прямого перебору і підстановки старого
ведення журналу історій пароля
підвищується ефективність попереднього
обмеження кількості спроб введення
перешкоджає підбору пароля
підтримка режиму примусової зміни пароля
збільшення ефекту виконання вимоги стосується зміни пароля
принцип зміна пароля після 1-ої реєстрації
захист від злочинних дій адміністратора
заборона на вибір пароля самим користувачем
захист від вибору користувачем легкого пароля
Затримка при введенні неправильного пароля
утрудняється підбір пароля коли він вводиться з клавіатури безпосередньо за комп'ютером

1. Кількісна оцінка стійкості пароля
Параметр
Спосіб визначення
"А"-потужність алфавіту паролів
L-довжина пароля
можуть застосовується для забезпечення необхідного значення S = A L
"S"-потужність простору паролів
визначається на основі заданих значень P, T, V
"V"-швидкість підбору паролів
швидкість обробки перших спроби реєстрації
"T" - термін дії пароля
визначається з параметра Р.
"P" - можливість вибору пароля протягом терміну його дії (підбір йде неправильно протягом всього часу)
вибирається заздалегідь
Зробимо кількісну оцінку пароля при заданих параметрах:
-Ймовірність підбору пароля Р-10 -4;
-Період дії пароля Т, хвилин-30;
-Довжина пароля L, 6 символів;
-Потужність алфавіту паролів А - великі та малі латинські букви і цифри від 0 до 9 тобто 62 символів;
Необхідно знайти швидкість підбору пароля.
Для знаходження швидкості підбору пароля скористаємося формулою P = V * T / S, причому потужність пароля дорівнює S = A L. Період дії виразимо у секундах (Т = 30 хв .* 60 сек. = 1800 сек.). Таким чином отримуємо V = P * A L / T. Підставивши значення отримали V = 10 -4 * 62 6 / 1800 = 3155 пар. / сек.
Підрахувавши, ми отримали величину швидкості підбору пароля рівну 3155 пар. / сек.

2. Інтерфейс
2.1 Поняття інтерфейсу і його призначення
Перед початком самого програмування і навіть складання алгоритмів необхідно представити себе як буде працювати програма, за допомогою чого вибрати інтерфейс.
Під інтерфейсом розуміють сукупність схемотехнічних засобів і правил, що забезпечують безпосередню взаємодію складових елементів обчислювальної системи і чи програм. Інтерфейс забезпечує взаємозв'язок між функціональними блоками або пристроями системи.
Основним призначенням інтерфейсу є уніфікація внутрішньосистемних і міжсистемних зв'язків та пристроїв сполучення з метою ефективної реалізації прогресивних методів проектування функціональних елементів обчислювальної системи.
Системний підхід при проектуванні є комплексним, взаємозалежне, пропорційним розглядом всіх чинників, шляхів і методів розв'язання складної багатофакторної і багатоваріантного задачі проектування інтерфейсу взаємодії. На відміну від класичного інженерно-технічного проектування при використанні системного підходу враховуються всі чинники проектованої системи - функціональні, психологічні, соціальні і навіть естетичні.
Автоматизація управління неминуче спричиняє за собою здійснення системного підходу, тому що вона передбачає наявність саморегульованої системи, яка має входами, виходами і механізмом управління. Вже саме поняття системи взаємодії указує на необхідність розгляду навколишнього середовища, в якому вона повинна функціонувати.
Таким чином, система взаємодії повинна розглядатися як частина більш обширної системи - АСУ реального часу, тоді як остання - системи керованого середовища.
В даний час можна вважати доведеним, що головна задача проектування інтерфейсу користувача полягає не в тому, щоб раціонально "вписати" людини в контур управління, а в тому, щоб, виходячи із завдань управління об'єктом, розробити систему взаємодії двох рівноправних партнерів (людина-оператор та апаратно-програмний комплекс АСУ), раціонально управляючих об'єктом управління.
2.2 Вибір інтерфейсу
Інтерфейс взаємодії з користувачем є важливим елементом будь-якої програми. Від його продуманості і зручності часто залежить комерційний успіх програмного продукту.
Інтерфейс користувача можна розділити на пакетний та інтерактивні. Пакетні характеризуються тим, що користувач повинен сформувати пакет із завданнями, потім програма ці завдання виконує і видає результат. Інтерактивні характеризуються тим, що користувач під час роботи програми постійно з нею взаємодіє. Існує інтерфейс на базі меню, псевдографічний інтерфейс, інтерактивно-командний інтерфейс, ці інтерфейси описувати не будемо, тому що програма, яку необхідно створити за завданням вимагає графічний інтерфейс. Графічний інтерфейс слід вибирати тільки для багатомодульних програм, які, імовірно будуть мати масове застосування. Відповідно до завдання і для більшої зручності і поняття принципу роботи програми інтерфейс повинен містити найменшу кількість кнопок. Внаслідок чого виберемо: 1 поле, в якому будемо генерувати сам код, одну кнопку після натискання, якій буде відбуватися генерація, і кнопку вихід.
Інтерфейс наведено на малюнку 1.

3. Розробка алгоритму програми
У даному розділі проводиться розробка алгоритму роботи програми, яка генерує паролі користувачів.
Перш ніж почати розробку, вводимо кілька обмежень:
- Програма повинна виключати підбір пароля за словником;
- Програма повинна забезпечувати взаємодію з користувачем за допомогою графічного інтерфейсу;
- Процес виконання генерації паролів повинен бути реалізований в інтегрованому середовищі розробки Microsoft Visual C + + v. 6.0.
- Символи не повинні повторюватися.
Після запуску програми і натискання на клавішу "Генерувати код" повинен генеруватися випадково перший символ з наперед створеного масиву символів PassAlfavit [], після чого цей символ записується в інший масив passwrd []. Далі генерується другий і відбувається перевірка, не повторюються чи символи. Якщо виконується дана умова, то відбувається видалення останнього символу, якщо ж ні, то відбувається запис в масив passwrd [] з наступним символом.
Потім відбувається перевірка, не досягнуто чи довжина пароля, що забезпечує його стійкість при заданих параметрах, відповідно до завдання довжина пароля буде дорівнює 6 символів. Після чого відбувається приєднання символів в одне слово і відбувається перевірка на наявність згенерованого пароля в словнику англійських слів і абревіатур, якщо даний пароль існує в словнику, то відбувається його видалення і генерація починається спочатку.
Після завершення генерації пароля він повинен бути виданий у спеціальному полі.
Структурна схема алгоритму програми, яка генерує паролі користувачів, наведена у додатку А.

4. Створення програми на базі розробленого алгоритму
У даному розділі наводиться опис тексту програми виконує генерацію паролів користувачів. Дана програма реалізована на мові програмування С + + за допомогою інтегрованого середовища обробки Visual С + +.
Оскільки архітектура Windows-програм заснована на принципі повідомлень, всі ці програми містять деякі загальні компоненти. Зазвичай їх доводиться в явному вигляді включати до початкового коду. Але, на щастя, при використанні бібліотеки MFC це відбувається автоматично; немає необхідності витрачати час і зусилля на їх написання. Створення діалогового застосування з використанням AppWizard
Робота з елементами управління
Для початку необхідно створити поле, в якому буде виводитися згенерований код. Для цього в робочу область перетягується елемент Edit Box (Текстове поле). Потім регулюються її розміри і положення.
Так само необхідно створити клавішу після, що буде відбуватися генерація коду, для цього перетягнемо з панелі інструментів елемент з назвою Button.
Відкриємо діалогове вікно Edit Properties. У тестове поле розкриває списку ID: (Ідентифікатор ресурсу) замість ідентифікатора IDC_EDIT1 введемо ідентифікатор IDGEN, а в полі caption введемо слово Generirowanie.
Клавішу Cancel яку створив MFC AppWizard залишимо без змін але вкажемо нове місце розташування.
На цьому етап формування діалогового вікна можна вважати закінченим. Справа в тому, що одночасно з виробленими нами діями програмна оболонка Visual C + + фіксувала все внесені зміни у файлах PassGen.rc і resource.h.
Створення класу діалогу
Приступимо до створення класу діалогу. Дуже велику частку роботи із створення цього класу вже виконав майстер AppWizard, а ще деяку частину роботи візьме на себе майстер ClassWizard.
Оболонка Visual C + + сама створить Password.cpp і Random.cpp. Далі необхідно буде замінити дані файли, на файли, наведені в додатку Б та В відповідно.
Далі залишається тільки зберегти і відкомпілювати дану програму.
На цьому створення програми на мові С + + закінчилося.

5. Експериментальна перевірка кількісних оцінок
Дану експериментальну перевірку будемо здійснювати, змінюючи швидкість підбору паролів, і фіксувати час, за який не буде скомпрометований пароль, при цьому значення P і S змінюватися не будуть.
- Ймовірність підбору пароля P = 10 -3;
- Потужність простору паролів S = 1,6 * 12 жовтня
Час, за який даний пароль не буде скомпрометований, обчислюється за такою формулою: T = (P * S) / V
1 Швидкість підбору пароля V, паролів / сек-1 * 10 5;
T = (10 -3 * 1.6 * 10 12) / 10 5 = 1600 секунд => 4.44 години
2 Швидкість підбору пароля V, паролів / сек-2 * 10 5;
T = (10 -3 * 1.6 * 10 12) / 2 * 10 5 = 8000 секунд => 2.22 години
3 Швидкість підбору пароля V, паролів / сек-2, 5 * 10 5;
T = (10 -3 * 1.6 * 10 12) / 2,5 * 10 5 = 6400 секунд => 1.77 години
4 Швидкість підбору пароля V, паролів / сек-3 * 10 5;
T = (10 -3 * 1.6 * 10 12) / 3 * 10 5 = 5333 секунд => 1.48 години
При збільшенні швидкості підбору паролів в два рази час, витрачений на підбір, зменшується також у два рази.
Для того, що б точно скомпрометувати пароль за три години, необхідна швидкість підбору паролів V = 1.5 * 10 8 паролів / сек. Час злому також зменшується від виду атаки і від ступеня обізнаності зловмисника. Так найпростіша програма для злому паролів архіватора RAR "Advanced RAR Password Recovery" передбачає 3 типи атаки:
- Перебір
- За маскою
- За словником
Скоротити час злому також можна, вказавши передбачувану довжину або встановивши її рамки, так само можна вказати мову або набір символів, з яких ймовірно складається пароль.

6. Керівництво користувача
Для початку роботи з програмою необхідно запустити файл з назвою PassGen. Після запуску з'явиться вікно. Для генерації пароля необхідно натиснути на клавішу "GENERIROVANIE". Після чого у віконці з'явиться сгенеррірованний пароль. Далі необхідно запам'ятати пароль і використовувати за призначенням. При повторному натисненні на клавішу пароль буде створений знову. Для виходу з програми необхідно натиснути на клавішу "Вихід" або натиснувши на "хрестик".

Висновок
У процесі виконання курсового проекту була розроблена програма, що генерує паролі користувачів. Програма була написана за допомогою інтегрованого середовища розробки Visual C + +. Програма відповідає всім функціональним вимогам, заданим на курсове проектування. Взаємодія з користувачем здійснюється за допомогою графічного інтерфейсу.
Таким чином, завдання на курсове проектування було повністю виконано.

Список використаних джерел
1 http://www.diwaxx.ru/hak/index.php
2 http://www.passwords.ru
3 Келецький Я. Енциклопедія мови Сі / Пер. з англ .- М.: Світ, 1992. -687с.
4 Керніган Б., Річі Д., Фьюер А. Мова програмування Сі. Завдання з мови С / Пер. з англ. - М.: Фінанси і статистика, 1985.-279с.

ДОДАТОК А
Алгоритм програми
початок
Завдання масиву символів PassAlfavit []
B


Випадкове генерування 1-го символу з масиву PassAlfavit []
-----------[ З ліста2
Запис символу в масив passwrd []
Генерування наступного символу
Такий символ є
Запис символу в масив passwrd [] з наступним індексом
Кількість символів досягнуто
Видалення останнього символу


А
Овал: А --------------[ На лист 2
Рисунок А.1. Алгоритм програми

А
Овал: А ---------------------------------------[ З листа 1
B
Овал: B



Приєднання символів
------[ На лист 1
Є у словнику
Видалення всього коду
Висновок пароля на екран
кінець


Рисунок А.1. Лист № 2

ДОДАТОК Б
Текст програми
/ / Password.cpp: implementation of the Password class.
////////////////////////////////////////////////// ////////////////////
# Include <afx.h>
# Include "stdafx.h"
# Include "PassGen.h"
# Include "Password.h"
# Include "Random.h"
# Ifdef _DEBUG
# Undef THIS_FILE
static char THIS_FILE []=__ FILE__;
# Define new DEBUG_NEW
# Endif
////////////////////////////////////////////////// ////////////////////
/ / Construction / Destruction
////////////////////////////////////////////////// ////////////////////
Password:: Password (int l)
{Length = l;
passwrd = new char [length +1];
dicstr = new char [length +1];
PassAlfavit = new char [36];
HowMuchn = new int [length];
dicstr [length] = '\ 0';
ValueOfDictionary = 134547;}
Password:: ~ Password ()
{Delete (passwrd);
delete (dicstr);
delete (PassAlfavit);
delete (HowMuchn);}
void Password:: GenAlfavit ()
{Char symbol = 'A';
for (int index = 0; index <36; index + +)
{If (index == 26)
symbol = "0";
PassAlfavit [index] = symbol;
symbol ++;}}
char * Password:: GetPassword ()
{Return passwrd;}
void Password:: GenPass ()
{Random rnd1;
for (int index = 0; index <length; index + +)
passwrd [index] = PassAlfavit [rnd1.NextR (35)];
passwrd [index] = '\ 0';}
BOOL Password:: TestChar ()
{ClearMass (length, HowMuchn);
for (int index1 = 0; index1 <length; index1 + +)
for (int index2 = 0; index2 <length; index2 + +)
if (passwrd [index1] == passwrd [index2])
HowMuchn [index1] + +;
if (HowMuch (length, HowMuchn))
return TRUE;
else return FALSE;}
void Password:: ClearMass (int length, int * mass)
{For (int index = 0; index <length; index + +)
mass [index] = 0;}
BOOL Password:: HowMuch (int length, int * HowMuch)
{For (int index = 0; index <length; index + +)
if (HowMuch [index]> 1)
return FALSE;
return TRUE;}
BOOL Password:: TestDictionary ()
{CFile Dictionary;
Try
{Dictionary.Open ("length08.txt", CFile.modeRead, NULL);}
catch (CFileException * e)
{Dictionary.Abort (); / / close file safely and quietly
e-> ~ CFileException ();
MessageBox (0, "Не вдається відкрити словник", "помилка", MB_APPLMODAL | MB_OK | MB_ICONSTOP);
return FALSE;}
for (int index = 0; index <ValueOfDictionary; index + +)
{Dictionary.Read (dicstr, 8);
Dictionary.Seek (2, CFile.current);
if (Compare (length))
return FALSE;}
Dictionary.Close ();
return TRUE;}
int Password:: Compare (int length)
{For (int index = 0; index <length; index + +)
if (passwrd [index]! = dicstr [index])
return 0;
return 1;}

ДОДАТОК В
Random.cpp
/ / Random.cpp: implementation of the Random class.
////////////////////////////////////////////////// ////////////////////
# Include <windows.h>
# Include <Winbase.h>
# Include <stdlib.h>
# Include "stdafx.h"
# Include "PassGen.h"
# Include "Random.h"
# Ifdef _DEBUG
# Undef THIS_FILE
static char THIS_FILE []=__ FILE__;
# Define new DEBUG_NEW
# Endif
////////////////////////////////////////////////// ////////////////////
/ / Construction / Destruction
////////////////////////////////////////////////// ////////////////////
Random:: Random ()
{Srand (GetTickCount ());}
Random:: ~ Random ()
{}
int Random:: NextR (int x)
{Int rnd1;
rnd1 = rand ();
srand (rnd1);
rnd1 = rand ()% x;
return rnd1;}

ДОДАТОК Г
PassGenDlg.cpp
/ / PassGenDlg.cpp: implementation file
# Include "stdafx.h"
# Include "PassGen.h"
# Include "PassGenDlg.h"
# Include "Password.h"
# Ifdef _DEBUG
# Define new DEBUG_NEW
# Undef THIS_FILE
static char THIS_FILE [] = __FILE__;
# Endif
////////////////////////////////////////////////// ///////////////////////////
/ / CPassGenDlg dialog
CPassGenDlg:: CPassGenDlg (CWnd * pParent / *= NULL * /)
: CDialog (CPassGenDlg:: IDD, pParent)
{//{{ AFX_DATA_INIT (CPassGenDlg)
/ / NOTE: the ClassWizard will add member initialization here
/ /}} AFX_DATA_INIT
/ / Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp () -> LoadIcon (IDR_MAINFRAME);}
void CPassGenDlg:: DoDataExchange (CDataExchange * pDX)
{CDialog:: DoDataExchange (pDX);
/ / {{AFX_DATA_MAP (CPassGenDlg)
/ / NOTE: the ClassWizard will add DDX and DDV calls here
/ /}} AFX_DATA_MAP}
BEGIN_MESSAGE_MAP (CPassGenDlg, CDialog)
/ / {{AFX_MSG_MAP (CPassGenDlg)
ON_WM_PAINT ()
ON_WM_QUERYDRAGICON ()
ON_BN_CLICKED (IDGEN, OnGen)
/ /}} AFX_MSG_MAP
END_MESSAGE_MAP ()
////////////////////////////////////////////////// ///////////////////////////
/ / CPassGenDlg message handlers
BOOL CPassGenDlg:: OnInitDialog ()
{CDialog:: OnInitDialog ();
/ / Set the icon for this dialog. The framework does this automatically
/ / When the application's main window is not a dialog
SetIcon (m_hIcon, TRUE); / / Set big icon
SetIcon (m_hIcon, FALSE); / / Set small icon
/ / TODO: Add extra initialization here
return TRUE; / / return TRUE unless you set the focus to a control}
/ / If you add a minimize button to your dialog, you will need the code below
/ / To draw the icon. For MFC applications using the document / view model,
/ / This is automatically done for you by the framework.
void CPassGenDlg:: OnPaint ()
{If (IsIconic ())
{CPaintDC dc (this); / / device context for painting
SendMessage (WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc (), 0);
/ / Center icon in client rectangle
int cxIcon = GetSystemMetrics (SM_CXICON);
int cyIcon = GetSystemMetrics (SM_CYICON);
CRect rect;
GetClientRect (& rect);
int x = (rect.Width () - cxIcon + 1) / 2;
int y = (rect.Height () - cyIcon + 1) / 2;
/ / Draw the icon
dc.DrawIcon (x, y, m_hIcon);}
else
{CDialog:: OnPaint ();}}
/ / The system calls this to obtain the cursor to display while the user drags
/ / The minimized window.
HCURSOR CPassGenDlg:: OnQueryDragIcon ()
{Return (HCURSOR) m_hIcon;}
void CPassGenDlg:: OnGen ()
{Password ps (8);
ps.GenAlfavit ();
do
{Ps.GenPass ();
if (! ps.TestChar ())
continue;
else
if (ps.TestDictionary ())
break;
else
continue;}
while (TRUE);
SetDlgItemText (IDC_EDIT1, ps.GetPassword ());}
Додати в блог або на сайт

Цей текст може містити помилки.

Програмування, комп'ютери, інформатика і кібернетика | Курсова
56.6кб. | скачати


Схожі роботи:
Розробка і створення СКС на базі мереж Ethernet при підключенні користувачів житлового будинку до глобальної
Розробка програми запитів
Розробка програми Helpopr
Розробка програми на Java
Розробка програми-компілятора
Розробка екскурсійної програми в м Челябінську
Розробка програми кадрового аудиту
Розробка комплексної програми стимулювання збуту
Розробка програми для квадратної матриці
© Усі права захищені
написати до нас