[Portuguese] Playing with sockets (port scanning)

EDB-ID:

13024

CVE:

N/A

Author:

Th1nk3r

Type:

papers

Platform:

Multiple

Published:

2008-09-28

=-|================================================-{ www.enye-sec.org }-====|
=-[ Bricando com sockets (port scanning) ]-==================================|
=-|==========================================================================|
=-[ por Pepelux <pepelux@enye-sec.org> ]-=====================-[13/11/2007]-=|
=-|==========================================================================|
=-[ Traduzido por: Th1nk3r <cnwfhguohrugbo@gmail.com> ]=======-[19/09/2008]-=|
=-|==========================================================================|


O Texto na sua versão original pode ser encontrado em:
http://www.milw0rm.com/papers/224

NOTA DO TRADUTOR (Note of Translator):
==============================================================================
	Todo o conteúdo apresentado neste documento é de responsabilidade do
escritor, sendo que eu apenas me dei o trabalho de traduzi-lo.
	Perdoem-me pelos poucos erros ortográficos e gramaticais, pois não 
tive tempo de fazer uma revisão completa. [:p]
	Dedico a tradução à todos meus amigos.
								Th1nk3r
==============================================================================

------[ 0.- Índice ]


0.- Índice

1.- Breve introdução
  1.1.- Scan aberto (Open Scan)
  1.2.- Scan semi-aberto (Half Open Scan)
  1.3.- Stealth Scan

2.- Brincando com sockets
  2.1.- TCP Sockets
  2.2.- UDP / ICMP Sockets

3.- Detecção de sistemas operacionais
  3.1.- Alguns testes

4.- Arquivos

5.- Referências

6.- Finalizando



------[ 1.- Breve Introdução ]

Por muitos tempo nossos métodos de escanear portas foi usando o telnet, fazendo manualmente.
Hoje as pessoas usam os mais sofisticados programas que possuem varios métodos para escanear
um faixa de IP procurando por uma grande quantidade de portas.

Eu estarei escrevendo de forma rapida os diferentes métodos de scanning, pois um conteúdo
que vá mais fundo pode ser encontrado na Internet. Além disso, ao fim desse arquivo você pode
encontrar dicas de como aprender sockets de maneira divertida.

------[ 1.1.- Scan aberto (Open Scan) ]

Conhecida como TCP Scan e normalmente usada para programar sockets, essa técnica é
antiga e trabalha fazendo uma conexão completa com o servidor. É como se conectar
a cada porta de um servidor através do telnet, mas automaticamente.

Com isso se faz uma conexão com 3 pacotes (conhecida como three-way-handshake [aperto-de-mao em tres passos]):

Para portas abertas temos:

      Cliente ---->   SYN   ---->
              <---- SYN/ACK <---- Servidor
      Cliente ---->   ACK   ---->

Para portas fechadas temos:

      Cliente ---->   SYN   ---->
              <----   RST   <---- Servidor

Vantagens    : Muito fácil de programar.
Desvantagens : Muito fácil de detectar e gera logs a cada conexão.


------[ 1.2.- Scan semi-aberto (Half Open Scan)]

Ésta tecnica trabalha fazendo com que a conexão seja iniciada, mas não completada.
Envia-se um SYN, mas não envia-se um ACK se a porta estiver aberta.

Usando RAW sockets nós podemos programar manualmente os cabeçalhos do socket e enviar
somente o inicio da conexão. Logo veremos isso melhor com alguns exemplos.

------[ 1.3.- Stealth Scan ]

É similar aos métodos anteriores, mas envia-se outra flag, ou uma combinação de flags.

O mais conhecido e usado pelo nmap é:
      SYN
      SYN+ACK
      FIN
      ACK
      NULL (all flags with 0)
      XMAS (FIN=URG=PSH=1)

Nos exemplos que virão nós veremos isso claramente.


------[ 2.- Brincando com sockets ]

É a hora de se divertir. Nós enviaremos diferentes pacotes alterando as flags e estudando
os resultados.

Nos testes eu usei dois computadores:

Cliente  : 192.168.2.5 (Linux Debian - kernel 2.6.18.1)
Servidor : 192.168.2.7 (Linux Debian - kernel 2.6.21.2)
Portas abertas no servidor: 22(TCP), 80(TCP), 111(UDP)


------[ 2.1.- TCP Sockets ]

Para examinar as portas TCP, nós usaremos um programa para enviar e receber RAW Sockets,
o que nos permitirá escolher os valores dos flags.

- sendsock.c -> 
Usage: ./sendsocket [s|a|r|p|u|f] [-x host_source] -d host_destination -c port
            -s SYN flag enabled
            -a ACK flag enabled
            -r RST flag enabled
            -p PSH flag enabled
            -u URG flag enabled
            -f FIN flag enabled


