phiral.net
Home

/*
 * aug 28, 2005
 */

packet fun.

unfinished ip, tcp, udp and icmp packet creafting. i'll probably be adding to this and fixing 
all the things i did wrong with it when i have a couple hours again. the error code is all 
from apue or unp i cant remember, but most all of my info is from unp 
1&2. the tabs are a bit f'ed up because i coded in vim then copied to a txt file. 

put all the files (Makefile, error.c error.h, packet.c, packet.h, ptest.c, ptest.h) 
in the same directory and type make. only tested on gentoo linux although any recent linux 
should work fine. `as is` will let you spoof udp packets, you can easily make it tcp, ip or 
icmp just read the code its easy to change. you have to be root to create a raw socket ;)

---> Makefile

CFLAGS=-fPIC -g -c -Wall -O2
AR=/usr/bin/ar
MV=/bin/mv

all: libpkt.a ptest

error.o: error.c error.h
        gcc $(PIC) $(CFLAGS) error.c

packet.o: packet.c packet.h
         gcc $(PIC) $(CFLAGS) packet.c

libpkt.a: error.o packet.o
        $(AR) ru $@ error.o packet.o
        ranlib $@

ptest: ptest.c ptest.h ptest.o
        gcc ptest.o -L. -lpkt -o $@

clean:
        rm -f *.o libpkt.a ptest

---> error.c

#include "error.h"

void
err_ret (const char *fmt, ...)
{
        va_list ap;

        va_start(ap, fmt);
        err_doit(1, fmt, ap);
        va_end(ap);
        return;
}

void
err_sys (const char *fmt, ...)
{
        va_list ap;

        va_start(ap, fmt);
        err_doit(1, fmt, ap);
        va_end(ap);
        exit(1);
}

void
err_dump (const char *fmt, ...)
{
        va_list ap;

        va_start(ap, fmt);
        err_doit(1, fmt, ap);
        va_end(ap);
        abort(); /* dump core and terminate */
        exit(1); /* shouldn't get here */
}

void
err_msg (const char *fmt, ...)
{
        va_list ap;

        va_start(ap, fmt);
        err_doit(0, fmt, ap);
        va_end(ap);
        return;
}

void
err_quit (const char *fmt, ...)
{
        va_list ap;

        va_start(ap, fmt);
        err_doit(0, fmt, ap);
        va_end(ap);
        exit(1);
}

static void
err_doit (int errnoflag, const char *fmt, va_list ap)
{
        int errno_save;
        char buf[MAXLINE];

        errno_save = errno; /* value caller might want printed */
        vsprintf(buf, fmt, ap);
        if (errnoflag)
                sprintf(buf+strlen(buf), ": %s", strerror(errno_save));
        strcat(buf, "\n");
        fflush(stdout); /* in case stdout and stderr are the same */
        fputs(buf, stderr);
        fflush(NULL); /* flushes all stdio output streams */
        return;
}

---> error.h

#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define MAXLINE 4096

static void err_doit(int, const char *, va_list);

char *pname = NULL; /* caller can set this from argv[0] */


---> packet.c

#include "packet.h"

int
sendPacket (int sock, int setsock, uint dest, int port, uchar *packet, int len)
{
        int on;
        struct sockaddr_in addr;
        on = 1;
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = (uint)dest;
        if (port > 0)
                addr.sin_port = htons(port);
        if (setsock == 1)
                if ((setsockopt(sock, IP, IP_HDRINCL, &on, sizeof(on)))<0)
                        err_sys("%s:%d setsockopt()\n", __FILE__, __LINE__);
        if ((sendto(sock, packet, len, 0, (struct sockaddr *)&addr,sizeof(struct sockaddr)))<0)
                err_sys("%s:%d sendto()\n", __FILE__, __LINE__);
        return 0;
}

uint
resolv (char *addr)
{
        uint daddr;
        struct hostent *h;
        h = NULL;
        daddr = inet_addr(addr);
        if (daddr == -1) {
                if(!(h == gethostbyname(addr)))
                        err_sys("%s:%d gethostbyname()\n", __FILE__, __LINE__);
                bcopy(h->h_addr, (char *)&daddr, h->h_length);
        }
        return daddr; 
}

