Programming: Delphi


Сканируем порты на Delphi

  Автор: freetonik

  Источник:



Всеобщие приветы! Сегодня будем вместе кодить настоящий сканер портов! Без лишних прелюдий начнем.

Что нам понадобится? Delphi (исходник версии 6.0 !) и стандартные компоненты. Если быть точнее, то: 6 Edit’ов, один ListBox, две кнопки (у меня – два компонента SuperButton), 3 Label’а, Memo, StatusBar, два PopupMenu и наконец главный компонент – powersock из закладки FastNet. Чтобы понять, как все расставить на форме – смотрите скриншот: ниже.

 

Расставили? Не забудьте поставить Caption’ы кнопкам и лейблам. Тут уже на ваше усмотрение – хотите вместо «Скан» наберите «Сканируйся, дурацкая штуковина!!!» - пожалуйста! От этого программа хуже работать не будет =)

Ну вот, с интерфейсом разобрались. Теперь самое время понять, как все будет работать.
Видите – там где написано «IP» стоят три Едита и еще два справа? Так вот – тут будет вводится диапазон IP-адресов. Первые три блока не изменяются, а последний может варьироваться от 1 до 255. Так что наш сканер разведывает наличие открытых портов не на одной машине, а на нескольких! В самом проекте я ввел адрес 127.0.0.1/1, чтобы при случайном нажатии кнопки «Скан» не вылетала ошибка.
Справа в листбоксе будут порты, в которые будет коннектиться программка. Значения берутся из файла ports.txt, туда их можно вставлять как вручную с помощью любого текстового редактора, так и в программе. Для этого нам и понадобится PopupMenu – при клике правой кнопкой на список портов будет появляться меню, где можно добавить и удалить порт (в моем исходнике это PopupMenu2). Свойство «Popupmenu» компонента ListBox’ нужно сделать равным «PopupMenu2», а свойство «Popupmenu» memo нужно сделать равным «PopupMenu1».
Теперь отредактируй эти самые менюшки. Кликни два раза по ним и добавь в первое меню: «копировать» и «очистить», а во второе – «добавить порт» и «удалить».
Под едитами есть еще один едит – там указывается пауза в миллисекундах. Для чего нужна пауза в сканере? Когда программа соединяется с портом (или пытается), то это увидит администратор в логах. Если сканирование делать без пауз, то есть сразу во все порты, то админ увидит неладное и примет меры. Так что пауза нужна! И помните – в секунде 1000 миллисекунд.

Все! Теперь будем шкодить!

Процедура нажатия на кнопку «Скан»:

 

procedure TForm1.Button1Click(Sender: TObject);
begin
Edit1.Enabled := false;
Edit2.Enabled := false;
Edit3.Enabled := false;
Edit4.Enabled := false;
Edit5.Enabled := false;
speedbutton1.Enabled := false;
speedbutton2.Enabled := true;
listbox1.Enabled := false;

Memo1.lines.add('Начало сканирования');
go:=true;
it:=0;
lastIP:=strtoint(edit4.text);
NextIP;
s.Connect;

Memo1.lines.add('Сканирование завершено');
Edit1.Enabled := true;
Edit2.Enabled := true;
Edit3.Enabled := true;
Edit4.Enabled := true;
Edit5.Enabled := true;
speedbutton2.Enabled := false;
speedbutton1.Enabled := true;
listbox1.Enabled := true;
s.Disconnect;
end;

Тут следует напомнить, что именем «s» я назвал powersock. Для краткости. И еще – в общие переменные я поместил:

It,lastIP:integer;
go:boolean;

В первой численной переменной будет храниться последний ip-адрес, а значение go показывает, запущено сканирование или нет.
Как вы наверное заметили, при сканировании вызывается процедура NextIP. Вот ее код:

procedure TForm1.NextIP;
begin
s.disconnect;
if it=listbox1.Items.Count then
begin
inc(lastIP);
s.Host := edit1.text +'.'+
edit2.text + '.'+
edit3.text + '.'+
inttostr(lastIP);
It:=1;
s.port:=strtoint(listbox1.items.Strings[it-1]);
end else
begin
inc(It);
s.port:=strtoint(listbox1.items.Strings[it-1]);
end;
statusbar1.SimpleText := 'Scanning '+s.Host+' : '+inttostr(s.port);
end;

Именно она и производит скан портов, значения которых процедура берет из листбокса.
Со сканом разобрались. Теперь кнопка «Стоп», по нажатию на которую сканирование останавливается.

