天天看點

Capture network packet and send rst packet to cut connection

These days I write a program to capture packet and build a rst packet to cut some connection which match some key url find by AC algorithm.

Find capture the packet by using libpcap.

Then move the pointer to read the context from packet. If this packet contains http protocol , use the AC algorithm to check this packet whether contains some key url.

If match the key url,   set the rst flag.The send the rst packet.The most difficult step of this work is calculate a new check code for tcp header . For this work ,we should add a Pseudo-header to tcp header .Then use the checksum function to do this .The detail of how to calculate tcp's check code can search from network . 

The detail is obvious in code. So read the code , you can understand all technology detail.

Have fun.

This is main.c's  code:

#include <stdio.h>
#include "zlib.h"
#include <stdlib.h>
#define HAVE_REMOTE
#include <pcap.h>
#include "pheader.h"
#include <string.h>
#include <arpa/inet.h>
#include <signal.h>
#define ETHERTYPE_IP 0x0800 /* ip protocol */
#define TCP_PROTOCAL 0x0600 /* tcp protocol */
#define PCAP_OPENFLAG_PROMISCUOUS 1
/*
* function: a simple program to analyze http
* author: blacksword
* date: Wed March 21 2012
*/
FILE * fp;
void my_handler(int signum)
{
    printf("catch the SIGINT:%d\n",signum);
    fclose(fp);
    exit(0);
}
/*void makefadetcp( srcether)
{


}*/
    u_short checksum(u_short *buffer,int size)
{
    unsigned long cksum=0;
    while(size>1)
    {
        cksum+=*buffer++;
        size-=sizeof(u_short);
    }
    if(size)
    {
        cksum+=*(u_char *)buffer;
    }
//将32位數轉換成16
    while (cksum>>16)
        cksum=(cksum>>16)+(cksum & 0xffff);
    return (u_short) (~cksum);
}

int main()
{
    pcap_if_t* alldevs; // list of all devices
    pcap_if_t* d; // device you chose

    pcap_t* adhandle;
    int a = 0;

    char errbuf[PCAP_ERRBUF_SIZE]; //error buffer
    int i=0;
    int inum;
	int packetlen;

    struct pcap_pkthdr *pheader; /* packet header */
    const u_char * pkt_data; /* packet data */
    int res;
    int compressflag;
    int flag;
    int compresssize;
    unsigned long dstLen = BUFFER_MAX_LENGTH;
    tcp_header *th;

    /* pcap_findalldevs_ex got something wrong */
    if (pcap_findalldevs( &alldevs, errbuf) == -1)
    {
        fprintf(stderr, "Error in pcap_findalldevs_ex: %s\n", errbuf);
        exit(1);
    }

    /* print the list of all devices */
    for(d = alldevs; d != NULL; d = d->next)
    {
        printf("%d. %s", ++i, d->name); // print device name , which starts with "rpcap://"
        if(d->description)
            printf(" (%s)\n", d->description); // print device description
        else
            printf(" (No description available)\n");
    }

    /* no interface found */
    if (i == 0)
    {
        printf("\nNo interface found! Make sure Winpcap is installed.\n");
        return -1;
    }

    printf("Enter the interface number (1-%d):", i);
    scanf("%d", &inum);

    if(inum < 1 || inum > i)
    {
        printf("\nInterface number out of range.\n");
        pcap_freealldevs(alldevs);
        return -1;
    }

    for(d=alldevs, i=0; i < inum-1; d=d->next, i++); /* jump to the selected interface */

    /* open the selected interface*/
    if((adhandle = pcap_open_live(d->name, /* the interface name */
                 65536, /* length of packet that has to be retained */
                 PCAP_OPENFLAG_PROMISCUOUS, /* promiscuous mode */
                 1000, /* read time out */
                 /*NULL,*/ /* auth */
                 errbuf /* error buffer */
                 )) == NULL)
                 {
                     fprintf(stderr, "\nUnable to open the adapter. %s is not supported by Winpcap\n",
                             d->description);
                     return -1;
                 }

    printf("\nListening on %s...\n", d->description);

    pcap_freealldevs(alldevs); // release device list
      
    //fp = fopen("text.txt","ab+");
    signal(SIGINT,my_handler);
    /* capture packet */
    while((res = pcap_next_ex(adhandle, &pheader, &pkt_data)) >= 0) {

        if(res == 0)
            continue; /* read time out*/

        ether_header * eheader = (ether_header*)pkt_data; /* transform packet Findata to ethernet header */
        if(eheader->ether_type == htons(ETHERTYPE_IP)) { /* ip packet only */
            ip_header * ih = (ip_header*)(pkt_data+14); /* get ip header */

            if(ih->proto == htons(TCP_PROTOCAL)) { /* tcp packet only */
		//printf("%c",htons(TCP_PROTOCAL));                    
					th = (char*)ih+20;
                   
                    /*unsigned char *fadepacket;
                    fadepacket = (unsigned char *)malloc(54);
                    printf("fadepacket length%d\n",sizeof(fadepacket));
                    memcpy((ether_header*)fadepacket,pkt_data,54);*/
                    tcp_fade_header * th_fade=NULL;
                    th_fade = (tcp_fade_header*)malloc(sizeof(tcp_fade_header));
                    th_fade->th_sport = th->th_sport;
                    th_fade->th_dport = th->th_dport;
                    th_fade->zeros = 0x00;
                    th_fade->proto = 0x06;
                    th_fade->len = 0x0020;
                    memcpy(&th_fade->th_header,th,sizeof(tcp_header));
                    th_fade->th_header.th_len = 0x50;
                    th_fade->th_header.resv_code = 0x04;
                    th_fade->th_header.th_sum = 0x0;
                    th_fade->th_header.th_sum = checksum((unsigned short *)th_fade,sizeof(tcp_fade_header));
                  
                    memcpy(th,&th_fade->th_header,sizeof(tcp_header));
                    eheader->ether_dhost[0] = 0x0a;
                    eheader->ether_dhost[1] = 0x0a;
                    eheader->ether_dhost[2] = 0x0a;
                    eheader->ether_dhost[3] = 0x0a;
                    eheader->ether_dhost[4] = 0x0a;
                    eheader->ether_dhost[5] = 0x0a;

			if(pcap_sendpacket(adhandle,(u_char *)pkt_data,54)==0)
            {
                printf("send  %d rst packet\n",a++);
            }
            //printf("%x\n",th->resv_code);

		int ip_len = ntohs(ih->tlen); /* get ip length, it contains header and body */

                   
                        printf("\n**********************************************\n\n");



                    }
                }

	}
    return 0;
}
           

