Контроль програм, які запускаються на даному комп"ютері

Описание:
Тип работы: курсовая работа
Програма, що контролює програми, які запускаються на комп"ютері на мові ASM-86. Алгоритм програми: перевірка параметрів, які задані в командному рядку, та функції обробника переривання 21h. Компілювання Turbo Assembler, зв"язування за допомогою TLINK.
Доступные действия
Введите защитный код для скачивания файла и нажмите "Скачать файл"
Защитный код
Введите защитный код

Нажмите на изображение для генерации защитного кода

Текст:

Міністерство освіти і науки України

Кiровоградський Державний Технiчний Унiверситет

Факультет автоматики енергетики та програмування

Кафедра програмного забезпечення

Курсовая работа

з дисципліни

“ASM-86 ”

на тему:

"Контроль програм, які запускаються на даному комп"ютері"


Зміст

1. Вступ

2. Постановка задачі

3. Обґрунтування вибору методів розв^язку задачі

4. Алгоритм програми

5. Реалізація програми

6. Системні вимоги

7. Інструкція для користувача

8. Висновки

Використана література

Додаток

Лістинг програми


1. Вступ

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

Але в наш час комп^ютер використовується і як ігровий автомат, на якому можна грати в різні ігри. Тому програма, яка б дозволяла контролювати ті програми, які запускаються на комп^ютері, була б дуже корисною.


2. Постановка задачі

Розробити програму “Контроль програм, які запускались на даному комп^ютері" на мові програмування ASM-86.

Програма розміщується резидентно в пам"ятi, тож не заважатиме pоботi iнших пpогpам, з якими може працювати користувач.

3. Обґрунтування вибору методів розв^язку задачі

Отже, необхідно написати програму, яка здійснює контроль програм, що запускалися на комп^ютері. При виборі алгоритму програми у мене не виникло варіантів. Тут все дуже просто. В int 21h є функція 4BH, яка запускає другі програми. Перепризначаємо цю функцію, та в процесі роботи цієї функції виділяємо ім^я, час та дату запуску програми, та записуємо цю інформацію до файлу. Також перевіряємо ім^я на присутність у стоповому файлі, і виходимо з функції, якщо ім^я присутнє в списку.

4. Алгоритм програми

Алгоритм головної програми:

Перевірка на присутність програми в пам"яті.

Присутня, перехід на перевірку параметрів.

Не присутня, встановлення нового обробника переривання 21h, залишення резидента в пам^яті.

Перевірка параметрів на символи /r, /?, /s, /d.

Якщо є символи /r, то вигрузка резидента з пам^яті (звільнення пам^яті, відновлення старого обробника переривання 21h).

Якщо є символи /?, то вивід допомоги.

Якщо є символи /s, то інвертування прапорцю зупинки (чи буде перевіряться ім^я на присутність в стоповому файлі).

Якщо є символи /d, то вилучаємо файл, в якому записується інформація про програми, які запускаються на комп^ютері.

Закінчити програму.

Алгоритм обробника переривання 21h:

Перевірка на функцію перевірки на присутність.

Перевірка на функцію 4Bh.

Якщо потрібно, перевірка на те, чи потрібно запускати дану програму.

Аналізується та записується інформація про дану програму в файл.

Виклик старого обробника переривання 21h.

Вихід з обробника.

5. Реалізація програми

Програма написана на мові ASM-86 з використанням команд процесора 86/286. Вона складається з головної програми, яка перевіряє параметри, які задані в командному рядку, та функції-обробника переривання 21h, який й контролює програми, які запускалися.

Перевага написаної мною програми-резидента в тому, що вона залишається постійно в пам^яті, завдяки чому користувач не помічає контролю.

Програма компілюється Turbo Assembler, зв^язується за допомогою TLINK.

6. Системні вимоги

IBM сумісний комп^ютер із мікропроцесором Intel 80086 або старшим.

Операційна система - ДОС

Пам^ять - 640 К і вище


7. Інструкція для користувача

Для запуску резидентної програми, яка здійснює контроль програм, які запускалися на комп^ютері, потрібно в командному рядку набрати kontrol.com та натиснути Enter. Також в командному рядку можна задавати параметри:

“/R" - вигрузити програму з пам^яті.

“/? ” - виводе допомогу.

