Generale

fastweb fast hack

PS.io non mi ritengo responsabile di quello che potreste fare con queste informazioni percio non fate cazzate e adesso buon divertimento.

-[ HACKiNG ]——————————————————————
—[ FASTWEB: V0RRETE DiRL0 A TUTTi (R0UND 1)
—–[ tHE rECIdjVO <[email protected]> – http://www.pkcrew.org

 

  -=[ FASTWEB: VORRETE DIRLO A TUTTI (round 1) ]=-

 

[00000000] – Sguardo dalla candida rosa

 [00000000] – Sguardo dalla candida rosa
 [00000001] – I campi coltivati
 [00000010] – Le vocine nella mente
 [00000011] – L’ultimo consiglio preparatorio
 [00000100] – Ragionevole dubbio
 [00000101] – Il viaggio comincia
 [00000110] – La sorgente nascosta
 [00000111] – Timori e coraggio
 [00001000] – Faccia a faccia
 [00001001] – HEAT
 [00001010] – I professionisti del mestiere
 [00001011] – Rinunce
 [00001100] – L’uomo dal cuore d’oro
 [00001101] – Hannibal Smith e compagni
 [00001110] – Due righe
 [00001111] – Il lungo cammino

 

[00000001] – I campi coltivati

Beh cosa dire? Evidentemente Fastweb ha fatto qualche sgarro a qualche
fattucchiera con i controfiocchi, e si e` fatto scagliare una maledizione
tremenda: ogni notte di luna piena, nella tratta tra Milano e Verona, i
passeggeri del treno delle Ferrovie dello Stato vengono colpiti da
illuminazioni paranormali su come poter lavorare sulla rete a fibra ottica
piu` famosa d’Italia.
Fatto sta` che come successe a naif mesi or sono (ma quanti or sono?
o-r-so-n-o.. 5!), mentre andavo a trovare |CyRaX| guardando fuori dal
finestrino ho visto un campo coltivato: ‘Che mondo strano c’e` qui fuori,’ ho
riflettuto tra me e me, e poi ho subito aggiunto ‘ecco un buon modo per
cercare di fregare Fastweb!’.
L’associazione logica ancora oggi mi e` molto oscura, ma ho imparato a non
pormi troppe domande sui processi del mio cervello, specialmente quelli fatti
nelle notti di luna piena su un treno delle Ferrovie dello Stato tra Milano e
Verona.

 

[00000010] – Le vocine nella mente

Per parecchio tempo ho avuto dei seri dubbi se rilasciare questo articolo o
meno, perche` alla fine potrebbe anche non essere troppo gradito.. Ogni giorno
mi svegliavo con questo assillo: ma sara` giusto farlo? Poi, dal nulla, mentre
torno a casa, scendo in metro` distratto al solito dai mille pensieri che si
affollano nella mia mente; tutto quello su cui stavo ragionando piano piano si
e` affievolito, il suono della mia voce e` scemato, coperto dalla calda voce
che mi creo` una sensazione quasi da sogno…
Improvvisamente non ero piu` in metro` viaggiante verso casa, ma intorno a me
si iniziarono a delineare delle figure di gente seduta a dei tavolini che
beveva dei drink.. Poi, da un palco appena davanti a me una ballerina
bellissima ha iniziato una danza sensuale, mi si e` avvicinata piano piano..
sempre di piu`.. sempre piu` vicino.. potevo quasi sentire la sua pelle contro
la mia, quando sono saltato in piedi e ho urlato: “Ma lo sai che con Fastweb
puoi eliminare la limitazione dei MAC address che impone il Catalyst dei
contratti residenziali, e virtualmente collegare quante macchine vuoi pagando
un abbonamento da solo 1 pc?”.

Appena dette queste parole ho visto la gente guardarmi in modo strano,
l’imbarazzo ha iniziato a colorarmi di porpora il volto, quando ho udito
ancora la voce che mi aveva portato fin li`, che con la calma che solo lei e`
stata capace di infondermi, ha proclamato la mia liberazione:

“NON SORPRENDETEVI SE SENTIRETE IL DESIDERIO IRREFRENABILE DI DIRLO A TUTTI.”
“FASTWEB. VORRETE DIRLO A TUTTI.”

 

[00000011] – L’ultimo consiglio preparatorio

Ottimamente; cominciamo.
Come prerequisito a questa trattazione sarebbe meglio che vi leggiate
l’articolo di naif su Fastweb [BFi10-13 – http://www.s0ftpj.org/] per avere
un’introduzione utile a questo tipo di rete che non mi dilunghero` a
rispiegare.
Uno dei topic principali lasciati irrisolti era questo: il contratto
residenziale di Fastweb (quindi quello che probabilmente puo` importare a voi)
pone una limitazione sul numero massimo di macchine collegate
all’infrastruttura, vuoi che siano CPV, videostation o personal computer.
Quello che effettivamente viene fatto e` un controllo sul numero massimo di
indirizzi hardware dei dispositivi collegati, in quanto ognuno di essi e` in
link diretto con il Cisco Catalyst che si trova nelle nostre cantine (e li`
rimarra`, non c’e` nulla di questo articolo che debba venire applicato al di
fuori della nostra casina), quindi che essi siano tostapane o coguari a
nessuno importa, l’unica cosa e` che abbiano una scheda ethernet, con
ovviamente relativo MAC (Per chiarimenti sul protocollo Ethernet e sui MAC
address si veda lo Stevens o si chieda al proprio cioccolataio di fiducia).
Lo schema e` semplice: se cerchiamo di attaccare piu` del numero massimo di
dispositivi hardware di quelli che ci sono concessi, tutto smette di
funzionare, e l’unica soluzione e` di chiamare il simpatico servizio clienti
e, se ci va bene dopo una mezz’ora, spiegare al ragazzo di turno che cosa e`
successo. Lui, con grande affabilita`, dopo pochi secondi ci dira`: “Bene,
controlli ora dovrebbe funzionare tutto correttamente..”, e.. MAGIA!
Effettivamente tutto e` tornato alla normalita`. Ovviamente fino al prossimo
completo blocco della rete (tra l’altro mi chiedo, se Fastweb e` bloccato, e,
da consiglio loro, ho disdetto il contratto con l’altro operatore telefonico,
io come la chiamo l’assistenza?!?! – Con il cellulare? – Peccato che la
chiamata sia gratuita solo da rete fissa, e che spesso i tempi di attesa x
parlare con qualcuno sono di ore..).

A logica, e cercando conferme sul sito della Cisco (http://www.cisco.com/),
vediamo che Fastweb non ha implementato questa specie di dittatura tutta da
sola (ne sarebbe capace?), ma che e` una feature fornita con i Catalyst.

“You can use port security to block input to an Ethernet, Fast Ethernet, or
Gigabit Ethernet port when the MAC address of the station attempting to access
the port is different from any of the MAC addresses specified for that port.
Alternatively, you can use port security to filter traffic destined to or
received from a specific host based on the host MAC address.”

L’opzione (“set port security”) permette quindi nel caso di Fastweb di
configurare un numero massimo di MAC address su ogni porta dello switch, e di
lasciare l’interfaccia in modalita` “autolearn”, ovvero “ascolta e impara”:
ogni volta che un pacchetto di rete uscira` da quella porta, il suo indirizzo
sorgente verra` analizzato dal software Cisco e qui si possono avere diversi
casi:
1. L’indirizzo e` gia` stato registrato per quella porta: in questo caso non
   viene fatto nulla e il pacchetto viene fatto passare.
2. L’indirizzo non e’ registrato per quella porta e non si e` ancora arrivati
   al numero massimo di hardware address consentiti dalla configurazione:
   l’indirizzo viene aggiunto alla lista di quelli riconosciuti
   sull’interfaccia e il pacchetto viene fatto passare regolarmente.
3. L’indirizzo non e’ registrato per quella porta e si e` gia` al limite
   consentito di indirizzi: la porta viene posta in shutdown (leggi: non passa
   piu` nulla ne` in ingresso ne` in uscita).

Da notare come tra tutte le soluzioni possibili implementate da Cisco
(scartare solo i pacchetti provenienti dagli indirizzi in eccesso, chiudere
solo temporaneamente la porta), quello scelto e` il piu` bastardo di tutti, ma
non staro` certo ora a chiedermi il perche` di tutte quelle piccolezze che dal
punto di vista tecnico non costerebbero nulla, mentre probabilmente da quello
commerciale hanno un valore rilevante..

Da quello che abbiamo visto probabilmente la procedura di configurazione della
nostra porta sul Catalyst (supponiamo di essere sulla 2/1) appare all’incirca
cosi`:
Console> (enable) set port security 2/1 enable
Console> (enable) set port security 2/1 maximum 5 (nel caso il nostro
                                                   contratto preveda 5
         dispositivi massimi)
Console> (enable) set port security 2/1 violation shutdown

Una volta che la porta viene messa in shutdown l’omino Fastweb si collega allo
switch ed esegue qualcosa del tipo:
Console> (enable) clear port security 2/1 all

eliminando tutte le entry e permettendo quindi al software di ricominciare il
learning degli indirizzi.

Ora il problema sembra individuato, quindi come ogni persona che si rispetti e
non avendo tutto questo tempo da perdere inutilmente (ho scoperto di di poter
giocare alla versione arcade di popeye, il mio sogno da quando ero un
pargolo!), analizziamo i possibili vantaggi che deriverebbero da fare qualcosa
di equivalente a quello che un angelo di omino Fastweb potrebbe fare nel caso
ci amasse un po’ di piu` dei suoi datori di lavoro (frase molto velata, chi
vuole intendere.. :D), ovvero:
Console> (enable) set port security 2/1 disable

 

[00000100] – Ragionevole dubbio

Beh, oltre al fatto di avere una preoccupazione in meno (e un po’ di vantaggio
ai punti nel risultato finale del match), ecco cosa mi e` venuto in mente:
– Non doversi MAI PIU` preoccupare di quali e quanti pc si attaccano
– Poter convertire un abbonamento, ad esempio, solo telefono in uno
  tv+telefono+internet senza costi aggiuntivi
– Non avere problemi nel caso di sostituzione delle schede di rete del proprio
  computer
E non da meno:
– Scrivere un articolo per BFi (0h m3 l33t hax0r ph33r m3 th0 l4m3rz0r!!! :>)
– Menarsela con le ragazze (‘aho ma lo sai che ti sfilo la limitazione dei mac
  indirizzi e poi ti collego tutti i pc che sogni, dolcezza?’)
– Passare un po’ il tempo (e lavorare? naaaaahhh :D)

Ok, andata.
Ora si comincia a giocare.

 

[00000101] – Il viaggio comincia

L’importante e` partire con il piede giusto, direbbe il saggio.
Tutto quello che stiamo per dire, fare, baciare, lettera e testamento non e`
per nulla innovativo, particolarmente difficile o impensabile.
E` semplicemente un esercizio di analisi, il percorrere una strada vista poco
prima su una mappa ingiallita, facendo le cose come si deve.
Il problema e`: la teoria c’e`, non e` difficile da mettere il pratica, ma
qualcuno dovra` pur farlo, perche` non e` certo con la teoria e basta che
potremo arrivare alla fine dell’incontro. La pratica, per quanto semplice e
banale, ci serve.
Come sempre, il portatore del messaggio puo` anche essere insignificante, e il
suo percorso senza cause di onori, ma senza di lui il prezioso messaggio non
potrebbe mai arrivare..

Il primo passo che dobbiamo affrontare e` chiederci come ragioni il Catalyst,
in modo da studiare 1 strategia per passare le sue difese: la cosa che viene
piu` ovvia e` che egli controlli tutti i pacchetti in arrivo su una
determinata porta e che analizzi il campo contenente l’hardware address del
mittente. E fin qui nessun problema, basta cambiare gli hardware address
tramite un transparent bridge. Bene. Ma il resto? Nel senso, i pacchetti che
tornano indietro come vengono reinstradati alla giusta macchina se non e`
possibile sapere il suo vero MAC address?

Con calma. Iniziamo a costruire un prototipo di quello che sara` il nostro
apparato di rete.
Punto cruciale abbiamo gia` deciso essere una macchina che, tra le sue
mansioni, ha quello di modificare tutti gli hardware address in uscita, quindi
dovra` avere almeno due nic, uno che si attacca al Catalyst (e che sara`
l’unico dispositivo che verra` visto), e l’altro sul lato della LAN dei pc che
vogliamo fare uscire, uniti da un hub o switch che sia; se puo` farvi comodo,
per ora siamo nella stessa configurazione fisica di una LAN che viene nattata
dal suo gateway.
Ora. Proviamo a pensare cosa succede quando un pc viene acceso, partendo
dall’inizio e supponendo che sia in modo dhcp: per prima cosa fa 1 query
broadcast ethernet (ff:ff:ff:ff:ff:ff) per richiedere una configurazione
valida, inserendo nel payload del pacchetto anche il suo hardware address..
quindi c’e` la remota possibilita` che il src address della query che arriva
al server dhcp non sia considerato per ottenere la reply, bensi` il (furbo)
protocollo usera` i dati contenuti nel payload.
E per quanto riguarda le query ARP? Anche li` il formato del protocollo
prevede che l’indirizzo sia presente nel payload del pacchetto.. E i pacchetti
IP? Beh quelli hanno il loro header, poi sta al sistema (con query ARP) a
trovare il MAC corrispondente.
Vuoi vedere che..

 

[00000110] – La sorgente nascosta

La migliore strategia nel caso di un esperimento del genere e` l’applicazione
pratica dei concetti appena formulati. Nel caso essi si rivelino corretti, e
le prove portino ai risultati aspettati, si prosegue. Nel caso falliscano, si
ragiona di nuovo ed eventualmente si cambia il percorso da seguire. Nel caso,
infine, che magari senza pensarci troppo si sia gia` arrivati alla soluzione,
non puo` rimanere altro da fare che sorridere alla sorte e perfezionare il
tutto in modo da trasformare l’esperienza da test a conclusione finale e
risolutiva.

Costruiamo quindi prima in locale la nostra piccola struttura di rete. Nel
caso che la nostra teoria si riveli corretta, dovremmo poter simulare la
connessione a Fastweb anche senza provarla direttamente. Visto che temo non
tutti abbiano un Cisco Catalyst a casa per le prove, iniziamo con il
controllare la fattibilita` e la semitrasparenza della modifica dei MAC
address in uscita.
Per fare cio` prendiamo tre computer, di cui uno fornito di due schede di
rete: uno di essi sara` il client (simulatore della nostra LAN), uno il bridge
(quello con le due schede), e il terzo il server (simulatore del Catalyst).
Il collegamento e` tanto ovvio quanto comune, e lo schema di funzionamento
sara` il seguente: il client cerchera` di comunicare con il server passando
attraverso il bridge, che si prendera` il compito di mascherare il suo
indirizzo hardware.
Prendiamo in analisi la richiesta di configurazione dinamica dei parametri di
rete (dhcp), configurando un server dhcp sulla macchina server.
Sorvolando ora sul codice di bridging e di modifica del pacchetto, vediamo che
esso parte dall’unica interfaccia del client diretto in broadcast ethernet;
una volta che l’interfaccia interna del bridge rileva il datagramma, questa
risveglia il codice che sostituisce l’hardware address con quello della sua
interfaccia esterna, e dopodiche` lo ritrasmette verso il server con solo quei
sei byte modificati.
Il server riceve il pacchetto, analizza il payload senza curarsi dell’hardware
address, ma forgiando la reply con il MAC trovato inalterato nella query.
Come risultato abbiamo un pacchetto di ritorno che ha indirizzo destinazione
uguale a quello del nic del client, nonostante ci sia stata la modifica da
parte del bridge.
La reply raggiunge la macchina centrale che la ritrasmette, questa volta
inalterata, sulla sua interfaccia interna.
Come conclusione, sul segmento interno dell’accrocchio viaggia un pacchetto
corretto e completamente uguale a quello che sarebbe stato ricevuto dal client
nel caso fosse stato direttamente collegato al server.
Analizziamo un traffico possibile, segnando il primo pacchetto in transito
sull’interfaccia interna e su quella esterna:

0:48:54:89:20:f7 ff:ff:ff:ff:ff:ff : DHCP:DISCOVER CID:[ether]00:48:54:89:20:f7
0:e0:4c:49:42:de ff:ff:ff:ff:ff:ff : ether 0:48:54:89:20:f7 DHCP:DISCOVER CID:[ether]00:48:54:89:20:f7

Come si nota facilmente, l’indirizzo sorgente e` stato cambiato nel passaggio
attraverso il bridge, ma non i dati nei payload: infatti il dumper della rete
segnala una discrepanza tra i dati della query e quelli dell’header (ether
0:48:54:89:20:f7).

Vediamo ora la risposta del server, sempre su entrambe le interfacce:

0:48:54:89:6:91 0:48:54:89:20:f7 : DHCP:OFFER
0:48:54:89:6:91 0:48:54:89:20:f7 : DHCP:OFFER

In questo caso, come avevamo stabilito durante la progettazione del bridge, il
pacchetto passa immutato, ma se notate l’indirizzo MAC di destinazione e` gia`
quello del client, e non quello dell’interfaccia esterna del bridge 😀

Aggiungendo computer sia a destra che a sinistra del bridge, la rete continua
a mantenere le sue caratteristiche e quindi la sua funzionalita`.

Dal punto di vista della teoria, quindi, abbiamo confermato tutte le attese (e
forse anche di piu` a ben vedere :>), e facendo delle prove notiamo come
questa semitrasparenza funzioni permettendo al client di vedere il server.
Ma purtroppo non abbiamo considerato che il nostro server manca della
caratteristica principale per la quale stiamo facendo tutto questo, ovvero che
per ora abbiamo solo evitato che uscissero pacchetti con MAC address
differenti, ma ancora non e` finita, perche` ci rimane da affrontare il
Catalyst e la sua port security.

 

[00000111] – Timori e coraggio

Preparazione. Arrivare allo scontro senza essersi preparati a dovere e` da
idioti. Cosa potrebbe capitare una volta faccia a faccia? L’occasione non e`
da bruciare, bisogna trarne quante piu` osservazioni possibili.
Il port security: tutto e` basato su quello. Potrebbe controllare il payload
delle query ARP, e riconoscere che l’indirizzo e` diverso.. Potrebbe anche,
una volta che la query ARP e` stata soddisfatta, non sapere su che porta
reindirizzare il pacchetto, visto che nessuna ha il MAC registrato.. Cosa
farebbe in questo caso? Scarterebbe il pacchetto? Lo reindirizzerebbe su una
porta di default? Lo manderebbe su tutte le porte?

In questo caso il nostro codice di bridging dovrebbe modificare anche tutti i
payload dei protocolli (principalmente ARP e dhcp) che fanno uso del MAC
address, mascherandolo a dovere e poi risistemando anche i pacchetti in
entrata verso la LAN..
Un bel lavoraccio, insomma.. Vale forse la pena di essere un po’ intrepidi e
di buttarsi in un primo test; nel caso fallisse, dovremmo rimetterci a
tavolino e cercare di studiare un’altra soluzione.

*click* *click* *click*

I cavi ethernet sono stati attaccati, il codice e` stato lanciato, non ci
rimane che la prova del fuoco. Incrociamo le dita, ripensiamo ai momenti belli
della nostra infanzia e saltiamo..

 

[00001000] – Faccia a faccia

E` il momento, l’infrastruttura e` collegata e operativa..
Facciamo delle prove, cambiando i pc collegati e controllando sempre che la
linea sia attiva..
Il primo MAC, il secondo, il terzo.. Tutto ancora bene.. Il quarto, il quinto..
Ci siamo..
Il sesto..

FUNZIONAAA!!! :>

Anche se non ci speravamo troppo, pare che tutto funzioni..
Ping, resolve degli host, dhcp, connessioni complete e stabili su tcp..
Proviamo ad attaccare anche videostation e CPV.. Paiono non accorgersi nemmeno
di quello che e` successo, ignare macchine create dal nemico..
Ma era davvero cosi` semplice? E tutti i nostri timori?
Beh, piu` che giustificabili, ma fortunatamente si sono rivelati falsi,
spianandoci la strada verso la vittoria 😀

Ma soprattutto, c’era bisogno di scrivere tutte queste follie mentali per un
si` semplice accrocchio?
Perdonatemi, ma cosi` e` la mia natura, e ogni tanto un piccolo sfogo mi fa
bene; addolcitevi con cio` che e` a venire, due piccoli codici che mettono in
pratica quello che fin’ora e` stato detto.
Sia chiaro. Non me ne prendo nessuna responsabilita`.
Credo che dal punto di vista legale sia davvero difficile capire se sia una
cosa fattibile o meno, visto che bisognerebbe definire il concetto di
periferica direttamente connessa a Fastweb (i tecnici stessi consigliano di
usare NAT per collegare piu` computer, e alla fine noi abbiamo fatto qualcosa
di simile ad un NAT, ma a layer2..); per di piu` i computer non sono
fisicamente connessi al Catalyst, perche` passano dal nostro bridge..
Tante e belle domande, ognuno ci ragioni su ed agisca di conseguenza.

 

[00001001] – HEAT

Tutto e` detto, si tratta ora solo di definirlo in maniera un po’ coerente e
di codificarlo in un idioma comprensibile dal nostro elaboratore.
HEAT. Half Ethernet Address Translation.
Il perche` di questo nome risulta abbastanza chiaro: i pacchetti vengono
sottoposti ad una modifica dell’indirizzo sorgente, ma, a differenza delle
tecniche di NAT, non quello IP (layer3), ma quello Ethernet (layer2); inoltre
solo quelli in uscita necessitano di questa modifica, mentre quelli in entrata
sono lasciati inalterati, quindi il lavoro di translation e` solo mezzo 😀

Per quanto riguarda l’infrastruttura fisica, un bridge con il relativo codice
di HEAT e` interposto tra la nostra lan e il Catalyst, comportandosi in modo
semitrasparente a layer2 mentre (spero) completamente trasparente ai livelli
superiori.

Questo e` quanto, il resto e` relativamente futile.

 

[00001010] – I professionisti del mestiere

Ebbene, e` giunta l’ora di svelare i professionisti del mestiere, loro, quelli
che durante tutto questo parlottare hanno svolto il compito principale, coloro
che hanno reso la teoria pratica, quelli che vengono chiamati sempre nel
momento del bisogno, e che per vari motivi non amano mettersi troppo in mostra
e condividere le passerelle della notorieta` con falsi messaggeri della
verita`, ma si accontentano di fare le cose che devono fare, e farle per bene.

Lui, il mitico giovane tuttofare, triste e solitario, ma sempre pronto ad
aiutare la gente, colui che viene chiuso dentro uno sgabuzzino delle pulizie
legato mani e piedi, ma si libera, e con le sostanza per lavare i pavimenti
apre la porta e si costruisce bombe per sgominare i cattivi. E` lui! Mac
Gyver!!!
MAC-gyver (il cui nome riflette anche il suo scopo) e` la prima e piu`
semplice versione del codice di HEAT.
Tutto quello di cui necessita e` una macchina con due interfacce di rete, il
supporto ethernet, libpcap e Libnet; non e` necessario il supporto IP, anche
se vedremo dopo che puo` essere sfruttato.
Il metodo di discriminazione dei pacchetti e` molto semplice, implementato
tramite i filtri pcap: i pacchetti che vengono letti sull’interfaccia interna
sono da forwardare sull’esterna, una volta modificati, solo se il loro
hardware address sorgente coincide con uno di quelli elencati nel file di
configurazione, mentre sull’interfaccia esterna il forward e` fatto per i
pacchetti che non hanno MAC sorgente coincidente con quello della stessa
interfaccia esterna del bridge.
Per usare MAC-gyver basta scrivere in un file l’elenco dei MAC dei pc da
mascherare tramite HEAT, e lanciare il programma definendo l’interfaccia
interna (verso la LAN) e quella esterna (verso il Catalyst). Il resto viene da
se`.

Se temete che Mac non ce la possa fare, potete sempre rivolgervi a loro, i
mitici, gli insuperabili, coloro che entrano nel loro box con una cinquecento
e delle lattine di fagioli ed escono con un blindato armato di tuttopunto 😀
Citando: “If you’ve a problem, if no one else can help, and if you can find
them, maybe you can hire, the A-TEAM.” :>
Le principali differenze che ci sono con MAC-gyver sono poco rilevanti: il
metodo di discriminazione di pacchetti non si basa piu` su regole dei filtri
pcap, ma su uno stack dove vengono salvati i pacchetti in transito e
confrontati per evitare i duplicati (che manderebbero in loop infinito ogni
datagramma causando un sovraccarico inutile della rete). Questo metodo si basa
sulla possibilita` dei due controllori (esterno e interno) di poter interagire
tra loro: e` quindi necessaria la libreria dei POSIX threads, ma i device
possono essere aggiunti a caldo sul sistema senza dover modificare il file di
configurazione e rilanciare il programma.
Per quanto riguarda il codice di gestione della discriminazione dei pacchetti
e` doveroso ringraziare il progetto hogwash (http://hogwash.sourceforge.net/),
da cui ho preso libero spunto. Grazie.

In poche parole, A-team risulta piu` versatile e comodo, ma ho voluto
includere comunque MAC-gyver perche` e` stato il codice su cui ho basato gran
parte dei miei esperimenti, e perche` qualcuno potrebbe trovare problemi a
usare i threads (ad esempio su NetBSD), o ancora perche` si vuole avere un
piu` stretto controllo su chi viene mascherato da HEAT.

 

[00001011] – Rinunce

Un’ultima piccola nota. A molti non fara` piacere, altri invece non ci avranno
nemmeno pensato.
Il bridge; o meglio: la macchina che fa da bridge.
Cosa possiamo farne? Il problema e` che modificando i pacchetti non puo`
essere usata per far parte della LAN, ma possiamo comunque usarla come una
stand alone workstation diretta su Fastweb.
Ma scordatevi con questo codice di poter in alcun modo farla interagire con il
resto delle vostre macchine.
Potra` andare su Internet, ma ogni tentativo di comunicazione con la LAN sara`
inutile.

Comunque non vediatela come una sconfitta, perche` teoricamente un bridge
dovrebbe essere senza ip, e non visibile da nessuno.
Qui vi si da la possibilita` di usare in qualche modo, anche se limitato una
macchina in piu`. Siatene felici.

[00001100] – L’uomo dal cuore d’oro

/*******************************************************************************
*                                                                              *
*            __  __    _    ____                                               *
*           |  \/  |  / \  / ___|      __ _ _   ___   _____ _ __               *
*           | |\/| | / _ \| |   _____ / _` | | | \ \ / / _ \ '__|              *
*           | |  | |/ ___ \ |__|_____| (_| | |_| |\ V /  __/ |                 *
*           |_|  |_/_/   \_\____|     \__, |\__, | \_/ \___|_|                 *
*                                     |___/ |___/                              *
*                                                                              *
*        based on HEAT - Half Ethernet Address Translation tecnology           *
*                   tHE rECIdjVO - [email protected]                         *
*                        http://www.pkcrew.org/                                *
*                                                                              *
*      Libraries needed:                                                       *
*      - libpcap - http://www.tcpdump.org/                                     *
*      - Libnet  - http://libnet.sourceforge.net/                              *
*                                                                              *
*   compile with:                                                              *
*   # cc -o MAC-gyver MAC-gyver.c `libnet-config --defines --libs` -lpcap      *
*                                                                              *
*                                                                              *
*******************************************************************************/

#define ETH_FILE "/etc/ethernet_hosts.conf"
#define ERRBUF_SIZE ((PCAP_ERRBUF_SIZE > LIBNET_ERRBUF_SIZE) ? PCAP_ERRBUF_SIZE : LIBNET_ERRBUF_SIZE)
#define READ_TIMEOUT 1000
#define SNAPLEN 1564
#define PROMISC 1
#define DEBUG 0
#define LOOP -1
#define debugf(x...); if(debug) { printf(x); fflush(stdout); }

#include <pcap.h>
#include <libnet.h>

struct interface {
        int id;
        char *name;
        pcap_t *pcap_desc;
        char *filterstr;
        struct libnet_link_int *net_link;
        unsigned char *out_packet;
};

struct ether_addr *ext_hw_addr = (struct ether_addr *)NULL;
struct interface internal, external;
char *eth_file = (char *)NULL;
char debug = DEBUG;

extern char pcap_version[];

int main(int argc, char *argv[]);
void getparms(int argc, char* argv[]);
void usage(char *progname);
void initialize(struct interface *iface);
int ether_readfile(void);
void heat(char *id, struct pcap_pkthdr *pcap_h, u_char *out_packet);

int main(int argc, char* argv[]) {
        /* Set id flags */
        internal.id = 0;
        external.id = 1;

        /* Get command line params */
        getparms(argc, argv);

        /* Initialize interfaces */
        initialize(&internal);
        initialize(&external);

        /* Fork && go! */
        if(!debug) {
                /* Go in the daemon land */
                if(fork()) {
                        exit(0);
                }
                setsid();
        }

        debugf("Logging traffic ( . -> from external to internal | o -> from internal to external)\n");
        if(fork()) {
                /* Parent process - internal interface */
                pcap_loop(internal.pcap_desc, LOOP, (pcap_handler)heat, (u_char *)internal.id);
        } else {
                /* Child process - external interface */
                pcap_loop(external.pcap_desc, LOOP, (pcap_handler)heat, (u_char *)external.id);
        }

        /* Never here */
        exit(0);
}

void getparms(int argc, char* argv[]) {
        char optc;

        /* Parse command line params */
        while((optc = getopt(argc, argv, "i:e:f:dh")) != EOF) {
                switch(optc) {
                        case 'i':
                                internal.name = optarg;
                                break;
                        case 'e':
                                external.name = optarg;
                                break;
                        case 'f':
                                eth_file = optarg;
                                break;
                        case 'd':
                                debug = 1;
                                 debugf("Set verbose mode ON\n");
                                break;
                        case 'h':
                                usage(argv[0]);
                                exit(0);
                        default:
                                break;
                }
        }
        if((internal.name == (char *)NULL) || (external.name == (char *)NULL)) {
                usage(argv[0]);
                exit(-1);
        }
        debugf("Set internal interface to: %s\n", internal.name);
        debugf("Set external interface to: %s\n", external.name);

        if(eth_file == (char *)NULL) {
                eth_file = (char *)malloc(strlen(ETH_FILE) + 1);
                memcpy(eth_file, ETH_FILE, strlen(ETH_FILE));
                eth_file[strlen(ETH_FILE)] = '\0';
        }
        debugf("Set ethernet address file to: %s\n", eth_file);

        return;
}

void usage(char *progname)
{
        /* Program usage */
        fprintf(stderr, "usage:\t%s -i internal_interface -e external_interface [-d] [-f addresses_file]\n\t%s -h\n\n", progname, progname);
        return;
}

void initialize(struct interface *iface){
        char errorstr[ERRBUF_SIZE];
        struct bpf_program bpf_p;

        debugf("Using libpcap %s\n", pcap_version);
        debugf("Using libnet " LIBNET_VERSION "\n");
       
        debugf("Initializing %s\n", iface->name);

        /* libpcap */
        debugf("[%s] reading.. ", iface->name);
        if((iface->pcap_desc = pcap_open_live(iface->name, SNAPLEN, PROMISC, READ_TIMEOUT, errorstr)) == (pcap_t *)NULL) {
                fprintf(stderr, "\n[%s] %s\n", iface->name, errorstr);
                exit(EXIT_FAILURE);
        }

        if(pcap_datalink(iface->pcap_desc) != DLT_EN10MB) {
                fprintf(stderr, "\n[%s] %s seems not to be an ethernet device.\n", iface->name, iface->name);
                pcap_close(iface->pcap_desc);
                exit(EXIT_FAILURE);
        }
        debugf("OK\n");

        /* Create filter ruleset */
        debugf("[%s] Setting interface data..\n", iface->name);
        if(iface->id) {
                /* External */
                if((ext_hw_addr = libnet_get_hwaddr((struct libnet_link_int *)NULL, iface->name, (u_char *)errorstr)) == (struct ether_addr *)NULL) {
                        libnet_error(0, "[%s] %s\n", iface->name, errorstr);
                        pcap_close(iface->pcap_desc);
                        exit(EXIT_FAILURE);
                }
                debugf("[%s] External hardware address set to [%02x:%02x:%02x:%02x:%02x:%02x]\n", iface->name,
                        ext_hw_addr->ether_addr_octet[0], ext_hw_addr->ether_addr_octet[1], ext_hw_addr->ether_addr_octet[2],
                        ext_hw_addr->ether_addr_octet[3], ext_hw_addr->ether_addr_octet[4], ext_hw_addr->ether_addr_octet[5]);

                iface->filterstr = (char *)malloc((size_t)37);

                sprintf(iface->filterstr, "not ether src host %02x:%02x:%02x:%02x:%02x:%02x",
                        ext_hw_addr->ether_addr_octet[0], ext_hw_addr->ether_addr_octet[1], ext_hw_addr->ether_addr_octet[2],
                        ext_hw_addr->ether_addr_octet[3], ext_hw_addr->ether_addr_octet[4], ext_hw_addr->ether_addr_octet[5]);
            } else {
                /* Internal */
                if(ether_readfile()) {
                        pcap_close(iface->pcap_desc);
                        exit(EXIT_FAILURE);
                }
        }

        if(pcap_compile(iface->pcap_desc, &bpf_p, iface->filterstr, 1, 0) < 0) {
                pcap_perror(iface->pcap_desc, (char *)NULL);
                pcap_close(iface->pcap_desc);
                exit(EXIT_FAILURE);
        }
        free(iface->filterstr);
       
        /* Set the filter */
        if(pcap_setfilter(iface->pcap_desc, &bpf_p) < 0)
        {
                pcap_perror(iface->pcap_desc, (char *)NULL);
                pcap_close(iface->pcap_desc);
                exit(EXIT_FAILURE);
        }
#if PCAP_VERSION_MINOR >= 6
        pcap_freecode(&bpf_p);
#endif
        debugf("[%s] OK\n", iface->name);

        /* libnet */       
        debugf("[%s] writing.. ", iface->name);
        if((iface->net_link = libnet_open_link_interface(iface->name, errorstr)) == (struct libnet_link_int *)NULL) {
                libnet_error(0, "[%s] %s\n", iface->name, errorstr);
                pcap_close(iface->pcap_desc);
                exit(EXIT_FAILURE);
        }
        if(libnet_init_packet(SNAPLEN, &iface->out_packet) == -1) {
                libnet_error(0, "[%s] libnet_init_packet() error.\n", iface->name);
                pcap_close(iface->pcap_desc);
                libnet_close_link_interface(iface->net_link);
                exit(EXIT_FAILURE);
        }
        debugf("OK\n");

        return;
}

int ether_readfile()
{
        FILE *fp;
        unsigned int tmp_addr[ETHER_ADDR_LEN];
        int line = 0, entries = 0;
        char tmp_line[1024];

        /* Open ethernet address file */
        if((fp = fopen(eth_file, "r")) == (FILE *)NULL) {
                fprintf(stderr, "Error opening %s\n", eth_file);
                return(1);
        }

        /* Count valid entries */
        while(1) {
                if((fgets(tmp_line, 1024, fp)) == (char *)NULL) {
                        break;
                }
                line++;
                if((tmp_line[0] == '#') || (strlen(tmp_line) <= 1) || (tmp_line[0] == ' ')) {
                        continue;
                }
                if(sscanf(tmp_line, "%x:%x:%x:%x:%x:%x", &tmp_addr[0], &tmp_addr[1], &tmp_addr[2],
                                                         &tmp_addr[3], &tmp_addr[4], &tmp_addr[5]) != 6) {
                        fprintf(stderr, "Error on %s (line:%d)\n", eth_file, line);
                        fclose(fp);
                        return(1);
                }
                entries++;
        }

        /* Create filter rules */
        internal.filterstr = (unsigned char *)malloc((size_t)(36 * entries));
        rewind(fp);
        while(1) {
                if((fgets(tmp_line, 1024, fp)) == (char *)NULL) {
                        break;
                }

                if((tmp_line[0] == '#') || (strlen(tmp_line) <= 1) || (tmp_line[0] == ' ')) {
                        continue;
                }

                sscanf(tmp_line, "%x:%x:%x:%x:%x:%x", &tmp_addr[0], &tmp_addr[1], &tmp_addr[2],
                                                      &tmp_addr[3], &tmp_addr[4], &tmp_addr[5]);

                if(!strlen(internal.filterstr)) {
                        sprintf(internal.filterstr, "ether src host %02x:%02x:%02x:%02x:%02x:%02x", tmp_addr[0], tmp_addr[1],
                                                                           tmp_addr[2], tmp_addr[3], tmp_addr[4], tmp_addr[5]);
                } else {
                        sprintf(internal.filterstr, "%s or ether src host %02x:%02x:%02x:%02x:%02x:%02x", internal.filterstr,
                                                tmp_addr[0], tmp_addr[1], tmp_addr[2], tmp_addr[3], tmp_addr[4], tmp_addr[5]);
                }
                debugf("[%s] Added hardware address [%02x:%02x:%02x:%02x:%02x:%02x]\n", internal.name,
                        tmp_addr[0], tmp_addr[1], tmp_addr[2], tmp_addr[3], tmp_addr[4], tmp_addr[5]);
        }

        /* Close file and return */
        fclose(fp);
        return(0);
}

void heat(char *id, struct pcap_pkthdr *pcap_h, u_char *out_packet) {
        struct interface *iface;
       
        /* Check where the packet is coming from */
        if((int)id) {
                /* From external interface to internal interface */
                iface = &internal;
        } else {
                /* From internal interface to external interface */
                memcpy(((struct libnet_ethernet_hdr *)out_packet)->ether_shost, ext_hw_addr->ether_addr_octet, ETHER_ADDR_LEN);
                iface = &external;
        }       

        /* Write the packet */
        libnet_write_link_layer(iface->net_link, iface->name, out_packet, pcap_h->len);
        debugf((int)id ? "." : "o");
}

/******************************************************************************/

 

[00001101] – Hannibal Smith e compagni

/*******************************************************************************
*                                                                              *
*                       _         _                                            *
*                      / \       | |_ ___  __ _ _ __ ___                       *
*                     / _ \ _____| __/ _ \/ _` | '_ ` _ \                      *
*                    / ___ \_____| ||  __/ (_| | | | | | |                     *
*                   /_/   \_\     \__\___|\__,_|_| |_| |_|                     *
*                                                                              *
*                                                                              *
*        based on HEAT - Half Ethernet Address Translation tecnology           *
*                   tHE rECIdjVO - [email protected]                         *
*                        http://www.pkcrew.org/                                *
*                                                                              *
*      Libraries needed:                                                       *
*      - libpcap - http://www.tcpdump.org/                                     *
*      - Libnet  - http://libnet.sourceforge.net/                              *
*                                                                              *
*   compile with:                                                              *
*   # cc -o A-team A-team.c `libnet-config --defines --libs` -lpcap -pthread   *
*                                                                              *
*                                                                              *
*******************************************************************************/

#define PROGNAME "A-team"
#define ERRBUF_SIZE ((PCAP_ERRBUF_SIZE > LIBNET_ERRBUF_SIZE) ? PCAP_ERRBUF_SIZE : LIBNET_ERRBUF_SIZE)
#define READ_TIMEOUT 1000
#define STACK_TIMEOUT 2
#define STACKLEN 50
#define SNAPLEN 1564
#define PROMISC 1
#define DEBUG 0
#define LOOP -1
#define debugf(x...); if(debug) { printf(x); fflush(stdout); }

#include <pcap.h>
#include <libnet.h>
#include <pthread.h>

struct interface {
        int id;
        char *name;
        pcap_t *pcap_desc;
        struct libnet_link_int *net_link;
        unsigned char *out_packet;
        pthread_t pthread;
};

struct stack_packet {
        char packet[SNAPLEN];
        unsigned int len;
        struct timeval timestamp;
};

struct stack_packet int_recs[STACKLEN];
struct stack_packet ext_recs[STACKLEN];
pthread_mutex_t int_packet_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t ext_packet_mutex = PTHREAD_MUTEX_INITIALIZER;
struct ether_addr *ext_hw_addr = (struct ether_addr *)NULL;
struct interface internal, external;
char debug = DEBUG;

extern char pcap_version[];

int main(int argc, char *argv[]);
void getparms(int argc, char* argv[]);
void usage(char *progname);
void initialize(struct interface *iface);
void *threadloop(void *iface);
void heat(char *id, struct pcap_pkthdr *pcap_h, u_char *out_packet);
void push(char *packet, int len, int id, struct timeval *tv);
int pop(char *packet, int len, int id);

int main(int argc, char* argv[]) {
        /* Set id flags */
        internal.id = 0;
        external.id = 1;

        /* Blank record structures */
        bzero(int_recs, sizeof(struct stack_packet) * STACKLEN);
        bzero(int_recs, sizeof(struct stack_packet) * STACKLEN);

        /* Get command line params */
        getparms(argc, argv);

        /* Initialize interfaces */
        initialize(&internal);
        initialize(&external);

        /* Fork && go! */
        if(!debug) {
                /* Go in the daemon land */
                if(fork()) {
                        exit(0);
                }
                setsid();
        }

        debugf("Logging traffic ( . -> from external to internal | o -> from internal to external)\n");
        pthread_create(&external.pthread, NULL, threadloop, (void *)&external);
        threadloop((void *)&internal);

        /* Never here */
        exit(0);
}

void getparms(int argc, char* argv[]) {
        char optc;

        /* Parse command line params */
        while((optc = getopt(argc, argv, "i:e:dh")) != EOF) {
                switch(optc) {
                        case 'i':
                                internal.name = optarg;
                                break;
                        case 'e':
                                external.name = optarg;
                                break;
                        case 'd':
                                debug = 1;
                                 debugf("Set verbose mode ON\n");
                                break;
                        case 'h':
                                usage(argv[0]);
                                exit(0);
                        default:
                                break;
                }
        }
        if((internal.name == (char *)NULL) || (external.name == (char *)NULL)) {
                usage(argv[0]);
                exit(-1);
        }
        debugf("Set internal interface to: %s\n", internal.name);
        debugf("Set external interface to: %s\n", external.name);

        return;
}

void usage(char *progname)
{
        /* Program usage */
        fprintf(stderr, "usage:\t%s -i internal_interface -e external_interface [-d]\n\t%s -h\n\n", progname, progname);
        return;
}

void initialize(struct interface *iface){
        char errorstr[ERRBUF_SIZE];

        debugf("Using libpcap %s\n", pcap_version);
        debugf("Using libnet " LIBNET_VERSION "\n");
       
        debugf("Initializing %s\n", iface->name);

        /* libpcap */
        debugf("[%s] reading.. ", iface->name);
        if((iface->pcap_desc = pcap_open_live(iface->name, SNAPLEN, PROMISC, READ_TIMEOUT, errorstr)) == (pcap_t *)NULL) {
                fprintf(stderr, "\n[%s] %s\n", iface->name, errorstr);
                exit(EXIT_FAILURE);
        }

        if(pcap_datalink(iface->pcap_desc) != DLT_EN10MB) {
                fprintf(stderr, "\n[%s] %s seems not to be an ethernet device.\n", iface->name, iface->name);
                pcap_close(iface->pcap_desc);
                exit(EXIT_FAILURE);
        }
        debugf("OK\n");

        /* Get external interface harwaer address */
        if(iface->id) {
                if((ext_hw_addr = libnet_get_hwaddr((struct libnet_link_int *)NULL, iface->name, (u_char *)errorstr)) == (struct ether_addr *)NULL) {
                        libnet_error(0, "[%s] %s\n", iface->name, errorstr);
                        pcap_close(iface->pcap_desc);
                        exit(EXIT_FAILURE);
                }
                debugf("[%s] External hardware address set to [%02x:%02x:%02x:%02x:%02x:%02x]\n", iface->name,
                        ext_hw_addr->ether_addr_octet[0], ext_hw_addr->ether_addr_octet[1], ext_hw_addr->ether_addr_octet[2],
                        ext_hw_addr->ether_addr_octet[3], ext_hw_addr->ether_addr_octet[4], ext_hw_addr->ether_addr_octet[5]);
        }

        /* libnet */       
        debugf("[%s] writing.. ", iface->name);
        if((iface->net_link = libnet_open_link_interface(iface->name, errorstr)) == (struct libnet_link_int *)NULL) {
                libnet_error(0, "[%s] %s\n", iface->name, errorstr);
                pcap_close(iface->pcap_desc);
                exit(EXIT_FAILURE);
        }
        if(libnet_init_packet(SNAPLEN, &iface->out_packet) == -1) {
                libnet_error(0, "[%s] libnet_init_packet() error.\n", iface->name);
                pcap_close(iface->pcap_desc);
                libnet_close_link_interface(iface->net_link);
                exit(EXIT_FAILURE);
        }
        debugf("OK\n");

        return;
}

void *threadloop(void* iface){
        /* Get packets */
        pcap_loop(((struct interface *)iface)->pcap_desc, -1, (pcap_handler)heat, (u_char *)((struct interface *)iface)->id);
        return NULL;
}

void heat(char *id, struct pcap_pkthdr *pcap_h, u_char *out_packet) {
        struct interface *iface;
       
        /* Check where the packet is coming from */
        if((int)id) {
                /* From external interface to internal interface */
                iface = &internal;

                /* Check for duplicates */
                pthread_mutex_lock(&ext_packet_mutex);
                if (pop(out_packet, pcap_h->len, (int)id)){
                        /* packet is duplicate */
                        pthread_mutex_unlock(&ext_packet_mutex);
                        return;
                }
                push(out_packet, pcap_h->len, (int)id, (struct timeval *)&pcap_h->ts);
                pthread_mutex_unlock(&ext_packet_mutex);

        } else {
                /* From internal interface to external interface */
                iface = &external;

                /* Check for duplicates */
                pthread_mutex_lock(&int_packet_mutex);
                if (pop(out_packet, pcap_h->len, (int)id)){
                        /* packet is duplicate */
                        pthread_mutex_unlock(&int_packet_mutex);
                        return;
                }
                memcpy(((struct libnet_ethernet_hdr *)out_packet)->ether_shost, ext_hw_addr->ether_addr_octet, ETHER_ADDR_LEN);
                push(out_packet, pcap_h->len, (int)id, (struct timeval *)&pcap_h->ts);
                pthread_mutex_unlock(&int_packet_mutex);
        }       

        /* Write the packet */
        libnet_write_link_layer(iface->net_link, iface->name, out_packet, pcap_h->len);
        debugf((int)id ? "." : "o");
}

/* Free rewrite from hogwash (http://hogwash.sourceforge.net/) */
void push(char *packet, int len, int id, struct timeval* tv) {
        struct stack_packet *seek;
        int i;

        if(id) {
                seek = &ext_recs[0];
        } else {
                seek = &int_recs[0];
        }

        /* Find a free slot */
        for(i = 0; i < STACKLEN; i++) {
                if(!seek[i].len) {
                        memcpy(seek[i].packet, packet, len);
                        seek[i].len = len;
                        memcpy(&seek[i].timestamp, tv, sizeof(struct timeval));
                        return;
                }

                /* Remove expired packets */
                if((tv->tv_sec - seek[i].timestamp.tv_sec) > STACK_TIMEOUT) {
                        seek[i].len = 0;
                        i--;
                }
        }
}

/* Free rewrite from hogwash (http://hogwash.sourceforge.net/) */
int pop(char *packet, int len, int id){
        struct stack_packet *seek;
        int i;

        if(id) {
                seek = int_recs;
        } else {
                seek = ext_recs;
        }

        for(i = 0; i < STACKLEN; i++) {
                if (seek[i].len == len) {
                        if(!memcmp(seek[i].packet, packet, len)) {
                                /* packet is in the stack */
                                seek[i].len = 0;
                                return 1;
                        }
                }
        }

        return 0;
}

/******************************************************************************/

 

[00001110] – Due righe

Due righe, solo perche` di solito alla fine ci sono i ringraziamenti, e tutta
quella roba che ci si aspetta.
Niente, per sta volta. A chi mi ha aiutato, grazie. A chi mi e` vicino,
grazie. A chi e` nel mio cuore, grazie.

 

[00001111] – Il lungo cammino

Siamo arrivati alla conclusione.
Forse qualcosa e` cambiato dopo tutto questo delirare, forse no, forse nessuno
ha avuto la forza di arrivare fino a qui 😀
Comunque sia, il codice sopra riportato e` solo a scopo didattico, e fa parte
delle distribuzioni complete presenti sul sito http://www.pkcrew.org/ .
Nulla di particolare in piu`, giusto qualche piccolo documento riassuntivo per
il futuro, un Makefile e la licenza, che comunque e` GPL.

Cosa sara` il futuro? E chi puo` dirlo? Piu` di una volta ho pensato di vedere
avanti, ma poi qualcosa sempre di diverso ed imprevisto c’e` stato, nel bene e
nel male. E chissa`, forse e` meglio cosi`, e` questo il bello.

Continuate a lavorare, continuate a pensare, perche` quando si smette di
pensare cos’altro si e` se non morti nell’anima?
Io, da parte mia, ho gia` in mente qualcosa di carino, e non ho certo sperato
di vincere per KO al primo round.
Non posso dire se si arrivera` mai ai punti, o se qualcuno di noi crollera`
prima. Staremo a vedere.

Sorrido, infine.
Tra poche settimane, in luna piena, andro` a Verona in treno a trovare
|CyRaX|, e questa volta non mi stupiro`.

VORRO` ANCORA DIRLO A TUTTI.


tHE rECIdjVO <[email protected]>
Member of the Packet Knights
http://www.pkcrew.org/
Public Key at http://www.pkcrew.org/keys/recidjvo.asc

 

-[ WEB ]———————————————————————-

 http://www.bfi.cx
 http://www.s0ftpj.org/bfi/
 http://bfi.itapac.net
-[ E-MAiL ]——————————————————————-

 [email protected]
-[ PGP ]———————————————————————-

—–BEGIN PGP PUBLIC KEY BLOCK—–
Version: 2.6.3i
mQENAzZsSu8AAAEIAM5FrActPz32W1AbxJ/LDG7bB371rhB1aG7/AzDEkXH67nni
DrMRyP+0u4tCTGizOGof0s/YDm2hH4jh+aGO9djJBzIEU8p1dvY677uw6oVCM374
nkjbyDjvBeuJVooKo+J6yGZuUq7jVgBKsR0uklfe5/0TUXsVva9b1pBfxqynK5OO
lQGJuq7g79jTSTqsa0mbFFxAlFq5GZmL+fnZdjWGI0c2pZrz+Tdj2+Ic3dl9dWax
iuy9Bp4Bq+H0mpCmnvwTMVdS2c+99s9unfnbzGvO6KqiwZzIWU9pQeK+v7W6vPa3
TbGHwwH4iaAWQH0mm7v+KdpMzqUPucgvfugfx+kABRO0FUJmSTk4IDxiZmk5OEB1
c2EubmV0PokBFQMFEDZsSu+5yC9+6B/H6QEBb6EIAMRP40T7m4Y1arNkj5enWC/b
a6M4oog42xr9UHOd8X2cOBBNB8qTe+dhBIhPX0fDJnnCr0WuEQ+eiw0YHJKyk5ql
GB/UkRH/hR4IpA0alUUjEYjTqL5HZmW9phMA9xiTAqoNhmXaIh7MVaYmcxhXwoOo
WYOaYoklxxA5qZxOwIXRxlmaN48SKsQuPrSrHwTdKxd+qB7QDU83h8nQ7dB4MAse
gDvMUdspekxAX8XBikXLvVuT0ai4xd8o8owWNR5fQAsNkbrdjOUWrOs0dbFx2K9J
l3XqeKl3XEgLvVG8JyhloKl65h9rUyw6Ek5hvb5ROuyS/lAGGWvxv2YJrN8ABLo=
=o7CG
—–END PGP PUBLIC KEY BLOCK—–
==============================================================================
———————————–[ EOF ]————————————
==============================================================================

Lascia un commento