BackDoor - удалённое администрирование 2
|
- В чем заключается многозадачность Windows?
- Она глючит и работает одновременно.
|
Начнем с отзывов. Во-первых, спасибо за положительные. Во-вторых, я допустил ошибку, а никто и не увидел. Процесс обработки очереди надо все-таки терминайтить. Но об этом далее. В-третьих, комментариев в коде вполне достаточно. Я так пишу. Охоту к написанию комментариев у меня отбили еще в универе. А если не можешь разобраться, так нафига вообще трепыхаться - ходи на порно-сайты и дыши с присвистом. В-четвертых, объясню почему сервер писался на асме. На это есть 6 причин:
- Быстродействие. Все равно быстрее будет работать чем на сях и delphi (не говоря уже о тормознутом визуал бейсике. Такой язык надо в школе изучать - это надо ж, грузить dll-и и запускать с них функции);
- Размеры. 11 kb "всунуть" в что-то все таки легче чем, например, 100;
- Если мы пишем на асме, то имеем дело с ошибками своими и мелкософта, а не с глюками программера из фирмы Borland. Взять хотя-бы "RadioGroup" в Delphi;
- В ранних версиях "DTr", периодически возникала ошибка 10060 асинхронной работы. Только на некоторых компьютерах, но все-таки. Написание сервера на сях не помогло. После выхода версии на асме и сооружения в клиенте процесса обработки очереди приходящих сообщений, у меня еще такой ошибки не возникало;
- В своих продуктах фирмы по производству программного обеспечения, любят при ошибке вызывать исключительную ситуацию, на что виндоуз реагирует показом "красивого" окошка с сообщением об ошибке. Некоторые такие реакции не подавляются try-except. Для сервера это, мягко сказать, нежелательно. В асме все проще;
- Для борьбы с буржуйскими программами с помощью 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. Статья и программа предоставлена в целях обучения и вся ответственность за использование ложится на твои хилые плечи.
|