Construindo um portscanner TCP com Python

Implementação de um portscanner básico em Python a fim de compreender um pouco o funcionamento de ferramentas como NMAP e sockets TCP.

[ Hits: 963 ]

Por: Vitor Marques em 05/11/2018 | Blog: https://github.com/10Seeker10/


Introdução



A maioria das pessoas da área de Segurança da Informação conhece a famigerada ferramenta Nmap, que possibilita um scan de portas na máquina alvo de diversas formas e métodos a gosto do usuário. Neste artigo ensinarei a criar um portscanner TCP a fim de prover o entendimento de como tais ferramentas trabalham. Partirei do pressuposto de que o leitor possui conhecimentos básicos em Python e protocolos de rede.

Estrutura do programa e requisitos

Primeiramente criarei a ferramenta da forma mais básica e depois a aprimorarei adicionando threads e funcionalidades extras. Para o programa usarei os módulos:
  • sys :: para a passagem de argumentos
  • socket :: para o uso de sockets TCP
  • threading :: para o uso de threads no programa mais avançado

A estrutura, a priori, será composta de quatro funções:
  • main :: função principal que receberá os argumentos e chamará scan
  • scan :: função que iterará sobre as portas chamando child para cada
  • child :: função que cuidará do scan de uma determinada porta, chamará banner
  • banner :: função que tentará descobrir o serviço rodando em determinada porta

Função Main

def main():
	args = sys.argv
	if len(args) < 2:
		print("[!]Falta argumentos para o programa!Saindo...")
		sys.exit(1)
	ip = args[1]  # 1
	portas = args[2] if len(args >= 3) else "1:65536" # 2 
	portas = (x for x in range(int(portas.split(":")[0]), int(portas.split(":")[1])+1)) # 3
	scan(ip, portas) # 4

  1. IP será o primeiro argumento, como o próprio programa é o primeiro item da lista então o index do segundo argumento é 1.
  2. Se o usuário não passar o segundo argumento então escaneará todas as portas.
  3. Cria-se um objeto gerador com todas as portas a serem escaneadas.
  4. Chamamos agora a função scan.

Função Scan

def scan(ip, portas):
	for c in portas:
		child(ip, c) 

Função bem simples que chama uma child para cada porta.

Função Child

Agora inicia-se realmente a parte lógica do programa:

def child(ip, port):
	try:
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 1
		s.settimeout(0.3) # 2
		if s.connect_ex((ip, port)) == 0: # 3
			print("{}/tcp open".format(port), end='|')
			print(banner(s, ip, port)) # 4
       	 except:
		 pass

  1. Criamos um socket IPv4(AF_INET), TCP(SOCK_STREAM) que interagirá com o alvo.
  2. Setamos um timeout, se o alvo não responder em 0.3 uma exceção será gerada e a função chegará ao fim no bloco except.
  3. O método connect_ex retorna um número igual a 0 se a porta estiver aberta, logo colocamos uma condicional baseada nisso.
  4. Após sabermos que a porta está aberta, chamamos o método banner que tentará pegar informações do serviço rodando nesta porta, printando seu retorno que pode ser 'Unknown' se não conseguir ou a string desejada.

Função Banner

def baner(sckt, ip, porta):
	try:
		sckt.settimeout(1) # 1
		sckt.connect((ip, porta)) # 2
		banner = sckt.recv(1024).decode().strip() # 3
		assert banner # 4
		return banner
	except: # 5
		return 'Unknown'

  1. Aumentamos um pouco o tempo de timeout haja vista que pode demorar um pouco mais para receber o banner.
  2. Dessa vez nos conectamos diretamente à porta.
  3. Recebemos 1024 bytes do serviço rodando remotamente, convertemos de bytes para string, removemos quebra de linhas.
  4. Se não tiver recebido nenhum banner, uma Assertion Error será gerada, indo assim para o bloco except.
  5. O bloco except capturará todo tipo de exceção possível, Assertion Error, socket.timeout, ou problema de conexão, retornando 'Unknown' nesses casos.

    Próxima página

Páginas do artigo
   1. Introdução
   2. Código completo
Outros artigos deste autor

Introdução a Threads e como implementá-las em Python

Interagindo com servidores HTTP com Python

Leitura recomendada

PEP 8 - Guia de estilo para código Python

Introdução ao clib (Command Line Book)

ISO8583py - Utilizando Python para o tratamento de mensagens ISO8583

Python + ADB

rwd - Restart When Down

  
Comentários

Nenhum comentário foi encontrado.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor HostGator.
Linux banner
Linux banner
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts