скрыть

скрыть

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

BackDoor - удалённое администрирование 2



Автор: Danil

- В чем заключается многозадачность Windows?
- Она глючит и работает одновременно.

Начнем с отзывов. Во-первых, спасибо за положительные. Во-вторых, я допустил ошибку, а никто и не увидел. Процесс обработки очереди надо все-таки терминайтить. Но об этом далее. В-третьих, комментариев в коде вполне достаточно. Я так пишу. Охоту к написанию комментариев у меня отбили еще в универе. А если не можешь разобраться, так нафига вообще трепыхаться - ходи на порно-сайты и дыши с присвистом. В-четвертых, объясню почему сервер писался на асме. На это есть 6 причин:

  1. Быстродействие. Все равно быстрее будет работать чем на сях и delphi (не говоря уже о тормознутом визуал бейсике. Такой язык надо в школе изучать - это надо ж, грузить dll-и и запускать с них функции);
  2. Размеры. 11 kb "всунуть" в что-то все таки легче чем, например, 100;
  3. Если мы пишем на асме, то имеем дело с ошибками своими и мелкософта, а не с глюками программера из фирмы Borland. Взять хотя-бы "RadioGroup" в Delphi;
  4. В ранних версиях "DTr", периодически возникала ошибка 10060 асинхронной работы. Только на некоторых компьютерах, но все-таки. Написание сервера на сях не помогло. После выхода версии на асме и сооружения в клиенте процесса обработки очереди приходящих сообщений, у меня еще такой ошибки не возникало;
  5. В своих продуктах фирмы по производству программного обеспечения, любят при ошибке вызывать исключительную ситуацию, на что виндоуз реагирует показом "красивого" окошка с сообщением об ошибке. Некоторые такие реакции не подавляются try-except. Для сервера это, мягко сказать, нежелательно. В асме все проще;
  6. Для борьбы с буржуйскими программами с помощью WINdasm, SoftIce и т.п., ассемблер надо знать. А для того чтобы его знать, на нем иногда надо писать. Завести 2-ой комп и бегать, смотреть на одном окно SoftIce, а на другом доки - это сильно круто.

Теперь продолжим разговор о нашем клиенте. Как я уже говорил, процесс обработки очереди при разсоединении и выходе из проги надо прерывать. Для этого модифицируем нашу процедуру "ClientSocket1Disconnect", вставив в нее вот такой код:


if not RecvThread.Terminated then
begin
  while not RecvThread.Terminated do
  begin
    try
      RecvThread.Terminate;
    except
    end;
    sleep(100);
    Application.ProcessMessages;
  end;
end;
LstRbeg:=nil;
LstRend:=nil;

Также нас интересует событие, происходящее перед выходом из клиента. Выделим нашу форму ("Form1"), перейдем в "Object Inspector" на закладку "Events" и 2 раза "click"-нем по "onClose". Перейдем в раздел кода и запишем:


// Выход из проги
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caNone;
  if constat then
    Form1.Button1Click(Sender);
  Application.ProcessMessages;
  Application.Terminate;
  Halt(1);
end;

Теперь поговорим о визуализации и удобстве работы с клиентом. Кнопки, которые отвечают за посылание серверу команд, надо как-то выделить. Для этого воспользуемся объектом "ImageList" с закладки "Win32" ("ImageList1"). Помещаем его на форму и с помощью правой кнопки мыши добавляем в него изображения для кнопок. Теперь нужно выделить "ToolBar1" и в его свойстве "Images", из всплывающего списка, поставить "ImageList1". После этого перейдем на "ToolButton1", в свойстве "ImageIndex", выберем нужный рисунок. Для отображения "всплывающей" подсказки в свойстве "ShowHint" поставим "true", а в свойстве "Hint", напишем "Кнопка № 1". Очень информативно.

Сканер для сервера.

Допустим, мы знаем, что серверная часть запущена у человека (это звучит гордо), пользующегося услуами провайдера "Slow". Мы также знаем пространство адресов этого провайдера. Но мы не знаем, какой адрес даст провайдер этому челу.

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

Или мы изменили порт, а какой забыли.