Enviar SYN (half open connection)
---------------------------------
Consiste em fazer uma semi conexão, enviando um SYN, e quando obtermos qualquer
resposta (ACK+SYN ou RST) enviaramos um RST para finalizar a conexão (usando RAW
Sockets, o pacote RST é enviado automaticamente pelo kernel).

A idéia original consiste em enviar um SYN e se o servidor responder com um ACK+SYN,
nós enviamos um pacote RST dizendo que nós não queremos fazer uma conexão. Como 
a conexão não foi completada o servidor nao salva nenhum log. :-)

Atualmente muitos computadores podem detectar essa tecnica e salvar um log ou bloquear
esse tipo de ataque com um firewall.

Vantangens   : Funciona em todos os sistemas operacionais e portas, se não existir um firewall.
Desvantagens : É muito fácil de detectar e gerar logs.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 80 -s
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  0  |  0  |  0  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=39553 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  1  |  0  |  0  |  0  |  0  | 64  | 53270
     seq=-1378930670 - ack_seq=863708102 - doff=6 - check=8049 - ID=0

Porta aberta. Nós obtemos um SYN+ACK e Window<>0

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 23 -s
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  0  |  0  |  0  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=54145 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  1  |  0  |  0  |  0  | 64  | 0
     seq=0 - ack_seq=863708102 - doff=5 - check=49281 - ID=0

Porta fechada. Nós obtemos um ACK+RST e Window=0.


Enviar ACK
----------
Este método apenas tem efeito em alguns DBS antigos e Sistemas Operacionais Unix. Consiste
em checar o campo Window. Se obter um Window=0 a porta está aberta e se obter um Window<>0 a
porta está fechada.

Vantangens    : É dificil de ser detectado.
Desvantangens : Não funciona em todos os SOs.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 80 -a
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  0  |  0  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=35969 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  1  |  0  |  0  |  0  | 64  | 0
     seq=0 - ack_seq=0 - doff=5 - check=61122 - ID=0

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 23 -a
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  0  |  0  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=50561 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  1  |  0  |  0  |  0  | 64  | 0
     seq=0 - ack_seq=0 - doff=5 - check=10179 - ID=0

Nesse caso meu linux não é vulnerável e nós obtemos o mesmo resultado resultados
com a porta aberta ou fechada.


Enviar RST
----------

Este ataque apenas tem efeito em alguns sistemas e nem sempre é eficaz. Nesse caso
nós obtemos apenas um ACK ou se nós nao obtemos resposta, a porta está aberta e se nós
obtermos um RST, a porta está fechada.

Vantangens    : É dificil de ser detectado.
Desvantangens : Não funciona em todos os SOs e nem em todas as portas.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 80 -r
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  1  |  0  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=39041 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  0  |  1  |  0  |  0  | 53  | 37920
     seq=1193401395 - ack_seq=908914171 - doff=5 - check=43532 - ID=4979

Porta aberta. Nós obtemos ACK+PSH, TTL<64 e Window<>0.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 23 -r
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  1  |  0  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=53633 - ID=27032

Sem resposta ... Porta fechada.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 22 -r
      DADOS ENVIADOS
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  1  |  0  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=53889 - ID=27032

Sem resposta ... A resposta não é confiável pois a porta está aberta.

Como nós podemos ver, se obtermos qualquer resposta a porta está aberta e se
nós nao obtermos resposta, nós nao podemos saber se a porta está aberta ou fechada.


Enviar PSH
----------
Este ataque apenas tem efeito em alguns sistemas e nem sempre é eficaz. Nesse caso se nós
obtemos um ACK+PSH e um Windows<>0 ou não obtermos resposta, a porta está aberta e se obtermos
um RST, a porta está fechada.

Vantagens    : É dificil de ser detectado.
Desvantagens : Não funciona em todos os SOs.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 80 -p
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  1  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=38017 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  0  |  1  |  0  |  0  | 53  | 17447
     seq=1710733151 - ack_seq=1317887646 - doff=5 - check=32634 - ID=4439


Porta aberta. Nós obtemos um ACK+PSH, TTL<64 e Window<>0.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 23 -p
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  1  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=52609 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  1  |  0  |  0  |  0  | 64  | 0
     seq=0 - ack_seq=846930886 - doff=5 - check=49537 - ID=0

Porta fechada. Nós obtemos RST, TTL=64 e Window=0.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 22 -p
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  1  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=52865 - ID=27032

Sem resposta ... porta fechada.


