SCAN

Portas abertas

 

Quantos de vocês trancam a porta de suas casas ao anoitecer, ou até mesmo à luz do dia? Acredito que a maioria. Com o forte avanço da Internet em todo o planeta nos deparamos com o mesmo problema em nossos computadores: portas abertas.

Neste artigo iremos desenvolver um aplicativo para scannear e apresentar as portas que estão abertas num determinado servidor.

Para facilitar a compreensão de todos, estou apresentando um exemplo muito simples, onde o usuário informa o Nome do Servidor (ou endereço IP), e o intervalo de portas a serem scanneadas.

Os leitores com conhecimentos mais avançados ou know-how em Threads irão me crucificar por falta das benditas. Acontece que o principal objetivo deste exemplo é demonstrar o uso do componente TCPClient, e não do uso de Threads. Isso iria complicar um pouco a compreensão dos nossos amigos leitores.

Aos amigos que se encaixam neste perfil, minhas sinceras desculpas. Bem, continuando, agora vem a parte boa: mão-na-massa. Vamos iniciar um novo projeto no Delphi (grave a unit como un_scan.pas e o projeto como pscan.drp) e inserir os objetos que seguem:

Objeto

Propriedade

Valor

 TPanel 

Align

AlTop

Caption

 

Name

PnTopo

 

 

 

 

 

 

Com o foco no objeto pnTopo insira os seguintes objetos:

Objeto

Propriedade

Valor

 TLabel

Caption

HOST

Left

16 

Top

14

 

 

 

 

 

Objeto

Propriedade

Valor

 TLabel

Caption

Porta Inicial

Left

16 

Top

43

 

 

 

 

 

Objeto

Propriedade

Valor

 TLabel

Caption

Porta Final

Left

232 

Top

43

 

 

 

 

 

 

Agora vamos inserir os objetos de controle e interatividade com o usuário. Mantenha o foco no objeto pnTopo e insira os seguintes objetos:

Objeto

Propriedade

Valor

 TEdit

Name

Nome do Servidor

Left

104

Top

10

Width

290

 

 

 

 

 

 

 

Objeto

Propriedade

Valor

 TSpinEdit

Name

Inicio

Left

104

Top

40

 

 

 

 

 

Objeto

Propriedade

Valor

 TSpinEdit

Name

Fim

Left

320

Top

40

 

 

 

 

 

 

Neste ponto vamos inserir o botão para iniciar o processo de scanner de portas.

Objeto

Propriedade

Valor

 TButton

Name

BtScan

Caption

Scan

Left

416

Top

8

 

 

 

 

 

 

 

 

Com isso concluímos a primeira etapa do projeto. Prosseguindo, vamos criar o módulo de saída das informações.

Agora com o foco no formulário e não mais no objeto pnTopo, insira um objeto do tipo Tpanel alterando as seguintes propriedades:

Objeto

Propriedade

Valor

 TPanel

Name

PnDados

Align

AlCliente

 

 

 

 

 

Vamos inserir os objetos deste painel, como segue:

Objeto

Propriedade

Valor

 TButton

Name

ListadePortas

Height

180

Left

16

Top

76

Width

500

 

 

 

 

 

 

 

 

 

Dentro deste mesmo painel pnDados, insira outro objeto do tipo TPanel alterando as propriedades que seguem:

Objeto

Propriedade

Valor

 TPanel

Name

PnProgresso

Caption

 

Height

65

Left

16

Top

8

Width

500

 

 

 

 

 

 

 

 

 

 

 

Com o foco no objeto pnProgresso insira os seguintes objetos:

Objeto

Propriedade

Valor

 TButton

Name

BtParar

Caption

Parar

Left

400

Top

32

 

 

 

 

 

 

 

Objeto

Propriedade

Valor

 TProgressBar

Name

ProgressBar1

Width

470

Left

16

Top

8

 

 

 

 

 

 

 

Objeto

Propriedade

Valor

 TLabel

Caption

Scaneando Porta...

Left

16

Top

36

 

 

 

 

 

Objeto

Propriedade

Valor

 TLabel

Caption

0

Left

112

Top

36

 

 

 

 

 

 

Ufa !!! E para concluir a “enorme” lista de objetos, insira um do tipo TTCPClient que se encontra na seção Internet.

Objeto

Propriedade

Valor

 TTCPClient

Name

TCPClient1

 

 

Codificando o Projeto

Finalmente vamos codificar o nosso projeto. Crie uma variável global pertencente a nossa classe Form1 com o nome Parar, do tipo Integer; veja:

 

var

  Form1: TForm1;

  parar:integer; // variavel auxiliar

implementation

 

A variável Parar será utilizada para finalizar o processo de Scanner das Portas. Neste ponto é que poderíamos criar uma Thread, mas não vamos complicar.

Só para aliviar um pouco a forte tensão, vamos dar uma olhadinha na interface do nosso projeto:

 

Figura 1. Projeto Port Scanner

 

Vamos codificar o botão btScan, responsável pelo núcleo do nosso projeto. No evento onClick do objeto btScan, insira o código que segue (para facilitar, numerei as linhas de programação, de forma que possamos analisar melhor o código).

 

