-------[  RtC Mag, At the end of the universe  ]

--------------[  Network Mapping  ]
---------[ in RtC mag 4 & 5 ]
----[  by S/ash [RtC] <slash-rtc@fr.st>  ]


-------[  Sommaire

I.   Complete TCP Scanning
II.  Half-Open Scanning : Scanning with the SYN flag ON
III. Stealth Scanning
  III.1 FIN Scanning
  III.2 ACK Scanning
IV.  UDP Scanning
V.   FTP Bounce Attack
VI.  ICMP Echo scanning
*    RtC Scan

-------[  I.   Complete TCP Scanning

Lors des communications TCP (et UDP), un port est demand.
Ce port correspond  un service qui va couter ce port. Un port
est en ralit un nombre qui permet d'identifier un service : chaque
service (ou client) coute les paquets IP et rcupre ceux qui lui
sont destins pour les traiter (ceux qui on comme port de destination
le port ouvert).
Il est trs interessant de connaitre les ports ouverts sur une machine :
ils reprsentent les services disponibles et donc attaquable sur la
machine.

Le premier scanning classique est le scanning de port TCP, son principe
est symple : lors d'une communication rseaux via TCP/IP, le programme
client demande une connexion  l'hote qui va lui rpondre si un programme
serveur coute sur le port.
Pour scanner la machine, on a juste  demander une connection sur le port
 scanner.

Ceci ce fait par la fonction connect(socket, struct sockaddr*, int).
la fonction qui fait cela est :

<-- snip snip snip -->
sock=socket(AF_INET,SOCK_STREAM,0); /* on cre la socket           */
addr.sin_port=htons(port);          /* on stocke le numro du port */
rc=connect(sock,(struct sockaddr*)&addr,sizeof(addr));
                                    /* on se connecte et stockons  */
                                    /* le rsultat dans rc         */
close(sock);                        /* on ferme la connexion       */
<-- snip snip snip -->

On a maintenant : rc<0 -> port ferm
                  rc>0 -> port ouvert

Ce scanning est trs simple et implmentable sur toutes les machines avec
n'importe quel droit donc trs usit mais il pose des problmes de rapidit
et d'anonymat (un simple port ouvert en coute permet de le repr)

-------[  II.  Half-Open Scanning : Scanning with the SYN flag ON

Le SYN scanning est le scanning sans doute le plus usit et le plus rapide.
Mais surement pas le plus discret. Il reste bien sur plus discret que le
scanning  connexion complte mais  le dsavantage de devoir l'implmenter
en construisant ses propres paquets TCP et d'utiliser les droits root pour
le faire tourner (sous Windows, l'implmentation WinSock ne permet pas
la cration de RAW Socket mais il est possible de crer sa propre librairie
pour pouvoir envoyer des paquets IP construit compltement).

Une connection TCP se fait en trois tapes. Tout d'abord la demande de
connexion qui se fait par l'envoie d'un paquet avec le flag SYN. Ensuite la 
rponse de l'hte qui est soit, si le port est ouvert, un paquet avec les flags
SYN et ACK, soit un paquet avec le flag RST. Puis le troisime, envoie qui ouvre
la connexion est un paquet envoy par le client avec le flag ACK.
Lors d'un SYN scanning on envoie un paquet SYN et on attend le paquet SYN+ACK ou
RST. Cela permet de ne pas avoir  ouvrir une connexion et donc ne pas avoir 
la fermer.

Explication de la construction du paquet TCP.
Un paquet TCP est fait de la faon suivante :
0                                   15|16                                     31
|------------------------------------------------------------------------------|
| Numro du port source (16 bits)     | Numro du port de destination (16 bits)|
|------------------------------------------------------------------------------|
|                         numro de squence sur 32 bits                       |
|------------------------------------------------------------------------------|
|                       numro d'acquittement sur 32 bits                      |
|------------------------------------------------------------------------------|
| longueur de l'entte 4| 6 | flags 6 |      taille de fentre sur 16-bits     |
|------------------------------------------------------------------------------|
|         checksum sur 16-bits        |        pointeur urgent sur 16-bits     |
|------------------------------------------------------------------------------|
|                          options (s'il y en a)                               |
|------------------------------------------------------------------------------|
|                          donnes (s'il y en a)                               |
|------------------------------------------------------------------------------|

les flags sont, dans l'ordre : URG, ACK, PUSH, RST, SYN, FIN.
URG est la pour indique que le pointeur urgent est valide (il sert a indique la
fin des donnes urgentes dans le paquet)
ACK est la pour indique que le numro d'acquittement est valide (numro de
sequence du prochain paquet).
PUSH : pour que le gestionnaire rseau passe la trame le plus vite possible au
soft.
RST : rinitialise la connexion.
SYN : signal de synchronisation pour les numro de squence
FIN : fin de la connexion.

bon ben en gros on vas envoyer un paquet avec le port source et le port de dest
et avec le flag SYN. Et on va attendre un paquet avec le flag RST ou avec les
flags ACK et SYN (avec les bon numro de port).


Le code :

<-- snip snip snip -->
int scan_port(long port, struct sockaddr_in *host, long scanport, long timeout)
{
  int rc, tcpsock, rawsock;
  fd_set rset;
  struct timeval cur_time, beg_time;
  struct sockaddr_in addr;
  char buf[3000];
  struct iphdr *ip = (struct iphdr *) buf;
  struct tcphdr *tcp = (struct tcphdr *) (buf + sizeof(struct iphdr));
  host->sin_port = htons(port);
  
  /* SYN scanning */
  FD_ZERO(&rset);
  rawsock=socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  tcpsock=socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  FD_SET(tcpsock, &rset);
  /* sending a SYN packet */
  memcpy(&addr, host, sizeof(addr));
  gettimeofday(&beg_time,NULL);
  tcp_send(tcpsock,&addr,             /* send a customized TCP packet */
	   localhost_addr,addr.sin_addr.s_addr,
	   scanport,port,
	   TH_SYN,
	   lrand48()+1, lrand48(),
	   512,
	   NULL,
	   0);
  /* check for reply */
  if(FD_ISSET(tcpsock,&rset))
    {
      gettimeofday(&cur_time, NULL);
      while(
	   (recvfrom(tcpsock,&buf,3000,0, NULL,0)>0) 
	   && (timeout > DIFFTIME(beg_time, cur_time))
	   )
        {
	  if ((ip->saddr == host->sin_addr.s_addr) && (ntohs(tcp->th_sport)==port) && (ntohs(tcp->th_dport)==scanport)) /* got a reply */
	    {
               close (tcpsock); close (rawsock);
	       if(tcp->th_flags & TH_RST) return 0;         /* port closed */
	       else if(tcp->th_flags & TH_SYN && tcp->th_flags & TH_ACK) return 1; /* port opened */
	       else return -2; /* port error */
	    }
	  gettimeofday(&cur_time, NULL);
	}
    }
  else rc = -1;
  close(tcpsock);
  close(rawsock);
  if(rc>0) return -1; /* time out */
  else return -2;     /* error */
}
<-- snip snip snip -->

Bien sur, le plus rapide reste de ne pas attendre la rception de paquets entre deux envois :
on envois un paquet SYN sur la machine et on teste sans attendre de rponse si l'on a reu un
paquet, et on recommence jusqu' avoir envoy tout les paquets SYN ; il ne nous reste plus
qu' couter les paquets arrivant pendant un court instant.

Ce scanning reste cependant dtectable : il suffit d'couter les paquets rentrant et de
vrifier que l'on a pas affaire  un scan.

-------[  III. Stealth Scanning

Le stealth scanning est un scanning de port TCP utilisant des bugs des
implmentation TCP. Le gros avantage de cette mthodes est qu'elle est
difficilement dtectable et qu'elle passe  travers plusieurs firewalls. Son
gros dsavantage est que c'est une mthode qui ne marche pas  tout les coups
(cela dpend des systmes).

La premire mthode est l'envoie d'un paquet avec le flag FIN. Si le port est
ferm, alors un paquet avec le flag RST sera retourn sinon le paquet sera
ignor. Cette mthode marche sur la plupart des systmes.

La deuxime mthode est l'envoie d'un paquet avec le flag ACK et on attend le
paquet avec le flag RST. Si le champs window du paquet est diffrent de 0 ou 
si le champs TTL est faible (<=64) alors le port est probablement ouvert. 
Ce bug marche essentiellement sur les anciennes implmentation BSD.


-------[  IV.  UDP Scanning

L'UDP est un protocol de merde (pas de vrification de la rception des paquets)
mais reste utile dans certains cas (faille ???).

Pour scanner les port UDP d'ouvert, le principe est trs con : on envoie un
paquet UDP sur le port et si l'on recoit une rponse ICMP Port Unreachable
alors le port est ferm, sinon le port est ouvert.
On est cependant pas oblig de construire les paquets : en effet, il suffit de
tester la fonction recvfrom qui retourne ECONNREFUSED si le port est ferm...

Bien sur, il est prfrable de construire ses propres paquets pour acclrer
le scan.

-------[  V.   FTP Bounce Attack

Ma prfre :). Elle permet d'utiliser un serveur FTP comme d'un "proxy" pour
le scanning de port (et d'autres chose galement mais qui ne nous interesse pas
ici).

Le principe ?
Le protocole FTP prvoie la possibilit d'effectuer des transferts de serveur
 serveur avec un client spar pour controler les transferts.
Ceci ce fait en pratique en spcifiant l'adresse d'un autre serveur avec la
commande PORT.

Par exemple, sur le serveur FTP, avant l'envoie d'une commande, on a :
PORT 172,52,36,4,10,1
qui spcifie d'utiliser le port 2561 (=10*256+1) sur la machine 172.52.36.4
pour le transfert de donnes.
Ensuite si l'on envoie la commande LIST au ftp, il renverra le rsultat sur
le port 2561 de la machine 172.52.36.4.

Donc pour faire un scan de port TCP en version FTP Bounce Attack, il suffit
de se connecter  un serveur FTP (non modifi donc qui accepte que l'on spcifie
n'importe quel IP). Puis d'envoyer si a.b.c.d est l'ip  scanner, d'envoyer les
commandes "PORT a,b,c,d,p1,p2" o p1,p2 dsigne le port et "LIST".
Il rpondra alors "425 Can't build data connection: Connection refused." si le
port est ferm et sinon le transfert russira (rponse 150 ou 226).

L'avantage est bien sur un "plus grand anonymat" dans le scan (plus
difficile  tracer). Il permet galement de contourner les firewall (spoofing).
LE desavantage de ce scanning est la lenteur (connexion complte, transfert de
donnes...).


-------[  VI.  ICMP Echo scanning

L'ICMP (Internet Control Message Protocol) permet d'envoyer des messages de
contrles (notamment lorsqu'une route est ferme il nous le dit).
Je pourrais m'tendre plus avant ici sur le protocole ICMP mais ce n'est pas le
sujet de plus il y a de trs bon articles dessus (notamment celui de feu CoD4
dans NoRoute 3 et de Sneakie 'ICMP My Friend').
Je vais simplement expliquer ici le message echo et echo reply.
0                  7|8              15|16                                     31
|------------------------------------------------------------------------------|
|   type (0 ou 8)   |    code (0)     |           checksum                     |
|------------------------------------------------------------------------------|
|          identificateur             |       numro de squence               |
|------------------------------------------------------------------------------|
|                       donnes optionnelles (s'il y en a)                     |
|------------------------------------------------------------------------------|
Donc un message ICMP Echo request est identifi par le type 8 et le code 0.
L'identificateur est l pour identifier l'change echo et le numro de squence
pour dire  quel paquet on est (c'est le champ icmp_seq lors d'un ping).
A un message echo est normalement renvoy un message echo reply identifi par le
type 0 et le code 0 avec les mmes champs que le message echo (numro 
d'identification et de squence).

Faire de l'ip scanning par message ICMP Echo
--------------------------------------------
Le principe est simple pour chaque ip on envoie un paquet echo et on attend
un paquet echo reply avec les mmes champs.
On rcuprera un paquet icmp unreacheable (destination indisponible) si l'hte
n'existe pas et un time out s'il est indisponible.
Ainsi on peut scanner une srie d'ip assez rapidement.
Voil le code des fonctions ralisant le ping dans l'IP-scan de la RtC :

<-- begin icmpping.c -->
/******************************************************************************
 *                    icmpping.c by S/asH (member of RtC)                     *
 *                     IP Scanning - ICMP Ping Request                        *
 *                        This is a tOOl of RtC TecH                          *
 ******************************************************************************/

#include "rtcipscan.h"

/******************************************************************************
 * in_chksum --                                                               *
 *  Checksum routine for Internet Protocol family headers (C Version)         *
 ******************************************************************************/
unsigned short in_chksum(addr, len)
    u_short *addr;
    int len;
{
    register int nleft = len;
    register u_short *w = addr;
    register int sum = 0;
    u_short answer = 0;
 
    /*
     * Our algorithm is simple, using a 32 bit accumulator (sum), we add
     * sequential 16 bit words to it, and at the end, fold back all the
     * carry bits from the top 16 bits into the lower 16 bits.
     */
    while (nleft > 1)  {
        sum += *w++;
        nleft -= 2;
    }
 
    /* mop up an odd byte, if necessary */
    if (nleft == 1) {
        *(u_char *)(&answer) = *(u_char *)w ;
        sum += answer;
    }
 
    /* add back carry outs from top 16 bits to low 16 bits */
    sum = (sum >> 16) + (sum & 0xffff);   /* add hi 16 to low 16 */
    sum += (sum >> 16);                   /* add carry */
    answer = ~sum;                        /* truncate to 16 bits */
    return(answer);
}


/******************************************************************************
 * send_icmp_echo -- Send an icmp echo request                                *
 * Input  : sock   : socket descriptor                                        *
 *          dest   : destination address                                      *
 *          ident  : icmp ident                                               *
 *          seq_nb : icmp sequence number                                     *
 *          data   : optional data                                            *
 *          sdata  : size of data                                             *
 * Output : return : success or failed                                        *
 ******************************************************************************/
int send_icmp_echo(int sock, struct sockaddr_in dest, u_short ident, u_short seq_nb, char *data, int sdata)
{
  char packet[2048];
  struct icmphdr *icmp     = (struct icmphdr*)packet;
  unsigned char  *datagram = (unsigned char*)(packet + 8);

  /* making the icmp header */
  memcpy(datagram, data, sdata);
  memset(packet, 0, 8);

  icmp->type = ICMP_ECHO;
  icmp->code = 0;
  icmp->un.echo.id = ident;
  icmp->un.echo.sequence = seq_nb;

  /* calculate the checksum */
  icmp->checksum = in_chksum((u_short*)packet, sdata+8);

  return sendto(sock, packet, 8+sdata, 0, (struct sockaddr*)&dest, sizeof(struct sockaddr));
}

/******************************************************************************
 * ping -- Send an icmp echo request and stand the reply                      *
 * Input  : sock     : socket descriptor                                      *
 *          dest     : destination address                                    *
 *          timeout  : time out for echo request                              *
 *          packsize : size of packet to send                                 *
 *          ident    : icmp ident                                             *
 *          seq_nb   : icmp sequence number                                   *
 * Output : return   : see section 'ping return values' in rtcipscan.h        *
 ******************************************************************************/
int ping(int sock, struct sockaddr_in dest, int timeout, int packsize, u_short ident, u_short seq_nb)
{
  int             rc;
  fd_set          rset;
  struct timeval  cur_time, beg_time, tv;
  char            buf[2048];
  struct iphdr   *ip   = (struct iphdr *) (buf);
  struct icmphdr *icmp = (struct icmphdr*)(buf + sizeof(struct iphdr));

  for(rc=0; rc<packsize-8; rc++) buf[rc] = rc; /* initialize packets */
  /* sending a ICMP echo request */
  gettimeofday(&beg_time,NULL);
  send_icmp_echo(sock,dest,ident,seq_nb, buf, packsize-8);
  tv.tv_sec = timeout / 1000; 
  tv.tv_usec = timeout * 1000; 

  /* check for reply */
  FD_ZERO(&rset);
  FD_SET(sock, &rset);
  tv.tv_sec = timeout / 1000; 
  tv.tv_usec = timeout * 1000;
  gettimeofday(&cur_time,NULL);
  while(timeout > DIFFTIME(beg_time, cur_time))
    {
      if ((rc=select(sock + 1, &rset, NULL, NULL, &tv)) == 0) 
	return HOST_TIMEDOUT;  /* time out */
      else if (rc < 0) return PING_ERROR;
      else 
	{
	  rc = read(sock,buf,2048);

	  if(rc==-1) return PING_ERROR; /* error in reading */
	  else if(rc>0)
	    {
	      if (ip->saddr == dest.sin_addr.s_addr) /* got a reply */
		{
		  if((icmp->type == ICMP_ECHOREPLY) && (icmp->un.echo.id == ident) && (icmp->un.echo.sequence == seq_nb))
		    return HOST_ANSWER;
		}
	      else if(icmp->type == ICMP_DEST_UNREACH) return HOST_UNREACHABLE;
	      gettimeofday(&cur_time, NULL);
	    }
	}
    }
  return HOST_TIMEDOUT; /* time out */
}
<-- end icmpping.c -->


-------[  *    RtC Scan

Bon le code du scanner implmentant toutes ces mthodes est fournit avec
ce mags...

-------[  EOF