Для всего этого нам нужен сканер по адресам и портам. То, о чем пойдет речь далее, можно использовать не только для нашего сервера. Итак, в Delphi, в проекте нашего сервера, выбираем в верхнем меню "File"-->"New Form". Пусть это будет "Form2". В свойстве "Caption" пишем "Сканер". Размещаем на форме компоненты:

Edit1
С какого порта начинать сканирование;
Edit2
По какой порт;
Edit3
Первые 3 цифры адреса в виде "xxx.xxx.xxx.xxx" (без точки в конце);
Edit4, Edit5
Диапазон последней цифры адреса;
Edit6
Время ожидания соединения (в секундах);
Button1
Начать/прекратить сканирование;
Memo1
Отчет сканирования;
ProgressBar1, ProgressBar2 (Win32)
Для визуализации процесса перебора по адресам и портам соответственно;
ClientSocket1
И так понятно.

Теперь на "Form1" лепим кнопку, обзываем ее "Scaner" и нажимаем на ней два раза. В разделе кода пишем :


// Scaner
procedure TForm1.Button2Click(Sender: TObject);
begin
  Form2.WindowState := wsNormal;
  Form2.Visible := true;
  Form2.SetFocus;
end;

В раздел "uses" добавляем "Unit2". Переходим на "Form2". Два раза нажимаем на "Button1", на события "onConnect" и "onError" в "ClientSocket1" и на "onClose" в "Form2". Вот текст модуля "Unit2.pas":


unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, StdCtrls, ScktComp;

type
  TForm2 = class(TForm)
  Edit1: TEdit;
  Edit2: TEdit;
  Edit3: TEdit;
  Edit4: TEdit;
  Edit5: TEdit;
  Edit6: TEdit;
  Button1: TButton;
  Memo1: TMemo;
  ProgressBar1: TProgressBar;
  ProgressBar2: TProgressBar;
  ClientSocket1: TClientSocket;
  procedure FormClose(Sender: TObject; var Action: TCloseAction);
  procedure Button1Click(Sender: TObject);
  procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
  procedure ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);
  private
    { Private declarations }
  public
    { Public declarations }
end;

var
  Form2: TForm2;
  Rez11: Boolean = false;
  Bool: Boolean = false;

implementation

{$R *.DFM}

//Close Scaner
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  // если запущен, то прерываем процесс
  if Rez11 then
  begin
    Action := caNone;
    Form2.Button1Click(Sender);
  end;
end;

// Включить/отключить сканер
procedure TForm2.Button1Click(Sender: TObject);
var
  I, J, K: Integer;
  DopStr: string;
