SCAN - Portas Abertas
Veja neste artigo de Emerson Facuntes, como scanear as "portas" que estão vulneráveis. Acesso exclusivo para Assinantes.
Você não gostou da qualidade deste conteúdo?
(opcional) Você gostaria de comentar o que não lhe agradou?
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.
Emerson Facunte
Emerson Facunte é especialista em aplicações e-business, e membro-fundador do DUG-BR. Ministrou palestras e cursos para mais de 5 mil pessoas em todo território nacional. Pode ser contatado em emerson@facunte.com.br