Enviar URG
----------
Este ataque apenas tem efeito em alguns sistemas e nem sempre é eficaz. Nesse caso se
obtermos um ACK sem um RST ou se nao obtermos resposta, a porta está aberta. Se obtermos
um RST, a porta está fechada.

Vantagens   : É dificil de ser detectado.
Desvantagens: Funciona no meu Linux mas pode nao funcionar em alguns sistemas.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 80 -u
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  0  |  1  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=31873 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  0  |  1  |  0  |  0  | 53  | 37920
     seq=-716127216 - ack_seq=1741636632 - doff=5 - check=41524 - ID=59663

Porta aberta. Obtemos ACK+PSH, TTL<64 e Window<>0.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 23 -u
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  0  |  1  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=46465 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  1  |  0  |  0  |  0  | 64  | 0
     seq=0 - ack_seq=846930886 - doff=5 - check=49537 - ID=0

Porta fechada. Obtemos ACK+RST, TTL=64 e Window=0.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 22 -u
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  0  |  1  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=3968 - ID=27032

Sem resposta: Porta aberta.


Enviar FIN
----------

Este ataque apenas tem efeito em alguns sistemas e nem sempre é eficaz. No caso se
obtermos um ACK ou se nao obtermos resposta, a porta está aberta. Se obtermos um RST
a porta está fechada.

Em outros sistemas voce poderá notar a diferença na flag RST. Se está ativada a porta
está fechada e se o valor de RST é zero a porta está aberta.

Vantagens   : É dificil de detectar.
Desvantagens: Nao funciona em todos os sistemas operacionais porque é baseada em um bug.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 80 -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  0  |  0  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=39809 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  0  |  1  |  0  |  1  | 53  | 37920
     seq=-1722694640 - ack_seq=1741636632 - doff=5 - check=39751 - ID=56001

Porta aberta. Nós obtemos ACK+PSH+FIN,TTL<64 e Window<>0.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 23 -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  0  |  0  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=54401 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  1  |  0  |  0  |  0  | 64  | 0
     seq=0 - ack_seq=863708102 - doff=5 - check=49281 - ID=0

Porta fechada. Obtemos ACK+RST, TTL=64 e Window=0.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 22 -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  0  |  0  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=54657 - ID=27032

Sem resposta... Porta aberta.


Enviar SYN+ACK
--------------
Nós usaremos algumas combinações de flags. Este ataque só funciona em alguns
sistemas. Quando funciona, se voce obter qualquer resposta, a porta está aberta
e se receber um RST, a porta está fechada.

Vantagens   : É dificil de detectar.
Desvantagens: Não funciona em todos os sistemas.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 80 -s -a
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  1  |  0  |  0  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=35457 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  1  |  0  |  0  |  0  | 64  | 0
     seq=0 - ack_seq=0 - doff=5 - check=61122 - ID=0

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 23 -s -a
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  1  |  0  |  0  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=50049 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  1  |  0  |  0  |  0  | 64  | 0
     seq=0 - ack_seq=0 - doff=5 - check=10179 - ID=0

No caso nós obtemos o mesmo resultado e nós nao sabemos se porta está
aberta ou fechada. Como eu disse, isso tem efeito em apenas alguns sistemas. :)


Enviar SYN+PSH
--------------
Quando nós nao obtemos um RST e Windows<>0, a porta está aberta e com um RST
e Window=0, a porta está fechada.

Vantagens   : É dificil detectar.
Desvantagens: Funciona no meu Linux mas nao sei se funciona em outros sistemas.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 80 -s -p
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  0  |  0  |  1  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=37505 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  1  |  0  |  0  |  0  |  0  | 64  | 53270
     seq=1874969709 - ack_seq=863708102 - doff=6 - check=51491 - ID=0

Porta aberta. Nós obtemos um SYN+ACK e Window<>0.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 22 -s -p
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  0  |  0  |  1  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=52353 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  1  |  0  |  0  |  0  |  0  | 64  | 53270
     seq=1445991790 - ack_seq=863708102 - doff=6 - check=52148 - ID=0

Porta aberta. Obtemos SYN+ACK e Window<>0.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 23 -s -p
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  0  |  0  |  1  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=52097 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  1  |  0  |  0  |  0  | 64  | 0
     seq=0 - ack_seq=863708102 - doff=5 - check=49281 - ID=0

Porta fechada. Obtemos ACK+RST e Window=0.


Enviar URG+FIN
--------------
Nesse método, se nós nao obtermos reposta, a porta está aberta e com RST,
a porta está fechada.

Vantagens   : É dificil detectar.
Desvantagens: Funciona no meu Linux mas nao sei se funciona em outros sistemas.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 80 -u -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  0  |  1  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=31617 - ID=27032

Sem resposta... porta aberta.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 23 -u -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  0  |  1  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=46209 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  1  |  0  |  0  |  0  | 64  | 0
     seq=0 - ack_seq=863708102 - doff=5 - check=49281 - ID=0

Porta fechada. Obtemos um ACK+RST.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 22 -u -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  0  |  1  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=46465 - ID=27032

Sem resposta... porta aberta.


Enviar URG+FIN+PSH
------------------
Mais conhecida como XMAS scan, quando nós nao obtemos resposta ou nao obtemos um RST,
a porta está aberta. Está fechada quando obtemos um RST.

Vantagens   : É dificil de detectar.
Desvantagens: Funciona somente em alguns sistemas.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 80 -p -u -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  1  |  1  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=23938 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  1  |  0  |  0  |  0  |  0  | 47  | 10262
     seq=128745367 - ack_seq=338264191 - doff=10 - check=49414 - ID=0

Porta aberta. Nós obtemos um SYN+ACK.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 22 -p -u -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  1  |  1  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=38786 - ID=27032

Sem resposta ... porta fechada.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 22 -u -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  1  |  1  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=38530 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  1  |  0  |  0  |  0  | 56  | 0
     seq=0 - ack_seq=863708102 - doff=5 - check=43650 - ID=56815

Porta fechada. Nós obtemos um ACK+RST.


Enviar nulo
-----------
Conhecido como "null scan", ésta técnica consiste em enviar flags com zero. Nesse caso,
quando a resposta é um ACK ou se nao obtemos resposta, a porta está aberta e com um RST,
a porta está fechada.

Vantagens   : É dificil de detectar.
Desvantagens: Funciona somente em alguns sistemas.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 80
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  0  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=40065 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  0  |  0  |  0  |  0  | 53  | 22560
     seq=-515721121 - ack_seq=1706581918 - doff=5 - check=55050 - ID=61453

Porta aberta. Nós obtemos ACK.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 23
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  0  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=54657 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  1  |  0  |  0  |  0  | 64  | 0
     seq=0 - ack_seq=846930886 - doff=5 - check=49537 - ID=0

Porta fechada. Obtemos ACK+RST.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 22
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  0  |  0  |  0  |  0  |  0  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=54913 - ID=27032

Sem resposta... porta aberta.


Enviar SYN+ACK+RST+PSH+URG+FIN
------------------------------
Consiste em enviar todas as flags ativadas (com valores 1). Nesse caso, quando
a resposta é um ACK ou se nao obtemos resposta, a porta está aberta.
Com um RST a porta está fechada.

Vantagens   : É dificil de detectar.
Desvantagens: Funciona somente em UNIX.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 80 -s -a -r 
                  -p -u -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  1  |  1  |  1  |  1  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=23937 - ID=27032

      DADOS RECEBIDOS
      -------------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  0  |  1  |  0  |  1  | 53  | 37920
     seq=2033962504 - ack_seq=-1093275500 - doff=5 - check=8061 - ID=35468

Porta aberta. Obtemos um ACK+PSH.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 23 -s -a -r 
                  -p -u -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  1  |  1  |  1  |  1  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=38529 - ID=27032

Sem resposta... resultado nao valido porque a porta está realmente fechada.

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 22 -s -a -r 
                  -p -u -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  1  |  1  |  1  |  1  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=38785 - ID=27032

Sem resposta... resultado nao valido porque a porta está aberta.

Nesse caso a tecnica nao é valida para nos porque as resposta nao batem. Como eu
disse, somente funciona em UNIXs.


------[ 2.2.- UDP / ICMP Sockets ]

Para verificar se portas UDP estão aberta nós iremos brincar um pouco mais enviando
pacotes. O protocolo UDP nao é orientado em uma conexão como o protocolo TCP, e nós nao
podemos esperar por uma resposta depois de enviar um pacote. Por isso, usando somente
UDP nós nao podemos saber se uma porta está ou não aberta.


Para escanear nós teremos o auxilio de pacotes ICMP. Por que? porque quando voce tenta
fazer uma conexão com uma porta UDP o servidor irá responder com um pacote ICMP em caso
de erro; justamente um pacote tipo 3 / codigo 3 , que se você ver nos documentos RFC 
você entenderá: tipo 3 = destino da mensagem inacessível /
codigo 3 = porta inacessível.

Como nós amamos fazer estas coisas manualmente, nós usaremos 2 programas:
- checkicmp.c -> Escuta por conexões ICMP no nosso computador.
- sendudp.c   -> Envia um pacote UDP em um host/porta.

     flashgordon# ./checkicmp
     Waiting data ...

Enquanto o programa aguarda, nós abriremos outro terminal e enviaremos em uma porta fechada:


     flashgordon# ./sendudp 192.168.2.7 100
     Sending UDP packet to 192.168.2.7:100

No primeiro terminal nós podemos ver:

     flashgordon# ./checkicmp
     Waiting data ...
     Received:       type 3  code 3

Isto nos diz que a porta está fechada... verifique em uma porta aberta para
ver o que acontece:

     flashgordon# ./sendudp 192.168.2.7 111
     Sending UDP packet to 192.168.2.7:111

E no outro terminal:

     flashgordon# ./checkicmp
     Waiting data ...
     Received:       type 3  code 3

Nada muda (a mensagem) ... como nós nao recebemos qualquer pacote nós podemos dizer
que a porta está aberta.

Teste outra vez com uma porta fechada:

     flashgordon# ./sendudp 192.168.2.7 101
     Sending UDP packet to 192.168.2.7:101

E no outro terminal:

     flashgordon# ./checkicmp
     Waiting data ...
     Received:       type 3  code 3
     Received:       type 3  code 3

Nós obtemos outro pacote ICMP nos dizendo que a porta 101 está fechada também.


------[ 3.- Detecção de sistemas operacionais ]

Nós podemos saber o sistema operacional rodando em um servidor sem fazer
uma conexão TCP. Como ocorre com os metodos de scan mostrados anteriormente,
servidores diferentes podem responder pacotes diferentes (nós vimos que 
conexões TCP envia um SYN e espera por um SYN+ACK ou um RST) porque cada sistema
pode responder de forma diferente. O mesmo acontece enviando pacotes UDP ou
ICMP que nao são típicos para fazer fazer uma conexão padrão.

Eu nao mostrarei todas as diferenças entre sistemas operacionais pois isso requer
uma grande quantidade de testes, de sistemas operacionais e de tempo. :) ....
Além do mais, o scanner nmap tem um ótimo banco de dados de sistemas operacionais 
detectáveis, baseado no famoso QueSO de Savage.

Mas nós iremos brincar um pouco mais com os sockets para ver e entender tudo isso.

Nos testes eu usei 4 computadores:

Cliente : 192.168.2.5 (Linux Debian - kernel 2.6.18.1)
Servidor1: 192.168.2.7 (Linux Debian)
Servidor2: 192.168.2.6 (Windows 2000 Server)
Servidor3: 192.168.2.8 (Solaris)
Porta aberta nos 3 servidores: 80(TCP)


Antes de fazer qualquer coisa para entender a detecção de sistemas operacionais
você pode brincar com mais headers de cada pacote, mas para nao alterar os programas
e como isso é somente um teste, eu usarei a mesma flag como antes.

------[ 3.1.- Alguns testes ]

Para fazer os testes eu enviarei um pacote TCP Ã  porta 80 (aberta) com flags
SYN+URG+FIN ativadas.

Primeiro servidor, sob Linux:

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.7 -c 80 -s -u -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  0  |  0  |  0  |  1  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=31617 - ID=27032

      DADOS RECEBIDOS
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  1  |  0  |  0  |  0  |  0  | 64  | 6272
     seq=24764339 - ack_seq=863708102 - doff=6 - check=32130 - ID=0

Segundo servidor, sob Windows:

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.6 -c 80 -s -u -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  0  |  0  |  0  |  1  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=17292 - ID=27032

      DADOS RECEBIDOS
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  0  |  1  |  0  |  1  |  0  |  0  | 48  | 33820
     seq=2043592525 - ack_seq=772288166 - doff=5 - check=30285 - ID=15717

Terceiro servidor, sob Solaris:

     flashgordon# ./sendsocket -x 192.168.2.5 -d 192.168.2.8 -c 80 -s -u -f
      DADOS ENVIADOS
      ---------
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  0  |  0  |  0  |  1  |  1  | 64  | 65535
     seq=846930886 - ack_seq=0 - doff=5 - check=50815 - ID=27032

      DADOS RECEBIDOS
     | SYN | ACK | RST | PSH | URG | FIN | TTL | Window
     |  1  |  1  |  0  |  0  |  0  |  0  | 41  | 65535
     seq=1684159920 - ack_seq=1278904408 - doff=6 - check=34271 - ID=62243

Se nós analisarmos as diferenças:
- Linux  : SYN+ACK - TTL=64 - Window= 6272
- Windows: ACK+PSH - TTL=48 - Window=33820
- Solaris: SYN+ACK - TTL=41 - Window=65535

Como eu disse anteriormente, isto é somente um teste para entender como a detecção de sistemas
operacionais funciona. Realmente nós temos que alterar mais campos e combinar com os pacotes UDP
e ICMP. As diferenças entre Linux, Windows e Solaris é evidente, mas usando mais testes nós
podemos ver as diferenças entre diferentes versões de sistemas operacionais, por exemplo
entre um Windows 98 e Windows 2000, ou ver diferenças entre cada Distribuição Linux ou
Kernels.


------[ 4.- Arquivos ]

Programas usados para fazer os testes:

--- sendsocket.c --------------------------8<---------------------------------
// sendsocket.c
// By Pepelux

// Change DEFAULT_HOST writing your private IP if you want to use always the 
// same IP address

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netdb.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/wait.h>
#include<sys/select.h>
#include<sys/time.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<linux/if_ether.h>
#include<linux/if_packet.h>
#include<netinet/tcp.h>


#define Error(msg) { perror(msg); exit -1; }
#define DEFAULT_HOST	"PUT HERE YOUR PRIVATE IP"
#define PBUFFER		10000
#define BUFFER_LONG	65536
#define DEFAULT_LEN     (sizeof(struct tcphdr)+sizeof(struct iphdr))

void usage(char *nom);
unsigned short cksum(unsigned short *, int);
void SendPacket(struct sockaddr_in saddr, struct sockaddr_in daddr, int dport,
	int syn, int ack, int psh, int rst, int urg, int fin);


int main(int argc, char *argv[]) {
	int dport;
	char *host_dest, *host_source;
	struct sockaddr_in saddr, daddr;
	struct hostent *hostentry;
	int i, c;
	int h = 0;		// destination flag
	int x = 0;		// Source flag
	int syn = 0;		// SYN flag
	int ack = 0;		// ACK flag
	int rst = 0;		// RST flag
	int urg = 0;		// URG flag
	int fin = 0;		// FIN flag
	int psh = 0;		// PSH flag

        if (geteuid() != 0) {
                printf("You must be root to use RAW Sockets\n");
                exit(0);
        }

	// Check params
	while((c = getopt(argc, argv, "saprufd:x:c:")) != -1) {
		switch(c) {
			case 'd': // destination host
				if(strlen(optarg) == 0) usage(argv[0]);
				host_dest = optarg;
				h++;
				break;

			case 's': // SYN
				syn = 1;
				break;

			case 'a': // ACK
				ack = 1;
				break;

			case 'r': // RST
				rst = 1;
				break;

			case 'p': // PUSH
				psh = 1;
				break;

			case 'u': // URG
				urg = 1;
				break;

			case 'f': // FIN
				fin = 1;
				break;

			case 'x': // source host
				if(strlen(optarg) == 0) usage(argv[0]);
				host_source = optarg;
				x++;
				break;

			case 'c': // destination port
				if(strlen(optarg) == 0) usage(argv[0]);
				dport = atoi(optarg);
				break;

			default:
				usage(argv[0]);
				break;
		}
	}

	if (x == 0) host_source = DEFAULT_HOST;
	
	if (h == 0) usage(argv[0]);  // you must write destination host. Error

	// IP source
	if((hostentry = gethostbyname(host_source)) == NULL) 
		Error("Error solving source address");

	bzero(&saddr, sizeof(struct sockaddr));
	saddr.sin_family = AF_INET;
	saddr.sin_addr = *((struct in_addr *)hostentry->h_addr);

	// IP destination
	if((hostentry = gethostbyname(host_dest)) == NULL) 
		Error("Error solving destination address");

	bzero(&daddr, sizeof(struct sockaddr));
	daddr.sin_family = AF_INET;
	daddr.sin_addr = *((struct in_addr *)hostentry->h_addr);

	// Send data
	SendPacket(saddr, daddr, dport, syn, ack, psh, rst, urg, fin);
}