procedure TForm1.Button2Click(Sender: TObject);
begin
go:=false;
memo1.Lines.Add('Сканирование отменено');
statusbar1.Simpletext := '';
s.cancel;

Edit1.Enabled := true;
Edit2.Enabled := true;
Edit3.Enabled := true;
Edit4.Enabled := true;
Edit5.Enabled := true;
speedbutton1.Enabled := true;
speedbutton2.Enabled := false;
listbox1.Enabled := true;
end;

Как видите, тут все проще. Значение go становится равным false (то есть ложь), в мемо добавляется надпись, а powersock’у делается cancel.

Теперь нужно прописать две процедуры для самого powersock’а: onConnect и onConnectionFailed. Вот листинги:

procedure TForm1.sConnect(Sender: TObject);
begin
if not go then
begin
s.Disconnect;
exit;
end;
memo1.lines.add('Connect on '+s.host+' : '+inttostr(s.port));
NextIP;
if lastIP>strtoint(edit5.text) then
begin
memo1.Lines.Add('Scan complete');
statusbar1.Simpletext := '';
go:=false;
Edit1.Enabled := true;
Edit2.Enabled := true;
Edit3.Enabled := true;
Edit4.Enabled := true;
Edit5.Enabled := true;
speedbutton1.Enabled := true;
speedbutton2.Enabled := false;
listbox1.Enabled := true;
exit;
end;
if go then s.connect else exit;
end;


И соответственно, вторая процедура:

procedure TForm1.sConnectionFailed(Sender: TObject);
begin
if not go then
begin
s.disconnect;
exit;
end;
NextIP;
if lastIP>strtoint(edit5.text) then
begin
memo1.Lines.Add('Сканирование завершено');
statusbar1.Simpletext := '';
go:=false;
Edit1.Enabled := true;
Edit2.Enabled := true;
Edit3.Enabled := true;
Edit4.Enabled := true;
Edit5.Enabled := true;
speedbutton1.Enabled := true;
speedbutton2.Enabled := false;
listbox1.Enabled := true;
exit;
end;
if go then s.connect else exit;
end;

Тут следует заметить, что когда идет строчка if go then… это эквивалентно if go=true then…

Тут, надеюсь, все ясно. Будут вопросы – пишите.
Теперь перейдем к меню.

procedure TForm1.N121Click(Sender: TObject);
begin
memo1.CopyToClipboard;
end;

procedure TForm1.N131Click(Sender: TObject);
begin
memo1.Clear;
end;

Первая процедура – для копирования содержимого memo (там высвечиваются данные о сканировании) в буфер обмена, а вторая очищает memo. Напомню, что это было popupmenu1 . Теперь второе меню:

procedure TForm1.Add1Click(Sender: TObject);
begin
listbox1.Items.Add(inputbox('Add port...','Port:',''));
end;

procedure TForm1.Delete1Click(Sender: TObject);
begin
listbox1.Items.Delete(listbox1.itemindex);
end;

Первая добавляет в листбокс новый порт с помощью вызова окошка inputbox. Вторая удаляет выделенный порт из списка. Все просто, как два пальца об асфальт! =)

Дважды кликни по форме – появится редактор кода. Тут нужно ввести следующее:

procedure TForm1.FormCreate(Sender: TObject);
begin
listbox1.Items.LoadFromFile('ports.txt');
memo1.clear;
memo1.lines.add('Port scanner by freetonik');
memo1.lines.add('');
end;

Внутри процедуры выполняется четыре действия – сначала в листбокс грузится содержимое файла ports.txt. Затем очищается memo1. Тут же добавляется строчка с описанием. Ее можно опустить или написать что-то типа «Мой супер-сканер». И последним добавляется пустая строка в мемо.

При закрытии формы нужно сохранить новые добавленные порты в файл ports.txt.

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
listbox1.Items.SaveToFile('ports.txt');
end;

Все тут ясно? Вот и хорошо!

В шестом едите хранится значение паузы между коннектом. При изменении нужно тут же посылать это значение:

procedure TForm1.Edit6Change(Sender: TObject);
begin
if edit6.text='' then s.TimeOut:=0;
if edit6.text='' then exit;
s.TimeOut := strtoint(edit6.text);
end;

У компонента powersock (s) есть свойство timeout – это и есть пауза.
Вот мы и закончили! Неплохо накодили, да? Если тебе что-то непонятно – то попробуй разобрать исходник, который идет вместе с журналом. Если есть еще вопросы – пишите на tonik@mail.kz – ответчу всем!

freetonik







При перепечатке любого материала с сайта, видимая ссылка на источник www.warayg.narod.ru и все имена, ссылки авторов обязательны.

© 2005