001 procedure TForm1.BtScanClick(Sender: TObject);

002 var i:integer;

003 begin

004 try

005   ListadePortas.Clear; // Limpa a Lista de Portas

006

007    parar:=0; // 0 = continua, 1 = conclui

008

009    // Definições da barra de progresso

010

011    ProgressBar1.Max:=Fim.Value;

012    ProgressBar1.Min:=Inicio.Value;

013

014    PainelProgresso.Visible:=True;

015    TcpClient1.RemoteHost := NomeServidor.Text;

016

017       for i := Inicio.Value to Fim.Value do

018        begin

019          if parar=1 then break; // finaliza o laço

020

021          ProgressBar1.Position:=i;

022          porta.Caption:=inttostr(i);

023

024          Application.ProcessMessages;

025          TcpClient1.RemotePort := inttostr(i);

026          TcpClient1.Active:=true;

027

028          if TcpClient1.Connect then

029    ListadePortas.Lines.Add('Porta ['+ inttostr(i) +'] aberta');

030

031          TcpClient1.Disconnect; // disconeta porta

032

033          end; //for loop

034       except

035        on E:Exception do begin

036          ListadePortas.Lines.Add('Erro: ' + E.Message);

037        end; // end on do begin

038 end; // end on do begin

039

040 ListadePortas.Lines.Add('Scaneamento das portas finalizado !');

041

042   PainelProgresso.Visible:=False;

043 end

Detalhamento do Código

A linha 002 declara uma variável “ i “ que irá auxiliar no laço de contagem das portas.

var i:integer;

 

Na linha 004 iniciamos uma proteção de erros da aplicação.

try

 

A linha 005 limpa o conteúdo do objeto ListaPortas.

ListadePortas.Clear

 

Na linha 007 inicializamos a variável parar com o valor 0, de forma que o sistema continue scanneando as portas até o limite solicitado pelo usuário, ou através do pressionamento da tecla Parar, fazendo com que a variável receba o valor 1

parar:=0; 

 

As linhas 011 e 012 configuram o objeto ProgressBar1 de maneira que o mesmo fique compatível com as informações porta inicial e final. Com isso temos um progresso adequado.

ProgressBar1.Max:=Fim.Value;

ProgressBar1.Min:=Inicio.Value;

 

A linha 014 torna visível o objeto PainelProgresso.

PainelProgresso.Visible:=True;

 

A linha 015 configura o servidor remoto do objeto TcpClient1.

TcpClient1.RemoteHost := NomeServidor.Text; 

 

A linha 017 inicia um loop baseado nas informações Porta Inicial e Final.

for i := Inicio.Value to Fim.Value do

 

Já na linha 019 nossa aplicação verifica se existe a obrigação de paralisar o loop. Esta informação vem do botão btParar.

if parar=1 then break;

 

A linha 021 posiciona a barra de progresso em relação ao andamento do loop.

ProgressBar1.Position:=i;

 

Na linha 022 apenas mostramos ao usuário através do objeto Porta, qual porta está sendo scanneada no momento

porta.Caption:=inttostr(i); 

 

A linha 024 solicita ao Windows que processe as informações da aplicação, de maneira que a mesma não tenha o efeito congelamento.

Application.ProcessMessages;

 

A linha 025 configura a porta que deve ser scanneada, a 026 tenta ativar, e a 028 verifica se houve sucesso na ativação, e em caso afirmativo, a linha 029 adiciona no objeto ListadePortas a informação que a Porta está aberta.

 

TcpClient1.RemotePort := inttostr(i);

    TcpClient1.Active:=true;

 

    if TcpClient1.Connect then

    ListadePortas.Lines.Add('Porta ['+ inttostr(i) + '] aberta');

 

A linha 031 disconecta a porta independente do seu estado (aberta ou fechada).

TcpClient1.Disconnect;

 

A linha 032 finaliza o loop. As linhas 033, 034 e 035 tratam qualquer exceção ocorrida no bloco protegido (try...except...end).

 

end; //for loop

except

0 on E:Exception do begin

ListadePortas.Lines.Add('Erro: ' + E.Message);

end; // end on do begin

end; //try block

 

Concluindo esta rotina, a linha 039 apresenta uma mensagem indicando o fim do scanneamento das portas, e a 041 torna o objeto PainelProgresso invisível.

ListadePortas.Lines.Add('Scaneamento das portas finalizado !');

PainelProgresso.Visible:=False;

 

Para concluir o nosso projeto, devemos codificar o botão btParar com o seguinte código (no evento OnClick):

Parar:=1;

 

Amigos, agora é só executar aplicativo, informar o nome do servidor (caso seu próprio equipamento, digite localhost, no campo Nome do Servidor), e o intervalo de portas a serem scanneadas.

 

Importante

Embora seja possível, não recomendo o uso deste aplicativo para scanear portas de servidores não-autorizados. Normalmente utilizamos este tipo de arquivo para vigiar nosso "quintal" e não o do vizinho.