“/D" - вилучення файлу зберігання програм, що запускалися.

“/S" - Інвертування стопового прапору.

Програма запам^ятовує імена, дату та час запуску всіх програм, які запускалися на комп^ютері, в файлі, який знаходиться в кореневому каталозі диску С з ім^ям history. asm. Також програма дозволяє задавати імена тих файлів, які не потрібно давати запускати. Ці імена задаються в файлі stop. asm в кореневому каталозі диску С.


8. Висновки

Отже, на мові ASM-86 створено програму, яка виконує контроль програм, що запускалися на комп^ютері.


Використана література

1) “Програмування на мові Асемблера ЕС ЕВМ" З.С. Брич, В.I. Воющ Москва 1989 р. ст. 166

2) “Програмування на сучасних мовах програмування. ” Москва 1990 р. ст. 206

3) “Основи мови” Асемблер” В.I. Криволап. Москва 1997р. ст.309

4) “Ассемблер для початкiвцiв” М.П. Шукiн. Київ 1980р. ст.155

5) “Турбо Асемблер” Л.В. Захаров. Харків 1995 р ст.178

6) “Макро Асемблер” К.С. Кропiйко, О.Д. Богатирова. Київ - “Наука” 1991 р.

7) Електронний довідник BOOK.


Додаток

Лістинг програми

jumps;

locals;

Leng EQU 0080h; Смещение байтов с длиной строки параметр.

Parametr EQU 0081h; Смещение параметров

model tiny; Модель памяти TINY - крошечная.

code; Начало сегмента кода.

org 100h; Установка точки входа.

start:; Метка с которой начинается программа

jmp init; Переход на установки.

old dw 0,0; Указатели на старые вектора прерываний.

string db 100 dup (0); Имя запускаемой программы

string1 db 100 dup (0); Имя запускаемой программы

comp db 0; флаг сравнения

err1 db 0; флаг ошибки

str1 db 0; буфер файла

stop1 db 0; проверять ли сравнение

lf db 13,10; сиволы перехода на новую строчку

nam db "c: history. asm",0; Имя файла, в котором будем сохранять

nam1 db "c: stop. asm",0; Имя файла, с запрещенными программами

len dw 0; длина строки с именем программы

OutFile dw 0; Номер канала файла

OutFile1 dw 0; Номер канала файла

tim db 25 dup (" "); Время и дата

new21 proc

; - ---------------------------------------------------------------------------¬

; ¦New21 - Процедура обработки 21h прерывания ¦

; L----------------------------------------------------------------------------

cmp ax,9090h; проверяем, если AX<>9090h

jnz q1; то переходим на продолжение обработки

mov ax,12h; иначе возвращаем AX=12h

iret; Выходим из прерывания

q1:

cmp ah,4bh; проверяем, если AH=4bh

je @@1; то переходим на продолжение обработки

jmp exit; иначе переходим на выход

@@1:

push ax bx cx dx ds si DI ES; сохраняем все используемые регистры в стеке

push dx; - ¬заносим в регистр SI сегмент, в котором

pop si; - содержится имя запускаемой программы

mov bx,0; обнуляем регистр BX

m1:

mov al,ds: [si+bx] ; =¬

mov cs: string [bx],al; ¦ копируем имя программы в переменную

inc bx; ¦ string

cmp al,0; =-

jnz m1

mov cs: len,bx; сохраняем длину строки

cmp cs: stop1,0; проверяем флаг проверки

jne noprov; надо проверять

call prov; если надо, то на проверку

noprov:; иначе не проверять

lea dx,cs: nam; адрес выходного файла

push cs

pop ds

call createFile; процедура создания файла

mov ah,40h; функция записи в файл

mov bx,cs: outfile; номер файла

mov cx,cs: len; длина буфера

lea dx,cs: string; адрес буфера

pushf

call dword ptr cs: old; вызываем функцию записи в файл

mov ah,02h; функция чтения текущего времени

int 1ah; прерывание работы с часами реального времени

mov ah,ch; - ¬

mov al,ch; ¦

and ah,11110000b; ¦выделяем цифры часов

and al,1111b; ¦

shr ah,4; ¦

add ah,48; ¦

add al,48; - -

mov tim [2],ah; - ¬сохраняем часы

mov tim [3],al; - -