/* jacked checksum funct */
ushort
inet_cksum (ushort *addr, int len)
{
        register int sum;
        ushort answer;
        register ushort *w;
        register int nleft;
        sum = answer = 0;
        w = addr;
        nleft = len;
        while (nleft > 1)  {
           sum += *w++;
                nleft -= 2;
        }
        if (nleft == 1) {
           *(uchar *)(&answer) = *(uchar *)w ;
                sum += answer;
        }                                                                                            
        sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
        sum += (sum >> 16);                     /* add carry */
        answer = ~sum;                          /* truncate to 16 bits */
        return answer;
}

ushort
rand16 (int seed)
{
        char n[2];
        ushort r;
        int fd;
        r = fd = 0;
        if ((fd = open("/dev/urandom", O_RDONLY)) < 0)
                err_sys("%s:%d open()\n", __FILE__, __LINE__);
        if (read(fd, n, 1) < 1)
                err_sys("%s:%d read()\n", __FILE__, __LINE__);
        n[1] = '\0';
        close(fd);
        srandom(seed*atoi(n));
        r = random();
        return r++;
}

int
rawSock (void)
{
        int sock;
        if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
           err_sys("%s:%d socket()\n", __FILE__, __LINE__);
        return sock;
}

void
ipPkt (struct ipPacket p)
{
   struct ip_hdr *ip_hdr = (struct ip_hdr *)p.packet;
        bzero(p.packet, IPHEADERLEN);
        ip_hdr->headlen = 5;
        ip_hdr->ver     = 4;
        ip_hdr->tos     = p.tos;
        ip_hdr->length  = htons(p.length);
        ip_hdr->id      = htons(p.id);
        ip_hdr->offset  = htons(p.offset);
        ip_hdr->ttl     = p.ttl;
        ip_hdr->proto   = p.proto;
        ip_hdr->sum     = 0;
        ip_hdr->source  = p.source;
        ip_hdr->dest    = p.dest;
        ip_hdr->sum     = inet_cksum((ushort *)ip_hdr, IPHEADERLEN);
}

void
icmpPkt (struct icmpPacket i)
{
   struct icmp_hdr *icmp_hdr = (struct icmp_hdr *)(i.packet+i.len);
   bzero(i.packet+i.len, ICMPHEADERLEN+i.ploadlen);
   icmp_hdr->type   = i.type;
   icmp_hdr->code   = i.code;
   icmp_hdr->sum    = 0;
   if (!i.id)
      icmp_hdr->id  = rand16(getpid());
   else
      icmp_hdr->id  = i.id;

   if (!i.seq)
      icmp_hdr->seq = rand16(getpid());
   else
      icmp_hdr->seq = i.seq;

   if (i.ploadlen > 0)
      memcpy(i.packet+i.len+ICMPHEADERLEN, (uchar *)i.pload, i.ploadlen);

   icmp_hdr->sum = inet_cksum((ushort *)icmp_hdr, ICMPHEADERLEN+i.ploadlen);

}

void
udpPkt (struct udpPacket u)
{
   struct udp_hdr *udp_hdr = (struct udp_hdr *)(u.packet+u.len);
   bzero(u.packet+u.len, UDPHEADERLEN+u.ploadlen);
   udp_hdr->sport  = htons(u.sport);
   udp_hdr->dport  = htons(u.dport);
   udp_hdr->length = htons(UDPHEADERLEN+u.ploadlen);
   udp_hdr->sum    = 0;
   if (u.ploadlen > 0)
      memcpy(u.packet+u.len+UDPHEADERLEN, (uchar *)u.pload, u.ploadlen);
} 

