/*
* 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, ...);
|