begin
  if Rez11 then
  begin
    // прервать сканирование
    if Application.MessageBox('Прервать сканирование?', 'Сканер', mb_YesNo + mb_IconQuestion) = idYes then
    begin
      Rez11 := false;
      Bool := false;
    end;
  end
  else
  begin
    // запуск сканера
    if StrToInt(Form2.Edit2.Text) < StrToInt(Form2.Edit1.Text) then
    begin
      Application.MessageBox('Неверно указан диапазон для портов','Сканер', mb_Ok + mb_IconStop);
      exit;
    end;

    if StrToInt(Form2.Edit5.Text) < StrToInt(Form2.Edit4.Text) then
    begin
      Application.MessageBox('Неверно указан диапазон IP-адресов','Сканер', mb_Ok + mb_IconStop);
      exit;
    end;

    Form2.Caption:='Идет сканирование...';
    Form2.Memo1.Lines.Clear;

    try
      DopStr := trim(Form2.Edit3.Text);
      Rez11 := true;
      Form2.Button1.Caption := 'Отмена';
      Form2.Memo1.Lines.Add('-------------' + #13 + #10 + '===========');

      // начальные значения для порта и адреса
      I := StrToInt(Form2.Edit1.Text);
      J := StrToInt(Form2.Edit4.Text);

      try
        Form2.ProgressBar1.Max := StrToInt(Form2.Edit2.Text) - StrToInt(Form2.Edit2.Text) + 2;
        Form2.ProgressBar1.Position := 1;
        Form2.ProgressBar2.Max := StrToInt(Form2.Edit5.Text) - StrToInt(Form2.Edit4.Text) + 2;
        Form2.ProgressBar2.Position := 1;

        // цикл по адресам
        while I <= StrToInt(Form2.Edit2.Text) do
        begin
          J := StrToInt(Form2.Edit4.Text);
          // цикл по портам
          while J <= StrToInt(Form2.Edit5.Text) do
          begin
            Application.ProcessMessages;
            if not Rez11 then
              break;
            Form2.ClientSocket1.Active := false;
            Form2.ClientSocket1.Port := I;
            Form2.ClientSocket1.Address := trim(DopStr) + '.' + trim(IntToStr(J));

            try
              // попытка соедениться
              Form2.ClientSocket1.Active := true;
              Application.ProcessMessages;

              // время ожидания
              Bool := true;
              K := round(StrToInt(Form2.Edit6.Text) * 1000 / 50);
              while Bool do
              begin
                Sleep(50);
                Application.ProcessMessages;
                dec(K);
                if K=0 then
                begin

                  try
                    Form2.ClientSocket1.Active:=false;
                  except
                  end;
                  break;
                end;
              end;
            except
            end;

            Application.ProcessMessages;
            Form2.ProgressBar2.Position := Form2.ProgressBar2.Position + 1;
            inc(J);
          end;
          inc(I);
          Application.ProcessMessages;

          if not Rez11 then
            break;

          Form2.ProgressBar1.Position := Form2.ProgressBar1.Position + 1;
        end;
        Form2.ProgressBar2.Position := Form2.ProgressBar1.Position + 1;
        Form2.ProgressBar1.Position := Form2.ProgressBar1.Position + 1;
      except
        Application.MessageBox('Ошибка выполнения операции', 'Сканер', MB_Ok + mb_IconStop);
      end;
      Form2.Button1.Caption := 'Сканер';
      Form2.ProgressBar1.Position := 0;
      Form2.ProgressBar2.Position := 0;
      Form2.Caption := 'Сканер по адресам и портам';
      if Rez11 then
      begin
        Application.MessageBox('Процедура сканирования по адресам и портам закончена.', 'Сканер', mb_Ok + mb_IconAsterisk);
        Form2.Memo1.Lines.Add('-----------------'+#13+#10+'========== ВСЕ АДРЕСА И ПОРТЫ ОТСКАНИРОВАНЫ'+#13+#10+#13+#10);
        Rez11 := false;
      end
      else
        Form2.Memo1.Lines.Add('------------'+#13+#10+'============== ПРЕРВАНО НА порт-'+IntToStr(I)+', адрес-'+trim(DopStr)+'.'+IntToStr(J-1)+#13+#10+#13+#10);
    except
      Application.MessageBox('Ошибка инициализации процесса.','Сканер',mb_Ok+mb_IconStop);
    end;
    Form2.Caption:='Сканер по адресам и портам';
  end;
end;

// Есть ответ сервера
procedure TForm2.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);
begin
  // если соеденились вывести сообщение
  Form2.Memo1.Lines.Add('***' + #13 + #10 + 'Порт: ' + IntToStr(Form2.ClientSocket1.Port) + ' ' + 'Адрес: ' + Form2.ClientSocket1.Address + ' - ЕСТЬ ОТВЕТ' + #13 + #10);
  Application.ProcessMessages;
  // прервать время ожидания
  try
    Form2.ClientSocket1.Active := false;
  except
  end;
  Bool := false;
end;

// Ошибка при соединении
procedure TForm2.ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  // прервать время ожидания если ошибка
  ErrorCode := 0;
  Bool := false;
end;

end.

Теперь проверим. Запускаем сервер и клиент. Жмем кнопку "Сканер". В "Edit1" пишем "10001", в "Edit2" - "10001", в "Edit3" - "127.0.0", в "Edit4" - "1", в "Edit5" - "254", в "Edit6" - "1". Все значения без кавычек. Жмем нашу кнопку начала сканирования. Все, проверка закончена.

P.S. Статья и программа предоставлена в целях обучения и вся ответственность за использование ложится на твои хилые плечи.






Copyright © 2004-2016 "Delphi Sources". Delphi World FAQ




Группа ВКонтакте   Ссылка на Twitter   Группа на Facebook