void
tcpPkt (struct tcpPacket t)
{
   struct pseudo_hdr *pseudo_hdr = (struct pseudo_hdr *)(t.packet + t.len-sizeof(struct pseudo_hdr));
   struct tcp_hdr *tcp_hdr = (struct tcp_hdr *)(t.packet + t.len);
   bzero(t.packet, t.len-sizeof(struct pseudo_hdr)+TCPHEADERLEN+t.ploadlen);
   pseudo_hdr->source = t.source;
   pseudo_hdr->dest   = t.dest;
   pseudo_hdr->zero   = 0;
   pseudo_hdr->proto  = TCP;
   pseudo_hdr->len    = htons(TCPHEADERLEN+t.ploadlen);
   tcp_hdr->sport = htons(t.sport);
   tcp_hdr->dport = htons(t.dport);
   tcp_hdr->seq   = htonl(t.seq);
   tcp_hdr->ack   = htonl(t.ack);
   tcp_hdr->x2    = 0;
   tcp_hdr->off   = 5;
   tcp_hdr->flags = t.flags;
   tcp_hdr->win   = htons(t.win);
   tcp_hdr->sum   = 0;
   tcp_hdr->urg   = t.urg;
   if(t.ploadlen > 0)
       memcpy(t.packet+t.len+TCPHEADERLEN,t.pload,t.ploadlen);
   tcp_hdr->sum = inet_cksum((ushort *)pseudo_hdr, sizeof(struct pseudo_hdr)+TCPHEADERLEN+t.ploadlen);
}

---> packet.h

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>

#define IPHEADERLEN   0x14
#define ICMPHEADERLEN 0x8
#define UDPHEADERLEN  0x8
#define TCPHEADERLEN  0x14

#define TCP           6
#define IP            0
#define ICMP          1
#define UDP           17

#define FIN           0x01
#define SYN           0x02
#define RST           0x04
#define PSH           0x08
#define ACK           0x10
#define URG           0x20


#define ICMP_TYPE_ECHO  8
#define ICMP_TYPE_EREQ  0

#define        IP_RF           0x8000
#define        IP_DF           0x4000
#define        IP_MF           0x2000

typedef unsigned char uchar;

/* ipv4 header */
struct ip_hdr {
        uchar  headlen:4;  /* header len      */
        uchar  ver:4;      /* version         */
        uchar  tos;        /* type of service */
        ushort length;     /* pack3t length   */
        ushort id;         /* ident           */
        ushort offset;     /* frag offset     */
        uchar  ttl;        /* time to live    */
        uchar  proto;      /* protocol        */
        ushort sum;        /* checksum        */
        uint   source;     /* source addr     */
        uint   dest;       /* dest addr       */
}; /* 20 bytes */

/* icmp header */
struct icmp_hdr {
        uchar  type;       /* icmp type      */
        uchar  code;       /* type of err    */
        ushort sum;        /* checksum       */
        ushort id;         /* id of request  */
        ushort seq;        /* seq of echo's  */
}; /* 8 bytes */

/* udp header */
struct udp_hdr {
        ushort sport;      /* source port    */
        ushort dport;      /* dest port      */
        ushort length;     /* length         */
        ushort sum;        /* checksum       */
}; /* 8 bytes */

/* tcp header */
struct tcp_hdr {
        ushort sport;       /* source port    */
        ushort dport;       /* dest port      */
        uint   seq;         /* sequence num   */
        uint   ack;         /* acknowledge    */
        uchar  x2:4;        /* unknown        */
        uchar  off:4;       /* segment offset */
        uchar  flags;       /* flags          */
        ushort win;         /* window size    */
        ushort sum;         /* checksum       */
        ushort urg;         /* urgent ptr     */
}; /* 20 bytes */

/* pseudo header */
struct pseudo_hdr {
        uint   source;      /* source address */
        uint   dest;        /* dest address   */
        uchar  zero;        /* zero           */
        uchar  proto;       /* protocol       */
        ushort len;         /* length         */
};

/* tcp options header */
struct tcpopt_hdr {
        unsigned char type;          /* type           */
        unsigned short len;          /* length         */
        unsigned short int val;      /* value          */
};

/* packet */
struct packet {
        struct ip_hdr i;
        struct tcp_hdr t;
};

/* checksum */
struct cksum {
        struct pseudo_hdr pseudo;
        struct tcp_hdr tcp;
};

struct tcpPacket {
        int sport;
        int dport;
        uint source;
        uint dest;
        uint seq;
        uint ack;
        int flags;
        int win;
        int urg;
        int len;
        uchar *pload;
        uint ploadlen;
        uchar *packet;
};