mov tim [4],": "; ставим двоеточие

mov ah,cl; - ¬

mov al,cl; ¦

and ah,11110000b; ¦выделяем цифры минут

and al,1111b; ¦

shr ah,4; ¦

add ah,48; ¦

add al,48; - -

mov tim [5],ah; - ¬сохраняем минуты

mov tim [6],al; - -

mov tim [7],": "; ставим двоеточие

mov ah,dh; - ¬

mov al,dh; ¦

and ah,11110000b; ¦выделяем цифры секунд

and al,1111b; ¦

shr ah,4; ¦

add ah,48; ¦

add al,48; - -

mov tim [8],ah; - ¬сохраняем секунды

mov tim [9],al; - -

mov ah,04h; функция чтения текущей даты

int 1ah; прерывание работы с часами реального времени

mov ah,dl; - ¬

mov al,dl; ¦

and ah,11110000b; ¦выделяем цифры дня

and al,1111b; ¦

shr ah,4; ¦

add ah,48; ¦

add al,48; - -

mov tim [12],ah; - ¬сохраняем день

mov tim [13],al; - -

mov tim [14],": ";

mov ah,dh; - ¬

mov al,dh; ¦

and ah,11110000b; ¦выделяем цифры месяца

and al,1111b; ¦

shr ah,4; ¦

add ah,48; ¦

add al,48; - -

mov tim [15],ah; - ¬сохраняем месяц

mov tim [16],al; - -

mov tim [17],": "; ставим двоеточие

mov ah,ch; - ¬

mov al,ch; ¦

and ah,11110000b; ¦выделяем цифры века

and al,1111b; ¦

shr ah,4; ¦

add ah,48; ¦

add al,48; - -

mov tim [18],ah; - ¬сохраняем век

mov tim [19],al; - -

mov ah,cl; - ¬

mov al,cl; ¦

and ah,11110000b; ¦выделяем цифры года

and al,1111b; ¦

shr ah,4; ¦

add ah,48; ¦

add al,48; - -

mov tim [20],ah; - ¬сохраняем год

mov tim [21],al; - -

mov ah,40h; Функция вывода в файл

mov bx,cs: outfile; номер файла

mov cx,25; количество выводимых символов=25 (время и дата)

lea dx,cs: tim; адрес выводимой строки

pushf; сохраняем регистр флагов в стеке

call dword ptr cs: old; вызываем старый обработчик прерывания

mov ah,40h; =¬

mov bx,cs: outfile; ¦

mov cx,2; ¦ переход в файле на следующую строку

lea dx,cs: lf; ¦

pushf; ¦

call dword ptr cs: old; =-

mov ah,3eh; Функция закрытия файла

mov bx,cs: outfile; номер файла

pushf; сохраняем регистр флагов в стеке

call dword ptr cs: old; вызываем старый обработчик прерывания

lea di,cs: string; =¬

push cs; ¦

pop es; ¦ обнуляем строку

mov cx,100; ¦

mov al,0; ¦

rep stosb; =-

pop ES DI si ds dx cx bx ax; восстанавливаем регистры из стека

cmp cs: stop1,0; надо ли проверять

jne exit; если ненадо то на старый обработчик

cmp cs: comp,1; иначе проверяем на совпадение

je exxit; если совпадает то на eexit

exit:

jmp dword ptr cs: old; переходим на старый обработчик

exxit:

iret; выход из обработчика

new21 endp; конец обработчика прерывания

CreateFile Proc

; - ---------------------------------------------------------------------------¬

; ¦CreateFile - процедура создания выходного файла, перед этим проверяется есть¦

; ¦ли он уже на диске. Если есть, то он открывается и позиционируется на конец¦

; ¦Вход DS: DX=имя файла ¦

; ¦Выход cf=0 операция прошла успешно ¦ ¦

; L----------------------------------------------------------------------------

mov al,1; Разрешаем только запись

mov ah,3dh; Функция DOS открытия файла

pushf

call dword ptr cs: old; вызываем старый обработчик прерывания

jc @@1; Проверка на существование:

mov cs: outfile,ax; =¬

mov ah,42h; ¦

mov bx,cs: outfile; ¦

mov cx,0; ¦позиционируется на конец

mov dx,0; ¦

mov al,2; ¦