void SendPacket(struct sockaddr_in saddr, struct sockaddr_in daddr, int dport,
	int syn, int ack, int psh, int rst, int urg, int fin) {
	int                 destination_port, source_port, on, s, rs, pid;
	int status, i;
	char                buffer[BUFFER_LONG], rbuffer[BUFFER_LONG];
	char string[BUFFER_LONG];
	struct iphdr        *iphdr, *riphdr;
	struct tcphdr       *tcphdr, *rtcphdr;
	struct sockaddr     from;
	int                 fromlen, ethlen;

	struct pseudohdr {
		struct in_addr saddr;
		struct in_addr daddr;
		unsigned char zero;
		unsigned char protocol;
		unsigned short length;
	} *pseudoheader;

	ethlen = sizeof(struct ethhdr);
	on = 1;
	source_port = htons(random());
	destination_port = htons(dport);
	
	setvbuf(stdout, NULL, _IONBF, 0);
	fflush(stdout);
	
	if((pid=fork()) == -1)
		Error("fork");

	if(pid) {
		if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
			Error("socket");

		if(setsockopt(s, IPPROTO_IP, IP_HDRINCL,(char *)&on, 
			sizeof(on)) < 0)
				Error("setsockopt");

		bzero(buffer, BUFFER_LONG);

		// TCP header
		tcphdr =                       (struct tcphdr *)(buffer+
						sizeof(struct iphdr));
		tcphdr->source =               htons(source_port);		// puerto origen
		tcphdr->dest =                 destination_port;			// puerto destino
		tcphdr->window =               htons(65535);			// ventana
		tcphdr->seq =                  random();			// numero de secuencia aleatorio
		tcphdr->syn =                  syn;				// flag SYN
		tcphdr->ack =                  ack;				// flag ACK
		tcphdr->rst =                  rst;				// flag RST
		tcphdr->psh =                  psh;				// flag PSH
		tcphdr->urg =                  urg;				// flag URG
		tcphdr->fin =                  fin;				// flag FIN
		tcphdr->doff =                 sizeof(struct tcphdr) / 4;

		// TCP pseudoheader
		pseudoheader =                 (struct pseudohdr *)
			((unsigned char *)tcphdr-sizeof(struct pseudohdr));
		pseudoheader->saddr =          saddr.sin_addr;			// direccion origen
		pseudoheader->daddr =          daddr.sin_addr;			// direccion destino
		pseudoheader->protocol =       IPPROTO_TCP;			// protocolo
		pseudoheader->length =         htons(sizeof(struct tcphdr));
		tcphdr->check =                cksum((unsigned short *)
		pseudoheader, sizeof(struct pseudohdr)+sizeof(struct tcphdr));
		
		// IP header
		bzero(buffer, sizeof(struct iphdr));
		iphdr =                        (struct iphdr *)buffer;
		iphdr->ihl =                   5;				// IHL (longitud de cabecera)
		iphdr->version =               4;				// version
		iphdr->tot_len =               htons(DEFAULT_LEN);		// longitud del datagrama
		iphdr->id =                    htons(random());			// numero de identifiacion (aleatorio)
		iphdr->ttl =                   IPDEFTTL;			// tiempo de vida
		iphdr->protocol =              IPPROTO_TCP;			// protocolo
		iphdr->daddr =                 daddr.sin_addr.s_addr;		// direccion origen
		iphdr->saddr =                 saddr.sin_addr.s_addr;		// direccion destino

		printf(" SENT DATA\n");
		printf(" ---------\n");
		printf("| SYN | ACK | RST | PSH | URG | FIN | TTL | 
			Window\n");
		printf("|  %d  |  %d  |  %d  |  %d  |  %d  |  %d  | %d  
			| %d\n", syn, ack, rst, psh, urg, fin, iphdr->ttl, 
			tcphdr->window);
		printf("seq=%d - ack_seq=%d - doff=%d - check=%d - ID=%d\n\n",
			tcphdr->seq, tcphdr->ack_seq, tcphdr->doff, 
			tcphdr->check, iphdr->id);
		
		if(sendto(s, buffer, DEFAULT_LEN, 0x0, (struct sockaddr *)
			&daddr, sizeof(struct sockaddr) ) != DEFAULT_LEN)
			Error("sendto");

		wait(&status);
		close(s);
		exit(0);
	} else {
		if((rs = socket(AF_INET, SOCK_PACKET, htons(ETH_P_IP))) < 0)
			Error("socket input");

		if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
			Error("socket");

		if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&on,
			sizeof(on)) < 0)
			Error("setsockopt");

		while(1) {
			if(recvfrom(rs, rbuffer, BUFFER_LONG, 0x0, 
				(struct sockaddr *)&from, &fromlen) <= 0)
				Error("recvfrom");

			riphdr = (struct iphdr *)(rbuffer+ethlen);

			if(riphdr->protocol == IPPROTO_TCP) {
				rtcphdr = (struct tcphdr *)(rbuffer+ethlen+
				sizeof(struct iphdr));
			
				if(rtcphdr->source == destination_port) {
					bzero(buffer, BUFFER_LONG);

					printf(" RECEIVED DATA\n");
					printf(" -------------\n");
					printf("| SYN | ACK | RST | PSH | URG 
					| FIN | TTL | Window\n");
					printf("|  %d  |  %d  |  %d  |  %d  
					|  %d  |  %d  | %d  | %d\n", 
					rtcphdr->syn, rtcphdr->ack, 
					rtcphdr->rst, rtcphdr->psh, 
					rtcphdr->urg, rtcphdr->fin, 
					riphdr->ttl, rtcphdr->window);
					printf("seq=%d - ack_seq=%d - 
					doff=%d - check=%d - ID=%d\n\n", 
					rtcphdr->seq, rtcphdr->ack_seq, 
					rtcphdr->doff, rtcphdr->check, 
					riphdr->id);

					return;
				}
			}
		}

		close(rs);
		close(s);
	}

	return;
}