struct udpPacket {
        int sport;
        int dport;
        int len;
        uchar *pload;
        int ploadlen;
        uchar *packet;
};

struct icmpPacket {
        uint type;
        uint code;
        ushort id;
        ushort seq;
        int len;
        char *pload;
        uint ploadlen;
        uchar *packet;
};

struct ipPacket {
        int tos;
        int length;
        int id;
        int offset;
        int ttl;
        int proto;
        uint source;
        uint dest;
        uchar *packet;
};

int sendPacket (int, int, uint, int, uchar *, int);
unsigned int resolv (char *);
unsigned short inet_cksum (ushort *, int);
unsigned short int rand16 (int);
int rawSock (void);
void ipPkt   (struct ipPacket);
void icmpPkt (struct icmpPacket);
void udpPkt  (struct udpPacket);
void tcpPkt  (struct tcpPacket);
extern void err_sys (const char *fmt, ...);
extern void err_quit (const char *fmt, ...);

---> ptest.c

#include "ptest.h"

int
main (int argc, char *argv[])
{
        /*
         * struct tcpPacket t;
         * struct icmpPacket i;
         */

        struct udpPacket u;
        struct ipPacket p;
        int sock;
        ushort sport, dport;
        unsigned long int saddr, daddr;
        unsigned char packet[400];

        if (argc < 2)
                err_quit("Usage: %s src_host src_prt dst_host dst_prt\n\n",argv[0]);

        sport = dport = 0;

        bzero( packet, IPHEADERLEN+UDPHEADERLEN);

        saddr = resolv(argv[1]);
        u.sport = atoi(argv[2]);
        daddr = resolv(argv[3]);
        u.dport = atoi(argv[4]);

        u.len = IPHEADERLEN;
        u.pload = NULL;
        u.ploadlen = 0;
        u.packet = packet;

        printf("Source address: %s , Source Port: %d\n", argv[1], sport);
        printf("Dest address: %s , Dest Port: %d\n\n", argv[3], dport);

        sock = rawSock();

        udpPkt(u);

        p.tos = 0;
        p.length = IPHEADERLEN+UDPHEADERLEN;
        p.id = 0;
        p.offset = IP_DF;
        p.ttl = 128;
        p.proto = UDP;
        p.source = saddr;
        p.dest = daddr;
        p.packet = packet;

        ipPkt(p);

        sleep(1);

        if ((sendPacket(sock, 0, daddr, 0, packet, IPHEADERLEN+UDPHEADERLEN)) < 0)
                err_quit("Error sending packet.\n");

        printf("Sent.\n");

        return 0;
}

---> ptest.h

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


#define IPHEADERLEN   0x14
#define ICMPHEADERLEN 0x8
#define UDPHEADERLEN  0x8
#define TCPHEADERLEN  0x14
#define IP_DF 0x4000
#define UDP 17

typedef unsigned char uchar;

struct tcpPacket {
        int sport;
        int dport;
        uint source;
        uint dest;
        uint seq;
        uint ack;
        int flags;
        int win;
        int urg;
        int len;
        uchar *pload;
        uint ploadlen;
        uchar *packet;
};

struct udpPacket {
        int sport;
        int dport;
        int len;
        uchar *pload;
        int ploadlen;
        uchar *packet;
};

struct icmpPacket {
        uint type;
        uint code;
        ushort id;
        ushort seq;
        int len;
        char *pload;
        uint ploadlen;
        uchar *packet;
};

struct ipPacket {
        int tos;
        int length;
        int id;
        int offset;
        int ttl;
        int proto;
        uint source;
        uint dest;
        uchar *packet;
};

extern void err_sys (const char *fmt, ...);
extern void err_quit (const char *fmt, ...);
extern int sendPacket (int, int, uint, int, uchar *, int);
extern uint resolv (char *);
extern ushort inet_cksum (ushort *, int);
extern ushort rand16 (int);
extern int rawSock (void);
extern void ipPkt   (struct ipPacket);
extern void icmpPkt (struct icmpPacket);
extern void udpPkt  (struct udpPacket);
extern void tcpPkt  (struct tcpPacket);
extern void err_sys (const char *fmt, ...);
extern void err_quit (const char *fmt, ...);