Распределенная атака на Delphi Alek Silverstone Хакер, номер #074, стр. 074-104-2 Теперь щелкаем по кнопке StopBtn и пишем пару строчек: procedure TForm1.StopBtnClick(Sender: TObject); begin Memo1.Lines.Add('Сервер остановлен'); IdTCPserver1.Active:=false; end; Теперь нужно задать наши команды и их обработчики. Щелкаем по компоненту IdTCPserver1 и по многоточию возле его свойства CommandHandlers. В появившемся окне щелкаем кнопку Add New и изменяем параметры нашей первой команды: в свойстве Command указываем <need_work>, а в свойстве Name - NeedWorkCmd. Переходим на вкладку «Events», щелкаем по единственному событию OnCommand и пишем код: Обработка команды <need_work> procedure TForm1.IdTCPServer1NeedWorkCmdCommand(ASender: TIdCommand); var i:integer; begin ASender.Response.Clear; ASender.Response.Add('Work:'); if DictP>=Dict.Count then Memo1.Lines.Add('СЛОВАРЬ ЗАКОНЧИЛСЯ!'); for i:=1 to SendWork do begin if DictP<Dict.Count then ASender.Response.Add(Dict[DictP]) else break; inc(DictP); end; ASender.SendReply; Memo1.Lines.Add('Клиенту '+ASender.Thread.Connection.Socket.Binding.PeerIP+' выслана работа'); end; Сначала мы очищаем наш ответ, потом добавляем туда нужное количество слов (либо задаем в начале константу SendWork, либо пишем вместо нее нужное число) и отправляем их. В конце мы добавляем сообщение в лог; страшная конструкция в этой строчке служит для получения IP-адреса клиента. У тебя, вероятно, возникнет два вопроса. Первый: а почему мы не останавливаем сервер, когда заканчивается словарь? Ответ прост - нам нужно дождаться завершения работы всех клиентов. Если SendWork имеет большое значение, клиентов много, а словарь мал, то он кончится уже после однократного обращения клиентов. Поэтому сервер придется выключать вручную. Второй вопрос: а почему на начало ответа мы добавили строку «Work:»? Дело в том, что опытным путем (как - читай раздел про отладку сетевых программ) я установил, что первая строчка ответа игнорируется клиентом. Теперь создаем еще одну команду (Command=<pass_find>, Name=PassFindCmd) и пишем такой ее обработчик: procedure TForm1.IdTCPServer1PassFindCmdCommand(ASender: TIdCommand); begin Memo1.Lines.Add('Пароль найден!!!'); Memo1.Lines.Add(ASender.Params[0]); StopBtn.Click; end; Здесь мы выводим найденный пароль, который передается как параметр команды <pass_find>, и останавливаем сервер щелчком по кнопке StopBtn. XXX ЗАГОЛОВОК XXX Кодим клиент Теперь мы будем писать клиент. Вот цикл его работы: 1) подключиться к серверу, 2) выполнить команду <need_work> и получить результат, 3) отключиться от сервера, 4) проверить последовательно все слова из работы, 5) если будет найден пароль, то отправить его командой <pass_find> и выйти из цикла, 6) иначе goto 1. Проверять пароль мы будем при помощи консольной программы rar.exe. Получив в качестве параметров имя архива, пароль и путь для извлечения, она пытается распаковать архив. Если после работы rar.exe останутся какие-то файлы - значит, пароль найден. Итак, приступим. Разместим на форме компонент Memo1 (лог), Edit1 для ввода IP-адреса сервера, кнопку StartBtn и два индикатора - ProgressBar1 (побольше - индикатор полного выполнения работы) и ProgressBar2 (поменьше - индикатор завершения подбора текущего слова). Для Memo1, как и в сервере, ставим ReadOnly в true и ScrollBars в ssVertical. Теперь добавим компонент IdTCPclient с вкладки Indy Clients. В поле Port вписываем наш порт - 31337. |