
#########################################################################################################
#													#
#					     U. R. C. project						#
#													#	
#					UDP 	Remote	  Controls					#
#				   Copyright (c) 2003 Angelo Rosiello (Guilecool)			#
#					   All Rights Reserved						#	
#########################################################################################################


Prima di passare alla descrizione del funzionamento del programma mi  sembrato indispensabile spiegare alcuni
fondamentali circa il protocollo di trasporto UDP, elemento su cui poggia l'intera implementazione.


User Datagram Protocol (rfc 768),  il protocollo corrispondente allo strato di trasporto del modello ISO/OSI,
insieme al TCP.
Il formato di un generico datagramma  il seguente:

Format
------

                  0      7 8     15 16    23 24    31  
                 +--------+--------+--------+--------+ 
                 |     Source      |   Destination   | 
                 |      Port       |      Port       | 
                 +--------+--------+--------+--------+ 
                 |                 |                 | 
                 |     Length      |    Checksum     | 
                 +--------+--------+--------+--------+ 
                 |                                     
                 |          data octets ...            
                 +---------------- ...                 

                      User Datagram Header Format

1. Source Port  : La porta sorgente  un campo opzionale, indica la porta dalla quale  stato trasmesso il pacchetto
    (16 bit)      ed eventualmente verso cui  attesa una risposta. Se non  imposto alcun valore viene inserito 0 
		  in default.
		
2. Destination
   Port(16 bit) : Indica la porta destinataria del processo paritario verso cui  indirizzato il datagramma.
  
3. Length       : Specifica in bytes la lunghezza del datagramma nella sua interezza (header + payload).
   (32 bit)

4. Checksum     : Consente la rivelazione di errori sull'unit informativa TCP alla quale viene aggiunto un "nuovo"
   (16 bit)	  header contenente gli indirizzi IP sorgente e di destinazione, il numero di protocollo TCP e il numero
   		  di byte del segmento UDP.

La funzione di controllo di errore realizzata dal campo checksum  opzionale, al fine di allegerire il piu' possibile
il protocollo.

Nella pila OSI il protocollo UDP si avvale dei servizi offerti dal protocollo IP.
Il servizio offerto dal protocollo UDP  di tipo connectionless, non stabilisce alcuna connessione logica fra i due host
comunicanti, non garantisce la sequenzialit del trasferimento delle Unit Informative attraverso la rete 
e non fornisce funzioni di controllo di flusso o errore, in definitiva non c' alcuna garanzia che l'informazione venga
trasferita correttamente.
Una "vulnerabilit" implicita di UDP  la possibilit di inviare pacchetti "spoofati", ossia provenienti da 
IP sorgenti non veritieri.
Questa  una diretta conseguenza del servizio privo di connessione, offerto dal protocollo in questione.
Al fine di rendere piu' pragmatiche le spiegazioni sudette, riporto di seguito un esempio di codice che consente di spoofare
l'IP sorgente di un datagramma:

.............
#include ...
main()
{
	int ....;
	char ....;
	int sd;
	int port = 34567;
	struct sockaddr_in source_addr, destination_addr;
	udp_initialize(&source_addr, 0, inet_addr(argv[1])); 		 	// (1)
	udp_initialize(&destination_addr, port, inet_addr(argv[2]));		// (2)
	sd = socket(AF_INET, SOCK_DGRAM, 0);
	bind(sd, (struct sockaddr *) &source_addr, sizeof(source_addr);
	sendto(sd, argv[3], strlen(argv[3]), 0, (struct sockaddr *) &destination_addr, sizeof(destination_addr)); 

void udp_initialize(struct sockaddr_in *address, int port, long IPaddr)
	{
	 address->sin_family = AF_INET;
	 address->sin_port = htons((u_short)port);
	 address->sin_addr.s_addr = IPaddr;
	}
	
Spiegazioni del codice:
(1) Il pezzo di codice richiama la procedura udp_initialize che consente di riempire i campi della struttura della socket.
    Nello specifico viene posta la porta della socket (IP+PORTA) source_addr a 0 e l'indirizzo IP da argv[1].
    N.B. Porta e IP sono scelti arbitrariamente, dato che non si aspetta alcun riscontro.

(2) In questo caso vengono impostati i valori della socket destinataria in modo corretto.

Il passo (1) ci ha consentito di originare un datagramma "spoofato".
Ora che abbiamo le idee piu' chiare  possibile capire il funzionamento del programma da me realizzato.
Gli usi possono essere arbitrari e dei piu' svariati, ma di sicuro molto istruttivi.


----------------------------------------------------------------------------------------------------------------------------
						KNOW-WHY 
						
Il programma  nato nel 2002 come strumento atto a garantire la possibilit di eseguire comandi remoti, senza aprire
connessioni logiche dirette con il server destinatario.
Ho scartato quindi subito l'uso del protocollo TCP in quanto orientato alla connessione.
Un altro aspetto che non volevo trascurare era la possibilit di non aprire porte TCP che sarebbero state soggette a 
banali port scan ed eventuali tentativi di "hacking".
La prima versione del programma prevedeva un algoritmo non abbastanza dinamico, in quanto non ospitava procedure di
lettura dei comandi da files esterni, bens direttamente dal sorgente.
E' stata implementata a questo scopo una procedura di lettura da file dei comandi da eseguire.

************************************ ANALISI DEL PROGRAMMA ****************************************************

$cat server.c

#define PORT 32980	// Indica la porta di ascolto del demone.

#define ETC "udp.conf"  // Indica il nome del file dal quale avverr al lettura dei comandi da eseguire.


Potete modificare i valori impostati nei define a vostro piacimento.

Il file udp.conf in chiaro (non crittato), prevede la seguente struttura al fine di un corretto funzionamento:

$cat udp.conf
PAROLA CHIAVE:/PATH/TO/PROGRAM

esempio: angelo:/home/angelo/ciao

Quando il server ricever la parola chiave angelo, avvier il programma "/home/angelo/ciao"

Il tool implementa anche una procedura di logging di tutti i comandi ricevuti con relativa data e IP sorgente.

fd = open("server.log", O_CREAT | O_RDWR | O_APPEND, 0644);	

Il file di log sar posto nella stessa cartella in cui  presente il binario del programma e avr etichetta "server.log".


Nel corso dell'implementazione ho deciso altres di crittare il file di configurazione ed il log file.
L'algoritmo di crittazione utilizzato  molto semplice ma al tempo stesso non cos debole; esso prevede uno XOR bit a bit
di una chiave con tutti i bit dei file suddetti.
La chiave di default  stata introdotta come riportato di seguito, nella procedura apposita denominata crypto():

int key = 0xff17261;		// This is the cryptation Key; Change IT!!!

Potete inserire una chiave a vostro piacimento del tipo 0xff71678 e cos via...

Il file UDP.CONF (di configurazione) una volta editato correttamente in chiaro, deve essere crittato mediante l'uso del
programma crypto (sorgente crypto.c), presente nel pacchetto. 
E' ASSOLUTAMENTE FONDAMENTALE che le chiavi presenti su server.c e crypto.c siano IDENTICHE, altrimenti il programma server
non riuscir a leggere correttamente il file udp.conf di configurazione !!!


*****************************************************************************************************************
						FAST-HOW-TO

Editate correttamente udp.conf seguendo le istruzioni suddette.
Cambiate le chiavi in server.c e crypto.c (ricordatevi di metterle IDENTICHE!).

Compilate il programma mediante Makefile (digitate make nel prompt).

$./server

A questo punto baster inviare i comandi chiave mediante client.

$./client SOURCE-IP DEST-IP PORT command

********************************************************************************************************************


Grazie....
Angelo Rosiello

contact: guilecool@usa.com