This code is phead.h:

#ifndef PHEADER_H_INCLUDED
#define PHEADER_H_INCLUDED
/*
*
*/
#define ETHER_ADDR_LEN 6 /* ethernet address */
#define ETHERTYPE_IP 0x0800 /* ip protocol */
#define TCP_PROTOCAL 0x0600 /* tcp protocol */
#define BUFFER_MAX_LENGTH 65536 /* buffer max length */
#define true 1  /* define true */
#define false 0 /* define false */

/*
* define struct of ethernet header , ip address , ip header and tcp header
*/
/* ethernet header */
typedef struct ether_header {
    u_char ether_shost[ETHER_ADDR_LEN]; /* source ethernet address, 8 bytes */
    u_char ether_dhost[ETHER_ADDR_LEN]; /* destination ethernet addresss, 8 bytes */
    u_short ether_type;                 /* ethernet type, 16 bytes */
}ether_header;

/* four bytes ip address */
typedef struct ip_address {
    u_char byte1;
    u_char byte2;
    u_char byte3;
    u_char byte4;
}ip_address;

/* ipv4 header */
typedef struct ip_header {
    u_char ver_ihl;         /* version and ip header length */
    u_char tos;             /* type of service */
    u_short tlen;           /* total length */
    u_short identification; /* identification */
    u_short flags_fo;       // flags and fragment offset
    u_char ttl;             /* time to live */
    u_char proto;           /* protocol */
    u_short crc;            /* header checksum */
    ip_address saddr;       /* source address */
    ip_address daddr;       /* destination address */
    u_int op_pad;           /* option and padding */
}ip_header;

/* tcp header */
typedef struct tcp_header {
    u_short th_sport;         /* source port */
    u_short th_dport;         /* destination port */
    u_int th_seq;             /* sequence number */
    u_int th_ack; 
	u_char th_len;
u_char resv_code;            /* acknowledgement number */
   // u_short th_len_resv_code; /* datagram length and reserved code */
    u_short th_window;        /* window */
    u_short th_sum;           /* checksum */
    u_short th_urp;           /* urgent pointer */
}tcp_header;
typedef struct tcp_fade_header{	
	u_short th_sport;
	u_short th_dport;
	u_char zeros;
	u_char proto;
	u_short len;
	tcp_header th_header;	
}tcp_fade_header;

#endif // PHEADER_H_INCLUDED
           

This code is AC.h:

#ifndef AC_H_INCLUDED

#define AC_H_INCLUDED

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <conio.h>
#include "quque.h"