pushf; ¦

call dword ptr cs: old; ¦

ret; =-

@@1:

lea dx,cs: nam; =¬

xor cx,cx; ¦

mov cx,110b; ¦

mov ah,3ch; ¦Если файла нет с таким именем, то он

pushf; ¦

call dword ptr cs: old; ¦создаётся

mov cs: outfile,ax; ¦

ret; =-

CreateFile endp

Prov proc

; - --------------------------------------------------------------------¬

; ¦Prov - процедура проверки имени программы которая запускается и имен¦

; ¦программ, которые берутся из файла stop. asm. ¦

; ¦Вход нет ¦

; ¦Выход comp=1 имена совпали ¦ ¦

; L---------------------------------------------------------------------

push ds es di si; сохраняем все используемые регистры в стеке

mov cs: comp,0; обнуляем флаг сравнения

mov cs: err1,0; обнуляем флаг ошибки

mov ah,3dh; Функция DOS открытия файла

lea dx,cs: nam1; адрес имени файла с запрещаемыми программами

push cs

pop ds

mov al,0; открытие файла на чтение

pushf

call dword ptr cs: old; вызываем старый обработчик прерывания

jnc @@9; Проверка на существование: если не существует, то

pop si di es ds; восстанавливаем регистры из стека

ret; выходим из процедуры

@@9:; иначе

mov cs: outfile1,ax; сохраняем номер файла

@@12:

lea di,cs: string1; адрес строки

@@11:

mov ah,3fh; Функция чтения из файла

mov bx,cs: outfile1; номер файла, который читаем

mov cx,1; количество читаемых символов

lea dx,cs: str1; адрес буфера

push cs;

pop ds;

pushf;

call dword ptr cs: old; вызываем старый обработчик прерывания

cmp ax,-1; проверка на ошибку

je error1;

cmp ax,0; проверка на количество прочитанных байт

je error1;

jmp noerror;

error1:; ошибка

mov cs: err1,1; устанавливаем флаг ошибки

jmp error;

noerror:; нет ошибки

cmp cs: str1,13; проверка на код перехода на новую строку

je @@21; если равно, то на @@21

mov al,cs: str1; записываем в al символ

cmp al,"a"; если меньше, чем "a", то

jb @@q1; на @@q1

cmp al,"z"; если больше, чем "z", то

ja @@q1; на @@q1

sub al,32; иначе вычитаем разницу между больш. и маленькими

@@q1:;

mov cs: [di],al; сохраняем символ в строке

inc di; увеличение текущей позиции

jmp @@11; переход к следующему символу

@@21:;

mov ah,3fh; Функция чтения из файла

mov bx,cs: outfile1; номер файла, который читаем

mov cx,1; количество читаемых символов

lea dx,cs: str1; адрес буфера

push cs;

pop ds;

pushf;

call dword ptr cs: old; вызываем старый обработчик прерывания

error:;

lea di,cs: string; адрес имени загружаемой программы

push cs;

pop es;

lea si,cs: string1; адрес имени программы, прочитанной из файла

push cs;

pop ds;

mov al,0; загружаем в al символ с кодом 0

mov cx,100; количество символов, в которых ищем

cld; направление поиска вперед

repne scasb; ищем символ с кодом 0

std; направление поиска назад

dec di; уменьшаем адрес поиска на 1

mov cx,13; длина имени и расширения программы

mov al,""; загружаем в al символ ""

repne scasb; ищем символ ""

cld; направление поиска вперед

inc di; увеличиваем адрес сравнения на 2

inc di;

mov cx,13; длина сравниваемых строк

repe cmpsb; сравниваем строки

je @@ex; если равно, то на @@ex

; mov cs: comp,0;

jmp @@ex1; иначе на @@ex1

@@ex:;

mov cs: comp,1; устанавливаем флаг равенства

@@ex1:;

mov cx,100; кол. байт

mov al,0;

lea di,cs: string1; адрес строки

push cs;

pop es;

rep stosb; обнуляем

cmp cs: comp,0; проверяем флаг сравнения

jne @@31; если не равен то на @@31

cmp cs: err1,1; проверяем флаг ошибки

je @@31; если равен то на @@31

jmp @@12; переход на начало сравнения

@@31:;

mov ah,3eh; Функция закрытия файла

mov bx,cs: outfile1; номер файла, который закрываем

pushf;

call dword ptr cs: old; Вызываем старый обработчик прерывания

pop si di es ds; восстанавливаем регистры из стека

ret

prov endp; конец процедуры сравнения

; - ---------------------------INIT----------------------------------------

init:; Установки.

mov ah,9h; функция вывода строки

mov dx,offset text; адрес сообщения о программе

int 21h; выводим сообщение

mov ax,9090h; наша функция проверки, есть лди в памяти

int 21h; вызываем нашу функцию проверки

cmp ax,12h; AX=12?

jz exi; если да, то на проверку парвметров

mov ah,35h; функция чтения адреса прерывания

mov al,21h; номер прерывания

int 21h; вызываем функцию чтения адреса прерывания

mov old,bx; сохраняем в переменной сегмент исмещение

mov old+2,es; обработчика прерывания

mov ah,25h; функция замены прерывания

mov al,21h; номер прерывания

mov dx,offset new21; адрес нового обработчика

int 21h; вызываем функцию замены прерывания

lea dx,cs: nam; адрес выходного файла

push cs

pop ds

call createFile; процедура создания файла

mov ah,40h; =¬

mov bx,cs: outfile; ¦

mov cx,2; ¦ переход в файле на следующую строку

lea dx,cs: lf; ¦

pushf; ¦

call dword ptr cs: old; =-

mov ah,3eh; Функция закрытия файла

mov bx,cs: outfile; номер файла

pushf; сохраняем регистр флагов в стеке

call dword ptr cs: old; вызываем старый обработчик прерывания

mov dx,offset init; адрес конца обработчика

int 27h; Выйти и остаться резидентом.

; Проверка параметров

exi:

push cs

pop ds

xor ch,ch; обнуляем CH

mov cl, [ds: Leng] ; CX=длина параметров

inc cx; добавить символ возврата каретки

mov si,Parametr; поместить адрес параметров в SI

; пропустить начальный пробелы и табуляцию

@@100:

call Separators; проверка на пробелы

jne @@20; переход если пробелов и табул. нет

inc si; иначе пропустить этот символ

loop @@100; переход пока не закончена обработка

@@20:

cmp cx,0; CX=0?

jne @@30; если нет, то есть параметры

jmp noparam; нет параметров

@@30:

mov ah,ds: [si] ; в AH заносим символы строки параметров

cmp ah,"/"; сравниваем AH с символом "/"

je param; если равно то следующий символ

cmp ah,"-"; сравниваем AH с символом "-"

je param; если равно то следующий символ

cmp ah,"r"; сравниваем AH с символом "r"

je release; если равно то на выгрузку резидента

cmp ah,"R"; сравниваем AH с символом "R"

je release; если равно то на выгрузку резидента

cmp ah,"d"; сравниваем AH с символом "d"

je delete; если равно то на удаление файла

cmp ah,"D"; сравниваем AH с символом "D"

je delete; если равно то на удаление файла

cmp ah,"s"; сравниваем AH с символом "s"

je stoped; если равно то на инвертирование флага stop1

cmp ah,"S"; сравниваем AH с символом "S"

je stoped; если равно то на инвертирование флага stop1

cmp ah,"? "; сравниваем AH с символом "? "

je help; если равно то на выдачу помощи

cmp ah,"h"; сравниваем AH с символом "h"

je help; если равно то на выдачу помощи

cmp ah,"H"; сравниваем AH с символом "H"

je help; если равно то на выдачу помощи

param: inc si

mov ah,ds: [si] ; берем следующий символ

cmp ah,"d"; сравниваем AH с символом "d"

je delete; если равно то на удаление файла

cmp ah,"D"; сравниваем AH с символом "D"

je delete; если равно то на удаление файла

cmp ah,"s"; сравниваем AH с символом "s"

je stoped; если равно то на инвертирование флага stop1

cmp ah,"S"; сравниваем AH с символом "S"

je stoped; если равно то на инвертирование флага stop1

cmp ah,"? "; сравниваем AH с символом "? "

je help; если равно то на выдачу помощи

cmp ah,"h"; сравниваем AH с символом "h"

je help; если равно то на выдачу помощи

cmp ah,"H"; сравниваем AH с символом "H"