unsigned short cksum(unsigned short *ptr,int nbytes)
{
	register long sum;
	unsigned short oddbyte;
	register unsigned short anwser;

	sum = 0;
	while(nbytes>1)
	{
		sum += *ptr++;
		nbytes -= 2;
	}
	if(nbytes==1)
	{
		oddbyte = 0;
		*((unsigned char *) & oddbyte) = *(unsigned char *)ptr;
		sum += oddbyte;
	}
	sum = (sum >> 16) + (sum & 0xffff);
	sum += (sum >> 16);
	anwser = ~sum;
	return(anwser);
}

void usage(char *nom) {
	printf("Usage: %s [s|a|r|p|u|f] [-x host_source] -d host_destination 
		-c port\n", nom);
	printf("\t-s SYN flag enabled\n");
	printf("\t-a ACK flag enabled\n");
	printf("\t-r RST flag enabled\n");
	printf("\t-p PSH flag enabled\n");
	printf("\t-u URG flag enabled\n");
	printf("\t-f FIN flag enabled\n");
	exit(-1);
}
-------------------------------------------8<---------------------------------


--- checkicmp.c ---------------------------8<---------------------------------
// checkicmp.c
// By Pepelux

#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>

#define Error(msg) { perror(msg); exit -1; }


int main(void) {
	int s;
        struct sockaddr_in dir = {AF_INET, 0, 0 };
        char buff[1024];
        int len = sizeof(dir);
        struct icmphdr *rec = (struct icmphdr*) (buff + sizeof(struct iphdr));

        if (geteuid() != 0) {
                printf("You must be root\n");
                exit(0);
	}
	
	if ((s = socket(AF_INET, SOCK_RAW, 1)) < 0)
		Error("socket");

        printf("Waiting data ...\n");

	while (1) {
        	bzero(buff, 1024);

        	while (recvfrom(s, buff, 1024, 0, (struct sockaddr_in*) &dir, 
        		&len) > 0)
			printf("Received:\ttype %d\tcode %d\n", rec->type, 
			rec->code);
        }
}
-------------------------------------------8<---------------------------------


--- sendudp.c -----------------------------8<---------------------------------
// sendudp.c
// By Pepelux

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>

#define Error(msg) { perror(msg); exit -1; }


main (int argc, char *argv[])
{
	int s;
	int dport;
	struct sockaddr_in addr_dest;

	if (argc!=3) {
		printf ("Usage: %s ip port\n", argv[0]);
		exit(0);
	}

	dport = atoi(argv[2]);

	printf ("Sending UDP packet to %s:%d\n",argv[1], dport);

	if ((s=socket(AF_INET,SOCK_DGRAM,0)) < 0)
		Error("socket");

	addr_dest.sin_addr.s_addr=inet_addr(argv[1]);
	addr_dest.sin_family=AF_INET;
	addr_dest.sin_port=htons(dport);

	if (sendto(s,"\n",1,0,(struct sockaddr*)&addr_dest,sizeof(struct 
		sockaddr_in)) < 0)
		Error("sendto");

	close (s);
}
-------------------------------------------8<---------------------------------




------[ 5.- Referências ]

Aqui estão links de páginas interessantes que eu usei para escrever este documento:

Standards (RFCs):
Protocolo TCP  : http://www.rfc-editor.org/rfc/rfc793.txt
Protocolo IP   : http://www.rfc-editor.org/rfc/rfc791.txt
Protocolo UDP  : http://www.rfc-editor.org/rfc/rfc768.txt
Protocolo ICMP : http://www.rfc-editor.org/rfc/rfc792.txt

Documentação do Nmap: http://insecure.org/nmap/man/


------[ 6.-Finalizando ]

Bem, sim, tudo o que é feito pelo nmap, é mais bonito, mais rápido e melhor
... mas, isso é engraçado, não? :p

Nmap tem muitos métodos de scan mas algumas vezes a resposta é imprevisível,
dependendo do sistema operacional rodando. Por isso é bom escanear manualmente!
Além do mais você vai deixar menos logs e irá aprender mais.

Abraços!!!


Pepelux <pepelux@enye-sec.org>
http://www.enye-sec.org


=-|================================================================ EOF =====|

# milw0rm.com [2008-09-28]