Isnprint.c displays the ISN numbers of a remote server. Useful for testing the recent ISN vulnerabilities, as discussed in Lcrzo.
e32886650c5ccf37157908d05cc0208309e7498aac9361658ec791133df9fbdc
/*
ISNprint.c - display ISN numbers of a server
Recently, attacks against TCP/IP Initial Sequence Numbers were published :
- CERT Advisory CA-2001-09 "Statistical Weaknesses in TCP/IP Initial
Sequence Numbers" - http://www.cert.org/advisories/CA-2001-09.html
- Michal Zalewski "Strange Attractors and TCP/IP Sequence Number Analysis"
http://razor.bindview.com/publish/papers/tcpseq.html
To predict ISN, there are two steps :
- obtain the serie of generated ISN values
- predict the next ISN which may be used by the server
This program achieves the first step by displaying ISN numbers of a server :
# ./ISNprint www.server.com 80
ISN
0 : 4213610146
1 : 1433396694 [diff -2780213452]
2 : 2342587356 [diff +0909190662]
3 : 3904132205 [diff +1561544849]
4 : 1742387478 [diff -2161744727]
5 : 3486208657 [diff +1743821179]
6 : 3263927723 [diff -0222280934]
7 : 3514925853 [diff +0250998130]
8 : 0729418132 [diff -2785507721]
9 : 2770073670 [diff +2040655538]
10 : 1643678857 [diff -1126394813]
11 : 1658572002 [diff +0014893145]
12 : 1871339414 [diff +0212767412]
The second step, the statistical prediction, is not done in this
program. If you are a statistical expert, you may want to complete
this program and publish it.
To compile :
# gcc -o ISNprint ISNprint.c -llcrzo -lpcap
The library lcrzo is needed :
http://www.laurentconstantin.com/us/lcrzo/lcrzo/ [main server]
http://go.to/laurentconstantin/us/lcrzo/lcrzo/ [backup server]
http://laurentconstantin.est-la.com/us/lcrzo/lcrzo/ [backup server]
*/
/* include the library headers */
#include <lcrzo.h>
#if ! defined _POSIX_SOURCE
#define _POSIX_SOURCE 1
#endif
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
/*-------------------------------------------------------------*/
/* function declarations */
void isn_sig_received1(int i);
void isn_sig_received2(int i);
int isn_sendsyn(lcrzo_device device,
lcrzo_etha clientetha,
lcrzo_etha destetha,
lcrzo_ipl clientipl,
lcrzo_ipl serveripl,
lcrzo_uint16 serverport,
lcrzo_uint16 startingclientport,
lcrzo_uint32 startingclientseqnum);
int isn_print(lcrzo_device device,
lcrzo_etha clientetha,
lcrzo_etha destetha,
lcrzo_ipl clientipl,
lcrzo_ipl serveripl,
lcrzo_uint16 serverport,
lcrzo_uint16 startingclientport,
lcrzo_uint32 startingclientseqnum);
int isn_printseqnum(lcrzo_data sniffdata,
lcrzo_int32 sniffdatasize,
lcrzo_etha clientetha,
lcrzo_etha destetha,
lcrzo_ipl clientipl,
lcrzo_ipl serveripl,
lcrzo_uint16 serverport,
lcrzo_uint16 startingclientport,
lcrzo_uint32 startingclientseqnum);
/*-------------------------------------------------------------*/
/* global variables */
int isn_pid;
lcrzo_spoof isn_spoof;
lcrzo_sniff isn_sniff;
/*-------------------------------------------------------------*/
int main(int argc, char *argv[])
{ lcrzo_etha clientetha, destetha;
lcrzo_ipl clientipl, serveripl;
lcrzo_device device;
lcrzo_uint16 serverport, startingclientport;
lcrzo_uint32 startingclientseqnum;
if ( argc<3 )
{ /* print usage */
printf("Usage : %s server port\n", argv[0]);
printf("Example : %s 1.2.3.4 80\n", argv[0]);
return(LCRZO_ERR_BULCRZOEXBADUSAGE);
}
/* set server information */
lcrzo_epr(lcrzo_ipl_init_hs(argv[1], &serveripl));
lcrzo_epr(lcrzo_uint16_init_text(argv[2], &serverport));
/* obtain device and Ethernet addresses */
lcrzo_epr(lcrzo_conf_route_to_host(serveripl, device,
clientetha, destetha,
&clientipl, NULL));
/* determine starting values */
lcrzo_epr(lcrzo_uint16_rand(5000, 30000, &startingclientport));
lcrzo_epr(lcrzo_uint32_rand(0, 0xEFFFFFFFU, &startingclientseqnum));
isn_pid=fork();
if (isn_pid<0) return(LCRZO_ERR_FUFORK);
if (isn_pid==0)
{ /* this process sends a SYN (we left to our computer the job to send
a RST) */
/* in case we receive a signal */
signal(SIGINT, isn_sig_received1);
lcrzo_epr(isn_sendsyn(device, clientetha, destetha,
clientipl, serveripl, serverport,
startingclientport, startingclientseqnum));
/*never reatched*/
}
else
{ /* this process sniff and prints sequence numbers */
/* in case we receive a signal */
signal(SIGINT, isn_sig_received2);
lcrzo_epr(isn_print(device, clientetha, destetha,
clientipl, serveripl, serverport,
startingclientport, startingclientseqnum));
/*never reatched*/
}
/* never reatched */
return (0);
}
/*-------------------------------------------------------------*/
void isn_sig_received1(int i)
{ int language;
lcrzo_global_get_language(&language);
if ( language==LCRZO_GLOBAL_FRLANG )
printf("Fermeture du spoof (recu : SIG%d)\n", i);
else
printf("Closing spoof (received : SIG%d)\n", i);
lcrzo_spoof_close(&isn_spoof);
raise(SIGTERM);
}
/*-------------------------------------------------------------*/
void isn_sig_received2(int i)
{ int status, language;
lcrzo_global_get_language(&language);
if ( language==LCRZO_GLOBAL_FRLANG )
printf("Fermeture du sniff (recu : SIG%d)\n", i);
else
printf("Closing sniff (received : SIG%d)\n", i);
kill(isn_pid, SIGINT);
waitpid(isn_pid, &status, 0);
lcrzo_sniff_close(&isn_sniff);
raise(SIGTERM);
}
/*-------------------------------------------------------------*/
int isn_sendsyn(lcrzo_device device,
lcrzo_etha clientetha,
lcrzo_etha destetha,
lcrzo_ipl clientipl,
lcrzo_ipl serveripl,
lcrzo_uint16 serverport,
lcrzo_uint16 startingclientport,
lcrzo_uint32 startingclientseqnum)
{ lcrzo_hdrleth hdrleth;
lcrzo_hdrlip hdrlip;
lcrzo_hdrltcp hdrltcp;
lcrzo_uint16 clientport;
lcrzo_uint32 clientseqnum;
/* initialize Ethernet header */
lcrzo_epr(lcrzo_hdrleth_initdefault(&hdrleth));
memcpy(hdrleth.src, clientetha, LCRZO_ETHA_MAXBYTES);
memcpy(hdrleth.dst, destetha, LCRZO_ETHA_MAXBYTES);
/* initialize IP header */
lcrzo_epr(lcrzo_hdrlip_initdefault(&hdrlip));
hdrlip.saddr=clientipl;
hdrlip.daddr=serveripl;
/* initialize TCP header */
lcrzo_epr(lcrzo_hdrltcp_initdefault(&hdrltcp));
hdrltcp.dport=serverport;
hdrltcp.syn=1;
clientport=startingclientport;
clientseqnum=startingclientseqnum;
/* spoof */
lcrzo_epr(lcrzo_spoof_init(&isn_spoof));
while(1)
{ lcrzo_epr(lcrzo_spoof_ethipopttcpoptdata(&isn_spoof, device, hdrleth,
hdrlip, NULL, 0,
hdrltcp, NULL, 0,
NULL, 0));
hdrltcp.sport=clientport++;
hdrltcp.seqnum=clientseqnum; clientseqnum+=10;
/* you may want to remove this sleep, if you own the server */
lcrzo_epr(lcrzo_time_sleep(100000));
}
/*never reatched*/
return(LCRZO_ERR_IEINTERNALERROR);
}
/*-------------------------------------------------------------*/
int isn_print(lcrzo_device device,
lcrzo_etha clientetha,
lcrzo_etha destetha,
lcrzo_ipl clientipl,
lcrzo_ipl serveripl,
lcrzo_uint16 serverport,
lcrzo_uint16 startingclientport,
lcrzo_uint32 startingclientseqnum)
{ lcrzo_uint32 mtu;
lcrzo_data sniffdata;
lcrzo_int32 sniffdatasize;
int ret;
/* init sniff */
lcrzo_epr(lcrzo_mtu_init_device(device, &mtu));
lcrzo_epr(lcrzo_sniff_init(device, mtu, "", &isn_sniff));
/* main loop */
ret=lcrzo_sniff_nextm(&isn_sniff, LCRZO_TRUE,
LCRZO_SNIFF_TYPE_NORMAL, &sniffdata, &sniffdatasize);
while (ret==LCRZO_ERR_OK)
{ /* decode TCP and print seqnum */
lcrzo_epr(isn_printseqnum(sniffdata, sniffdatasize,
clientetha, destetha,
clientipl, serveripl, serverport,
startingclientport,
startingclientseqnum));
lcrzo_data_free(sniffdata);
/* sniff next packet */
ret=lcrzo_sniff_nextm(&isn_sniff, LCRZO_TRUE,
LCRZO_SNIFF_TYPE_NORMAL, &sniffdata, &sniffdatasize);
}
/* close everything */
raise(SIGINT);
/*never reatched*/
return(LCRZO_ERR_IEINTERNALERROR);
}
/*-------------------------------------------------------------*/
int isn_printseqnum(lcrzo_data sniffdata,
lcrzo_int32 sniffdatasize,
lcrzo_etha clientetha,
lcrzo_etha destetha,
lcrzo_ipl clientipl,
lcrzo_ipl serveripl,
lcrzo_uint16 serverport,
lcrzo_uint16 startingclientport,
lcrzo_uint32 startingclientseqnum)
{ static lcrzo_uint32 oldseqnum;
lcrzo_hdrleth hdrleth;
lcrzo_hdrlip hdrlip;
lcrzo_hdrltcp hdrltcp;
int ret;
lcrzo_uint32 diff1, diff2;
/* try to decode it */
ret=lcrzo_packet_decodem_ethipopttcpoptdata(sniffdata, sniffdatasize,
&hdrleth, &hdrlip, NULL, NULL,
&hdrltcp, NULL, NULL,
NULL, NULL);
if ( ret!=LCRZO_ERR_OK )
return(LCRZO_ERR_OK);
/* only count synack */
if ( ! (hdrltcp.syn && hdrltcp.ack) )
return(LCRZO_ERR_OK);
/* check if the addresses are the one we are looking for */
if ( ! lcrzo_etha_equal(hdrleth.src, destetha) )
return(LCRZO_ERR_OK);
if ( ! lcrzo_etha_equal(hdrleth.dst, clientetha) )
return(LCRZO_ERR_OK);
if ( ! lcrzo_ipl_equal(hdrlip.saddr, serveripl) )
return(LCRZO_ERR_OK);
if ( ! lcrzo_ipl_equal(hdrlip.daddr, clientipl) )
return(LCRZO_ERR_OK);
/* check server port */
if ( hdrltcp.sport!=serverport )
return(LCRZO_ERR_OK);
/* now this seems ok, but we verify with starting values */
diff1=hdrltcp.dport-startingclientport;
diff2=(hdrltcp.acknum-1-startingclientseqnum)/10;
if ( diff1!=diff2 )
return(LCRZO_ERR_OK);
/* now, it's OK, so we print the seqnum */
printf("% 6ld : %.10lu\t[diff ", diff1, hdrltcp.seqnum);
if (hdrltcp.seqnum>=oldseqnum)
printf("+%.10lu]\n", hdrltcp.seqnum-oldseqnum);
else
printf("-%.10lu]\n", oldseqnum-hdrltcp.seqnum);
oldseqnum=hdrltcp.seqnum;
return(LCRZO_ERR_OK);
}