#define MAX_STATE   100        //自動機最大狀态數

#define MAX_SYMBOL      256        //比對的字元數可以比對所有的ASCII碼

#define MAX_MODE   4                  //最大模式串數

#define MODE_LEN   10

int DFD[MAX_STATE][MAX_SYMBOL];               //狀态轉移表--DFA包括轉向函數和失效函數

int F[MAX_STATE] ; //失敗函數

struct output_t

{

      int flag;

      char str[MODE_LEN];

}output[MAX_STATE];

int father[MAX_STATE];


unsigned int statecount;//總狀态數-1

unsigned int modecount;             //模式串數-1


struct struct_quque * bfs_quque;


void printAC()

{

   int i = 0;

   int j = 0;

   printf("DFD\n");

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

   {

       for(j = 0; j < MAX_SYMBOL; j++)

       {

           printf("%d ",DFD[i][j]);

           if(j == MAX_SYMBOL - 1)

               printf("\n");

       }


   }

   printf("F\n");

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

       printf("%d ",F[i]);

   printf("\noutput\n");

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

       printf("%d %s\n",output[i].flag,output[i].str);


}


void init_ac()

{


   int i,j;

   statecount = 1;

   modecount = 0;


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

   {

       output[i].flag = -1;

       output[i].str[0] = '\0';

       F[i] = 0;

       father[i] = 0;

       for (j = 0 ; j < MAX_SYMBOL; j++)

       {

           DFD[i][j] = 0;

       }

   }

}


void go()

{

   int c;

   int currentstate ;

   char str[MODE_LEN];

   int start = 1;

   int temp = 0;


      //getchar();

   printf("input patter strings,interval with blank and end with enter:\n");

   while((c = getchar()) != '\n')

   {

       if (c != ' ')

       {

           if (start)

           {

               start = 0;

               modecount++;

               currentstate = 0;

               temp = 0;

           }

           str[temp++] = c;


           if(DFD[currentstate][c] == 0)

           {

               DFD[currentstate][c] = statecount;

               father[statecount] = currentstate;

               currentstate = statecount;

               statecount++;

           }

           else

               currentstate = DFD[currentstate][c];


       }

       else

       {

           output[currentstate].flag = 1;

           str[temp] = '\0';

           strcpy(output[currentstate].str, str);

           start = 1;

           if (modecount == MAX_MODE)

           {

               printf("Max patter string number is: %d",MAX_MODE);

               goto END;

           }

       }

   }


   output[currentstate].flag = 1;

   str[temp] = '\0';

   strcpy(output[currentstate].str, str);

   return;

END:

   printf("Press any key to continue...");

   c = getchar();

   return;


}
void fail()

{

   int i,j,t;

   int ch;

   init_bfs_quque(&bfs_quque);

   in_quque(0, bfs_quque);


   while(is_empty(bfs_quque))

   {

       t = out_quque(bfs_quque);

       if(t)

       {


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

           {

               if(DFD[father[t]][i] == t)

               {

                   ch = i;

                   break;

               }

           }

           j = t;

           while((j = F[father[j]]) != 0)

           {

               if(DFD[j][ch])

               {

                   F[t] = DFD[j][ch];

                   break;

               }

           }

           if(j == 0)

           {

               F[t] = (DFD[j][ch] == t)? 0 : DFD[j][ch];

           }


       }

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

       {

           if(DFD[t][i] != 0)

               in_quque(DFD[t][i], bfs_quque);

       }

   }


}

void output_str(int state,int j)

{

   do

   {

       if(output[state].str[0])

           printf("%d %s\n",j - strlen(output[state].str) + 1, output[state].str);

   }

   while((state = F[state]) != 0);


}


void prec()

{

      printf("init ac\n");

   //初始化變量

   init_ac();

   //建立轉向函數

   go();

   //建立失效函數

   fail();

   //列印自動機

   //printAC();


}


int AC(unsigned char *s, int http_len)

{

   int j = -1;

   int flag = 0;

   int currentstate = 0;

   int state = 0;

      int i = 0;


   while(j++ < http_len)

   {

       if (s[j] < MAX_SYMBOL)

       {

           state = DFD[currentstate][s[j]];

           if (state == 0)

           {

               while(currentstate && (!state))

               {

                   state = DFD[F[currentstate]][s[j]];

                   currentstate = state;

               }

           }

           else

               currentstate = state;

           if (output[currentstate].flag == 1)

           {

               output_str(currentstate,j);

                           flag = 1;

           }

       }

   }

   return flag;


}

#endif // AC_H_INCLUDED