je help; если равно то на выдачу помощи

cmp ah,"r"; сравниваем AH с символом "r"

je release; если равно то на выгрузку резидента

cmp ah,"R"; сравниваем AH с символом "R"

jne noparam; если не равно то на noparam

release:

mov ah,09h; функция вывода строки

lea dx,mes2; адрес сообщения о выгрузке

int 21h; выводим сообщение

mov ah,35h; функция чтения адреса прерывания

mov al,21h; номер прерывания

int 21h; вызываем функцию чтения адреса прерывания

push es

mov ah,25h; функция замены прерывания

mov al,21h; номер прерывания 21h

mov dx,es: old; адрес старого обработчика

mov ds,es: old+2

int 21h; вызываем функцию замены прерывания

pop ds

mov ah,49h; функция освобождения паияти

int 21h; освобождаем паиять

jmp ex_init; переход на выход

delete:

mov ah,9; функция вывода строки

mov dx,offset cs: mes3; адрес сообщения о удалении

int 21h; выводим сообщение

mov ah,41h; функция удаления файла

mov dx,offset cs: nam; адрес удаляемого файла

int 21h; удаляем файл

jmp noparam

stoped:

mov ah,35h; функция чтения адреса прерывания

mov al,21h; номер прерывания

int 21h; вызываем функцию чтения адреса прерывания

mov ah,9; функция вывода строки

not es: stop1; инвертируем флаг проверки

stoped2: cmp es: stop1,0; сравниваем флаг проверки с 0

jne stoped1; если не равно то на stoped1

mov dx,offset cs: mes4; адрес сообщения о наличии проверки

int 21h; выводим сообщение

jmp noparam

stoped1: mov dx,offset cs: mes5; адрес сообщения о не наличии проверки

int 21h; выводим сообщение

jmp noparam

help: mov ah,9; функция вывода строки

mov dx,offset helpt; адрес сообщения помощи

int 21h; выводим сообщение

mov ah,35h; функция чтения адреса прерывания

mov al,21h; номер прерывания

int 21h; вызываем функцию чтения адреса прерывания

mov ah,9; функция вывода строки

jmp stoped2

noparam:

lea dx,cs: mes1; адрес сообщения о наличии резидента в памяти

mov ah,9; функция вывода строки

int 21h; выводим сообщение

ex_init:

mov ah,4ch; функция выхода из программы

mov al,0; возвращает код ошибки 0

int 21h; выход из программы

Separators Proc

; - ---------------------------------------------------------------------------¬

; ¦Separators - процедура проверки на пробелы ¦

; ¦ВЫХОД: ¦

; ¦zf=1: символ является пробелом, табуляцией или возвратом каретки ¦

; ¦zf=0: символ не является разделителем ¦

; L----------------------------------------------------------------------------

mov al,ds: [si] ; взять символ из ds: si

cmp al,020h; символ пробел?

je @@10; Если да то переход

cmp al,009h; символ табуляция?

je @@10; Если да то переход

cmp al,00dh; символ возврата каретки?

@@10:

ret

Separators EndP

Text db 13,10,"History Version 1.0 Copyright (c) 1999 Мороз Р. ",13,10

db "Сохранение названий всех программ, которые запускались на компьютере",13,10,"$"

Helpt db "Syntax: History [/r|/R|-r|-R|r|R] [/d|/D|-d|-D|d|D] [/? |/h|/H|-? |-h|-H|? |h|H] ",13,10

db " /r - released History from memory",13,10

db " /d - delete files History",13,10

db " /s - invert stop flag ",13,10

db " /? - HELP",13,10,"$"

mes1 db 13,10," Program alredy in memory $"

mes2 db 13,10," Program released in memory $"

mes3 db 13,10," delete files History $"

mes4 db 13,10," stoped files $"

mes5 db 13,10," not stoped files $"

end start; Конец программы, точка входа

Информация о файле
Название файла Контроль програм, які запускаються на даному комп"ютері от пользователя z3rg
Дата добавления 11.1.2012, 19:24
Дата обновления 11.1.2012, 19:24
Тип файла Тип файла (zip - application/zip)
Скриншот Не доступно
Статистика
Размер файла 23.97 килобайт (Примерное время скачивания)
Просмотров 555
Скачиваний 75
Оценить файл